Commit a75c118a authored by JC Brand's avatar JC Brand

Prioritize roster nickname as message and chatbox display name

Set reference to roster contact on the message and chatbox object and
listen for changes to the nickname.

Currently, because chat boxes are fetched and initialized before the
roster, messages and chats are repainted with the correct display name
only later, causing a "flash" effect.

Ideally we would only initialize the chat boxes after the roster
contacts have been fetched, but this is currently not easily possible
because we need the control box to render before everything else.
parent d450ab58
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Bugfix: Don't set `muc_domain` for roomspanel if `locked_muc_domain` is `true`. * Bugfix: Don't set `muc_domain` for roomspanel if `locked_muc_domain` is `true`.
* Bugfix: Modal auto-closes when you open it for a second time. * Bugfix: Modal auto-closes when you open it for a second time.
* Take roster nickname into consideration when rendering messages and chat headings.
## 4.2.0 (2019-04-04) ## 4.2.0 (2019-04-04)
......
...@@ -48734,7 +48734,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins ...@@ -48734,7 +48734,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
initStatus: function initStatus(reconnecting) { initStatus: function initStatus(reconnecting) {
const _converse = this.__super__._converse; const _converse = this.__super__._converse;
if (!reconnecting) { if (!reconnecting && _converse.chatboxviews) {
_converse.chatboxviews.closeAllChatBoxes(); _converse.chatboxviews.closeAllChatBoxes();
} }
...@@ -49097,20 +49097,26 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_5__["default"].plugins ...@@ -49097,20 +49097,26 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_5__["default"].plugins
_converse.ChatBoxHeading = _converse.ViewWithAvatar.extend({ _converse.ChatBoxHeading = _converse.ViewWithAvatar.extend({
initialize() { initialize() {
this.model.on('change:status', this.onStatusMessageChanged, this); this.model.on('change:status', this.onStatusMessageChanged, this);
this.model.vcard.on('change', this.render, this); this.debouncedRender = _.debounce(this.render, 50);
this.model.vcard.on('change', this.debouncedRender, this);
this.model.on('rosterContactAdded', () => {
this.model.contact.on('change:nickname', this.debouncedRender, this);
this.debouncedRender();
});
}, },
render() { render() {
this.el.innerHTML = templates_chatbox_head_html__WEBPACK_IMPORTED_MODULE_8___default()(_.extend(this.model.vcard.toJSON(), this.model.toJSON(), { this.el.innerHTML = templates_chatbox_head_html__WEBPACK_IMPORTED_MODULE_8___default()(_.extend(this.model.vcard.toJSON(), this.model.toJSON(), {
'_converse': _converse, '_converse': _converse,
'info_close': __('Close this chat box') 'info_close': __('Close this chat box'),
'display_name': this.model.getDisplayName()
})); }));
this.renderAvatar(); this.renderAvatar();
return this; return this;
}, },
onStatusMessageChanged(item) { onStatusMessageChanged(item) {
this.render(); this.debouncedRender();
/** /**
* When a contact's custom status message has changed. * When a contact's custom status message has changed.
* @event _converse#contactStatusMessageChanged * @event _converse#contactStatusMessageChanged
...@@ -52271,10 +52277,16 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_1__["default"].plugins ...@@ -52271,10 +52277,16 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_1__["default"].plugins
}, },
initialize() { initialize() {
this.debouncedRender = _.debounce(this.render, 50);
if (this.model.vcard) { if (this.model.vcard) {
this.model.vcard.on('change', this.render, this); this.model.vcard.on('change', this.debouncedRender, this);
} }
this.model.on('rosterContactAdded', () => {
this.model.contact.on('change:nickname', this.debouncedRender, this);
this.debouncedRender();
});
this.model.on('change', this.onChanged, this); this.model.on('change', this.onChanged, this);
this.model.on('destroy', this.remove, this); this.model.on('destroy', this.remove, this);
}, },
...@@ -52316,7 +52328,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_1__["default"].plugins ...@@ -52316,7 +52328,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_1__["default"].plugins
} }
if (_.filter(['correcting', 'message', 'type', 'upload', 'received'], prop => Object.prototype.hasOwnProperty.call(this.model.changed, prop)).length) { if (_.filter(['correcting', 'message', 'type', 'upload', 'received'], prop => Object.prototype.hasOwnProperty.call(this.model.changed, prop)).length) {
await this.render(); await this.debouncedRender();
} }
if (edited) { if (edited) {
...@@ -60201,7 +60213,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_4__["default"].plugins ...@@ -60201,7 +60213,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_4__["default"].plugins
}, },
onContactChange(contact) { onContactChange(contact) {
this.updateChatBox(contact);
this.update(); this.update();
if (_.has(contact.changed, 'subscription')) { if (_.has(contact.changed, 'subscription')) {
...@@ -60223,21 +60234,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_4__["default"].plugins ...@@ -60223,21 +60234,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_4__["default"].plugins
this.updateFilter(); this.updateFilter();
}, },
updateChatBox(contact) {
if (!this.model.chatbox) {
return this;
}
const changes = {};
if (_.has(contact.changed, 'status')) {
changes.status = contact.get('status');
}
this.model.chatbox.save(changes);
return this;
},
getGroup(name) { getGroup(name) {
/* Returns the group as specified by name. /* Returns the group as specified by name.
* Creates the group if it doesn't exist. * Creates the group if it doesn't exist.
...@@ -61771,7 +61767,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -61771,7 +61767,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
_converse.router.route('converse/chat?jid=:jid', openChat); _converse.router.route('converse/chat?jid=:jid', openChat);
_converse.Message = Backbone.Model.extend({ const ModelWithContact = Backbone.Model.extend({
async setRosterContact(jid) {
await _converse.api.waitUntil('rosterContactsFetched');
const contact = _converse.roster.get(jid);
if (contact) {
this.contact = contact;
this.trigger('rosterContactAdded');
}
}
});
_converse.Message = ModelWithContact.extend({
defaults() { defaults() {
return { return {
'msgid': _converse.connection.getUniqueId(), 'msgid': _converse.connection.getUniqueId(),
...@@ -61782,6 +61791,10 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -61782,6 +61791,10 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
initialize() { initialize() {
this.setVCard(); this.setVCard();
if (this.get('type') === 'chat') {
this.setRosterContact(Strophe.getBareJidFromJid(this.get('from')));
}
if (this.get('file')) { if (this.get('file')) {
this.on('change:put', this.uploadFile, this); this.on('change:put', this.uploadFile, this);
} }
...@@ -61857,7 +61870,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -61857,7 +61870,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
if (this.get('type') === 'groupchat') { if (this.get('type') === 'groupchat') {
return this.get('nick'); return this.get('nick');
} else { } else {
return this.vcard.get('fullname') || this.get('from'); if (this.contact) {
return this.contact.getDisplayName();
}
return this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('from');
} }
}, },
...@@ -61971,7 +61988,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -61971,7 +61988,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
* @memberOf _converse * @memberOf _converse
*/ */
_converse.ChatBox = Backbone.Model.extend({ _converse.ChatBox = ModelWithContact.extend({
defaults() { defaults() {
return { return {
'bookmarked': false, 'bookmarked': false,
...@@ -62012,6 +62029,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -62012,6 +62029,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
}) || _converse.presences.create({ }) || _converse.presences.create({
'jid': jid 'jid': jid
}); });
if (this.get('type') === _converse.PRIVATE_CHAT_TYPE) {
this.setRosterContact(jid);
}
this.messages = new _converse.Messages(); this.messages = new _converse.Messages();
const storage = _converse.config.get('storage'); const storage = _converse.config.get('storage');
...@@ -62045,7 +62067,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -62045,7 +62067,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
}, },
getDisplayName() { getDisplayName() {
return this.vcard.get('fullname') || this.get('jid'); if (this.contact) {
return this.contact.getDisplayName();
}
return this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid');
}, },
getUpdatedMessageAttributes(message, stanza) { getUpdatedMessageAttributes(message, stanza) {
...@@ -68833,7 +68859,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins ...@@ -68833,7 +68859,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
'jid': bare_jid, 'jid': bare_jid,
'user_id': Strophe.getNodeFromJid(jid) 'user_id': Strophe.getNodeFromJid(jid)
}, attributes)); }, attributes));
this.setChatBox();
/** /**
* When a contact's presence status has changed. * When a contact's presence status has changed.
* The presence status is either `online`, `offline`, `dnd`, `away` or `xa`. * The presence status is either `online`, `offline`, `dnd`, `away` or `xa`.
...@@ -68846,16 +68871,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins ...@@ -68846,16 +68871,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
this.presence.on('change:show', () => this.trigger('presenceChanged')); this.presence.on('change:show', () => this.trigger('presenceChanged'));
}, },
setChatBox() {
let chatbox = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
chatbox = chatbox || _converse.chatboxes.get(this.get('jid'));
if (chatbox) {
this.chatbox = chatbox;
this.chatbox.on('change:hidden', this.render, this);
}
},
getDisplayName() { getDisplayName() {
return this.get('nickname') || this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid'); return this.get('nickname') || this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid');
}, },
...@@ -93010,7 +93025,7 @@ __e(o.url) + ...@@ -93010,7 +93025,7 @@ __e(o.url) +
'" target="_blank" rel="noopener" class="user">\n '; '" target="_blank" rel="noopener" class="user">\n ';
} ; } ;
__p += '\n ' + __p += '\n ' +
__e( o.nickname || o.fullname || o.jid ) + __e( o.display_name ) +
'\n '; '\n ';
if (o.url) { ; if (o.url) { ;
__p += '\n </a>\n '; __p += '\n </a>\n ';
...@@ -99,7 +99,7 @@ ...@@ -99,7 +99,7 @@
expect(textarea.value).toBe(''); expect(textarea.value).toBe('');
expect(view.model.messages.at(0).get('correcting')).toBe(false); expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false); await test_utils.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
// Test that messages from other users don't have the pencil icon // Test that messages from other users don't have the pencil icon
_converse.chatboxes.onMessage( _converse.chatboxes.onMessage(
...@@ -154,7 +154,7 @@ ...@@ -154,7 +154,7 @@
expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?'); expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true); expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg'))); await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
spyOn(_converse.connection, 'send'); spyOn(_converse.connection, 'send');
textarea.value = 'But soft, what light through yonder window breaks?'; textarea.value = 'But soft, what light through yonder window breaks?';
...@@ -185,7 +185,7 @@ ...@@ -185,7 +185,7 @@
expect(corrected_message.get('older_versions')[0]).toBe('But soft, what light through yonder airlock breaks?'); expect(corrected_message.get('older_versions')[0]).toBe('But soft, what light through yonder airlock breaks?');
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false); await test_utils.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
// Test that pressing the down arrow cancels message correction // Test that pressing the down arrow cancels message correction
expect(textarea.value).toBe(''); expect(textarea.value).toBe('');
...@@ -196,7 +196,7 @@ ...@@ -196,7 +196,7 @@
expect(textarea.value).toBe('But soft, what light through yonder window breaks?'); expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true); expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === true); await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
expect(textarea.value).toBe('But soft, what light through yonder window breaks?'); expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
view.keyPressed({ view.keyPressed({
target: textarea, target: textarea,
...@@ -205,7 +205,7 @@ ...@@ -205,7 +205,7 @@
expect(textarea.value).toBe(''); expect(textarea.value).toBe('');
expect(view.model.messages.at(0).get('correcting')).toBe(false); expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false); await test_utils.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
textarea.value = 'It is the east, and Juliet is the one.'; textarea.value = 'It is the east, and Juliet is the one.';
view.keyPressed({ view.keyPressed({
...@@ -233,7 +233,7 @@ ...@@ -233,7 +233,7 @@
expect(view.model.messages.at(0).get('correcting')).toBeFalsy(); expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
expect(view.model.messages.at(1).get('correcting')).toBeFalsy(); expect(view.model.messages.at(1).get('correcting')).toBeFalsy();
expect(view.model.messages.at(2).get('correcting')).toBe(true); expect(view.model.messages.at(2).get('correcting')).toBe(true);
await test_utils.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg:last', view.el).pop())); await test_utils.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg:last', view.el).pop()), 500);
textarea.selectionEnd = 0; // Happens by pressing up, textarea.selectionEnd = 0; // Happens by pressing up,
// but for some reason not in tests, so we set it manually. // but for some reason not in tests, so we set it manually.
...@@ -245,7 +245,7 @@ ...@@ -245,7 +245,7 @@
expect(view.model.messages.at(0).get('correcting')).toBeFalsy(); expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
expect(view.model.messages.at(1).get('correcting')).toBe(true); expect(view.model.messages.at(1).get('correcting')).toBe(true);
expect(view.model.messages.at(2).get('correcting')).toBeFalsy(); expect(view.model.messages.at(2).get('correcting')).toBeFalsy();
await test_utils.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg', view.el)[1])); await test_utils.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg', view.el)[1]), 500);
textarea.value = 'It is the east, and Juliet is the sun.'; textarea.value = 'It is the east, and Juliet is the sun.';
view.keyPressed({ view.keyPressed({
...@@ -2335,7 +2335,7 @@ ...@@ -2335,7 +2335,7 @@
}).c('body').t('But soft, what light through yonder chimney breaks?').up() }).c('body').t('But soft, what light through yonder chimney breaks?').up()
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree()); .c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent === await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
'But soft, what light through yonder chimney breaks?'); 'But soft, what light through yonder chimney breaks?', 500);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1);
...@@ -2348,7 +2348,7 @@ ...@@ -2348,7 +2348,7 @@
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree()); .c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent === await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
'But soft, what light through yonder window breaks?'); 'But soft, what light through yonder window breaks?', 500);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1);
view.el.querySelector('.chat-msg__content .fa-edit').click(); view.el.querySelector('.chat-msg__content .fa-edit').click();
...@@ -2451,7 +2451,7 @@ ...@@ -2451,7 +2451,7 @@
expect(textarea.value).toBe('But soft, what light through yonder window breaks?'); expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
expect(view.model.messages.at(0).get('correcting')).toBe(true); expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2); expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg'))); await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
expect(textarea.value).toBe('But soft, what light through yonder window breaks?'); expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
view.keyPressed({ view.keyPressed({
target: textarea, target: textarea,
...@@ -2460,7 +2460,7 @@ ...@@ -2460,7 +2460,7 @@
expect(textarea.value).toBe(''); expect(textarea.value).toBe('');
expect(view.model.messages.at(0).get('correcting')).toBe(false); expect(view.model.messages.at(0).get('correcting')).toBe(false);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2); expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
await test_utils.waitUntil(() => !u.hasClass('correcting', view.el.querySelector('.chat-msg'))); await test_utils.waitUntil(() => !u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
done(); done();
})); }));
...@@ -2493,7 +2493,7 @@ ...@@ -2493,7 +2493,7 @@
<origin-id xmlns="urn:xmpp:sid:0" id="${msg_obj.get('origin_id')}"/> <origin-id xmlns="urn:xmpp:sid:0" id="${msg_obj.get('origin_id')}"/>
</message>`); </message>`);
await view.model.onMessage(stanza); await view.model.onMessage(stanza);
await test_utils.waitUntil(() => view.el.querySelectorAll('.chat-msg__receipt').length); await test_utils.waitUntil(() => view.el.querySelectorAll('.chat-msg__receipt').length, 500);
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(1);
expect(view.model.messages.length).toBe(1); expect(view.model.messages.length).toBe(1);
...@@ -2854,10 +2854,12 @@ ...@@ -2854,10 +2854,12 @@
expect(textarea.value).toBe('hello @z3r0 @gibson @mr.robot, how are you?'); expect(textarea.value).toBe('hello @z3r0 @gibson @mr.robot, how are you?');
expect(view.model.messages.at(0).get('correcting')).toBe(true); expect(view.model.messages.at(0).get('correcting')).toBe(true);
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1); expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg'))); await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
textarea.value = 'hello @z3r0 @gibson @sw0rdf1sh, how are you?'; textarea.value = 'hello @z3r0 @gibson @sw0rdf1sh, how are you?';
view.keyPressed(enter_event); view.keyPressed(enter_event);
await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
'hello z3r0 gibson sw0rdf1sh, how are you?', 500);
const correction = _converse.connection.send.calls.all()[1].args[0]; const correction = _converse.connection.send.calls.all()[1].args[0];
expect(correction.toLocaleString()) expect(correction.toLocaleString())
...@@ -2866,9 +2868,9 @@ ...@@ -2866,9 +2868,9 @@
`xmlns="jabber:client">`+ `xmlns="jabber:client">`+
`<body>hello z3r0 gibson sw0rdf1sh, how are you?</body>`+ `<body>hello z3r0 gibson sw0rdf1sh, how are you?</body>`+
`<active xmlns="http://jabber.org/protocol/chatstates"/>`+ `<active xmlns="http://jabber.org/protocol/chatstates"/>`+
`<reference begin="18" end="27" type="mention" uri="xmpp:sw0rdf1sh@localhost" xmlns="urn:xmpp:reference:0"/>`+
`<reference begin="11" end="17" type="mention" uri="xmpp:gibson@localhost" xmlns="urn:xmpp:reference:0"/>`+
`<reference begin="6" end="10" type="mention" uri="xmpp:z3r0@localhost" xmlns="urn:xmpp:reference:0"/>`+ `<reference begin="6" end="10" type="mention" uri="xmpp:z3r0@localhost" xmlns="urn:xmpp:reference:0"/>`+
`<reference begin="11" end="17" type="mention" uri="xmpp:gibson@localhost" xmlns="urn:xmpp:reference:0"/>`+
`<reference begin="18" end="27" type="mention" uri="xmpp:sw0rdf1sh@localhost" xmlns="urn:xmpp:reference:0"/>`+
`<replace id="${msg.nodeTree.getAttribute("id")}" xmlns="urn:xmpp:message-correct:0"/>`+ `<replace id="${msg.nodeTree.getAttribute("id")}" xmlns="urn:xmpp:message-correct:0"/>`+
`<origin-id id="${msg.nodeTree.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+ `<origin-id id="${msg.nodeTree.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+
`</message>`); `</message>`);
......
(function (root, factory) { (function (root, factory) {
define(["jquery", "jasmine", "mock", "test-utils"], factory); define(["jasmine", "mock", "test-utils"], factory);
} (this, function ($, jasmine, mock, test_utils) { } (this, function (jasmine, mock, test_utils) {
const _ = converse.env._; const _ = converse.env._;
const $msg = converse.env.$msg; const $msg = converse.env.$msg;
const u = converse.env.utils; const u = converse.env.utils;
......
...@@ -47,7 +47,7 @@ converse.plugins.add('converse-chatboxviews', { ...@@ -47,7 +47,7 @@ converse.plugins.add('converse-chatboxviews', {
initStatus: function (reconnecting) { initStatus: function (reconnecting) {
const { _converse } = this.__super__; const { _converse } = this.__super__;
if (!reconnecting) { if (!reconnecting && _converse.chatboxviews) {
_converse.chatboxviews.closeAllChatBoxes(); _converse.chatboxviews.closeAllChatBoxes();
} }
return this.__super__.initStatus.apply(this, arguments); return this.__super__.initStatus.apply(this, arguments);
......
...@@ -161,7 +161,13 @@ converse.plugins.add('converse-chatview', { ...@@ -161,7 +161,13 @@ converse.plugins.add('converse-chatview', {
_converse.ChatBoxHeading = _converse.ViewWithAvatar.extend({ _converse.ChatBoxHeading = _converse.ViewWithAvatar.extend({
initialize () { initialize () {
this.model.on('change:status', this.onStatusMessageChanged, this); this.model.on('change:status', this.onStatusMessageChanged, this);
this.model.vcard.on('change', this.render, this);
this.debouncedRender = _.debounce(this.render, 50);
this.model.vcard.on('change', this.debouncedRender, this);
this.model.on('rosterContactAdded', () => {
this.model.contact.on('change:nickname', this.debouncedRender, this);
this.debouncedRender();
});
}, },
render () { render () {
...@@ -170,7 +176,8 @@ converse.plugins.add('converse-chatview', { ...@@ -170,7 +176,8 @@ converse.plugins.add('converse-chatview', {
this.model.vcard.toJSON(), this.model.vcard.toJSON(),
this.model.toJSON(), this.model.toJSON(),
{ '_converse': _converse, { '_converse': _converse,
'info_close': __('Close this chat box') 'info_close': __('Close this chat box'),
'display_name': this.model.getDisplayName()
} }
) )
); );
...@@ -179,7 +186,7 @@ converse.plugins.add('converse-chatview', { ...@@ -179,7 +186,7 @@ converse.plugins.add('converse-chatview', {
}, },
onStatusMessageChanged (item) { onStatusMessageChanged (item) {
this.render(); this.debouncedRender();
/** /**
* When a contact's custom status message has changed. * When a contact's custom status message has changed.
* @event _converse#contactStatusMessageChanged * @event _converse#contactStatusMessageChanged
......
...@@ -81,9 +81,14 @@ converse.plugins.add('converse-message-view', { ...@@ -81,9 +81,14 @@ converse.plugins.add('converse-message-view', {
}, },
initialize () { initialize () {
this.debouncedRender = _.debounce(this.render, 50);
if (this.model.vcard) { if (this.model.vcard) {
this.model.vcard.on('change', this.render, this); this.model.vcard.on('change', this.debouncedRender, this);
} }
this.model.on('rosterContactAdded', () => {
this.model.contact.on('change:nickname', this.debouncedRender, this);
this.debouncedRender();
});
this.model.on('change', this.onChanged, this); this.model.on('change', this.onChanged, this);
this.model.on('destroy', this.remove, this); this.model.on('destroy', this.remove, this);
}, },
...@@ -119,7 +124,7 @@ converse.plugins.add('converse-message-view', { ...@@ -119,7 +124,7 @@ converse.plugins.add('converse-message-view', {
} }
if (_.filter(['correcting', 'message', 'type', 'upload', 'received'], if (_.filter(['correcting', 'message', 'type', 'upload', 'received'],
prop => Object.prototype.hasOwnProperty.call(this.model.changed, prop)).length) { prop => Object.prototype.hasOwnProperty.call(this.model.changed, prop)).length) {
await this.render(); await this.debouncedRender();
} }
if (edited) { if (edited) {
this.onMessageEdited(); this.onMessageEdited();
......
...@@ -926,7 +926,6 @@ converse.plugins.add('converse-rosterview', { ...@@ -926,7 +926,6 @@ converse.plugins.add('converse-rosterview', {
}, },
onContactChange (contact) { onContactChange (contact) {
this.updateChatBox(contact)
this.update(); this.update();
if (_.has(contact.changed, 'subscription')) { if (_.has(contact.changed, 'subscription')) {
if (contact.changed.subscription === 'from') { if (contact.changed.subscription === 'from') {
...@@ -944,18 +943,6 @@ converse.plugins.add('converse-rosterview', { ...@@ -944,18 +943,6 @@ converse.plugins.add('converse-rosterview', {
this.updateFilter(); this.updateFilter();
}, },
updateChatBox (contact) {
if (!this.model.chatbox) {
return this;
}
const changes = {};
if (_.has(contact.changed, 'status')) {
changes.status = contact.get('status');
}
this.model.chatbox.save(changes);
return this;
},
getGroup (name) { getGroup (name) {
/* Returns the group as specified by name. /* Returns the group as specified by name.
* Creates the group if it doesn't exist. * Creates the group if it doesn't exist.
......
...@@ -56,7 +56,20 @@ converse.plugins.add('converse-chatboxes', { ...@@ -56,7 +56,20 @@ converse.plugins.add('converse-chatboxes', {
_converse.router.route('converse/chat?jid=:jid', openChat); _converse.router.route('converse/chat?jid=:jid', openChat);
_converse.Message = Backbone.Model.extend({ const ModelWithContact = Backbone.Model.extend({
async setRosterContact (jid) {
await _converse.api.waitUntil('rosterContactsFetched');
const contact = _converse.roster.get(jid);
if (contact) {
this.contact = contact;
this.trigger('rosterContactAdded');
}
}
});
_converse.Message = ModelWithContact.extend({
defaults () { defaults () {
return { return {
...@@ -67,6 +80,9 @@ converse.plugins.add('converse-chatboxes', { ...@@ -67,6 +80,9 @@ converse.plugins.add('converse-chatboxes', {
initialize () { initialize () {
this.setVCard(); this.setVCard();
if (this.get('type') === 'chat') {
this.setRosterContact(Strophe.getBareJidFromJid(this.get('from')));
}
if (this.get('file')) { if (this.get('file')) {
this.on('change:put', this.uploadFile, this); this.on('change:put', this.uploadFile, this);
} }
...@@ -120,7 +136,10 @@ converse.plugins.add('converse-chatboxes', { ...@@ -120,7 +136,10 @@ converse.plugins.add('converse-chatboxes', {
if (this.get('type') === 'groupchat') { if (this.get('type') === 'groupchat') {
return this.get('nick'); return this.get('nick');
} else { } else {
return this.vcard.get('fullname') || this.get('from'); if (this.contact) {
return this.contact.getDisplayName();
}
return this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('from');
} }
}, },
...@@ -226,7 +245,7 @@ converse.plugins.add('converse-chatboxes', { ...@@ -226,7 +245,7 @@ converse.plugins.add('converse-chatboxes', {
* @namespace _converse.ChatBox * @namespace _converse.ChatBox
* @memberOf _converse * @memberOf _converse
*/ */
_converse.ChatBox = Backbone.Model.extend({ _converse.ChatBox = ModelWithContact.extend({
defaults () { defaults () {
return { return {
'bookmarked': false, 'bookmarked': false,
...@@ -258,6 +277,9 @@ converse.plugins.add('converse-chatboxes', { ...@@ -258,6 +277,9 @@ converse.plugins.add('converse-chatboxes', {
// probably shouldn't have here, so we should probably move // probably shouldn't have here, so we should probably move
// ChatBox out of converse-chatboxes // ChatBox out of converse-chatboxes
this.presence = _converse.presences.findWhere({'jid': jid}) || _converse.presences.create({'jid': jid}); this.presence = _converse.presences.findWhere({'jid': jid}) || _converse.presences.create({'jid': jid});
if (this.get('type') === _converse.PRIVATE_CHAT_TYPE) {
this.setRosterContact(jid);
}
this.messages = new _converse.Messages(); this.messages = new _converse.Messages();
const storage = _converse.config.get('storage'); const storage = _converse.config.get('storage');
...@@ -293,7 +315,10 @@ converse.plugins.add('converse-chatboxes', { ...@@ -293,7 +315,10 @@ converse.plugins.add('converse-chatboxes', {
}, },
getDisplayName () { getDisplayName () {
return this.vcard.get('fullname') || this.get('jid'); if (this.contact) {
return this.contact.getDisplayName();
}
return this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid');
}, },
getUpdatedMessageAttributes (message, stanza) { getUpdatedMessageAttributes (message, stanza) {
......
...@@ -246,9 +246,6 @@ converse.plugins.add('converse-roster', { ...@@ -246,9 +246,6 @@ converse.plugins.add('converse-roster', {
'jid': bare_jid, 'jid': bare_jid,
'user_id': Strophe.getNodeFromJid(jid) 'user_id': Strophe.getNodeFromJid(jid)
}, attributes)); }, attributes));
this.setChatBox();
/** /**
* When a contact's presence status has changed. * When a contact's presence status has changed.
* The presence status is either `online`, `offline`, `dnd`, `away` or `xa`. * The presence status is either `online`, `offline`, `dnd`, `away` or `xa`.
...@@ -260,14 +257,6 @@ converse.plugins.add('converse-roster', { ...@@ -260,14 +257,6 @@ converse.plugins.add('converse-roster', {
this.presence.on('change:show', () => this.trigger('presenceChanged')); this.presence.on('change:show', () => this.trigger('presenceChanged'));
}, },
setChatBox (chatbox=null) {
chatbox = chatbox || _converse.chatboxes.get(this.get('jid'));
if (chatbox) {
this.chatbox = chatbox;
this.chatbox.on('change:hidden', this.render, this);
}
},
getDisplayName () { getDisplayName () {
return this.get('nickname') || this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid'); return this.get('nickname') || this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid');
}, },
......
...@@ -40215,7 +40215,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -40215,7 +40215,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
_converse.router.route('converse/chat?jid=:jid', openChat); _converse.router.route('converse/chat?jid=:jid', openChat);
_converse.Message = Backbone.Model.extend({ const ModelWithContact = Backbone.Model.extend({
async setRosterContact(jid) {
await _converse.api.waitUntil('rosterContactsFetched');
const contact = _converse.roster.get(jid);
if (contact) {
this.contact = contact;
this.trigger('rosterContactAdded');
}
}
});
_converse.Message = ModelWithContact.extend({
defaults() { defaults() {
return { return {
'msgid': _converse.connection.getUniqueId(), 'msgid': _converse.connection.getUniqueId(),
...@@ -40226,6 +40239,10 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -40226,6 +40239,10 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
initialize() { initialize() {
this.setVCard(); this.setVCard();
if (this.get('type') === 'chat') {
this.setRosterContact(Strophe.getBareJidFromJid(this.get('from')));
}
if (this.get('file')) { if (this.get('file')) {
this.on('change:put', this.uploadFile, this); this.on('change:put', this.uploadFile, this);
} }
...@@ -40301,7 +40318,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -40301,7 +40318,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
if (this.get('type') === 'groupchat') { if (this.get('type') === 'groupchat') {
return this.get('nick'); return this.get('nick');
} else { } else {
return this.vcard.get('fullname') || this.get('from'); if (this.contact) {
return this.contact.getDisplayName();
}
return this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('from');
} }
}, },
...@@ -40415,7 +40436,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -40415,7 +40436,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
* @memberOf _converse * @memberOf _converse
*/ */
_converse.ChatBox = Backbone.Model.extend({ _converse.ChatBox = ModelWithContact.extend({
defaults() { defaults() {
return { return {
'bookmarked': false, 'bookmarked': false,
...@@ -40456,6 +40477,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -40456,6 +40477,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
}) || _converse.presences.create({ }) || _converse.presences.create({
'jid': jid 'jid': jid
}); });
if (this.get('type') === _converse.PRIVATE_CHAT_TYPE) {
this.setRosterContact(jid);
}
this.messages = new _converse.Messages(); this.messages = new _converse.Messages();
const storage = _converse.config.get('storage'); const storage = _converse.config.get('storage');
...@@ -40489,7 +40515,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha ...@@ -40489,7 +40515,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
}, },
getDisplayName() { getDisplayName() {
return this.vcard.get('fullname') || this.get('jid'); if (this.contact) {
return this.contact.getDisplayName();
}
return this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid');
}, },
getUpdatedMessageAttributes(message, stanza) { getUpdatedMessageAttributes(message, stanza) {
...@@ -47277,7 +47307,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins ...@@ -47277,7 +47307,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
'jid': bare_jid, 'jid': bare_jid,
'user_id': Strophe.getNodeFromJid(jid) 'user_id': Strophe.getNodeFromJid(jid)
}, attributes)); }, attributes));
this.setChatBox();
/** /**
* When a contact's presence status has changed. * When a contact's presence status has changed.
* The presence status is either `online`, `offline`, `dnd`, `away` or `xa`. * The presence status is either `online`, `offline`, `dnd`, `away` or `xa`.
...@@ -47290,16 +47319,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins ...@@ -47290,16 +47319,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
this.presence.on('change:show', () => this.trigger('presenceChanged')); this.presence.on('change:show', () => this.trigger('presenceChanged'));
}, },
setChatBox() {
let chatbox = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
chatbox = chatbox || _converse.chatboxes.get(this.get('jid'));
if (chatbox) {
this.chatbox = chatbox;
this.chatbox.on('change:hidden', this.render, this);
}
},
getDisplayName() { getDisplayName() {
return this.get('nickname') || this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid'); return this.get('nickname') || this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid');
}, },
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
{[ if (o.url) { ]} {[ if (o.url) { ]}
<a href="{{{o.url}}}" target="_blank" rel="noopener" class="user"> <a href="{{{o.url}}}" target="_blank" rel="noopener" class="user">
{[ } ]} {[ } ]}
{{{ o.nickname || o.fullname || o.jid }}} {{{ o.display_name }}}
{[ if (o.url) { ]} {[ if (o.url) { ]}
</a> </a>
{[ } ]} {[ } ]}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment