Add support for rendering avatars in groupchats
This commit is contained in:
parent
c14ef3bb75
commit
53f5627b72
@ -1306,6 +1306,8 @@ Fetches the VCard associated with a particular `Backbone.Model` instance
|
||||
(by using its `jid` or `muc_jid` attribute) and then updates the model with the
|
||||
returned VCard data.
|
||||
|
||||
Returns a promise;
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
@ -53,6 +53,7 @@
|
||||
</div>
|
||||
|
||||
<div class="message chat-msg">
|
||||
<div class="avatar montague"></div>
|
||||
<canvas data-avatar="/mockup/images/romeo.jpg" height="36" width="36" class="avatar"></canvas>
|
||||
<div class="chat-msg-content">
|
||||
<span class="chat-msg-heading">
|
||||
|
@ -87,6 +87,15 @@
|
||||
},
|
||||
|
||||
initialize () {
|
||||
if (this.get('type') === 'groupchat') {
|
||||
this.avatar = this.collection.chatbox.avatars.findWhere({'muc_jid': this.get('from')});
|
||||
if (_.isNil(this.avatar)) {
|
||||
this.avatar = this.collection.chatbox.avatars.create({
|
||||
'muc_jid': this.get('from')
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this.get('file')) {
|
||||
this.on('change:put', this.uploadFile, this);
|
||||
|
||||
|
@ -53,6 +53,9 @@
|
||||
})
|
||||
}
|
||||
});
|
||||
if (this.model.get('type') === 'groupchat') {
|
||||
this.model.avatar.on('change:image', this.renderAvatar, this);
|
||||
}
|
||||
this.model.on('change:fullname', this.render, this);
|
||||
this.model.on('change:progress', this.renderFileUploadProgresBar, this);
|
||||
this.model.on('change:type', this.render, this);
|
||||
@ -66,33 +69,28 @@
|
||||
} else if (this.model.get('type') === 'error') {
|
||||
return this.renderErrorMessage();
|
||||
}
|
||||
let template, image, image_type,
|
||||
text = this.model.get('message');
|
||||
|
||||
let template, text = this.model.get('message');
|
||||
if (this.isMeCommand()) {
|
||||
template = tpl_action;
|
||||
text = this.model.get('message').replace(/^\/me/, '');
|
||||
} else {
|
||||
template = this.model.get('is_spoiler') ? tpl_spoiler_message : tpl_message;
|
||||
if (this.model.get('type') !== 'headline') {
|
||||
if (this.model.get('sender') === 'me') {
|
||||
image_type = _converse.xmppstatus.get('image_type');
|
||||
image = _converse.xmppstatus.get('image');
|
||||
}
|
||||
|
||||
let username;
|
||||
if (this.chatbox.get('type') === 'chatroom') {
|
||||
username = this.model.get('nick');
|
||||
} else {
|
||||
image_type = this.chatbox.get('image_type');
|
||||
image = this.chatbox.get('image');
|
||||
}
|
||||
}
|
||||
username = this.model.get('fullname') || this.model.get('from');
|
||||
}
|
||||
|
||||
const moment_time = moment(this.model.get('time'));
|
||||
const msg = u.stringToElement(template(
|
||||
_.extend(this.model.toJSON(), {
|
||||
'pretty_time': moment_time.format(_converse.time_format),
|
||||
'time': moment_time.format(),
|
||||
'extra_classes': this.getExtraMessageClasses(),
|
||||
'label_show': __('Show more'),
|
||||
'image_type': image_type,
|
||||
'image': image
|
||||
'label_show': __('Show more')
|
||||
})
|
||||
));
|
||||
|
||||
@ -119,7 +117,42 @@
|
||||
u.renderImageURLs(_converse, msg_content).then(() => {
|
||||
this.model.collection.trigger('rendered');
|
||||
});
|
||||
return this.replaceElement(msg);
|
||||
this.replaceElement(msg);
|
||||
if (this.model.get('type') !== 'headline') {
|
||||
this.renderAvatar();
|
||||
}
|
||||
},
|
||||
|
||||
renderAvatar () {
|
||||
const canvas_el = this.el.querySelector('canvas');
|
||||
if (_.isNull(canvas_el)) {
|
||||
return;
|
||||
}
|
||||
let image, image_type;
|
||||
|
||||
if (this.chatbox.get('type') === 'chatroom') {
|
||||
image_type = this.model.avatar.get('image_type');
|
||||
image = this.model.avatar.get('image');
|
||||
} else if (this.model.get('sender') === 'me') {
|
||||
image_type = _converse.xmppstatus.get('image_type');
|
||||
image = _converse.xmppstatus.get('image');
|
||||
} else {
|
||||
image_type = this.chatbox.get('image_type');
|
||||
image = this.chatbox.get('image');
|
||||
}
|
||||
|
||||
const img_src = "data:" + image_type + ";base64," + image,
|
||||
img = new Image();
|
||||
img.onload = () => {
|
||||
const ctx = canvas_el.getContext('2d'),
|
||||
ratio = img.width / img.height;
|
||||
if (ratio < 1) {
|
||||
ctx.drawImage(img, 0, 0, canvas_el.width, canvas_el.height * (1 / ratio));
|
||||
} else {
|
||||
ctx.drawImage(img, 0, 0, canvas_el.width, canvas_el.height * ratio);
|
||||
}
|
||||
};
|
||||
img.src = img_src;
|
||||
},
|
||||
|
||||
replaceElement (msg) {
|
||||
|
@ -99,8 +99,8 @@
|
||||
const { _converse } = this.__super__;
|
||||
this.roomspanel = new _converse.RoomsPanel({
|
||||
'model': new (_converse.RoomsPanelModel.extend({
|
||||
id: b64_sha1(`converse.roomspanel${_converse.bare_jid}`), // Required by sessionStorage
|
||||
browserStorage: new Backbone.BrowserStorage[_converse.storage](
|
||||
'id': b64_sha1(`converse.roomspanel${_converse.bare_jid}`), // Required by sessionStorage
|
||||
'browserStorage': new Backbone.BrowserStorage[_converse.storage](
|
||||
b64_sha1(`converse.roomspanel${_converse.bare_jid}`))
|
||||
}))()
|
||||
});
|
||||
@ -1585,8 +1585,6 @@
|
||||
this.chatroomview.model.on('change:unmoderated', this.onFeatureChanged, this);
|
||||
this.chatroomview.model.on('change:unsecured', this.onFeatureChanged, this);
|
||||
|
||||
const id = b64_sha1(`converse.occupants${_converse.bare_jid}${this.chatroomview.model.get('jid')}`);
|
||||
this.model.browserStorage = new Backbone.BrowserStorage.session(id);
|
||||
this.render();
|
||||
this.model.fetch({
|
||||
'add': true,
|
||||
|
@ -185,8 +185,16 @@
|
||||
initialize() {
|
||||
this.constructor.__super__.initialize.apply(this, arguments);
|
||||
this.occupants = new _converse.ChatRoomOccupants();
|
||||
this.registerHandlers();
|
||||
this.occupants.browserStorage = new Backbone.BrowserStorage.session(
|
||||
b64_sha1(`converse.occupants-${_converse.bare_jid}${this.get('jid')}`)
|
||||
);
|
||||
this.avatars = new _converse.Avatars();
|
||||
this.avatars.browserStorage = new Backbone.BrowserStorage.session(
|
||||
b64_sha1(`converse.avatars-${_converse.bare_jid}${this.get('jid')}`)
|
||||
);
|
||||
this.avatars.fetch();
|
||||
|
||||
this.registerHandlers();
|
||||
this.on('change:chat_state', this.sendChatState, this);
|
||||
},
|
||||
|
||||
@ -280,8 +288,16 @@
|
||||
* (String) exit_msg: Optional message to indicate your
|
||||
* reason for leaving.
|
||||
*/
|
||||
this.occupants.reset();
|
||||
if (_converse.connection.mock) {
|
||||
// Clear for tests, but keep otherwise.
|
||||
// We can only get avatars for current occupants in a
|
||||
// room, so we'd rather cache avatars in the hopes of
|
||||
// having more hits.
|
||||
this.avatars.browserStorage._clear();
|
||||
this.avatars.reset();
|
||||
}
|
||||
this.occupants.browserStorage._clear();
|
||||
this.occupants.reset();
|
||||
if (_converse.connection.connected) {
|
||||
this.sendUnavailablePresence(exit_msg);
|
||||
}
|
||||
@ -304,13 +320,14 @@
|
||||
getOutgoingMessageAttributes (text, spoiler_hint) {
|
||||
const is_spoiler = this.get('composing_spoiler');
|
||||
return {
|
||||
'from': `${this.get('jid')}/${this.get('nick')}`,
|
||||
'fullname': this.get('nick'),
|
||||
'username': this.get('nick'),
|
||||
'is_spoiler': is_spoiler,
|
||||
'message': text ? u.httpToGeoUri(emojione.shortnameToUnicode(text), _converse) : undefined,
|
||||
'sender': 'me',
|
||||
'spoiler_hint': is_spoiler ? spoiler_hint : undefined,
|
||||
'type': 'groupchat',
|
||||
'type': 'groupchat'
|
||||
};
|
||||
},
|
||||
|
||||
@ -1014,6 +1031,15 @@
|
||||
});
|
||||
|
||||
|
||||
_converse.Avatars = Backbone.Collection.extend({
|
||||
model: _converse.ModelWithDefaultAvatar,
|
||||
|
||||
initialize () {
|
||||
this.on('add', (avatar) => _converse.api.vcard.update(avatar));
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
_converse.RoomsPanelModel = Backbone.Model.extend({
|
||||
defaults: {
|
||||
'muc_domain': '',
|
||||
|
@ -178,12 +178,15 @@
|
||||
},
|
||||
|
||||
'update' (model, force) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.get(model, force).then((vcard) => {
|
||||
model.save(_.extend(
|
||||
_.pick(vcard, ['fullname', 'url', 'image_type', 'image', 'vcard_updated']),
|
||||
{'vcard_updated': moment().format()}
|
||||
));
|
||||
}).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -1,6 +1,6 @@
|
||||
<div class="message chat-msg {{{o.type}}} {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}" data-from="{{{o.from}}}">
|
||||
{[ if (o.type !== 'headline') { ]}
|
||||
<img alt="User Avatar" class="avatar" height="36px" width="36px" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
|
||||
<canvas class="avatar" height="36" width="36"></canvas>
|
||||
{[ } ]}
|
||||
<div class="chat-msg-content">
|
||||
<span class="chat-msg-heading">
|
||||
|
@ -1,5 +1,5 @@
|
||||
<div class="message chat-msg {{{o.extra_classes}}}" data-isodate="{{{o.time}}}" data-msgid="{{{o.msgid}}}">
|
||||
<img alt="User Avatar" class="avatar" height="36px" width="36px" src="data:{{{o.image_type}}};base64,{{{o.image}}}"/>
|
||||
<canvas class="avatar" height="36" width="36"></canvas>
|
||||
<div class="chat-msg-content">
|
||||
<span class="chat-msg-heading">
|
||||
<span class="chat-msg-author">{{{o.username}}}</span>
|
||||
|
Loading…
Reference in New Issue
Block a user