diff --git a/clientapp/app.js b/clientapp/app.js index 966dab4..fdff2e0 100644 --- a/clientapp/app.js +++ b/clientapp/app.js @@ -102,6 +102,10 @@ module.exports = { cb(); }, function (cb) { + app.whenConnected(function () { + me.publishAvatar(); + }); + function start() { // start our router and show the appropriate page app.history.start({pushState: true, root: '/'}); diff --git a/clientapp/helpers/fetchAvatar.js b/clientapp/helpers/avatarHandler.js similarity index 82% rename from clientapp/helpers/fetchAvatar.js rename to clientapp/helpers/avatarHandler.js index d9e8d37..2d2668b 100644 --- a/clientapp/helpers/fetchAvatar.js +++ b/clientapp/helpers/avatarHandler.js @@ -2,18 +2,18 @@ "use strict"; var crypto = require('crypto'); - -function fallback(jid) { +module.exports.getGravatar = function (jid) { var gID = crypto.createHash('md5').update(jid).digest('hex'); return { uri: 'https://gravatar.com/avatar/' + gID + '?s=80&d=mm' }; -} +}; +var getGravatar = module.exports.getGravatar; -module.exports = function (jid, id, type, source, cb) { +module.exports.fetch = function (jid, id, type, source, cb) { if (!id) { - return cb(fallback(jid)); + return cb(getGravatar(jid)); } app.storage.avatars.get(id, function (err, avatar) { @@ -22,14 +22,14 @@ module.exports = function (jid, id, type, source, cb) { } if (!type) { - return cb(fallback(jid)); + return cb(getGravatar(jid)); } app.whenConnected(function () { if (source == 'vcard') { app.api.getVCard(jid, function (err, resp) { if (err) { - return cb(fallback(jid)); + return cb(getGravatar(jid)); } type = resp.vCardTemp.photo.type || type; @@ -49,7 +49,7 @@ module.exports = function (jid, id, type, source, cb) { } else { app.api.getAvatar(jid, id, function (err, resp) { if (err) { - return cb(fallback(jid)); + return cb(getGravatar(jid)); } var data = resp.pubsub.retrieve.item.avatarData; diff --git a/clientapp/models/contact.js b/clientapp/models/contact.js index d03c1d3..0350fc7 100644 --- a/clientapp/models/contact.js +++ b/clientapp/models/contact.js @@ -10,7 +10,7 @@ var Resources = require('./resources'); var Messages = require('./messages'); var Message = require('./message'); var logger = require('andlog'); -var fetchAvatar = require('../helpers/fetchAvatar'); +var avatarHandler = require('../helpers/avatarHandler'); module.exports = HumanModel.define({ @@ -231,8 +231,10 @@ module.exports = HumanModel.define({ } }, setAvatar: function (id, type, source) { + if (!this.avatar) this.avatar = avatarHandler.getGravatar(this.jid).uri; + var self = this; - fetchAvatar(this.jid, id, type, source, function (avatar) { + avatarHandler.fetch(this.jid, id, type, source, function (avatar) { if (source == 'vcard' && self.avatarSource == 'pubsub') return; self.avatarID = avatar.id; self.avatar = avatar.uri; diff --git a/clientapp/models/me.js b/clientapp/models/me.js index 80071bc..c85dbbc 100644 --- a/clientapp/models/me.js +++ b/clientapp/models/me.js @@ -9,7 +9,8 @@ var Contact = require('./contact'); var MUCs = require('./mucs'); var MUC = require('./muc'); var ContactRequests = require('./contactRequests'); -var fetchAvatar = require('../helpers/fetchAvatar'); +var avatarHandler = require('../helpers/avatarHandler'); +var crypto = require('crypto'); module.exports = HumanModel.define({ initialize: function (opts) { @@ -105,12 +106,34 @@ module.exports = HumanModel.define({ return this.avatar; }, setAvatar: function (id, type, source) { + if (!this.avatar) this.avatar = avatarHandler.getGravatar('').uri; + var self = this; - fetchAvatar('', id, type, source, function (avatar) { + avatarHandler.fetch('', id, type, source, function (avatar) { self.avatarID = avatar.id; self.avatar = avatar.uri; }); }, + publishAvatar: function (data) { + if (!data) data = this.avatar; + if (!data || data.indexOf('https://') != -1) return; + + var resampler = new Resample(data, 80, 80, function (data) { + var b64Data = data.split(',')[1]; + var id = crypto.createHash('sha1').update(atob(b64Data)).digest('hex'); + app.storage.avatars.add({id: id, uri: data}); + client.publishAvatar(id, b64Data, function (err, res) { + if (err) return; + client.useAvatars([{ + id: id, + width: 80, + height: 80, + type: 'image/png', + bytes: b64Data.length + }]); + }); + }); + }, hasLdapUsers: function () { return app.ldapUsers.length > 0 ? 'hasLdapUsers' : ''; }, diff --git a/clientapp/models/muc.js b/clientapp/models/muc.js index ce3c1c7..4aa9f19 100644 --- a/clientapp/models/muc.js +++ b/clientapp/models/muc.js @@ -9,6 +9,7 @@ var HumanModel = require('human-model'); var Resources = require('./resources'); var Messages = require('./messages'); var Message = require('./message'); +var avatarHandler = require('../helpers/avatarHandler'); module.exports = HumanModel.define({ initialize: function (attrs) { @@ -90,7 +91,7 @@ module.exports = HumanModel.define({ return nickname != this.getName(jid) ? nickname : ''; }, getAvatar: function (jid) { - var avatar = ""; + var avatar = avatarHandler.getGravatar('').uri; var xmppContact = me.getContact(jid.split('/')[1]); if (xmppContact) { avatar = xmppContact.avatar; diff --git a/clientapp/pages/chat.js b/clientapp/pages/chat.js index 5a47852..29489d0 100644 --- a/clientapp/pages/chat.js +++ b/clientapp/pages/chat.js @@ -25,6 +25,7 @@ module.exports = BasePage.extend({ this.listenTo(this.model, 'refresh', this.renderCollection); app.state.bind('change:connected', this.connectionChange, this); + this.model.bind('change:avatar', this.handleAvatarChanged, this); this.render(); }, @@ -37,7 +38,6 @@ module.exports = BasePage.extend({ 'click .mute': 'handleMuteClick' }, srcBindings: { - avatar: 'header .avatar', streamUrl: 'video.remote' }, textBindings: { @@ -233,6 +233,11 @@ module.exports = BasePage.extend({ var resources = val || this.model.jingleResources; this.$('button.call').prop('disabled', !resources.length); }, + handleAvatarChanged: function (contact, uri) { + if (!me.isMe(contact.jid)) { + $('.' + contact.jid.substr(0, contact.jid.indexOf('@')) + ' .messageAvatar img').attr('src', uri); + } + }, appendModel: function (model, preload) { var newEl, first, last; var msgDate = Date.create(model.timestamp); @@ -259,6 +264,7 @@ module.exports = BasePage.extend({ this.staydown.checkdown(); } else { newEl = $(model.templateHtml); + if (!me.isMe(model.sender.jid)) newEl.addClass(model.sender.jid.substr(0, model.sender.jid.indexOf('@'))); this.staydown.append(newEl[0]); this.lastModel = model; } @@ -283,6 +289,7 @@ module.exports = BasePage.extend({ first.addClass('chatGroup'); } else { newEl = $(model.templateHtml); + if (!me.isMe(model.sender.jid)) newEl.addClass(model.sender.jid.substr(0, model.sender.jid.indexOf('@'))); firstEl.after(newEl[0]); this.firstModel = model; } diff --git a/clientapp/pages/groupchat.js b/clientapp/pages/groupchat.js index 42dc9e9..5a48afd 100644 --- a/clientapp/pages/groupchat.js +++ b/clientapp/pages/groupchat.js @@ -90,6 +90,7 @@ module.exports = BasePage.extend({ this.listenTo(this, 'rosterItemClicked', this.rosterItemSelected); this.listenTo(this.model.messages, 'add', this.handleChatAdded); + this.listenTo(this.model.resources, 'add', this.handleResourceAdded); $(window).on('resize', _.bind(this.resizeInput, this)); @@ -114,6 +115,17 @@ module.exports = BasePage.extend({ handleChatAdded: function (model) { this.appendModel(model, true); }, + handleResourceAdded: function (model) { + var xmppContact = me.getContact(model.id.split('/')[1]); + if (xmppContact) { + xmppContact.bind('change:avatar', this.handleAvatarChanged, this); + } + }, + handleAvatarChanged: function(contact, uri) { + if (!me.isMe(contact.jid)) { + $('.' + contact.jid.substr(0, contact.jid.indexOf('@')) + ' .messageAvatar img').attr('src', uri); + } + }, handlePageLoaded: function () { this.staydown.checkdown(); this.resizeInput(); @@ -354,6 +366,7 @@ module.exports = BasePage.extend({ this.staydown.checkdown(); } else { newEl = $(model.templateHtml); + newEl.addClass(model.sender.getNickname(model.from.full)); this.staydown.append(newEl[0]); this.lastModel = model; } @@ -378,6 +391,7 @@ module.exports = BasePage.extend({ first.addClass('chatGroup'); } else { newEl = $(model.templateHtml); + newEl.addClass(model.sender.getNickname(model.from.full)); firstEl.after(newEl[0]); this.firstModel = model; } diff --git a/clientapp/pages/settings.js b/clientapp/pages/settings.js index a83d0f3..3647fe4 100644 --- a/clientapp/pages/settings.js +++ b/clientapp/pages/settings.js @@ -1,7 +1,6 @@ /*global app, me, client, Resample*/ "use strict"; -var crypto = require('crypto'); var BasePage = require('./base'); var templates = require('../templates'); var LDAPUserItem = require('../views/ldapUserItem'); @@ -79,21 +78,7 @@ module.exports = BasePage.extend({ if (file.type.match('image.*')) { var fileTracker = new FileReader(); fileTracker.onload = function () { - var resampler = new Resample(this.result, 80, 80, function (data) { - var b64Data = data.split(',')[1]; - var id = crypto.createHash('sha1').update(atob(b64Data)).digest('hex'); - app.storage.avatars.add({id: id, uri: data}); - client.publishAvatar(id, b64Data, function (err, res) { - if (err) return; - client.useAvatars([{ - id: id, - width: 80, - height: 80, - type: 'image/png', - bytes: b64Data.length - }]); - }); - }); + me.publishAvatar(this.result); }; fileTracker.readAsDataURL(file); }