diff --git a/clientapp/models/resource.js b/clientapp/models/resource.js index b4d6023..64aa748 100644 --- a/clientapp/models/resource.js +++ b/clientapp/models/resource.js @@ -18,6 +18,18 @@ module.exports = HumanModel.define({ timezoneOffset: 'number' }, derived: { + mucDisplayName: { + deps: ['id'], + fn: function () { + return this.id.split('/')[1] || ''; + } + }, + idle: { + deps: ['idleSince'], + fn: function () { + return !!this.idleSince; + } + }, supportsChatStates: { deps: ['discoInfo'], fn: function () { diff --git a/clientapp/pages/groupchat.js b/clientapp/pages/groupchat.js index 9de3db4..fd57595 100644 --- a/clientapp/pages/groupchat.js +++ b/clientapp/pages/groupchat.js @@ -4,6 +4,7 @@ var _ = require('underscore'); var BasePage = require('./base'); var templates = require('../templates'); +var MUCRosterItem = require('../views/mucRosterItem'); var Message = require('../views/mucMessage'); var MessageModel = require('../models/message'); var chatHelpers = require('../helpers/chatHelpers'); @@ -62,7 +63,8 @@ module.exports = BasePage.extend(chatHelpers).extend({ this.listenTo(this.model.messages, 'add', this.handleChatAdded); - this.renderCollection(); + this.renderMessages(); + this.renderCollection(this.model.resources, MUCRosterItem, this.$('.groupRoster')); $(window).on('resize', _.bind(this.handleWindowResize, this)); @@ -72,7 +74,7 @@ module.exports = BasePage.extend(chatHelpers).extend({ return this; }, - renderCollection: function () { + renderMessages: function () { var self = this; var previous; var bottom = this.isBottom() || this.$messageList.is(':empty'); diff --git a/clientapp/templates.js b/clientapp/templates.js index d1c8e76..fb48762 100644 --- a/clientapp/templates.js +++ b/clientapp/templates.js @@ -125,6 +125,15 @@ exports.includes.mucListItem = function anonymous(locals) { return buf.join(""); }; +// mucRosterItem.jade compiled template +exports.includes.mucRosterItem = function anonymous(locals) { + var buf = []; + with (locals || {}) { + buf.push('
  • '); + } + return buf.join(""); +}; + // mucWrappedMessage.jade compiled template exports.includes.mucWrappedMessage = function anonymous(locals) { var buf = []; @@ -203,7 +212,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/includes/contactListItem.jade b/clientapp/templates/includes/contactListItem.jade index 54d2722..78bd2fe 100644 --- a/clientapp/templates/includes/contactListItem.jade +++ b/clientapp/templates/includes/contactListItem.jade @@ -6,4 +6,3 @@ li.contact span.idleTime=contact.idleSince .unread=contact.unreadCount .status=contact.status - diff --git a/clientapp/templates/includes/mucRosterItem.jade b/clientapp/templates/includes/mucRosterItem.jade new file mode 100644 index 0000000..4d7988d --- /dev/null +++ b/clientapp/templates/includes/mucRosterItem.jade @@ -0,0 +1,2 @@ +li.online + .name diff --git a/clientapp/templates/pages/groupchat.jade b/clientapp/templates/pages/groupchat.jade index ac91847..48a7f1d 100644 --- a/clientapp/templates/pages/groupchat.jade +++ b/clientapp/templates/pages/groupchat.jade @@ -1,5 +1,5 @@ section.page.chat - section.conversation + section.group.conversation header.online h1 span.name @@ -8,6 +8,7 @@ section.page.chat button.primary.small.joinRoom Join button.secondary.small.leaveRoom Leave ul.messages + ul.groupRoster .chatBox form textarea(name='chatInput', type='text', placeholder='Send a message...', autocomplete='off') diff --git a/clientapp/views/mucRosteritem.js b/clientapp/views/mucRosteritem.js new file mode 100644 index 0000000..9704ce4 --- /dev/null +++ b/clientapp/views/mucRosteritem.js @@ -0,0 +1,23 @@ +/*global $, app, me*/ +"use strict"; + +var _ = require('underscore'); +var HumanView = require('human-view'); +var templates = require('../templates'); + + +module.exports = HumanView.extend({ + template: templates.includes.mucRosterItem, + classBindings: { + show: '', + chatState: '', + idle: '' + }, + textBindings: { + mucDisplayName: '.name' + }, + render: function () { + this.renderAndBind({contact: this.model}); + return this; + } +}); diff --git a/public/css/otalk.css b/public/css/otalk.css index a9009a7..f79c042 100644 --- a/public/css/otalk.css +++ b/public/css/otalk.css @@ -1069,8 +1069,8 @@ button.secondary:hover:not(:disabled) { overflow-y: auto; overflow-x: hidden; position: absolute; - width: 100%; top: 0px; + right: 0px; bottom: 55px; padding-top: 75px; -moz-box-sizing: border-box; @@ -1238,6 +1238,75 @@ button.secondary:hover:not(:disabled) { border: 1px solid #efe391; color: #d2bd2d; } +.group.conversation .messages { + right: 150px; +} +.group.conversation .groupRoster { + width: 150px; + margin: 0px; + padding: 0px; + overflow-y: auto; + overflow-x: hidden; + position: absolute; + top: 0px; + right: 0px; + bottom: 50px; + padding-top: 80px; + padding-bottom: 10px; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + -webkit-overflow-scrolling: touch; + background: #f7f7f7; + border-left: 1px solid #d6d6d6; +} +.group.conversation .groupRoster li { + padding: 3px; + margin: 0px; + font-size: 12px; + position: relative; +} +.group.conversation .groupRoster li .name { + padding-left: 10px; +} +.group.conversation .groupRoster li:before { + content: ''; + position: absolute; + left: 4px; + top: 11px; + height: 6px; + width: 6px; + margin-top: -3px; + -moz-border-radius: 10px; + -webkit-border-radius: 10px; + -khtml-border-radius: 10px; + -o-border-radius: 10px; + -border-radius: 10px; + border-radius: 10px; +} +.group.conversation .groupRoster li.online:before, +.group.conversation .groupRoster li.chat:before { + background: #43bb6e; +} +.group.conversation .groupRoster li.dnd:before { + background: #de0a32; +} +.group.conversation .groupRoster li.away:before, +.group.conversation .groupRoster li.xa:before { + background: #f18902; +} +.group.conversation .groupRoster li.offline:before { + background: #2d2d2d; +} +.group.conversation .groupRoster li.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; +} +.group.conversation .groupRoster li.paused:before, +.group.conversation .groupRoster li.idle:before { + background: #ababab; +} .main > div { padding: 20px; border-bottom: 1px solid #eee; diff --git a/public/css/pages/chat.styl b/public/css/pages/chat.styl index 3935111..3f882ed 100644 --- a/public/css/pages/chat.styl +++ b/public/css/pages/chat.styl @@ -187,8 +187,8 @@ overflow-y: auto overflow-x: hidden position: absolute - width: 100% top: 0px + right: 0px bottom: 55px padding-top: 75px borderbox() @@ -340,3 +340,69 @@ background-color: #fffcea border: 1px solid #efe391 color: #d2bd2d + + +.group.conversation + + .messages + right: 150px + + .groupRoster + width: 150px + margin: 0px + padding: 0px + overflow-y: auto + overflow-x: hidden + position: absolute + top: 0px + right: 0px + bottom: 50px + padding-top: 80px + padding-bottom: 10px + borderbox() + -webkit-overflow-scrolling: touch + background: lighten($gray, 95%) + border-left: 1px solid darken($gray-lighter, 10%) + + li + padding: 3px + margin: 0px + font-size: 12px + position: relative + + .name + padding-left: 10px + + &:before + content: '' + position: absolute + left: 4px + top: 11px + height: 6px + width: 6px + margin-top: -3px + roundall(10px) + + &.online, + &.chat + &:before + background: $green + + &.dnd:before + background: $red + + &.away:before, + &.xa:before + background: $orange + + &.offline:before + background: $gray-dark + + &.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, + &.idle:before + background: lighten($gray-light, 30%) diff --git a/public/x-manifest.cache b/public/x-manifest.cache index d72f881..c91621a 100644 --- a/public/x-manifest.cache +++ b/public/x-manifest.cache @@ -1,5 +1,5 @@ CACHE MANIFEST -# 0.0.1 1387579027983 +# 0.0.1 1388530344722 CACHE: /app.js diff --git a/server.js b/server.js index 581ee33..e2481a6 100644 --- a/server.js +++ b/server.js @@ -92,7 +92,7 @@ app.get('*', clientApp.html()); app.use(function handleError(err, req, res, next) { var errorResult = {message: 'Something bad happened :('}; - + if (config.isDev) { if (err instanceof Error) { if (err.message) {