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) {