From a6aaf3f5954351efa8b7a738623b0e62c9c0a51d Mon Sep 17 00:00:00 2001 From: Lance Stout Date: Wed, 26 Feb 2020 17:42:09 -0800 Subject: [PATCH] Update chat state notifications when message is edited. --- CHANGES.md | 1 + spec/chatbox.js | 62 +++++++++++++++++++++++++++++++++++++++ src/converse-chatview.js | 24 +++++++++++++-- src/converse-muc-views.js | 1 + 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 7ce4fca18..1d8c86d5b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -4,6 +4,7 @@ - #1313: Stylistic improvements to the send button - #1535: Add option to destroy a MUC +- #1715: Update chat state notification after receiving a message correction. - #1793: Send button doesn't appear in Firefox in 1:1 chats - #1820: Set focus on jid field after controlbox is loaded - #1822: Don't log error if user has no bookmarks diff --git a/spec/chatbox.js b/spec/chatbox.js index b470adfd0..23abb39dd 100644 --- a/spec/chatbox.js +++ b/spec/chatbox.js @@ -1057,6 +1057,68 @@ done(); })); }); + + describe("On receiving a message correction", function () { + it("will be updated", + mock.initConverse( + ['rosterGroupsFetched'], {}, + async function (done, _converse) { + + await test_utils.waitForRoster(_converse, 'current'); + await test_utils.openControlBox(_converse); + + // See XEP-0085 https://xmpp.org/extensions/xep-0085.html#definitions + const sender_jid = mock.cur_names[1].replace(/ /g,'.').toLowerCase() + '@montague.lit'; + await u.waitUntil(() => _converse.rosterview.el.querySelectorAll('.roster-group').length); + await test_utils.openChatBoxFor(_converse, sender_jid); + + // Original message + const original_id = u.getUniqueId(); + const original = $msg({ + from: sender_jid, + to: _converse.connection.jid, + type: 'chat', + id: original_id, + body: "Original message", + }).c('active', {'xmlns': Strophe.NS.CHATSTATES}).tree(); + + spyOn(_converse.api, "trigger").and.callThrough(); + _converse.connection._dataRecv(test_utils.createRequest(original)); + await u.waitUntil(() => _converse.api.trigger.calls.count()); + expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object)); + const view = _converse.chatboxviews.get(sender_jid); + expect(view).toBeDefined(); + + // state + const msg = $msg({ + from: sender_jid, + to: _converse.connection.jid, + type: 'chat', + id: u.getUniqueId() + }).c('composing', {'xmlns': Strophe.NS.CHATSTATES}).tree(); + + await _converse.handleMessageStanza(msg); + const event = await u.waitUntil(() => view.el.querySelector('.chat-state-notification')); + expect(event.textContent).toEqual(mock.cur_names[1] + ' is typing'); + + // Edited message + const edited = $msg({ + from: sender_jid, + to: _converse.connection.jid, + type: 'chat', + id: u.getUniqueId(), + body: "Edited message", + }) + .c('active', {'xmlns': Strophe.NS.CHATSTATES}).up() + .c('replace', {'xmlns': Strophe.NS.MESSAGE_CORRECT, 'id': original_id }).tree(); + + await _converse.handleMessageStanza(edited); + + const events = view.el.querySelectorAll('.chat-state-notification'); + expect(events.length).toBe(0); + done(); + })); + }); }); }); diff --git a/src/converse-chatview.js b/src/converse-chatview.js index 68e87dbfd..475d18bf0 100644 --- a/src/converse-chatview.js +++ b/src/converse-chatview.js @@ -196,6 +196,7 @@ converse.plugins.add('converse-chatview', { this.initDebounced(); this.listenTo(this.model.messages, 'add', this.onMessageAdded); + this.listenTo(this.model.messages, 'change:edited', this.onMessageEdited); this.listenTo(this.model.messages, 'rendered', this.scrollDown); this.model.messages.on('reset', () => { this.content.innerHTML = ''; @@ -724,8 +725,7 @@ converse.plugins.add('converse-chatview', { await message.initialized; const view = this.add(message.get('id'), new _converse.MessageView({'model': message})); await view.render(); - // Clear chat state notifications - sizzle(`.chat-state-notification[data-csn="${message.get('from')}"]`, this.content).forEach(u.removeElement); + this.clearChatStateForSender(message.get('from')); this.insertMessage(view); this.insertDayIndicator(view.el); this.setScrollPosition(view.el); @@ -780,6 +780,16 @@ converse.plugins.add('converse-chatview', { }); }, + /** + * Handler that gets called when a message object has been edited via LMC. + * @private + * @method _converse.ChatBoxView#onMessageEdited + * @param { object } message - The updated message object. + */ + onMessageEdited (message) { + this.clearChatStateForSender(message.get('from')); + }, + parseMessageForCommands (text) { const match = text.replace(/^\s*/, "").match(/^\/(.*)\s*$/); if (match) { @@ -1072,6 +1082,16 @@ converse.plugins.add('converse-chatview', { return this; }, + /** + * Remove chat state notifications for a given sender JID. + * @private + * @method _converse.ChatBoxView#clearChatStateForSender + * @param {string} sender - The sender of the chat state + */ + clearChatStateForSender (sender) { + sizzle(`.chat-state-notification[data-csn="${sender}"]`, this.content).forEach(u.removeElement); + }, + /** * Insert a particular string value into the textarea of this chat box. * @private diff --git a/src/converse-muc-views.js b/src/converse-muc-views.js index c892aa3ef..8b3000999 100644 --- a/src/converse-muc-views.js +++ b/src/converse-muc-views.js @@ -700,6 +700,7 @@ converse.plugins.add('converse-muc-views', { this.initDebounced(); this.listenTo(this.model.messages, 'add', this.onMessageAdded); + this.listenTo(this.model.messages, 'change:edited', this.onMessageEdited); this.listenTo(this.model.messages, 'rendered', this.scrollDown); this.model.messages.on('reset', () => { this.content.innerHTML = '';