Skip to content

Commit a75c118

Browse files
committed
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.
1 parent d450ab5 commit a75c118

12 files changed

+155
-105
lines changed

CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
* Bugfix: Don't set `muc_domain` for roomspanel if `locked_muc_domain` is `true`.
66
* Bugfix: Modal auto-closes when you open it for a second time.
7+
* Take roster nickname into consideration when rendering messages and chat headings.
78

89
## 4.2.0 (2019-04-04)
910

dist/converse.js

Lines changed: 53 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -48734,7 +48734,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
4873448734
initStatus: function initStatus(reconnecting) {
4873548735
const _converse = this.__super__._converse;
4873648736

48737-
if (!reconnecting) {
48737+
if (!reconnecting && _converse.chatboxviews) {
4873848738
_converse.chatboxviews.closeAllChatBoxes();
4873948739
}
4874048740

@@ -49097,20 +49097,26 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_5__["default"].plugins
4909749097
_converse.ChatBoxHeading = _converse.ViewWithAvatar.extend({
4909849098
initialize() {
4909949099
this.model.on('change:status', this.onStatusMessageChanged, this);
49100-
this.model.vcard.on('change', this.render, this);
49100+
this.debouncedRender = _.debounce(this.render, 50);
49101+
this.model.vcard.on('change', this.debouncedRender, this);
49102+
this.model.on('rosterContactAdded', () => {
49103+
this.model.contact.on('change:nickname', this.debouncedRender, this);
49104+
this.debouncedRender();
49105+
});
4910149106
},
4910249107

4910349108
render() {
4910449109
this.el.innerHTML = templates_chatbox_head_html__WEBPACK_IMPORTED_MODULE_8___default()(_.extend(this.model.vcard.toJSON(), this.model.toJSON(), {
4910549110
'_converse': _converse,
49106-
'info_close': __('Close this chat box')
49111+
'info_close': __('Close this chat box'),
49112+
'display_name': this.model.getDisplayName()
4910749113
}));
4910849114
this.renderAvatar();
4910949115
return this;
4911049116
},
4911149117

4911249118
onStatusMessageChanged(item) {
49113-
this.render();
49119+
this.debouncedRender();
4911449120
/**
4911549121
* When a contact's custom status message has changed.
4911649122
* @event _converse#contactStatusMessageChanged
@@ -52271,10 +52277,16 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_1__["default"].plugins
5227152277
},
5227252278

5227352279
initialize() {
52280+
this.debouncedRender = _.debounce(this.render, 50);
52281+
5227452282
if (this.model.vcard) {
52275-
this.model.vcard.on('change', this.render, this);
52283+
this.model.vcard.on('change', this.debouncedRender, this);
5227652284
}
5227752285

52286+
this.model.on('rosterContactAdded', () => {
52287+
this.model.contact.on('change:nickname', this.debouncedRender, this);
52288+
this.debouncedRender();
52289+
});
5227852290
this.model.on('change', this.onChanged, this);
5227952291
this.model.on('destroy', this.remove, this);
5228052292
},
@@ -52316,7 +52328,7 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_1__["default"].plugins
5231652328
}
5231752329

5231852330
if (_.filter(['correcting', 'message', 'type', 'upload', 'received'], prop => Object.prototype.hasOwnProperty.call(this.model.changed, prop)).length) {
52319-
await this.render();
52331+
await this.debouncedRender();
5232052332
}
5232152333

5232252334
if (edited) {
@@ -60201,7 +60213,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_4__["default"].plugins
6020160213
},
6020260214

6020360215
onContactChange(contact) {
60204-
this.updateChatBox(contact);
6020560216
this.update();
6020660217

6020760218
if (_.has(contact.changed, 'subscription')) {
@@ -60223,21 +60234,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_4__["default"].plugins
6022360234
this.updateFilter();
6022460235
},
6022560236

60226-
updateChatBox(contact) {
60227-
if (!this.model.chatbox) {
60228-
return this;
60229-
}
60230-
60231-
const changes = {};
60232-
60233-
if (_.has(contact.changed, 'status')) {
60234-
changes.status = contact.get('status');
60235-
}
60236-
60237-
this.model.chatbox.save(changes);
60238-
return this;
60239-
},
60240-
6024160237
getGroup(name) {
6024260238
/* Returns the group as specified by name.
6024360239
* Creates the group if it doesn't exist.
@@ -61771,7 +61767,20 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
6177161767

6177261768
_converse.router.route('converse/chat?jid=:jid', openChat);
6177361769

61774-
_converse.Message = Backbone.Model.extend({
61770+
const ModelWithContact = Backbone.Model.extend({
61771+
async setRosterContact(jid) {
61772+
await _converse.api.waitUntil('rosterContactsFetched');
61773+
61774+
const contact = _converse.roster.get(jid);
61775+
61776+
if (contact) {
61777+
this.contact = contact;
61778+
this.trigger('rosterContactAdded');
61779+
}
61780+
}
61781+
61782+
});
61783+
_converse.Message = ModelWithContact.extend({
6177561784
defaults() {
6177661785
return {
6177761786
'msgid': _converse.connection.getUniqueId(),
@@ -61782,6 +61791,10 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
6178261791
initialize() {
6178361792
this.setVCard();
6178461793

61794+
if (this.get('type') === 'chat') {
61795+
this.setRosterContact(Strophe.getBareJidFromJid(this.get('from')));
61796+
}
61797+
6178561798
if (this.get('file')) {
6178661799
this.on('change:put', this.uploadFile, this);
6178761800
}
@@ -61857,7 +61870,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
6185761870
if (this.get('type') === 'groupchat') {
6185861871
return this.get('nick');
6185961872
} else {
61860-
return this.vcard.get('fullname') || this.get('from');
61873+
if (this.contact) {
61874+
return this.contact.getDisplayName();
61875+
}
61876+
61877+
return this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('from');
6186161878
}
6186261879
},
6186361880

@@ -61971,7 +61988,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
6197161988
* @memberOf _converse
6197261989
*/
6197361990

61974-
_converse.ChatBox = Backbone.Model.extend({
61991+
_converse.ChatBox = ModelWithContact.extend({
6197561992
defaults() {
6197661993
return {
6197761994
'bookmarked': false,
@@ -62012,6 +62029,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
6201262029
}) || _converse.presences.create({
6201362030
'jid': jid
6201462031
});
62032+
62033+
if (this.get('type') === _converse.PRIVATE_CHAT_TYPE) {
62034+
this.setRosterContact(jid);
62035+
}
62036+
6201562037
this.messages = new _converse.Messages();
6201662038

6201762039
const storage = _converse.config.get('storage');
@@ -62045,7 +62067,11 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha
6204562067
},
6204662068

6204762069
getDisplayName() {
62048-
return this.vcard.get('fullname') || this.get('jid');
62070+
if (this.contact) {
62071+
return this.contact.getDisplayName();
62072+
}
62073+
62074+
return this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid');
6204962075
},
6205062076

6205162077
getUpdatedMessageAttributes(message, stanza) {
@@ -68833,7 +68859,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
6883368859
'jid': bare_jid,
6883468860
'user_id': Strophe.getNodeFromJid(jid)
6883568861
}, attributes));
68836-
this.setChatBox();
6883768862
/**
6883868863
* When a contact's presence status has changed.
6883968864
* 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
6884668871
this.presence.on('change:show', () => this.trigger('presenceChanged'));
6884768872
},
6884868873

68849-
setChatBox() {
68850-
let chatbox = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
68851-
chatbox = chatbox || _converse.chatboxes.get(this.get('jid'));
68852-
68853-
if (chatbox) {
68854-
this.chatbox = chatbox;
68855-
this.chatbox.on('change:hidden', this.render, this);
68856-
}
68857-
},
68858-
6885968874
getDisplayName() {
6886068875
return this.get('nickname') || this.vcard.get('nickname') || this.vcard.get('fullname') || this.get('jid');
6886168876
},
@@ -93010,7 +93025,7 @@ __e(o.url) +
9301093025
'" target="_blank" rel="noopener" class="user">\n ';
9301193026
} ;
9301293027
__p += '\n ' +
93013-
__e( o.nickname || o.fullname || o.jid ) +
93028+
__e( o.display_name ) +
9301493029
'\n ';
9301593030
if (o.url) { ;
9301693031
__p += '\n </a>\n ';

spec/messages.js

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@
9999
expect(textarea.value).toBe('');
100100
expect(view.model.messages.at(0).get('correcting')).toBe(false);
101101
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
102-
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false);
102+
await test_utils.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
103103

104104
// Test that messages from other users don't have the pencil icon
105105
_converse.chatboxes.onMessage(
@@ -154,7 +154,7 @@
154154
expect(textarea.value).toBe('But soft, what light through yonder airlock breaks?');
155155
expect(view.model.messages.at(0).get('correcting')).toBe(true);
156156
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
157-
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')));
157+
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
158158

159159
spyOn(_converse.connection, 'send');
160160
textarea.value = 'But soft, what light through yonder window breaks?';
@@ -185,7 +185,7 @@
185185
expect(corrected_message.get('older_versions')[0]).toBe('But soft, what light through yonder airlock breaks?');
186186

187187
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
188-
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false);
188+
await test_utils.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
189189

190190
// Test that pressing the down arrow cancels message correction
191191
expect(textarea.value).toBe('');
@@ -196,7 +196,7 @@
196196
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
197197
expect(view.model.messages.at(0).get('correcting')).toBe(true);
198198
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
199-
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === true);
199+
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
200200
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
201201
view.keyPressed({
202202
target: textarea,
@@ -205,7 +205,7 @@
205205
expect(textarea.value).toBe('');
206206
expect(view.model.messages.at(0).get('correcting')).toBe(false);
207207
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
208-
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false);
208+
await test_utils.waitUntil(() => (u.hasClass('correcting', view.el.querySelector('.chat-msg')) === false), 500);
209209

210210
textarea.value = 'It is the east, and Juliet is the one.';
211211
view.keyPressed({
@@ -233,7 +233,7 @@
233233
expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
234234
expect(view.model.messages.at(1).get('correcting')).toBeFalsy();
235235
expect(view.model.messages.at(2).get('correcting')).toBe(true);
236-
await test_utils.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg:last', view.el).pop()));
236+
await test_utils.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg:last', view.el).pop()), 500);
237237

238238
textarea.selectionEnd = 0; // Happens by pressing up,
239239
// but for some reason not in tests, so we set it manually.
@@ -245,7 +245,7 @@
245245
expect(view.model.messages.at(0).get('correcting')).toBeFalsy();
246246
expect(view.model.messages.at(1).get('correcting')).toBe(true);
247247
expect(view.model.messages.at(2).get('correcting')).toBeFalsy();
248-
await test_utils.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg', view.el)[1]));
248+
await test_utils.waitUntil(() => u.hasClass('correcting', sizzle('.chat-msg', view.el)[1]), 500);
249249

250250
textarea.value = 'It is the east, and Juliet is the sun.';
251251
view.keyPressed({
@@ -2335,7 +2335,7 @@
23352335
}).c('body').t('But soft, what light through yonder chimney breaks?').up()
23362336
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
23372337
await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
2338-
'But soft, what light through yonder chimney breaks?');
2338+
'But soft, what light through yonder chimney breaks?', 500);
23392339
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
23402340
expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1);
23412341

@@ -2348,7 +2348,7 @@
23482348
.c('replace', {'id': msg_id, 'xmlns': 'urn:xmpp:message-correct:0'}).tree());
23492349

23502350
await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
2351-
'But soft, what light through yonder window breaks?');
2351+
'But soft, what light through yonder window breaks?', 500);
23522352
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
23532353
expect(view.el.querySelectorAll('.chat-msg__content .fa-edit').length).toBe(1);
23542354
view.el.querySelector('.chat-msg__content .fa-edit').click();
@@ -2451,7 +2451,7 @@
24512451
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
24522452
expect(view.model.messages.at(0).get('correcting')).toBe(true);
24532453
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
2454-
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')));
2454+
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
24552455
expect(textarea.value).toBe('But soft, what light through yonder window breaks?');
24562456
view.keyPressed({
24572457
target: textarea,
@@ -2460,7 +2460,7 @@
24602460
expect(textarea.value).toBe('');
24612461
expect(view.model.messages.at(0).get('correcting')).toBe(false);
24622462
expect(view.el.querySelectorAll('.chat-msg').length).toBe(2);
2463-
await test_utils.waitUntil(() => !u.hasClass('correcting', view.el.querySelector('.chat-msg')));
2463+
await test_utils.waitUntil(() => !u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
24642464
done();
24652465
}));
24662466

@@ -2493,7 +2493,7 @@
24932493
<origin-id xmlns="urn:xmpp:sid:0" id="${msg_obj.get('origin_id')}"/>
24942494
</message>`);
24952495
await view.model.onMessage(stanza);
2496-
await test_utils.waitUntil(() => view.el.querySelectorAll('.chat-msg__receipt').length);
2496+
await test_utils.waitUntil(() => view.el.querySelectorAll('.chat-msg__receipt').length, 500);
24972497
expect(view.el.querySelectorAll('.chat-msg__receipt').length).toBe(1);
24982498
expect(view.model.messages.length).toBe(1);
24992499

@@ -2854,10 +2854,12 @@
28542854
expect(textarea.value).toBe('hello @z3r0 @gibson @mr.robot, how are you?');
28552855
expect(view.model.messages.at(0).get('correcting')).toBe(true);
28562856
expect(view.el.querySelectorAll('.chat-msg').length).toBe(1);
2857-
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')));
2857+
await test_utils.waitUntil(() => u.hasClass('correcting', view.el.querySelector('.chat-msg')), 500);
28582858

28592859
textarea.value = 'hello @z3r0 @gibson @sw0rdf1sh, how are you?';
28602860
view.keyPressed(enter_event);
2861+
await test_utils.waitUntil(() => view.el.querySelector('.chat-msg__text').textContent ===
2862+
'hello z3r0 gibson sw0rdf1sh, how are you?', 500);
28612863

28622864
const correction = _converse.connection.send.calls.all()[1].args[0];
28632865
expect(correction.toLocaleString())
@@ -2866,9 +2868,9 @@
28662868
`xmlns="jabber:client">`+
28672869
`<body>hello z3r0 gibson sw0rdf1sh, how are you?</body>`+
28682870
`<active xmlns="http://jabber.org/protocol/chatstates"/>`+
2869-
`<reference begin="18" end="27" type="mention" uri="xmpp:sw0rdf1sh@localhost" xmlns="urn:xmpp:reference:0"/>`+
2870-
`<reference begin="11" end="17" type="mention" uri="xmpp:gibson@localhost" xmlns="urn:xmpp:reference:0"/>`+
28712871
`<reference begin="6" end="10" type="mention" uri="xmpp:z3r0@localhost" xmlns="urn:xmpp:reference:0"/>`+
2872+
`<reference begin="11" end="17" type="mention" uri="xmpp:gibson@localhost" xmlns="urn:xmpp:reference:0"/>`+
2873+
`<reference begin="18" end="27" type="mention" uri="xmpp:sw0rdf1sh@localhost" xmlns="urn:xmpp:reference:0"/>`+
28722874
`<replace id="${msg.nodeTree.getAttribute("id")}" xmlns="urn:xmpp:message-correct:0"/>`+
28732875
`<origin-id id="${msg.nodeTree.querySelector('origin-id').getAttribute("id")}" xmlns="urn:xmpp:sid:0"/>`+
28742876
`</message>`);

spec/minchats.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(function (root, factory) {
2-
define(["jquery", "jasmine", "mock", "test-utils"], factory);
3-
} (this, function ($, jasmine, mock, test_utils) {
2+
define(["jasmine", "mock", "test-utils"], factory);
3+
} (this, function (jasmine, mock, test_utils) {
44
const _ = converse.env._;
55
const $msg = converse.env.$msg;
66
const u = converse.env.utils;

src/converse-chatboxviews.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ converse.plugins.add('converse-chatboxviews', {
4747

4848
initStatus: function (reconnecting) {
4949
const { _converse } = this.__super__;
50-
if (!reconnecting) {
50+
if (!reconnecting && _converse.chatboxviews) {
5151
_converse.chatboxviews.closeAllChatBoxes();
5252
}
5353
return this.__super__.initStatus.apply(this, arguments);

0 commit comments

Comments
 (0)