diff --git a/clientapp/helpers/callbar.js b/clientapp/helpers/callbar.js new file mode 100644 index 0000000..c258c84 --- /dev/null +++ b/clientapp/helpers/callbar.js @@ -0,0 +1,248 @@ +var CallBar = function (options) { + var spec = options || {}; + this.states = { + incoming: { + buttons: [ + { + cls: 'answer', + label: 'Answer' + }, + { + cls: 'ignore', + label: 'Ignore' + } + ] + }, + calling: { + buttons: [{ + cls: 'cancel', + label: 'Cancel' + }] + }, + active: { + buttons: [{ + cls: 'end', + label: 'End Call' + }], + timer: true + }, + inactive: { + buttons: [], + clearUser: true, + hidden: true + }, + ending: { + buttons: [] + }, + waiting: { + buttons: [] + } + }; + + this.config = { + defaultName: '', + defaultNumber: 'Unknown Number' + }; +}; + +CallBar.prototype.render = function () { + if (!this.dom) { + this.dom = this.domify(template(this)); + this.addButtonHandlers(); + document.body.insertBefore(this.dom, document.body.firstChild); + } else { + this.dom.innerHTML = this.domify(template(this)).innerHTML; + } + this.setState('inactive'); + return this.dom; +}; + +CallBar.prototype.addButtonHandlers = function () { + var self = this; + this.dom.addEventListener('click', function (e) { + var target = e.target; + if (target.tagName === 'BUTTON') { + if (self[target.className]) { + self[target.className](); + } + return false; + } + }, true); +}; + +CallBar.prototype.getStates = function () { + return Object.keys(this.states); +}; + +CallBar.prototype.setState = function (state) { + if (!this.dom) return this; + var buttons = this.dom.querySelectorAll('button'), + callActionsEl = this.dom.querySelector('.callActions'), + self = this, + stateDef = this.states[state], + forEach = Array.prototype.forEach; + if (stateDef) { + // set proper class on bar itself + this.getStates().forEach(function (cls) { + self.dom.classList.remove(cls); + }); + self.dom.classList.add(state); + + // set/remove 'hidden' class on bar itself + if (stateDef.hidden) { + self.dom.classList.remove('visible'); + document.body.classList.remove('candybarVisible'); + } else { + self.dom.classList.add('visible'); + document.body.classList.add('candybarVisible'); + } + + // remove all the buttons + forEach.call(buttons, function (button) { + button.parentElement.removeChild(button); + }); + + // add buttons + stateDef.buttons.forEach(function (button) { + callActionsEl.appendChild(self.domify('')); + }); + + // start/stop timer + if (stateDef.timer) { + if (this.timerStopped) { + this.startTimer(); + } + } else { + this.resetTimer(); + } + + // reset user if relevant + if (stateDef.clearUser) { + this.clearUser(); + } + + } else { + throw new Error('Invalid value for CallBar state. Valid values are: ' + this.getStates().join(', ')); + } + return this; +}; + +CallBar.prototype.endGently = function (delay) { + var self = this; + this.setState('ending'); + setTimeout(function () { + self.dom.classList.remove('visible'); + setTimeout(function () { + self.setState('inactive'); + self.clearUser(); + }, 1000); + }, 1000); + return this; +}; + +CallBar.prototype.setImageUrl = function (url) { + this.attachImageDom(!!url); + this.imageDom.src = url; + this.dom.classList[!!url ? 'add' : 'remove']('havatar'); +}; + +CallBar.prototype.attachImageDom = function (bool) { + if (!this.imageDom) { + this.imageDom = this.dom.querySelector('.callerAvatar'); + } + if (bool && !this.imageDom.parentElement) { + this.dom.insertBefore(this.imageDom, this.dom.firstChild); + } else if (this.imageDom.parentElement) { + this.imageDom.parentElement.removeChild(this.imageDom); + } + return this.imageDom; +}; + +CallBar.prototype.getUser = function () { + var user = this.user || {}, + self = this; + return { + picUrl: user.picUrl, + name: (user.name && user.name) || this.config.defaultName, + number: function () { + if (user.number && user.number !== self.config.defaultNumber) { + if (phoney) { + return phoney.stringify(user.number); + } else { + return escape(user.number); + } + } else { + return self.config.defaultNumber; + } + }() + }; +}; + +CallBar.prototype.setUser = function (details) { + this.user = details; + if (!this.dom) return; + var user = this.getUser(); + this.dom.querySelector('.callerNumber').innerHTML = user.number; + this.dom.querySelector('.callerName').innerHTML = user.name; + this.setImageUrl(user.picUrl); + return this; +}; + +CallBar.prototype.clearUser = function () { + this.setUser({ + picUrl: '', + name: '', + number: '' + }); + return this; +}; + +CallBar.prototype.domify = function (str) { + var div = document.createElement('div'); + div.innerHTML = str; + return div.firstElementChild; +}; + +CallBar.prototype.startTimer = function () { + this.timerStartTime = Date.now(); + this.timerStopped = false; + this.updateTimer(); + return this; +}; + +CallBar.prototype.stopTimer = function () { + this.timerStopped = true; + return this; +}; + +CallBar.prototype.resetTimer = function () { + this.timerStopped = true; + this.setTimeInDom('0:00:00'); + return this; +}; + +CallBar.prototype.updateTimer = function () { + if (this.timerStopped) return; + + var diff = Date.now() - this.timerStartTime, + s = Math.floor(diff / 1000) % 60, + min = Math.floor((diff / 1000) / 60) % 60, + hr = Math.floor(((diff / 1000) / 60) / 60) % 60, + time = [hr, this.zeroPad(min), this.zeroPad(s)].join(':'); + + if (this.time !== time) { + this.time = time; + this.setTimeInDom(time); + } + + setTimeout(this.updateTimer.bind(this), 100); +}; + +CallBar.prototype.setTimeInDom = function (timeString) { + if (!this.dom) return; + this.dom.querySelector('.callTime').innerHTML = timeString; +}; + +CallBar.prototype.zeroPad = function (num) { + return ((num + '').length === 1) ? '0' + num : num; +}; diff --git a/clientapp/models/call.js b/clientapp/models/call.js new file mode 100644 index 0000000..c0ba7f1 --- /dev/null +++ b/clientapp/models/call.js @@ -0,0 +1,17 @@ +/*global app, me, client*/ +"use strict"; + +var _ = require('underscore'); +var HumanModel = require('human-model'); +var logger = require('andlog'); + + +module.exports = HumanModel.define({ + type: 'call', + session: { + contactJid: 'object', + jingleSession: 'object', + state: ['string', true, 'inactive'], + multiUser: ['boolean', true, false] + } +}); diff --git a/clientapp/models/calls.js b/clientapp/models/calls.js new file mode 100644 index 0000000..dd153b0 --- /dev/null +++ b/clientapp/models/calls.js @@ -0,0 +1,10 @@ +"use strict"; + +var BaseCollection = require('./baseCollection'); +var Call = require('./call'); + + +module.exports = BaseCollection.extend({ + type: 'calls', + model: Call +}); diff --git a/clientapp/models/contact.js b/clientapp/models/contact.js index fdafdcf..a5e225d 100644 --- a/clientapp/models/contact.js +++ b/clientapp/models/contact.js @@ -9,6 +9,7 @@ var HumanModel = require('human-model'); var Resources = require('./resources'); var Messages = require('./messages'); var Message = require('./message'); +var logger = require('andlog'); var fetchAvatar = require('../helpers/fetchAvatar'); @@ -46,6 +47,7 @@ module.exports = HumanModel.define({ topResource: 'string', unreadCount: ['number', true, 0], _forceUpdate: ['number', true, 0], + // options: incomingCall, ringing, activeCall, starting callState: ['string', true, ''], stream: 'object' }, @@ -153,7 +155,7 @@ module.exports = HumanModel.define({ messages: Messages }, call: function () { - if (this.jingleResources) { + if (this.jingleResources.length) { var peer = this.jingleResources[0]; this.callState = 'starting'; app.api.jingle.startLocalMedia(null, function (err) { @@ -161,6 +163,8 @@ module.exports = HumanModel.define({ app.api.call(peer.id); } }); + } else { + logger.error('no jingle resources for this user'); } }, setAvatar: function (id, type) { diff --git a/clientapp/models/me.js b/clientapp/models/me.js index 41735c7..633804f 100644 --- a/clientapp/models/me.js +++ b/clientapp/models/me.js @@ -3,6 +3,7 @@ var HumanModel = require('human-model'); var Contacts = require('./contacts'); +var Calls = require('./calls'); var Contact = require('./contact'); var MUCs = require('./mucs'); var MUC = require('./muc'); @@ -32,7 +33,8 @@ module.exports = HumanModel.define({ }, collections: { contacts: Contacts, - mucs: MUCs + mucs: MUCs, + calls: Calls }, setActiveContact: function (jid) { var prev = this.getContact(this._activeContact); diff --git a/clientapp/templates.js b/clientapp/templates.js index 44813c4..dd4c7c2 100644 --- a/clientapp/templates.js +++ b/clientapp/templates.js @@ -13,7 +13,7 @@ exports.pages = {}; exports.body = function anonymous(locals) { var buf = []; with (locals || {}) { - buf.push('
'); + buf.push('
'); } return buf.join(""); }; @@ -42,6 +42,15 @@ exports.includes.bareMessage = function anonymous(locals) { return buf.join(""); }; +// call.jade compiled template +exports.includes.call = function anonymous(locals) { + var buf = []; + with (locals || {}) { + buf.push('

'); + } + return buf.join(""); +}; + // contactListItem.jade compiled template exports.includes.contactListItem = function anonymous(locals) { var buf = []; @@ -160,7 +169,7 @@ exports.misc.growlMessage = function anonymous(locals) { exports.pages.chat = function anonymous(locals) { var buf = []; with (locals || {}) { - buf.push('

'); + buf.push('

'); } return buf.join(""); }; diff --git a/clientapp/templates/body.jade b/clientapp/templates/body.jade index 3f89a22..c59d6f7 100644 --- a/clientapp/templates/body.jade +++ b/clientapp/templates/body.jade @@ -5,6 +5,7 @@ body | You're currently strong disconnected button.reconnect Reconnect + header#calls aside#menu nav.main li diff --git a/clientapp/templates/includes/call.jade b/clientapp/templates/includes/call.jade new file mode 100644 index 0000000..2d4ce7e --- /dev/null +++ b/clientapp/templates/includes/call.jade @@ -0,0 +1,7 @@ +.call + img.callerAvatar + h1.caller + span.callerName + span.callerNumber + h2.callTime + .callActions diff --git a/clientapp/templates/pages/chat.jade b/clientapp/templates/pages/chat.jade index 2a5aa9c..aed9795 100644 --- a/clientapp/templates/pages/chat.jade +++ b/clientapp/templates/pages/chat.jade @@ -5,7 +5,6 @@ section.page.chat h1.name .tzo button.call call - video.remoteVideo ul.messages.scroll-container .chatBox form diff --git a/clientapp/views/call.js b/clientapp/views/call.js new file mode 100644 index 0000000..397af17 --- /dev/null +++ b/clientapp/views/call.js @@ -0,0 +1,28 @@ +/*global $*/ +"use strict"; + +var _ = require('underscore'); +var HumanView = require('human-view'); +var templates = require('../templates'); + + +module.exports = HumanView.extend({ + template: templates.includes.call, + classBindings: { + state: '' + }, + render: function () { + this.renderAndBind(); + // register bindings for sub model + this.registerBindings(this.model.contact, { + textBindings: { + displayName: '.callerName' + }, + srcBindings: { + avatar: '.callerAvatar' + } + }); + + return this; + } +}); diff --git a/clientapp/views/main.js b/clientapp/views/main.js index ebc8506..aa1ba06 100644 --- a/clientapp/views/main.js +++ b/clientapp/views/main.js @@ -5,6 +5,7 @@ var HumanView = require('human-view'); var templates = require('../templates'); var ContactListItem = require('../views/contactListItem'); var MUCListItem = require('../views/mucListItem'); +var CallView = require('../views/call'); module.exports = HumanView.extend({ @@ -26,6 +27,7 @@ module.exports = HumanView.extend({ this.renderAndBind(); this.renderCollection(me.contacts, ContactListItem, this.$('#roster nav')); this.renderCollection(me.mucs, MUCListItem, this.$('#bookmarks nav')); + this.renderCollection(me.calls, CallView, this.$('#calls')); return this; }, handleReconnect: function (e) { diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json deleted file mode 100644 index 3373103..0000000 --- a/npm-shrinkwrap.json +++ /dev/null @@ -1,1362 +0,0 @@ -{ - "name": "otalk.im", - "version": "0.0.1", - "dependencies": { - "andlog": { - "version": "0.0.4", - "from": "andlog@0.0.4" - }, - "async": { - "version": "0.2.9", - "from": "async@0.2.9" - }, - "backbone": { - "version": "1.0.0", - "from": "backbone@1.0.0" - }, - "express": { - "version": "3.3.7", - "from": "express@3.3.7", - "dependencies": { - "connect": { - "version": "2.8.7", - "from": "connect@2.8.7", - "dependencies": { - "qs": { - "version": "0.6.5", - "from": "qs@0.6.5" - }, - "formidable": { - "version": "1.0.14", - "from": "formidable@1.0.14" - }, - "bytes": { - "version": "0.2.0", - "from": "bytes@0.2.0" - }, - "pause": { - "version": "0.0.1", - "from": "pause@0.0.1" - }, - "uid2": { - "version": "0.0.2", - "from": "uid2@0.0.2" - } - } - }, - "commander": { - "version": "1.2.0", - "from": "commander@1.2.0", - "dependencies": { - "keypress": { - "version": "0.1.0", - "from": "keypress@0.1.x" - } - } - }, - "range-parser": { - "version": "0.0.4", - "from": "range-parser@0.0.4" - }, - "mkdirp": { - "version": "0.3.5", - "from": "mkdirp@0.3.5" - }, - "cookie": { - "version": "0.1.0", - "from": "cookie@0.1.0" - }, - "buffer-crc32": { - "version": "0.2.1", - "from": "buffer-crc32@0.2.1" - }, - "fresh": { - "version": "0.2.0", - "from": "fresh@0.2.0" - }, - "methods": { - "version": "0.0.1", - "from": "methods@0.0.1" - }, - "send": { - "version": "0.1.4", - "from": "send@0.1.4", - "dependencies": { - "mime": { - "version": "1.2.11", - "from": "mime@~1.2.9" - } - } - }, - "cookie-signature": { - "version": "1.0.1", - "from": "cookie-signature@1.0.1" - }, - "debug": { - "version": "0.7.2", - "from": "debug@*" - } - } - }, - "getconfig": { - "version": "0.0.5", - "from": "getconfig@0.0.5", - "dependencies": { - "colors": { - "version": "0.6.2", - "from": "colors@" - } - } - }, - "jade": { - "version": "0.35.0", - "from": "jade@0.35.0", - "dependencies": { - "commander": { - "version": "2.0.0", - "from": "commander@2.0.0" - }, - "mkdirp": { - "version": "0.3.5", - "from": "mkdirp@0.3.x" - }, - "transformers": { - "version": "2.1.0", - "from": "transformers@2.1.0", - "dependencies": { - "promise": { - "version": "2.0.0", - "from": "promise@~2.0", - "dependencies": { - "is-promise": { - "version": "1.0.0", - "from": "is-promise@~1" - } - } - }, - "css": { - "version": "1.0.8", - "from": "css@~1.0.8", - "dependencies": { - "css-parse": { - "version": "1.0.4", - "from": "css-parse@1.0.4" - }, - "css-stringify": { - "version": "1.0.5", - "from": "css-stringify@1.0.5" - } - } - }, - "uglify-js": { - "version": "2.2.5", - "from": "uglify-js@~2.2.5", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.7", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - }, - "optimist": { - "version": "0.3.7", - "from": "optimist@~0.3.5", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - } - } - } - } - }, - "character-parser": { - "version": "1.2.0", - "from": "character-parser@1.2.0" - }, - "monocle": { - "version": "1.1.50", - "from": "monocle@1.1.50", - "dependencies": { - "readdirp": { - "version": "0.2.5", - "from": "readdirp@~0.2.3", - "dependencies": { - "minimatch": { - "version": "0.2.12", - "from": "minimatch@>=0.2.4", - "dependencies": { - "lru-cache": { - "version": "2.3.1", - "from": "lru-cache@2" - }, - "sigmund": { - "version": "1.0.0", - "from": "sigmund@~1.0.0" - } - } - } - } - } - } - }, - "with": { - "version": "1.1.1", - "from": "with@~1.1.0", - "dependencies": { - "uglify-js": { - "version": "2.4.0", - "from": "uglify-js@2.4.0", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.7", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - }, - "optimist": { - "version": "0.3.7", - "from": "optimist@~0.3.5", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - }, - "uglify-to-browserify": { - "version": "1.0.1", - "from": "uglify-to-browserify@~1.0.0" - } - } - } - } - }, - "constantinople": { - "version": "1.0.2", - "from": "constantinople@~1.0.1", - "dependencies": { - "uglify-js": { - "version": "2.4.0", - "from": "uglify-js@~2.4.0", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.7", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - }, - "optimist": { - "version": "0.3.7", - "from": "optimist@~0.3.5", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - }, - "uglify-to-browserify": { - "version": "1.0.1", - "from": "uglify-to-browserify@~1.0.0" - } - } - } - } - } - } - }, - "moonboots": { - "version": "0.7.0", - "from": "moonboots@0.7.0", - "dependencies": { - "uglify-js": { - "version": "2.4.0", - "from": "uglify-js@2.4.0", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.7", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - }, - "optimist": { - "version": "0.3.7", - "from": "optimist@~0.3.5", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - }, - "uglify-to-browserify": { - "version": "1.0.1", - "from": "uglify-to-browserify@~1.0.0" - } - } - }, - "browserify": { - "version": "2.20.1", - "from": "browserify@2.20.1", - "dependencies": { - "module-deps": { - "version": "0.12.0", - "from": "module-deps@~0.12.0", - "dependencies": { - "resolve": { - "version": "0.4.3", - "from": "resolve@~0.4.0" - }, - "detective": { - "version": "2.1.2", - "from": "detective@~2.1.2", - "dependencies": { - "esprima": { - "version": "1.0.2", - "from": "esprima@1.0.2" - }, - "escodegen": { - "version": "0.0.15", - "from": "escodegen@0.0.15", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@>= 0.1.2", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - } - } - } - } - } - } - }, - "browser-pack": { - "version": "0.9.4", - "from": "browser-pack@~0.9.2", - "dependencies": { - "combine-source-map": { - "version": "0.1.3", - "from": "combine-source-map@~0.1.1", - "dependencies": { - "convert-source-map": { - "version": "0.2.6", - "from": "convert-source-map@~0.2.3" - }, - "parse-base64vlq-mappings": { - "version": "0.1.4", - "from": "parse-base64vlq-mappings@~0.1.1" - }, - "inline-source-map": { - "version": "0.2.5", - "from": "inline-source-map@~0.2.1", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.25", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - } - } - } - } - } - } - }, - "shell-quote": { - "version": "0.0.1", - "from": "shell-quote@~0.0.1" - }, - "through": { - "version": "2.3.4", - "from": "through@~2.3.4" - }, - "duplexer": { - "version": "0.0.4", - "from": "duplexer@~0.0.2" - }, - "concat-stream": { - "version": "1.0.1", - "from": "concat-stream@~1.0.0", - "dependencies": { - "bops": { - "version": "0.0.6", - "from": "bops@0.0.6", - "dependencies": { - "base64-js": { - "version": "0.0.2", - "from": "base64-js@0.0.2" - }, - "to-utf8": { - "version": "0.0.1", - "from": "to-utf8@0.0.1" - } - } - } - } - }, - "insert-module-globals": { - "version": "1.1.2", - "from": "insert-module-globals@~1.1.0", - "dependencies": { - "commondir": { - "version": "0.0.1", - "from": "commondir@~0.0.1" - }, - "lexical-scope": { - "version": "0.0.14", - "from": "lexical-scope@~0.0.5", - "dependencies": { - "astw": { - "version": "0.0.0", - "from": "astw@~0.0.0", - "dependencies": { - "esprima": { - "version": "1.0.2", - "from": "esprima@1.0.2" - } - } - } - } - }, - "process": { - "version": "0.5.1", - "from": "process@~0.5.1" - }, - "through": { - "version": "2.2.7", - "from": "through@~2.2.0" - }, - "JSONStream": { - "version": "0.4.4", - "from": "JSONStream@~0.4.3", - "dependencies": { - "jsonparse": { - "version": "0.0.5", - "from": "jsonparse@0.0.5" - } - } - } - } - }, - "syntax-error": { - "version": "0.0.1", - "from": "syntax-error@~0.0.0", - "dependencies": { - "esprima": { - "version": "0.9.9", - "from": "esprima@~0.9.9" - } - } - }, - "browser-resolve": { - "version": "1.1.4", - "from": "browser-resolve@~1.1.0", - "dependencies": { - "resolve": { - "version": "0.5.1", - "from": "resolve@0.5.1" - } - } - }, - "browser-builtins": { - "version": "1.0.7", - "from": "browser-builtins@~1.0.1", - "dependencies": { - "resolve": { - "version": "0.3.1", - "from": "resolve@0.3.x" - }, - "punycode": { - "version": "1.2.3", - "from": "punycode@1.2.x" - }, - "console-browserify": { - "version": "0.1.6", - "from": "console-browserify@0.1.x" - }, - "vm-browserify": { - "version": "0.0.1", - "from": "vm-browserify@0.0.x" - }, - "http-browserify": { - "version": "0.1.13", - "from": "http-browserify@0.1.x", - "dependencies": { - "Base64": { - "version": "0.1.4", - "from": "Base64@~0.1.2" - } - } - }, - "buffer-browserify": { - "version": "0.1.0", - "from": "buffer-browserify@0.1.x", - "dependencies": { - "base64-js": { - "version": "0.0.2", - "from": "base64-js@0.0.2" - } - } - }, - "zlib-browserify": { - "version": "0.0.3", - "from": "zlib-browserify@0.0.x", - "dependencies": { - "tape": { - "version": "0.2.2", - "from": "tape@~0.2.2", - "dependencies": { - "jsonify": { - "version": "0.0.0", - "from": "jsonify@~0.0.0" - }, - "deep-equal": { - "version": "0.0.0", - "from": "deep-equal@~0.0.0" - }, - "defined": { - "version": "0.0.0", - "from": "defined@~0.0.0" - } - } - } - } - }, - "constants-browserify": { - "version": "0.0.1", - "from": "constants-browserify@0.0.x" - } - } - }, - "inherits": { - "version": "1.0.0", - "from": "inherits@~1.0.0" - }, - "optimist": { - "version": "0.5.2", - "from": "optimist@~0.5.1", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - }, - "JSONStream": { - "version": "0.6.4", - "from": "JSONStream@~0.6.4", - "dependencies": { - "jsonparse": { - "version": "0.0.5", - "from": "jsonparse@0.0.5" - }, - "through": { - "version": "2.2.7", - "from": "through@~2.2.7" - } - } - }, - "umd": { - "version": "1.1.1", - "from": "umd@~1.1.0", - "dependencies": { - "rfile": { - "version": "1.0.0", - "from": "rfile@~1.0.0", - "dependencies": { - "callsite": { - "version": "1.0.0", - "from": "callsite@~1.0.0" - }, - "resolve": { - "version": "0.3.1", - "from": "resolve@~0.3.0" - } - } - }, - "ruglify": { - "version": "1.0.0", - "from": "ruglify@~1.0.0" - }, - "uglify-js": { - "version": "2.2.5", - "from": "uglify-js@~2.2.5", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.7", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - }, - "optimist": { - "version": "0.3.7", - "from": "optimist@~0.3.5", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - } - } - } - } - } - } - }, - "cssmin": { - "version": "0.4.1", - "from": "cssmin@0.4.1" - } - } - }, - "helmet": { - "version": "0.1.0", - "from": "helmet@0.1.0" - }, - "node-uuid": { - "version": "1.4.1", - "from": "node-uuid@1.4.1" - }, - "semi-static": { - "version": "0.0.4", - "from": "semi-static@0.0.4" - }, - "sound-effect-manager": { - "version": "0.0.5", - "from": "sound-effect-manager@0.0.5" - }, - "human-model": { - "version": "1.4.0", - "from": "human-model@1.4.0" - }, - "human-view": { - "version": "1.2.0", - "from": "human-view@1.2.0" - }, - "templatizer": { - "version": "0.1.2", - "from": "templatizer@0.1.2", - "dependencies": { - "jade": { - "version": "0.30.0", - "from": "jade@0.30.x", - "dependencies": { - "commander": { - "version": "1.1.1", - "from": "commander@~1.1.1", - "dependencies": { - "keypress": { - "version": "0.1.0", - "from": "keypress@0.1.x" - } - } - }, - "mkdirp": { - "version": "0.3.5", - "from": "mkdirp@0.3.x" - }, - "transformers": { - "version": "2.0.1", - "from": "transformers@~2.0.1", - "dependencies": { - "promise": { - "version": "2.0.0", - "from": "promise@~2.0", - "dependencies": { - "is-promise": { - "version": "1.0.0", - "from": "is-promise@~1" - } - } - }, - "css": { - "version": "1.0.8", - "from": "css@~1.0.8", - "dependencies": { - "css-parse": { - "version": "1.0.4", - "from": "css-parse@1.0.4" - }, - "css-stringify": { - "version": "1.0.5", - "from": "css-stringify@1.0.5" - } - } - } - } - }, - "character-parser": { - "version": "1.0.2", - "from": "character-parser@~1.0.0" - }, - "monocle": { - "version": "0.1.50", - "from": "monocle@~0.1.46", - "dependencies": { - "readdirp": { - "version": "0.2.5", - "from": "readdirp@~0.2.3", - "dependencies": { - "minimatch": { - "version": "0.2.12", - "from": "minimatch@>=0.2.4", - "dependencies": { - "lru-cache": { - "version": "2.3.1", - "from": "lru-cache@2" - }, - "sigmund": { - "version": "1.0.0", - "from": "sigmund@~1.0.0" - } - } - } - } - } - } - } - } - }, - "uglify-js": { - "version": "2.2.5", - "from": "uglify-js@2.2.x", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.7", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - }, - "optimist": { - "version": "0.3.7", - "from": "optimist@~0.3.5", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - } - } - }, - "walkdir": { - "version": "0.0.7", - "from": "walkdir@0.0.7" - }, - "underscore": { - "version": "1.4.4", - "from": "underscore@1.4.4" - }, - "colors": { - "version": "0.6.2", - "from": "colors@0.6.x" - }, - "yetify": { - "version": "0.0.1", - "from": "yetify@0.0.1" - } - } - }, - "underscore": { - "version": "1.5.1", - "from": "underscore@1.5.1" - }, - "raf-component": { - "version": "1.1.1", - "from": "raf-component@1.1.1" - }, - "stanza.io": { - "version": "2.5.9", - "from": "stanza.io@2.5.9", - "dependencies": { - "node-uuid": { - "version": "1.4.0", - "from": "node-uuid@1.4.0" - }, - "jxt": { - "version": "0.2.10", - "from": "jxt@0.2.10" - }, - "paddle": { - "version": "1.0.0", - "from": "paddle@1.0.0" - }, - "hostmeta": { - "version": "0.1.1", - "from": "hostmeta@0.1.1", - "dependencies": { - "jxt": { - "version": "0.0.7", - "from": "jxt@0.0.7" - }, - "xhr": { - "version": "1.2.3", - "from": "xhr@1.2.3", - "dependencies": { - "once": { - "version": "1.1.1", - "from": "once@~1.1.1" - }, - "global": { - "version": "2.0.7", - "from": "global@~2.0.7", - "dependencies": { - "process": { - "version": "0.5.1", - "from": "process@~0.5.1" - }, - "min-document": { - "version": "0.2.8", - "from": "min-document@~0.2.2", - "dependencies": { - "tape": { - "version": "1.0.4", - "from": "tape@~1.0.2", - "dependencies": { - "jsonify": { - "version": "0.0.0", - "from": "jsonify@~0.0.0" - }, - "deep-equal": { - "version": "0.0.0", - "from": "deep-equal@~0.0.0" - }, - "defined": { - "version": "0.0.0", - "from": "defined@~0.0.0" - }, - "through": { - "version": "2.3.4", - "from": "through@~2.3.4" - } - } - } - } - } - } - } - } - } - } - }, - "saslmechanisms": { - "version": "0.1.1", - "from": "saslmechanisms@0.1.1" - }, - "sasl-external": { - "version": "0.1.0", - "from": "sasl-external@0.1.0" - }, - "sasl-scram-sha-1": { - "version": "0.2.1", - "from": "sasl-scram-sha-1@0.2.1" - }, - "sasl-digest-md5": { - "version": "0.1.0", - "from": "sasl-digest-md5@0.1.0" - }, - "sasl-plain": { - "version": "0.1.0", - "from": "sasl-plain@0.1.0" - }, - "sasl-anonymous": { - "version": "0.1.0", - "from": "sasl-anonymous@0.1.0" - }, - "underscore": { - "version": "1.5.2", - "from": "underscore@1.5.2" - }, - "jingle": { - "version": "0.1.5", - "from": "jingle@0.1.5", - "dependencies": { - "bows": { - "version": "0.2.0", - "from": "bows@0.2.0" - }, - "webrtcsupport": { - "version": "0.7.0", - "from": "webrtcsupport@0.7.0" - }, - "jingle-rtcpeerconnection": { - "version": "0.2.7", - "from": "jingle-rtcpeerconnection@0.2.7", - "dependencies": { - "rtcpeerconnection": { - "version": "1.1.0", - "from": "rtcpeerconnection@1.1.0" - } - } - }, - "sdp-jingle-json": { - "version": "0.3.4", - "from": "sdp-jingle-json@0.3.4" - }, - "getusermedia": { - "version": "0.2.1", - "from": "getusermedia@0.2.1" - }, - "hark": { - "version": "0.1.1", - "from": "hark@0.1.1" - }, - "mediastream-gain": { - "version": "0.1.0", - "from": "mediastream-gain@0.1.0", - "dependencies": { - "webrtcsupport": { - "version": "0.5.0", - "from": "webrtcsupport@0.5.0" - } - } - }, - "mockconsole": { - "version": "0.0.1", - "from": "mockconsole@0.0.1" - } - } - } - } - }, - "notify.js": { - "version": "0.0.1", - "from": "notify.js@0.0.1", - "dependencies": { - "underscore": { - "version": "1.5.2", - "from": "underscore@1.5.2" - } - } - }, - "wildemitter": { - "version": "0.0.5", - "from": "wildemitter@0.0.5" - }, - "attachmediastream": { - "version": "1.0.1", - "from": "attachmediastream@" - }, - "crypto-browserify": { - "version": "1.0.3", - "from": "crypto-browserify@1.0.3" - }, - "browserify": { - "version": "2.25.1", - "from": "browserify@2.25.1", - "dependencies": { - "module-deps": { - "version": "1.0.2", - "from": "module-deps@~1.0.1", - "dependencies": { - "resolve": { - "version": "0.4.3", - "from": "resolve@~0.4.0" - }, - "detective": { - "version": "2.1.2", - "from": "detective@~2.1.2", - "dependencies": { - "esprima": { - "version": "1.0.2", - "from": "esprima@1.0.2" - }, - "escodegen": { - "version": "0.0.15", - "from": "escodegen@0.0.15", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@>= 0.1.2", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - } - } - } - } - }, - "minimist": { - "version": "0.0.5", - "from": "minimist@~0.0.1" - } - } - }, - "browser-pack": { - "version": "0.9.4", - "from": "browser-pack@~0.9.4", - "dependencies": { - "combine-source-map": { - "version": "0.1.3", - "from": "combine-source-map@~0.1.1", - "dependencies": { - "convert-source-map": { - "version": "0.2.6", - "from": "convert-source-map@~0.2.3" - }, - "parse-base64vlq-mappings": { - "version": "0.1.4", - "from": "parse-base64vlq-mappings@~0.1.1" - }, - "inline-source-map": { - "version": "0.2.5", - "from": "inline-source-map@~0.2.1", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.25", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - } - } - } - } - } - } - }, - "deps-sort": { - "version": "0.1.1", - "from": "deps-sort@~0.1.1", - "dependencies": { - "minimist": { - "version": "0.0.5", - "from": "minimist@~0.0.1" - } - } - }, - "shell-quote": { - "version": "0.0.1", - "from": "shell-quote@~0.0.1" - }, - "through": { - "version": "2.3.4", - "from": "through@~2.3.4" - }, - "duplexer": { - "version": "0.1.1", - "from": "duplexer@~0.1.1" - }, - "event-stream": { - "version": "3.0.16", - "from": "event-stream@~3.0.15", - "dependencies": { - "duplexer": { - "version": "0.0.4", - "from": "duplexer@~0.0.2" - }, - "from": { - "version": "0.1.3", - "from": "from@~0" - }, - "map-stream": { - "version": "0.0.2", - "from": "map-stream@0.0.2" - }, - "pause-stream": { - "version": "0.0.10", - "from": "pause-stream@0.0.10" - }, - "split": { - "version": "0.2.10", - "from": "split@0.2" - }, - "stream-combiner": { - "version": "0.0.0", - "from": "stream-combiner@0.0.0", - "dependencies": { - "duplexer": { - "version": "0.0.2", - "from": "duplexer@0.0.2" - } - } - } - } - }, - "concat-stream": { - "version": "1.0.1", - "from": "concat-stream@~1.0.0", - "dependencies": { - "bops": { - "version": "0.0.6", - "from": "bops@0.0.6", - "dependencies": { - "base64-js": { - "version": "0.0.2", - "from": "base64-js@0.0.2" - }, - "to-utf8": { - "version": "0.0.1", - "from": "to-utf8@0.0.1" - } - } - } - } - }, - "insert-module-globals": { - "version": "1.2.1", - "from": "insert-module-globals@~1.2.0", - "dependencies": { - "commondir": { - "version": "0.0.1", - "from": "commondir@~0.0.1" - }, - "lexical-scope": { - "version": "0.0.14", - "from": "lexical-scope@~0.0.5", - "dependencies": { - "astw": { - "version": "0.0.0", - "from": "astw@~0.0.0", - "dependencies": { - "esprima": { - "version": "1.0.2", - "from": "esprima@1.0.2" - } - } - } - } - }, - "process": { - "version": "0.5.1", - "from": "process@~0.5.1" - }, - "through": { - "version": "2.2.7", - "from": "through@~2.2.0" - }, - "duplexer": { - "version": "0.0.4", - "from": "duplexer@~0.0.2" - }, - "JSONStream": { - "version": "0.4.4", - "from": "JSONStream@~0.4.3", - "dependencies": { - "jsonparse": { - "version": "0.0.5", - "from": "jsonparse@0.0.5" - } - } - } - } - }, - "syntax-error": { - "version": "0.0.1", - "from": "syntax-error@~0.0.0", - "dependencies": { - "esprima": { - "version": "0.9.9", - "from": "esprima@~0.9.9" - } - } - }, - "browser-resolve": { - "version": "1.1.4", - "from": "browser-resolve@~1.1.0", - "dependencies": { - "resolve": { - "version": "0.5.1", - "from": "resolve@0.5.1" - } - } - }, - "browser-builtins": { - "version": "1.0.7", - "from": "browser-builtins@~1.0.1", - "dependencies": { - "resolve": { - "version": "0.3.1", - "from": "resolve@0.3.x" - }, - "punycode": { - "version": "1.2.3", - "from": "punycode@1.2.x" - }, - "console-browserify": { - "version": "0.1.6", - "from": "console-browserify@0.1.x" - }, - "vm-browserify": { - "version": "0.0.1", - "from": "vm-browserify@0.0.x" - }, - "http-browserify": { - "version": "0.1.13", - "from": "http-browserify@0.1.x", - "dependencies": { - "Base64": { - "version": "0.1.4", - "from": "Base64@~0.1.2" - } - } - }, - "buffer-browserify": { - "version": "0.1.0", - "from": "buffer-browserify@0.1.x", - "dependencies": { - "base64-js": { - "version": "0.0.2", - "from": "base64-js@0.0.2" - } - } - }, - "zlib-browserify": { - "version": "0.0.3", - "from": "zlib-browserify@0.0.x", - "dependencies": { - "tape": { - "version": "0.2.2", - "from": "tape@~0.2.2", - "dependencies": { - "jsonify": { - "version": "0.0.0", - "from": "jsonify@~0.0.0" - }, - "deep-equal": { - "version": "0.0.0", - "from": "deep-equal@~0.0.0" - }, - "defined": { - "version": "0.0.0", - "from": "defined@~0.0.0" - } - } - } - } - }, - "constants-browserify": { - "version": "0.0.1", - "from": "constants-browserify@0.0.x" - } - } - }, - "inherits": { - "version": "1.0.0", - "from": "inherits@~1.0.0" - }, - "optimist": { - "version": "0.5.2", - "from": "optimist@~0.5.1", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - }, - "JSONStream": { - "version": "0.6.4", - "from": "JSONStream@~0.6.4", - "dependencies": { - "jsonparse": { - "version": "0.0.5", - "from": "jsonparse@0.0.5" - }, - "through": { - "version": "2.2.7", - "from": "through@~2.2.0" - } - } - }, - "umd": { - "version": "1.1.1", - "from": "umd@~1.1.0", - "dependencies": { - "rfile": { - "version": "1.0.0", - "from": "rfile@~1.0.0", - "dependencies": { - "callsite": { - "version": "1.0.0", - "from": "callsite@~1.0.0" - }, - "resolve": { - "version": "0.3.1", - "from": "resolve@~0.3.0" - } - } - }, - "ruglify": { - "version": "1.0.0", - "from": "ruglify@~1.0.0" - }, - "uglify-js": { - "version": "2.2.5", - "from": "uglify-js@~2.2.5", - "dependencies": { - "source-map": { - "version": "0.1.30", - "from": "source-map@~0.1.7", - "dependencies": { - "amdefine": { - "version": "0.1.0", - "from": "amdefine@>=0.0.4" - } - } - }, - "optimist": { - "version": "0.3.7", - "from": "optimist@~0.3.5", - "dependencies": { - "wordwrap": { - "version": "0.0.2", - "from": "wordwrap@~0.0.2" - } - } - } - } - } - } - }, - "parents": { - "version": "0.0.1", - "from": "parents@~0.0.1" - } - } - } - } -} diff --git a/package.json b/package.json index 1de6254..2dadd4c 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "express": "3.3.7", "getconfig": "0.0.5", "jade": "0.35.0", - "moonboots": "0.7.0", + "moonboots": "1.0.0", "helmet": "0.1.0", "node-uuid": "1.4.1", "semi-static": "0.0.4", diff --git a/public/css/app/callbar.styl b/public/css/app/callbar.styl new file mode 100644 index 0000000..30bc81c --- /dev/null +++ b/public/css/app/callbar.styl @@ -0,0 +1,138 @@ +@import _mixins +@import _variables + +body + position: relative !important + -webkit-transition: top 1s + + &.candybarVisible + top: 100px + +#calls + position: fixed + top: -120px + left: 0px + -webkit-transition: background-color 1s + -webkit-transition: top 1s + width: 100% + height: 80px + padding: 10px + z-index: 1000 + + &.visible + top: 0px + + &.havatar + .callActions + left: 100px + .caller + margin-left: 90px + + &.incoming + background: blue + .callTime + display: none + .callerName:before + content: "Incoming: " + + &.waiting + callbar($orange) + + .spinner div + background-color: #fff + + &.calling + callbar($blue) + .callTime + display: none + .callerName:before + content: "Calling: " + + &.active + callbar($green) + .callerName:before + content: "On Call: " + + &.inactive + callbar(#fff) + + &.remote + callbar($blue #333) + .callTime + display: none + + &.ending + .callerName:before + content: "Call ending with: " + callbar($grey) + + .callActions + position: absolute + left: 10px + top: 50px + display: block + width: 100% + + nav + float: left + + button + min-width: auto + background-color: rgba(255,255,255,.3) + gradient(rgba(255,255,255,.5),rgba(0,0,0,.1)) + border: + top: 1px solid rgba(255,255,255,.6) + bottom: 1px solid rgba(0,0,0,.1) + left: 1px solid rgba(255,255,255,.2) + right: 1px solid rgba(255,255,255,.2) + width: 100px + margin-right: 10px + font-size: 16px + color: rgba(0,0,0,.75) + text_shadow(rgba(255,255,255,.5),0,1px,0) + float: left + shadow(rgba(0,0,0,.3), 0, 1px, 3) + &:hover + background-color: rgba(255,255,255,.4) + &:active + inner_shadow(rgba(0,0,0,.2),0,1px,3) + padding-top: 11px + padding-bottom: 9px + border: + bottom: 1px solid rgba(255,255,255,1) + top: 1px solid rgba(0,0,0,.2) + + .callerAvatar + float: left + width: 65px + height: 65px + border: 5px solid #eee + margin-right: 10px + + .callerName, .callTime + font-weight: bold + color: #fff + text_shadow(rgba(0,0,0,.7),0,1px,0) + line-height: 1 + + .caller + margin: + top: 0px + right: 30px + left: 0px + font-size: 20px + padding-bottom: 0px + border-bottom: 2px groove rgba(255,255,255,.4) + + .callerName + display: inline + .callerNumber + display: inline + margin-left: 10px + + .callTime + position: absolute + top: 12px + right: 40px + font-size: 20px + margin: 0 diff --git a/public/css/otalk.css b/public/css/otalk.css index e7e8120..5506da4 100644 --- a/public/css/otalk.css +++ b/public/css/otalk.css @@ -1027,3 +1027,138 @@ button:hover, a.button:hover { background: #007aa7; } +body { + position: relative !important; + -webkit-transition: top 1s; +} +body.candybarVisible { + top: 100px; +} +#calls { + position: fixed; + top: -120px; + left: 0px; + -webkit-transition: background-color 1s; + -webkit-transition: top 1s; + width: 100%; + height: 80px; + padding: 10px; + z-index: 1000; +} +#calls.visible { + top: 0px; +} +#calls.havatar .callActions { + left: 100px; +} +#calls.havatar .caller { + margin-left: 90px; +} +#calls.incoming { + background: #00f; +} +#calls.incoming .callTime { + display: none; +} +#calls.incoming .callerName:before { + content: "Incoming: "; +} +#calls.waiting .spinner div { + background-color: #fff; +} +#calls.calling .callTime { + display: none; +} +#calls.calling .callerName:before { + content: "Calling: "; +} +#calls.active .callerName:before { + content: "On Call: "; +} +#calls.remote .callTime { + display: none; +} +#calls.ending .callerName:before { + content: "Call ending with: "; +} +#calls .callActions { + position: absolute; + left: 10px; + top: 50px; + display: block; + width: 100%; +} +#calls nav { + float: left; +} +#calls button { + min-width: auto; + background-color: rgba(255,255,255,0.3); +rgba(0,0,0,0.1) + width: 100px; + margin-right: 10px; + font-size: 16px; + color: rgba(0,0,0,0.75); +rgba(255,255,255,0.5) + float: left; +rgba(0,0,0,0.3) +} +#calls button border:top: 1pxsolid rgba(255, +#calls button 255, +#calls button 255, +#calls button 0.6) { + bottom: 1px solid rgba(0,0,0,0.1); + left: 1px solid rgba(255,255,255,0.2); + right: 1px solid rgba(255,255,255,0.2); +} +#calls button:hover { + background-color: rgba(255,255,255,0.4); +} +#calls button:active { +rgba(0,0,0,0.2) + padding-top: 11px; + padding-bottom: 9px; +} +#calls button:active border:bottom: 1pxsolid rgba(255, +#calls button:active 255, +#calls button:active 255, +#calls button:active 1) { + top: 1px solid rgba(0,0,0,0.2); +} +#calls .callerAvatar { + float: left; + width: 65px; + height: 65px; + border: 5px solid #eee; + margin-right: 10px; +} +#calls .callerName, +#calls .callTime { + font-weight: bold; + color: #fff; +rgba(0,0,0,0.7) + line-height: 1; +} +#calls .caller { + font-size: 20px; + padding-bottom: 0px; + border-bottom: 2px groove rgba(255,255,255,0.4); +} +#calls .caller margin:top: 0px { + right: 30px; + left: 0px; +} +#calls .callerName { + display: inline; +} +#calls .callerNumber { + display: inline; + margin-left: 10px; +} +#calls .callTime { + position: absolute; + top: 12px; + right: 40px; + font-size: 20px; + margin: 0; +} diff --git a/public/css/otalk.styl b/public/css/otalk.styl index 88eed45..389a090 100644 --- a/public/css/otalk.styl +++ b/public/css/otalk.styl @@ -8,3 +8,4 @@ @import 'app/settings' @import 'app/aux' @import 'app/forms' +@import 'app/callbar' diff --git a/public/x-manifest.cache b/public/x-manifest.cache index 1b78766..d540405 100644 --- a/public/x-manifest.cache +++ b/public/x-manifest.cache @@ -1,5 +1,5 @@ CACHE MANIFEST -# 0.0.1 1381823999689 +# 0.0.1 1381864472792 CACHE: /app.js diff --git a/server.js b/server.js index e53a7c7..5dd5d32 100644 --- a/server.js +++ b/server.js @@ -38,7 +38,7 @@ var clientApp = new Moonboots({ }); if (config.isDev) { - clientApp.config.beforeBuild = function () { + clientApp.config.beforeBuildJS = function () { var clientFolder = __dirname + '/clientapp'; templatizer(clientFolder + '/templates', clientFolder + '/templates.js');