diff --git a/clientapp/helpers/xmppEventHandlers.js b/clientapp/helpers/xmppEventHandlers.js index 78a4a39..cbdec08 100644 --- a/clientapp/helpers/xmppEventHandlers.js +++ b/clientapp/helpers/xmppEventHandlers.js @@ -4,7 +4,7 @@ var _ = require('underscore'); var async = require('async'); var crypto = require('crypto'); -var log = require('andlog'); +var bows = require('bows'); var uuid = require('node-uuid'); var HumanModel = require('human-model'); var Contact = require('../models/contact'); @@ -13,11 +13,16 @@ var Message = require('../models/message'); var Call = require('../models/call'); +var log = bows('Otalk'); +var ioLogIn = bows('<< in'); +var ioLogOut = bows('>> out'); + + var discoCapsQueue = async.queue(function (pres, cb) { var jid = pres.from; var caps = pres.caps; - log.debug('Checking storage for ' + caps.ver); + log.info('Checking storage for ' + caps.ver); var contact = me.getContact(jid); var resource = null; @@ -26,28 +31,26 @@ var discoCapsQueue = async.queue(function (pres, cb) { } app.storage.disco.get(caps.ver, function (err, existing) { - log.debug(err, existing); if (existing) { - log.debug('Already found info for ' + caps.ver); + log.info('Already found info for ' + caps.ver); if (resource) resource.discoInfo = existing; return cb(); } - log.debug('getting info for ' + caps.ver + ' from ' + jid); + log.info('getting info for ' + caps.ver + ' from ' + jid); client.getDiscoInfo(jid, caps.node + '#' + caps.ver, function (err, result) { - log.debug(caps.ver, err, result); if (err) { - log.debug('Couldnt get info for ' + caps.ver); + log.error('Couldnt get info for ' + caps.ver); return cb(); } if (client.verifyVerString(result.discoInfo, caps.hash, caps.ver)) { - log.debug('Saving info for ' + caps.ver); + log.info('Saving info for ' + caps.ver); var data = result.discoInfo.toJSON(); app.storage.disco.add(caps.ver, data, function () { if (resource) resource.discoInfo = existing; cb(); }); } else { - log.debug('Couldnt verify info for ' + caps.ver + ' from ' + jid); + log.info('Couldnt verify info for ' + caps.ver + ' from ' + jid); cb(); } }); @@ -58,9 +61,10 @@ var discoCapsQueue = async.queue(function (pres, cb) { module.exports = function (client, app) { client.on('*', function (name, data) { - log.debug(name, data); - if (name === 'raw:outgoing') { - log.debug(data.toString()); + if (name === 'raw:incoming') { + ioLogIn.debug(data.toString()); + } else if (name === 'raw:outgoing') { + ioLogOut.debug(data.toString()); } }); @@ -93,7 +97,7 @@ module.exports = function (client, app) { }); client.on('auth:failed', function () { - log.debug('auth failed'); + log.warning('auth failed'); window.location = '/login'; }); @@ -287,6 +291,13 @@ module.exports = function (client, app) { } }); + client.on('groupchat:subject', function (msg) { + var contact = me.getContact(msg.from, msg.to); + if (contact) { + contact.subject = msg.subject; + } + }); + client.on('replace', function (msg) { msg = msg.toJSON(); msg.mid = msg.id; @@ -336,7 +347,7 @@ module.exports = function (client, app) { client.on('disco:caps', function (pres) { if (pres.caps.hash) { - log.debug('Caps from ' + pres.from + ' ver: ' + pres.caps.ver); + log.info('Caps from ' + pres.from + ' ver: ' + pres.caps.ver); discoCapsQueue.push(pres); } }); diff --git a/clientapp/models/muc.js b/clientapp/models/muc.js index 8c34e90..408a417 100644 --- a/clientapp/models/muc.js +++ b/clientapp/models/muc.js @@ -4,6 +4,7 @@ var _ = require('underscore'); var async = require('async'); var uuid = require('node-uuid'); +var htmlify = require('../helpers/htmlify'); var HumanModel = require('human-model'); var Resources = require('./resources'); var Messages = require('./messages'); @@ -25,6 +26,7 @@ module.exports = HumanModel.define({ jid: 'object' }, session: { + subject: 'string', activeContact: ['bool', true, false], lastInteraction: 'data', lastSentMessage: 'object', @@ -47,6 +49,12 @@ module.exports = HumanModel.define({ return ''; } }, + displaySubject: { + deps: ['subject'], + fn: function () { + return htmlify.toHTML(this.subject); + } + }, hasUnread: { deps: ['unreadCount'], fn: function () { diff --git a/clientapp/pages/chat.js b/clientapp/pages/chat.js index 5031d8f..45f5979 100644 --- a/clientapp/pages/chat.js +++ b/clientapp/pages/chat.js @@ -36,10 +36,14 @@ module.exports = BasePage.extend(chatHelpers).extend({ }, textBindings: { displayName: 'header .name', - formattedTZO: 'header .tzo' + formattedTZO: 'header .tzo', + status: 'header .status' }, classBindings: { - onCall: '.messages' + chatState: 'header', + idle: 'header', + show: 'header', + onCall: '.conversation' }, show: function (animation) { BasePage.prototype.show.apply(this, [animation]); @@ -104,10 +108,10 @@ module.exports = BasePage.extend(chatHelpers).extend({ }); this.scrollIfPinned(); }, - handleWindowResize: function () { + handleWindowResize: _.debounce(function () { this.scrollIfPinned(); this.resizeInput(); - }, + }), handleKeyDown: function (e) { if (e.which === 13 && !e.shiftKey) { this.sendChat(); diff --git a/clientapp/pages/groupchat.js b/clientapp/pages/groupchat.js index 81bd2d6..9de3db4 100644 --- a/clientapp/pages/groupchat.js +++ b/clientapp/pages/groupchat.js @@ -31,7 +31,8 @@ module.exports = BasePage.extend(chatHelpers).extend({ joined: '.controls' }, textBindings: { - displayName: 'header .name' + displayName: 'header .name', + subject: 'header .status' }, show: function (animation) { BasePage.prototype.show.apply(this, [animation]); diff --git a/clientapp/templates.js b/clientapp/templates.js index f282edf..c8ed69f 100644 --- a/clientapp/templates.js +++ b/clientapp/templates.js @@ -194,7 +194,7 @@ exports.misc.growlMessage = function anonymous(locals) { exports.pages.chat = function anonymous(locals) { var buf = []; with (locals || {}) { - buf.push('

'); + buf.push('

'); } return buf.join(""); }; @@ -203,7 +203,7 @@ exports.pages.chat = function anonymous(locals) { exports.pages.groupchat = function anonymous(locals) { var buf = []; with (locals || {}) { - buf.push('

'); + buf.push('

'); } return buf.join(""); }; diff --git a/clientapp/templates/pages/chat.jade b/clientapp/templates/pages/chat.jade index 52ee2fe..e5bb7ab 100644 --- a/clientapp/templates/pages/chat.jade +++ b/clientapp/templates/pages/chat.jade @@ -1,8 +1,9 @@ section.page.chat section.conversation header - img.avatar h1.name + .status + .idleTime .tzo button.primary.small.call call .activeCall diff --git a/clientapp/templates/pages/groupchat.jade b/clientapp/templates/pages/groupchat.jade index c38440c..be81614 100644 --- a/clientapp/templates/pages/groupchat.jade +++ b/clientapp/templates/pages/groupchat.jade @@ -1,10 +1,11 @@ section.page.chat section.conversation - header + header.online h1.name + .status .controls - button.primary.joinRoom Join - button.secondary.leaveRoom Leave + button.primary.small.joinRoom Join + button.secondary.small.leaveRoom Leave ul.messages .chatBox form diff --git a/package.json b/package.json index afa925a..352acf3 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "url": "git@github.com:andyet/otalk.git" }, "dependencies": { - "andlog": "0.0.4", + "bows": "", "async": "0.2.9", "backbone": "1.0.0", "express": "3.3.7", @@ -22,7 +22,7 @@ "human-view": "1.2.0", "templatizer": "0.1.2", "underscore": "1.5.1", - "stanza.io": "2.9.3", + "stanza.io": "2.9.4", "notify.js": "0.0.3", "wildemitter": "0.0.5", "attachmediastream": "1.0.1", diff --git a/public/css/otalk.css b/public/css/otalk.css index 110d894..ac7626f 100644 --- a/public/css/otalk.css +++ b/public/css/otalk.css @@ -878,7 +878,8 @@ button.secondary:hover:not(:disabled) { box-sizing: border-box; } .conversation header { - padding: 5px; + padding: 0px; + padding-left: 8px; border-bottom: 2px solid #eee; position: fixed; right: 0px; @@ -889,6 +890,59 @@ button.secondary:hover:not(:disabled) { box-sizing: border-box; background: #f7f7f7; } +.conversation header.online:not(.idle):before, +.conversation header.chat:before, +.conversation header.dnd:before, +.conversation header.away:before, +.conversation header.xa:before { + content: ''; + position: absolute; + top: 50%; + height: 8px; + width: 8px; + margin-top: -4px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -khtml-border-radius: 10px; + -o-border-radius: 10px; + -border-radius: 10px; + border-radius: 10px; +} +.conversation header.online:before, +.conversation header.chat:before { + background: #43bb6e; +} +.conversation header.dnd:before { + background: #de0a32; +} +.conversation header.away:before, +.conversation header.xa:before { + background: #f18902; +} +.conversation header.offline:not(:hover) .name { + color: #515151; +} +.conversation header.offline:not(:hover) .status { + color: #2f2f2f; +} +.conversation header.offline:not(:hover) .avatar { + opacity: 0.25; +} +.conversation header.composing:before { + animation: pulsate 1.5s infinite ease-in; + -webkit-animation: pulsate 1.5s infinite ease-in; + -moz-animation: pulsate 1.5s infinite ease-in; +} +.conversation header.paused:before { + background: #878787; +} +.conversation header.idle { + padding-right: 15px; +} +.conversation header.idle .name { + color: #878787; + max-width: 60%; +} .conversation header .controls { float: right; } @@ -898,10 +952,13 @@ button.secondary:hover:not(:disabled) { .conversation header .controls .joinRoom { display: block; } -.conversation header .joined .joinRoom { +.conversation header .controls button { + margin-top: 4px; +} +.conversation header .controls.joined .joinRoom { display: none; } -.conversation header .joined .leaveRoom { +.conversation header .controls.joined .leaveRoom { display: block; } .conversation header .avatar { @@ -924,17 +981,33 @@ button.secondary:hover:not(:disabled) { float: left; } .conversation header .name { - margin: 15px; + margin: 10px; + margin-left: 15px; + margin-right: 5px; padding: 0px; - margin-left: 45px; font-size: 14px; line-height: 14px; max-width: 50%; } +.conversation header .status { + margin: 10px; + margin-left: 0px; + padding: 0px; + font-size: 14px; + line-height: 14px; + max-width: 75%; + float: left; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.conversation header .status:not(:empty):before { + content: '- '; +} .conversation header .tzo:not(:empty) { position: absolute; right: 15px; - top: 28px; + top: 18px; height: 20px; margin-top: -10px; padding: 0 5px; @@ -944,15 +1017,18 @@ button.secondary:hover:not(:disabled) { -o-border-radius: 3px; -border-radius: 3px; border-radius: 3px; - text-transform: uppercase; font-size: 12px; font-weight: 800; line-height: 20px; color: #898989; background: #eee; } +.conversation header .tzo:not(:empty):before { + content: 'Current Time: '; + font-weight: bold; +} .conversation header .call { - margin-top: 9px; + margin-top: 4px; text-transform: capitalize; } .conversation header .activeCall { @@ -996,7 +1072,7 @@ button.secondary:hover:not(:disabled) { position: absolute; top: 0px; bottom: 0px; - padding-top: 55px; + padding-top: 35px; padding-bottom: 55px; width: 100%; -moz-box-sizing: border-box; diff --git a/public/css/pages/chat.styl b/public/css/pages/chat.styl index b884c7e..3625fa9 100644 --- a/public/css/pages/chat.styl +++ b/public/css/pages/chat.styl @@ -16,7 +16,8 @@ borderbox() header - padding: 5px + padding: 0px + padding-left: 8px border-bottom: 2px solid $gray-lighter position: fixed right: 0px @@ -25,6 +26,56 @@ borderbox() background: lighten($gray-light, 93%) + &.online:not(.idle), &.chat, &.dnd, &.away, &.xa + &:before + content: '' + position: absolute + top: 50% + height: 8px + width: 8px + margin-top: -4px + roundall(10px) + + &.online, + &.chat + &:before + background: $green + + &.dnd + &:before + background: $red + + &.away, + &.xa + &:before + background: $orange + + &.offline:not(:hover) + .name + color: darken($gray-light, 40%) + + .status + color: darken($gray-light, 65%) + + .avatar + opacity: .25 + + &.composing + &:before + animation: pulsate 1.5s infinite ease-in + -webkit-animation: pulsate 1.5s infinite ease-in + -moz-animation: pulsate 1.5s infinite ease-in + + &.paused + &:before + background: $gray-light + + &.idle + padding-right: 15px + .name + color: $gray-light + max-width: 60% + .controls float: right @@ -34,12 +85,15 @@ .joinRoom display: block - .joined - .joinRoom - display: none + button + margin-top: 4px - .leaveRoom - display: block + &.joined + .joinRoom + display: none + + .leaveRoom + display: block .avatar margin-right: 5px @@ -53,30 +107,49 @@ float: left .name - margin: 15px + margin: 10px + margin-left: 15px + margin-right: 5px padding: 0px - margin-left: 45px font-size: $font-size-base line-height: 14px max-width: 50% + .status + margin: 10px + margin-left: 0px + padding: 0px + font-size: $font-size-base + line-height: 14px + max-width: 75% + float: left + overflow: hidden + text-overflow: ellipsis + white-space: nowrap + + &:not(:empty):before + content: '- ' + .tzo:not(:empty) position: absolute right: 15px - top: 28px + top: 18px height: 20px margin-top: -10px padding: 0 5px roundall(3px) - text-transform: uppercase font-size: $font-size-small font-weight: $font-weight-bold line-height: 20px color: lighten($gray, 30%) background: $gray-lighter + &:before + content: 'Current Time: ' + font-weight: bold + .call - margin-top: 9px + margin-top: 4px text-transform: capitalize .activeCall @@ -84,7 +157,7 @@ height: 0px position: relative top: 0px - + .remote position: absolute top: 60px @@ -121,7 +194,7 @@ position: absolute top: 0px bottom: 0px - padding-top: 55px + padding-top: 35px padding-bottom: 55px width: 100% borderbox() diff --git a/public/x-manifest.cache b/public/x-manifest.cache index 0cfff05..dcc967c 100644 --- a/public/x-manifest.cache +++ b/public/x-manifest.cache @@ -1,5 +1,5 @@ CACHE MANIFEST -# 0.0.1 1387497051758 +# 0.0.1 1387522881010 CACHE: /app.js