Change when/how chats are shown

Goal is to fix a timing bug that results in `show` being triggered
before the `ChatBoxView` has been initialized, which means that 1:1
chats aren't opened when you reload the page.
This commit is contained in:
JC Brand 2020-02-02 15:38:37 +01:00
parent da493430f8
commit 39d140005e
8 changed files with 23 additions and 18 deletions

View File

@ -1228,9 +1228,7 @@
const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit';
const msg_id = u.getUniqueId(); const msg_id = u.getUniqueId();
const sent_stanzas = []; const sent_stanzas = [];
spyOn(_converse.connection, 'send').and.callFake(function (stanza) { spyOn(_converse.connection, 'send').and.callFake(stanza => sent_stanzas.push(stanza));
sent_stanzas.push(stanza);
});
const msg = $msg({ const msg = $msg({
'from': sender_jid, 'from': sender_jid,
'to': _converse.connection.jid, 'to': _converse.connection.jid,
@ -1240,8 +1238,9 @@
.c('request', {'xmlns': Strophe.NS.RECEIPTS}).tree(); .c('request', {'xmlns': Strophe.NS.RECEIPTS}).tree();
await _converse.handleMessageStanza(msg); await _converse.handleMessageStanza(msg);
const sent_messages = sent_stanzas.map(s => _.isElement(s) ? s : s.nodeTree).filter(s => s.nodeName === 'message'); const sent_messages = sent_stanzas.map(s => _.isElement(s) ? s : s.nodeTree).filter(s => s.nodeName === 'message');
expect(sent_messages.length).toBe(1); // A chat state message is also included
const receipt = sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, sent_messages[0]).pop(); expect(sent_messages.length).toBe(2);
const receipt = sizzle(`received[xmlns="${Strophe.NS.RECEIPTS}"]`, sent_messages[1]).pop();
expect(Strophe.serialize(receipt)).toBe(`<received id="${msg_id}" xmlns="${Strophe.NS.RECEIPTS}"/>`); expect(Strophe.serialize(receipt)).toBe(`<received id="${msg_id}" xmlns="${Strophe.NS.RECEIPTS}"/>`);
done(); done();
})); }));
@ -2116,7 +2115,15 @@
const sent_messages = sent_stanzas const sent_messages = sent_stanzas
.map(s => _.isElement(s) ? s : s.nodeTree) .map(s => _.isElement(s) ? s : s.nodeTree)
.filter(e => e.nodeName === 'message'); .filter(e => e.nodeName === 'message');
expect(sent_messages.length).toBe(0);
expect(sent_messages.length).toBe(1);
expect(Strophe.serialize(sent_messages[0])).toBe(
`<message id="${sent_messages[0].getAttribute('id')}" to="${contact_jid}" type="chat" xmlns="jabber:client">`+
`<active xmlns="http://jabber.org/protocol/chatstates"/>`+
`<no-store xmlns="urn:xmpp:hints"/>`+
`<no-permanent-store xmlns="urn:xmpp:hints"/>`+
`</message>`
);
done(); done();
})); }));

View File

@ -116,7 +116,7 @@
}, async function (done, _converse) { }, async function (done, _converse) {
const muc_jid = 'coven@chat.shakespeare.lit'; const muc_jid = 'coven@chat.shakespeare.lit';
await _converse.api.rooms.open(muc_jid, {'nick': 'some1'}); await _converse.api.rooms.open(muc_jid, {'nick': 'some1'}, true);
const lview = _converse.rooms_list_view const lview = _converse.rooms_list_view
await u.waitUntil(() => lview.el.querySelectorAll(".open-room").length); await u.waitUntil(() => lview.el.querySelectorAll(".open-room").length);
let room_els = lview.el.querySelectorAll(".available-chatroom"); let room_els = lview.el.querySelectorAll(".available-chatroom");
@ -126,7 +126,7 @@
await u.waitUntil(() => lview.model.get(muc_jid).get('hidden') === false); await u.waitUntil(() => lview.model.get(muc_jid).get('hidden') === false);
await u.waitUntil(() => u.hasClass('open', item), 1000); await u.waitUntil(() => u.hasClass('open', item), 1000);
expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit'); expect(item.textContent.trim()).toBe('coven@chat.shakespeare.lit');
await _converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'}); await _converse.api.rooms.open('balcony@chat.shakespeare.lit', {'nick': 'some1'}, true);
await u.waitUntil(() => lview.el.querySelectorAll(".open-room").length > 1); await u.waitUntil(() => lview.el.querySelectorAll(".open-room").length > 1);
room_els = lview.el.querySelectorAll(".open-room"); room_els = lview.el.querySelectorAll(".open-room");
expect(room_els.length).toBe(2); expect(room_els.length).toBe(2);

View File

@ -72,6 +72,7 @@
_converse.connection._dataRecv(test_utils.createRequest(msg)); _converse.connection._dataRecv(test_utils.createRequest(msg));
await new Promise(resolve => _converse.api.listen.once('chatBoxViewInitialized', resolve)); await new Promise(resolve => _converse.api.listen.once('chatBoxViewInitialized', resolve));
const view = _converse.chatboxviews.get(sender_jid); const view = _converse.chatboxviews.get(sender_jid);
await new Promise(resolve => view.model.messages.once('rendered', resolve));
await u.waitUntil(() => u.isVisible(view.el)); await u.waitUntil(() => u.isVisible(view.el));
await u.waitUntil(() => view.model.vcard.get('fullname') === 'Mercutio') await u.waitUntil(() => view.model.vcard.get('fullname') === 'Mercutio')
expect(view.el.querySelector('.chat-msg__author').textContent.includes('Mercutio')).toBeTruthy(); expect(view.el.querySelector('.chat-msg__author').textContent.includes('Mercutio')).toBeTruthy();

View File

@ -220,6 +220,7 @@ converse.plugins.add('converse-chatview', {
this.listenTo(this.model.presence, 'change:show', this.onPresenceChanged); this.listenTo(this.model.presence, 'change:show', this.onPresenceChanged);
this.render(); this.render();
await this.updateAfterMessagesFetched(); await this.updateAfterMessagesFetched();
this.model.maybeShow();
/** /**
* Triggered once the {@link _converse.ChatBoxView} has been initialized * Triggered once the {@link _converse.ChatBoxView} has been initialized
* @event _converse#chatBoxViewInitialized * @event _converse#chatBoxViewInitialized

View File

@ -142,6 +142,7 @@ converse.plugins.add('converse-headlines-view', {
this.renderHeading(); this.renderHeading();
this.updateAfterMessagesFetched(); this.updateAfterMessagesFetched();
this.insertIntoDOM().hide(); this.insertIntoDOM().hide();
this.model.maybeShow();
/** /**
* Triggered once the {@link _converse.HeadlinesBoxView} has been initialized * Triggered once the {@link _converse.HeadlinesBoxView} has been initialized
* @event _converse#headlinesBoxViewInitialized * @event _converse#headlinesBoxViewInitialized

View File

@ -702,6 +702,7 @@ converse.plugins.add('converse-muc-views', {
this.createSidebarView(); this.createSidebarView();
await this.updateAfterMessagesFetched(); await this.updateAfterMessagesFetched();
this.onConnectionStatusChanged(); this.onConnectionStatusChanged();
this.model.maybeShow();
/** /**
* Triggered once a { @link _converse.ChatRoomView } has been opened * Triggered once a { @link _converse.ChatRoomView } has been opened
* @event _converse#chatRoomViewInitialized * @event _converse#chatRoomViewInitialized

View File

@ -22,11 +22,6 @@ function hideChat (view) {
view.hide(); view.hide();
} }
function visibleChats (_converse) {
return _converse.chatboxes
.filter(cb => (cb.get('id') !== 'controlbox' && !cb.get('hidden'))).length > 0;
}
converse.plugins.add('converse-uniview', { converse.plugins.add('converse-uniview', {
// It's possible however to make optional dependencies non-optional. // It's possible however to make optional dependencies non-optional.
@ -53,10 +48,11 @@ converse.plugins.add('converse-uniview', {
}, },
ChatBox: { ChatBox: {
maybeShow () { maybeShow (force) {
force && u.safeSave(this, {'hidden': false});
const { _converse } = this.__super__; const { _converse } = this.__super__;
if (_converse.isUniView() && (!this.get('hidden') || !visibleChats(_converse))) { if (_converse.isUniView() && this.get('hidden')) {
return this.trigger("show"); return;
} else { } else {
return this.__super__.maybeShow.apply(this, arguments); return this.__super__.maybeShow.apply(this, arguments);
} }

View File

@ -68,9 +68,7 @@ converse.plugins.add('converse-chatboxes', {
}, },
onChatBoxesFetched (collection) { onChatBoxesFetched (collection) {
/* Show chat boxes upon receiving them from storage */
collection.filter(c => !c.isValid()).forEach(c => c.destroy()); collection.filter(c => !c.isValid()).forEach(c => c.destroy());
collection.forEach(c => c.maybeShow());
/** /**
* Triggered when a message stanza is been received and processed. * Triggered when a message stanza is been received and processed.
* @event _converse#chatBoxesFetched * @event _converse#chatBoxesFetched