From 9fb92080f2ba43bfa88c18f95833ec5a51e7e6ad Mon Sep 17 00:00:00 2001 From: JC Brand Date: Mon, 14 Jun 2021 15:44:50 +0200 Subject: [PATCH] Get rid of the APIs to fetch chat views This is largely a leftover from the Backbone.View days and makes less sense now that the UI is componentized. Ideally we don't want to call commands on the "views themselves, instead we should be working on the the models and let the "views" update themselves automatically. Also, given that the `jid` attribute on the chat views might change, especially when rendered declaratively in other frameworks like React, a view might not be available at times where we previously might have expected it to be (since it's been repurposed for a different JID). --- CHANGES.md | 4 ++ karma.conf.js | 2 +- src/plugins/chatboxviews/index.js | 4 -- src/plugins/chatview/api.js | 35 ---------- src/plugins/chatview/{view.js => chat.js} | 0 src/plugins/chatview/index.js | 8 +-- src/plugins/chatview/tests/corrections.js | 4 +- src/plugins/chatview/tests/emojis.js | 6 +- src/plugins/chatview/tests/markers.js | 65 +---------------- src/plugins/chatview/tests/message-images.js | 10 +-- src/plugins/chatview/tests/messages.js | 34 ++++----- src/plugins/chatview/tests/spoilers.js | 4 +- src/plugins/chatview/tests/xss.js | 8 +-- src/plugins/minimize/tests/minchats.js | 2 +- src/plugins/muc-views/api.js | 69 ------------------- src/plugins/muc-views/index.js | 3 - src/plugins/muc-views/tests/corrections.js | 6 +- src/plugins/muc-views/tests/markers.js | 69 +++++++++++++++++++ src/plugins/muc-views/tests/mentions.js | 20 +++--- src/plugins/muc-views/tests/muc-api.js | 20 ++++-- src/plugins/muc-views/tests/muc-messages.js | 28 ++++---- src/plugins/muc-views/tests/muc.js | 24 +++---- src/plugins/muc-views/tests/rai.js | 4 +- src/plugins/muc-views/tests/retractions.js | 24 +++---- src/plugins/muc-views/tests/styling.js | 4 +- src/plugins/muc-views/tests/unfurls.js | 16 ++--- .../notifications/tests/notification.js | 4 +- src/shared/chat/baseview.js | 1 + src/shared/chat/tests/styling.js | 12 ++-- 29 files changed, 199 insertions(+), 291 deletions(-) delete mode 100644 src/plugins/chatview/api.js rename src/plugins/chatview/{view.js => chat.js} (100%) delete mode 100644 src/plugins/muc-views/api.js create mode 100644 src/plugins/muc-views/tests/markers.js diff --git a/CHANGES.md b/CHANGES.md index 285f2fb54..1e09a3645 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -42,6 +42,10 @@ Removed events: The `chatBoxClosed`, `chatBoxMaximized` and `chatBoxMinimized` events now have the `model` as payload and not the `view`. +The `api.chatviews` and `api.roomviews` API groupings and methods have been +removed. The original "views" don't really exist anymore, the UI is now composed web +components which should update reactively based on changes made on the models. + ## 7.0.6 (unreleased) - #2500: Wrong assignment in OMEMO code diff --git a/karma.conf.js b/karma.conf.js index a0debd2df..5a58e332e 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -41,7 +41,6 @@ module.exports = function(config) { { pattern: "src/headless/tests/persistence.js", type: 'module' }, { pattern: "src/plugins/bookmark-views/tests/bookmarks.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/chatbox.js", type: 'module' }, - { pattern: "src/plugins/chatview/tests/emojis.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/corrections.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/emojis.js", type: 'module' }, { pattern: "src/plugins/chatview/tests/http-file-upload.js", type: 'module' }, @@ -63,6 +62,7 @@ module.exports = function(config) { { pattern: "src/plugins/muc-views/tests/emojis.js", type: 'module' }, { pattern: "src/plugins/muc-views/tests/hats.js", type: 'module' }, { pattern: "src/plugins/muc-views/tests/http-file-upload.js", type: 'module' }, + { pattern: "src/plugins/muc-views/tests/markers.js", type: 'module' }, { pattern: "src/plugins/muc-views/tests/mentions.js", type: 'module' }, { pattern: "src/plugins/muc-views/tests/modtools.js", type: 'module' }, { pattern: "src/plugins/muc-views/tests/muc-api.js", type: 'module' }, diff --git a/src/plugins/chatboxviews/index.js b/src/plugins/chatboxviews/index.js index 92eb18cf8..4a516b54f 100644 --- a/src/plugins/chatboxviews/index.js +++ b/src/plugins/chatboxviews/index.js @@ -65,10 +65,6 @@ converse.plugins.add('converse-chatboxviews', { const el = _converse.chatboxviews?.el; if (el && !container.contains(el)) { container.insertAdjacentElement('afterBegin', el); - api.chatviews - .get() - .filter(v => v.model.get('id') !== 'controlbox') - .forEach(v => v.maintainScrollTop()); } else if (!el) { throw new Error('Cannot insert non-existing #conversejs element into the DOM'); } diff --git a/src/plugins/chatview/api.js b/src/plugins/chatview/api.js deleted file mode 100644 index 540a33fa1..000000000 --- a/src/plugins/chatview/api.js +++ /dev/null @@ -1,35 +0,0 @@ -import { _converse } from '@converse/headless/core'; - - -export default { - /** - * The "chatview" namespace groups methods pertaining to views - * for one-on-one chats. - * - * @namespace _converse.api.chatviews - * @memberOf _converse.api - */ - chatviews: { - /** - * Get the view of an already open chat. - * @method _converse.api.chatviews.get - * @param { Array.string | string } jids - * @returns { _converse.ChatBoxView|undefined } The chat should already be open, otherwise `undefined` will be returned. - * @example - * // To return a single view, provide the JID of the contact: - * _converse.api.chatviews.get('buddy@example.com') - * @example - * // To return an array of views, provide an array of JIDs: - * _converse.api.chatviews.get(['buddy1@example.com', 'buddy2@example.com']) - */ - get (jids) { - if (jids === undefined) { - return Object.values(_converse.chatboxviews.getAll()); - } - if (typeof jids === 'string') { - return _converse.chatboxviews.get(jids); - } - return jids.map(jid => _converse.chatboxviews.get(jid)); - } - } -} diff --git a/src/plugins/chatview/view.js b/src/plugins/chatview/chat.js similarity index 100% rename from src/plugins/chatview/view.js rename to src/plugins/chatview/chat.js diff --git a/src/plugins/chatview/index.js b/src/plugins/chatview/index.js index 5cb3f6a8c..e983cc07f 100644 --- a/src/plugins/chatview/index.js +++ b/src/plugins/chatview/index.js @@ -1,5 +1,4 @@ /** - * @module converse-chatview * @copyright 2020, the Converse.js contributors * @license Mozilla Public License (MPLv2) */ @@ -8,8 +7,7 @@ import '../modal.js'; import 'shared/chat/chat-content.js'; import 'shared/chat/help-messages.js'; import 'shared/chat/toolbar.js'; -import ChatBoxView from './view.js'; -import chatview_api from './api.js'; +import ChatView from './chat.js'; import { _converse, api, converse } from '@converse/headless/core'; import './styles/index.scss'; @@ -56,9 +54,7 @@ converse.plugins.add('converse-chatview', { } }); - Object.assign(api, chatview_api); - - _converse.ChatBoxView = ChatBoxView; + _converse.ChatBoxView = ChatView; api.listen.on('connected', () => api.disco.own.features.add(Strophe.NS.SPOILER)); } diff --git a/src/plugins/chatview/tests/corrections.js b/src/plugins/chatview/tests/corrections.js index 416bd1773..ab36dc1fd 100644 --- a/src/plugins/chatview/tests/corrections.js +++ b/src/plugins/chatview/tests/corrections.js @@ -11,7 +11,7 @@ describe("A Chat Message", function () { await mock.openControlBox(_converse); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); const textarea = view.querySelector('textarea.chat-textarea'); expect(textarea.value).toBe(''); const message_form = view.querySelector('converse-message-form'); @@ -172,7 +172,7 @@ describe("A Chat Message", function () { await mock.openControlBox(_converse); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); const textarea = view.querySelector('textarea.chat-textarea'); textarea.value = 'But soft, what light through yonder airlock breaks?'; diff --git a/src/plugins/chatview/tests/emojis.js b/src/plugins/chatview/tests/emojis.js index 26d4d3e38..f100643e3 100644 --- a/src/plugins/chatview/tests/emojis.js +++ b/src/plugins/chatview/tests/emojis.js @@ -44,7 +44,7 @@ describe("Emojis", function () { }).c('body').t('😇').up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); await new Promise(resolve => _converse.on('chatBoxViewInitialized', resolve)); - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length); await u.waitUntil(() => u.hasClass('chat-msg__text--larger', view.querySelector('.chat-msg__text'))); @@ -132,7 +132,7 @@ describe("Emojis", function () { }).c('body').t('😇').up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); await new Promise(resolve => _converse.on('chatBoxViewInitialized', resolve)); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); await new Promise(resolve => view.model.messages.once('rendered', resolve)); await u.waitUntil(() => view.querySelector('.chat-msg__text').innerHTML.replace(//g, '') === '😇'); @@ -186,7 +186,7 @@ describe("Emojis", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); const toolbar = await u.waitUntil(() => view.querySelector('.chat-toolbar')); toolbar.querySelector('.toggle-emojis').click(); diff --git a/src/plugins/chatview/tests/markers.js b/src/plugins/chatview/tests/markers.js index 4acf4499b..31f985fc0 100644 --- a/src/plugins/chatview/tests/markers.js +++ b/src/plugins/chatview/tests/markers.js @@ -77,7 +77,7 @@ describe("A XEP-0333 Chat Marker", function () { const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); let stanza = u.toStanza(` view.querySelector('.chat-textarea')); - textarea.value = 'But soft, what light through yonder airlock breaks?'; - const message_form = view.querySelector('converse-muc-message-form'); - message_form.onKeyDown({ - target: textarea, - preventDefault: function preventDefault () {}, - keyCode: 13 // Enter - }); - await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length); - expect(view.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.querySelector('.chat-msg .chat-msg__text').textContent.trim()) - .toBe("But soft, what light through yonder airlock breaks?"); - - const msg_obj = view.model.messages.at(0); - let stanza = u.toStanza(` - - - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 1); - expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0); - - stanza = u.toStanza(` - - - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - expect(view.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0); - - stanza = u.toStanza(` - - - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - - expect(view.querySelectorAll('.chat-msg').length).toBe(1); - expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0); - - stanza = u.toStanza(` - - 'tis I! - - - `); - _converse.connection._dataRecv(mock.createRequest(stanza)); - await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 2); - expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0); - done(); - })); }); diff --git a/src/plugins/chatview/tests/message-images.js b/src/plugins/chatview/tests/message-images.js index 3b8ec9d2f..d997a22c0 100644 --- a/src/plugins/chatview/tests/message-images.js +++ b/src/plugins/chatview/tests/message-images.js @@ -10,7 +10,7 @@ describe("A Chat Message", function () { let message = base_url+"/logo/conversejs-filled.svg"; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); await mock.sendMessage(view, message); await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-image').length, 1000) @@ -62,7 +62,7 @@ describe("A Chat Message", function () { let message = 'https://imgur.com/oxymPax.png'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); await mock.sendMessage(view, message); await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-msg').length === 1); @@ -85,7 +85,7 @@ describe("A Chat Message", function () { const message = base_url+"/logo/non-existing.svg"; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); await mock.sendMessage(view, message); await u.waitUntil(() => view.querySelectorAll('.chat-content .chat-image').length, 1000) @@ -108,7 +108,7 @@ describe("A Chat Message", function () { const message = "https://pbs.twimg.com/media/string?format=jpg&name=small"; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); await mock.sendMessage(view, message); expect(view.model.sendMessage).toHaveBeenCalled(); @@ -129,7 +129,7 @@ describe("A Chat Message", function () { const message = 'https://imgur.com/oxymPax.png'; const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); await mock.sendMessage(view, message); await u.waitUntil(() => view.querySelectorAll('converse-chat-message-body .chat-image').length === 1); api.settings.set('show_images_inline', false); diff --git a/src/plugins/chatview/tests/messages.js b/src/plugins/chatview/tests/messages.js index 84a8103ce..b48d0a7fc 100644 --- a/src/plugins/chatview/tests/messages.js +++ b/src/plugins/chatview/tests/messages.js @@ -12,7 +12,7 @@ describe("A Chat Message", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); await _converse.handleMessageStanza(mock.createChatMessage(_converse, contact_jid, 'This message will be read')); const msg_el = await u.waitUntil(() => view.querySelector('converse-chat-message')); expect(msg_el.querySelector('.chat-msg__text').textContent).toBe('This message will be read'); @@ -98,7 +98,7 @@ describe("A Chat Message", function () { .c('delay', {'xmlns': 'urn:xmpp:delay', 'stamp':'2018-01-02T13:08:25Z'}) .tree(); await _converse.handleMessageStanza(msg); - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); msg = $msg({ 'xmlns': 'jabber:client', @@ -345,7 +345,7 @@ describe("A Chat Message", function () { await _converse.handleMessageStanza(msg); // Check that the chatbox and its view now exist const chatbox = await _converse.api.chats.get(recipient_jid); - const view = _converse.api.chatviews.get(recipient_jid); + const view = _converse.chatboxviews.get(recipient_jid); expect(chatbox).toBeDefined(); expect(view).toBeDefined(); @@ -504,7 +504,7 @@ describe("A Chat Message", function () { await mock.openControlBox(_converse); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); const message = '

This message contains some markup

'; spyOn(view.model, 'sendMessage').and.callThrough(); await mock.sendMessage(view, message); @@ -522,7 +522,7 @@ describe("A Chat Message", function () { await mock.openControlBox(_converse); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); const message = 'This message contains a hyperlink: www.opkode.com'; spyOn(view.model, 'sendMessage').and.callThrough(); await mock.sendMessage(view, message); @@ -543,7 +543,7 @@ describe("A Chat Message", function () { await mock.openControlBox(_converse); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); let message = 'This message contains a hyperlink with forbidden query params: https://www.opkode.com/?id=0&utm_content=1&utm_medium=2&s=1'; await mock.sendMessage(view, message); await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length); @@ -622,7 +622,7 @@ describe("A Chat Message", function () { api.settings.set('time_format', 'hh:mm'); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); const message = 'This message is sent from this chatbox'; await mock.sendMessage(view, message); @@ -666,7 +666,7 @@ describe("A Chat Message", function () { }).c('body').t('A message').up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree()); await new Promise(resolve => _converse.on('chatBoxViewInitialized', resolve)); - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); await new Promise(resolve => view.model.messages.once('rendered', resolve)); jasmine.clock().tick(3*ONE_MINUTE_LATER); @@ -868,7 +868,7 @@ describe("A Chat Message", function () { ); const chatbox = await _converse.chatboxes.get(sender_jid); expect(chatbox).toBeDefined(); - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); expect(view).toBeDefined(); expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object)); @@ -906,7 +906,7 @@ describe("A Chat Message", function () { }).c('body').t(message).up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree() ); - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); await u.waitUntil(() => view.model.messages.length); expect(view.model.messages.length).toEqual(1); const msg_obj = view.model.messages.at(0); @@ -949,7 +949,7 @@ describe("A Chat Message", function () { expect(_converse.chatboxes.get(sender_jid)).not.toBeDefined(); await _converse.handleMessageStanza(msg); - const view = await u.waitUntil(() => _converse.api.chatviews.get(sender_jid)); + const view = await u.waitUntil(() => _converse.chatboxviews.get(sender_jid)); await u.waitUntil(() => view.querySelectorAll('.chat-msg').length); expect(_converse.api.trigger).toHaveBeenCalledWith('message', jasmine.any(Object)); @@ -1052,7 +1052,7 @@ describe("A Chat Message", function () { const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await _converse.api.chats.open(sender_jid) let msg_text = 'This message will not be sent, due to an error'; - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); const message = await view.model.sendMessage(msg_text); await u.waitUntil(() => view.querySelectorAll('.chat-msg').length); let msg_txt = sizzle('.chat-msg:last .chat-msg__text', view).pop().textContent; @@ -1195,7 +1195,7 @@ describe("A Chat Message", function () { await mock.waitForRoster(_converse, 'current'); const sender_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, sender_jid) - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); // Create enough messages so that there's a scrollbar. const promises = []; view.querySelector('.chat-content').scrollTop = 0; @@ -1281,7 +1281,7 @@ describe("A Chat Message", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); let stanza = u.toStanza(` @@ -1331,7 +1331,7 @@ describe("A Chat Message", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); let stanza = u.toStanza(` @@ -1377,7 +1377,7 @@ describe("A Chat Message", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); spyOn(view.model, 'sendMessage').and.callThrough(); const stanza = u.toStanza(` view.querySelector('.toggle-compose-spoiler')); @@ -180,7 +180,7 @@ describe("A spoiler message", function () { _converse.connection._dataRecv(mock.createRequest(presence)); await mock.openChatBoxFor(_converse, contact_jid); await mock.waitUntilDiscoConfirmed(_converse, contact_jid+'/phone', [], [Strophe.NS.SPOILER]); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); await u.waitUntil(() => view.querySelector('.toggle-compose-spoiler')); let spoiler_toggle = view.querySelector('.toggle-compose-spoiler'); diff --git a/src/plugins/chatview/tests/xss.js b/src/plugins/chatview/tests/xss.js index b3448c3a8..726adc54e 100644 --- a/src/plugins/chatview/tests/xss.js +++ b/src/plugins/chatview/tests/xss.js @@ -13,7 +13,7 @@ describe("XSS", function () { const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); let message = ""; await mock.sendMessage(view, message); @@ -69,7 +69,7 @@ describe("XSS", function () { const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); let message = ""; await mock.sendMessage(view, message); @@ -125,7 +125,7 @@ describe("XSS", function () { const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); let message = "http://www.opkode.com/'onmouseover='alert(1)'whatever"; await mock.sendMessage(view, message); @@ -181,7 +181,7 @@ describe("XSS", function () { const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid) - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); const bad_urls =[ 'http://^$^(*^#$%^_1*(', diff --git a/src/plugins/minimize/tests/minchats.js b/src/plugins/minimize/tests/minchats.js index 2854eb907..de7929b85 100644 --- a/src/plugins/minimize/tests/minchats.js +++ b/src/plugins/minimize/tests/minchats.js @@ -22,7 +22,7 @@ describe("A chat message", function () { const rosterview = document.querySelector('converse-roster'); await u.waitUntil(() => rosterview.querySelectorAll('.roster-group').length); await mock.openChatBoxFor(_converse, contact_jid); - const chatview = _converse.api.chatviews.get(contact_jid); + const chatview = _converse.chatboxviews.get(contact_jid); expect(u.isVisible(chatview)).toBeTruthy(); expect(chatview.model.get('minimized')).toBeFalsy(); chatview.querySelector('.toggle-chatbox-button').click(); diff --git a/src/plugins/muc-views/api.js b/src/plugins/muc-views/api.js deleted file mode 100644 index b250ee3f6..000000000 --- a/src/plugins/muc-views/api.js +++ /dev/null @@ -1,69 +0,0 @@ -import { _converse, api } from "@converse/headless/core"; - -export default { - /** - * The "roomviews" namespace groups methods relevant to chatroom - * (aka groupchats) views. - * - * @namespace _converse.api.roomviews - * @memberOf _converse.api - */ - roomviews: { - /** - * Retrieves a groupchat (aka chatroom) view. The chat should already be open. - * - * @method _converse.api.roomviews.get - * @param {String|string[]} name - e.g. 'coven@conference.shakespeare.lit' or - * ['coven@conference.shakespeare.lit', 'cave@conference.shakespeare.lit'] - * @returns {View} View representing the groupchat - * - * @example - * // To return a single view, provide the JID of the groupchat - * const view = _converse.api.roomviews.get('coven@conference.shakespeare.lit'); - * - * @example - * // To return an array of views, provide an array of JIDs: - * const views = _converse.api.roomviews.get(['coven@conference.shakespeare.lit', 'cave@conference.shakespeare.lit']); - * - * @example - * // To return views of all open groupchats, call the method without any parameters:: - * const views = _converse.api.roomviews.get(); - * - */ - get (jids) { - if (Array.isArray(jids)) { - const views = api.chatviews.get(jids); - return views.filter(v => v.model.get('type') === _converse.CHATROOMS_TYPE) - } else { - const view = api.chatviews.get(jids); - if (view.model.get('type') === _converse.CHATROOMS_TYPE) { - return view; - } else { - return null; - } - } - }, - /** - * Lets you close open chatrooms. - * - * You can call this method without any arguments to close - * all open chatrooms, or you can specify a single JID or - * an array of JIDs. - * - * @method _converse.api.roomviews.close - * @param {(String[]|String)} jids The JID or array of JIDs of the chatroom(s) - * @returns { Promise } - Promise which resolves once the views have been closed. - */ - close (jids) { - let views; - if (jids === undefined) { - views = _converse.chatboxviews; - } else if (typeof jids === 'string') { - views = [_converse.chatboxviews.get(jids)].filter(v => v); - } else if (Array.isArray(jids)) { - views = jids.map(jid => _converse.chatboxviews.get(jid)); - } - return Promise.all(views.map(v => (v.is_chatroom && v.model && v.close()))) - } - } -} diff --git a/src/plugins/muc-views/index.js b/src/plugins/muc-views/index.js index 37e763af7..d39a4dd99 100644 --- a/src/plugins/muc-views/index.js +++ b/src/plugins/muc-views/index.js @@ -7,7 +7,6 @@ import '../chatboxviews/index.js'; import '../modal.js'; import './adhoc-commands.js'; import MUCView from './muc.js'; -import muc_api from './api.js'; import { api, converse } from '@converse/headless/core'; import { fetchAndSetMUCDomain } from './utils.js'; @@ -61,8 +60,6 @@ converse.plugins.add('converse-muc-views', { _converse.ChatRoomView = MUCView; - Object.assign(_converse.api, muc_api); - api.listen.on('clearsession', () => { const view = _converse.chatboxviews.get('controlbox'); if (view && view.roomspanel) { diff --git a/src/plugins/muc-views/tests/corrections.js b/src/plugins/muc-views/tests/corrections.js index a8533cd9f..d7993d870 100644 --- a/src/plugins/muc-views/tests/corrections.js +++ b/src/plugins/muc-views/tests/corrections.js @@ -9,7 +9,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const stanza = $pres({ to: 'romeo@montague.lit/_converse.js-29092160', from: 'coven@chat.shakespeare.lit/newguy' @@ -74,7 +74,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const stanza = $pres({ to: 'romeo@montague.lit/_converse.js-29092160', from: 'coven@chat.shakespeare.lit/newguy' @@ -166,7 +166,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const textarea = await u.waitUntil(() => view.querySelector('textarea.chat-textarea')); expect(textarea.value).toBe(''); const message_form = view.querySelector('converse-muc-message-form'); diff --git a/src/plugins/muc-views/tests/markers.js b/src/plugins/muc-views/tests/markers.js new file mode 100644 index 000000000..f37d3f22c --- /dev/null +++ b/src/plugins/muc-views/tests/markers.js @@ -0,0 +1,69 @@ +/*global mock, converse */ + +const u = converse.env.utils; +// See: https://xmpp.org/rfcs/rfc3921.html + + +describe("A XEP-0333 Chat Marker", function () { + it("may be returned for a MUC message", + mock.initConverse([], {}, async function (done, _converse) { + + await mock.waitForRoster(_converse, 'current'); + const muc_jid = 'lounge@montague.lit'; + await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); + const view = _converse.chatboxviews.get(muc_jid); + const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea')); + textarea.value = 'But soft, what light through yonder airlock breaks?'; + const message_form = view.querySelector('converse-muc-message-form'); + message_form.onKeyDown({ + target: textarea, + preventDefault: function preventDefault () {}, + keyCode: 13 // Enter + }); + await u.waitUntil(() => view.querySelectorAll('.chat-msg__text').length); + expect(view.querySelectorAll('.chat-msg').length).toBe(1); + expect(view.querySelector('.chat-msg .chat-msg__text').textContent.trim()) + .toBe("But soft, what light through yonder airlock breaks?"); + + const msg_obj = view.model.messages.at(0); + let stanza = u.toStanza(` + + + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 1); + expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0); + + stanza = u.toStanza(` + + + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + expect(view.querySelectorAll('.chat-msg').length).toBe(1); + expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0); + + stanza = u.toStanza(` + + + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + + expect(view.querySelectorAll('.chat-msg').length).toBe(1); + expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0); + + stanza = u.toStanza(` + + 'tis I! + + + `); + _converse.connection._dataRecv(mock.createRequest(stanza)); + await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 2); + expect(view.querySelectorAll('.chat-msg__receipt').length).toBe(0); + done(); + })); +}); diff --git a/src/plugins/muc-views/tests/mentions.js b/src/plugins/muc-views/tests/mentions.js index 69e661c80..9058a7fa0 100644 --- a/src/plugins/muc-views/tests/mentions.js +++ b/src/plugins/muc-views/tests/mentions.js @@ -11,7 +11,7 @@ describe("An incoming groupchat message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); if (!view.querySelectorAll('.chat-area').length) { view.renderChatArea(); } const message = 'romeo: Your attention is required'; const nick = mock.chatroom_names[0], @@ -33,7 +33,7 @@ describe("An incoming groupchat message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); ['z3r0', 'mr.robot', 'gibson', 'sw0rdf1sh'].forEach((nick) => { _converse.connection._dataRecv(mock.createRequest( $pres({ @@ -88,7 +88,7 @@ describe("An incoming groupchat message", function () { const muc_jid = 'lounge@montague.lit'; const nick = 'romeo'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); _converse.connection._dataRecv(mock.createRequest( $pres({ 'to': 'romeo@montague.lit/resource', @@ -136,7 +136,7 @@ describe("An incoming groupchat message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); ['z3r0', 'mr.robot', 'gibson', 'sw0rdf1sh'].forEach((nick) => { _converse.connection._dataRecv(mock.createRequest( $pres({ @@ -194,7 +194,7 @@ describe("A sent groupchat message", function () { 'muc_nonanonymous' ]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); ['z3r0', 'mr.robot', 'gibson', 'sw0rdf1sh', 'Link Mauve', 'robot'].forEach((nick) => { _converse.connection._dataRecv(mock.createRequest( $pres({ @@ -310,7 +310,7 @@ describe("A sent groupchat message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); ['NotAnAdress', 'darnuria'].forEach((nick) => { _converse.connection._dataRecv(mock.createRequest( $pres({ @@ -342,7 +342,7 @@ describe("A sent groupchat message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom'); - const view = _converse.api.roomviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); _converse.connection._dataRecv(mock.createRequest( $pres({ 'to': 'tom@montague.lit/resource', @@ -399,7 +399,7 @@ describe("A sent groupchat message", function () { 'muc_nonanonymous' ]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); ['z3r0', 'mr.robot', 'gibson', 'sw0rdf1sh'].forEach((nick) => { _converse.connection._dataRecv(mock.createRequest( $pres({ @@ -482,7 +482,7 @@ describe("A sent groupchat message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); ['z3r0', 'mr.robot', 'gibson', 'sw0rdf1sh'].forEach((nick) => { _converse.connection._dataRecv(mock.createRequest( $pres({ @@ -533,7 +533,7 @@ describe("A sent groupchat message", function () { const members = [{'jid': 'gibson@gibson.net', 'nick': 'gibson', 'affiliation': 'member'}]; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'tom', [], members); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea')); textarea.value = "Welcome @gibson 💩 We have a guide on how to do that here: https://conversejs.org/docs/html/index.html"; const enter_event = { diff --git a/src/plugins/muc-views/tests/muc-api.js b/src/plugins/muc-views/tests/muc-api.js index 3026f5688..73f05ad3f 100644 --- a/src/plugins/muc-views/tests/muc-api.js +++ b/src/plugins/muc-views/tests/muc-api.js @@ -22,20 +22,32 @@ describe("Groupchats", function () { expect(u.isVisible(_converse.chatboxviews.get('leisure@montague.lit'))).toBeTruthy(); expect(u.isVisible(_converse.chatboxviews.get('news@montague.lit'))).toBeTruthy(); - await _converse.api.roomviews.close('lounge@montague.lit'); - expect(_converse.chatboxviews.get('lounge@montague.lit')).toBeUndefined(); + _converse.chatboxviews.get('lounge@montague.lit').close(); + await u.waitUntil(() => !_converse.chatboxviews.get('lounge@montague.lit')); expect(u.isVisible(_converse.chatboxviews.get('leisure@montague.lit'))).toBeTruthy(); expect(u.isVisible(_converse.chatboxviews.get('news@montague.lit'))).toBeTruthy(); - await _converse.api.roomviews.close(['leisure@montague.lit', 'news@montague.lit']); + _converse.chatboxviews.get('leisure@montague.lit').close(); + await u.waitUntil(() => !_converse.chatboxviews.get('leisure@montague.lit')); + + _converse.chatboxviews.get('news@montague.lit').close(); + await u.waitUntil(() => !_converse.chatboxviews.get('news@montague.lit')); + expect(_converse.chatboxviews.get('lounge@montague.lit')).toBeUndefined(); expect(_converse.chatboxviews.get('leisure@montague.lit')).toBeUndefined(); expect(_converse.chatboxviews.get('news@montague.lit')).toBeUndefined(); + await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); await mock.openAndEnterChatRoom(_converse, 'leisure@montague.lit', 'romeo'); expect(u.isVisible(_converse.chatboxviews.get('lounge@montague.lit'))).toBeTruthy(); expect(u.isVisible(_converse.chatboxviews.get('leisure@montague.lit'))).toBeTruthy(); - await _converse.api.roomviews.close(); + + _converse.chatboxviews.get('leisure@montague.lit').close(); + await u.waitUntil(() => !_converse.chatboxviews.get('leisure@montague.lit')); + + _converse.chatboxviews.get('lounge@montague.lit').close(); + await u.waitUntil(() => !_converse.chatboxviews.get('lounge@montague.lit')); + expect(_converse.chatboxviews.get('lounge@montague.lit')).toBeUndefined(); expect(_converse.chatboxviews.get('leisure@montague.lit')).toBeUndefined(); done(); diff --git a/src/plugins/muc-views/tests/muc-messages.js b/src/plugins/muc-views/tests/muc-messages.js index f9df5c95d..d75d852eb 100644 --- a/src/plugins/muc-views/tests/muc-messages.js +++ b/src/plugins/muc-views/tests/muc-messages.js @@ -16,7 +16,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea')); textarea.value = 'hello world' const enter_event = { @@ -61,7 +61,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; const nick = 'romeo'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); let presence = u.toStanza(` @@ -97,7 +97,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const presence = u.toStanza(` @@ -145,7 +145,7 @@ describe("A Groupchat Message", function () {
`); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); spyOn(view.model, 'onMessage').and.callThrough(); spyOn(converse.env.log, 'error'); _converse.connection._dataRecv(mock.createRequest(received_stanza)); @@ -163,7 +163,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); if (!view.querySelectorAll('.chat-area').length) { view.renderChatArea(); } const message = 'romeo: Your attention is required'; const nick = mock.chatroom_names[0], @@ -186,7 +186,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); if (!view.querySelectorAll('.chat-area').length) { view.renderChatArea(); } const id = u.getUniqueId(); let msg = $msg({ @@ -215,7 +215,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'room@muc.example.com'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); spyOn(view.model, 'getDuplicateMessage').and.callThrough(); let stanza = u.toStanza(` converse.env.log.error.calls.count()); @@ -365,7 +365,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); let msg = $msg({ from: 'lounge@montague.lit/romeo', id: u.getUniqueId(), @@ -492,7 +492,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const msg = $msg({ from: 'lounge@montague.lit/romeo', id: u.getUniqueId(), @@ -511,7 +511,7 @@ describe("A Groupchat Message", function () { await mock.waitForRoster(_converse, 'current'); const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea')); textarea.value = 'But soft, what light through yonder airlock breaks?'; const message_form = view.querySelector('converse-muc-message-form'); @@ -552,7 +552,7 @@ describe("A Groupchat Message", function () { const muc_jid = 'room@muc.example.com'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); view.model.sendMessage('hello world'); await u.waitUntil(() => view.model.messages.length === 1); @@ -586,7 +586,7 @@ describe("A Groupchat Message", function () { await mock.waitForRoster(_converse, 'current'); const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const textarea = await u.waitUntil(() => view.querySelector('.chat-textarea')); textarea.value = 'But soft, what light through yonder airlock breaks?'; const message_form = view.querySelector('converse-muc-message-form'); diff --git a/src/plugins/muc-views/tests/muc.js b/src/plugins/muc-views/tests/muc.js index 18caa5dc0..365b5ba71 100644 --- a/src/plugins/muc-views/tests/muc.js +++ b/src/plugins/muc-views/tests/muc.js @@ -2637,7 +2637,7 @@ describe("Groupchats", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); let presence = $pres({ 'from': 'lounge@montague.lit/annoyingGuy', 'id':'27C55F89-1C6A-459A-9EB5-77690145D624', @@ -2707,7 +2707,7 @@ describe("Groupchats", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); let message = $msg({ from: 'lounge@montague.lit', @@ -3297,7 +3297,7 @@ describe("Groupchats", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); spyOn(view.model, 'setRole').and.callThrough(); spyOn(view.model, 'validateRoleOrAffiliationChangeArgs').and.callThrough(); @@ -3381,7 +3381,7 @@ describe("Groupchats", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); let sent_IQ, IQ_id; const sendIQ = _converse.connection.sendIQ; spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { @@ -3521,7 +3521,7 @@ describe("Groupchats", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); var sent_IQ, IQ_id; var sendIQ = _converse.connection.sendIQ; spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { @@ -3659,7 +3659,7 @@ describe("Groupchats", function () { const muc_jid = 'lounge@montague.lit'; const new_muc_jid = 'foyer@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - let view = _converse.api.chatviews.get(muc_jid); + let view = _converse.chatboxviews.get(muc_jid); spyOn(_converse.api, 'confirm').and.callThrough(); let textarea = await u.waitUntil(() => view.querySelector('.chat-textarea')); textarea.value = '/destroy'; @@ -3711,7 +3711,7 @@ describe("Groupchats", function () { _converse.connection.IQ_stanzas = []; sent_IQs = _converse.connection.IQ_stanzas; await mock.openAndEnterChatRoom(_converse, new_muc_jid, 'romeo'); - view = _converse.api.chatviews.get(new_muc_jid); + view = _converse.chatboxviews.get(new_muc_jid); textarea = await u.waitUntil(() => view.querySelector('.chat-textarea')); textarea.value = '/destroy'; message_form = view.querySelector('converse-muc-message-form'); @@ -4671,7 +4671,7 @@ describe("Groupchats", function () { const muc_jid = 'kitchen@conference.shakespeare.lit'; const message = 'fires: Your attention is required'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'fires'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); await u.waitUntil(() => roomspanel.querySelectorAll('.available-room').length); expect(roomspanel.querySelectorAll('.available-room').length).toBe(1); expect(roomspanel.querySelectorAll('.msgs-indicator').length).toBe(0); @@ -4729,7 +4729,7 @@ describe("Groupchats", function () { ] await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); view.model.setChatState(_converse.ACTIVE); expect(view.model.sendChatState).toHaveBeenCalled(); @@ -4770,7 +4770,7 @@ describe("Groupchats", function () { {'affiliation': 'admin', 'nick': 'groundcontrol', 'jid': 'groundcontrol@example.org'} ]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'some1', [], members); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); let csntext = await u.waitUntil(() => view.querySelector('.chat-content__notifications').textContent); expect(csntext.trim()).toEqual("some1 has entered the groupchat"); @@ -4988,7 +4988,7 @@ describe("Groupchats", function () { const muc_jid = 'trollbox@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'troll'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const textarea = await u.waitUntil(() => view.querySelector('textarea.chat-textarea')); textarea.value = 'Hello world'; const message_form = view.querySelector('converse-muc-message-form'); @@ -5043,7 +5043,7 @@ describe("Groupchats", function () { ] const muc_jid = 'trollbox@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'troll', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); await u.waitUntil(() => view.querySelector('.chat-textarea')); let stanza = u.toStanza(` diff --git a/src/plugins/muc-views/tests/rai.js b/src/plugins/muc-views/tests/rai.js index 25951f0ba..cf31e2b92 100644 --- a/src/plugins/muc-views/tests/rai.js +++ b/src/plugins/muc-views/tests/rai.js @@ -19,7 +19,7 @@ describe("XEP-0437 Room Activity Indicators", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); expect(view.model.get('hidden')).toBe(false); const sent_IQs = _converse.connection.IQ_stanzas; @@ -189,7 +189,7 @@ describe("XEP-0437 Room Activity Indicators", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); expect(view.model.get('hidden')).toBe(false); const sent_stanzas = []; spyOn(_converse.connection, 'send').and.callFake(s => sent_stanzas.push(s?.nodeTree ?? s)); diff --git a/src/plugins/muc-views/tests/retractions.js b/src/plugins/muc-views/tests/retractions.js index 06fc0a33c..d314f27ae 100644 --- a/src/plugins/muc-views/tests/retractions.js +++ b/src/plugins/muc-views/tests/retractions.js @@ -49,7 +49,7 @@ describe("Message Retractions", function () { `); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); await view.model.handleMessageStanza(received_stanza); await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 1); expect(view.model.messages.at(0).get('retracted')).toBeFalsy(); @@ -93,7 +93,7 @@ describe("Message Retractions", function () { `); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); spyOn(converse.env.log, 'warn'); spyOn(view.model, 'handleRetraction').and.callThrough(); _converse.connection._dataRecv(mock.createRequest(retraction_stanza)); @@ -149,7 +149,7 @@ describe("Message Retractions", function () { `); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); spyOn(converse.env.log, 'warn'); spyOn(view.model, 'handleModeration').and.callThrough(); _converse.connection._dataRecv(mock.createRequest(retraction_stanza)); @@ -371,7 +371,7 @@ describe("Message Retractions", function () { `); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); await view.model.handleMessageStanza(received_stanza); await u.waitUntil(() => view.querySelectorAll('.chat-msg').length === 1); expect(view.model.messages.at(0).get('retracted')).toBeFalsy(); @@ -406,7 +406,7 @@ describe("Message Retractions", function () { const features = [...mock.default_muc_features, Strophe.NS.MODERATE]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const occupant = view.model.getOwnOccupant(); expect(occupant.get('role')).toBe('moderator'); @@ -488,7 +488,7 @@ describe("Message Retractions", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const occupant = view.model.getOwnOccupant(); expect(occupant.get('role')).toBe('moderator'); @@ -513,7 +513,7 @@ describe("Message Retractions", function () { const muc_jid = 'lounge@montague.lit'; const features = [...mock.default_muc_features, Strophe.NS.MODERATE]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const occupant = view.model.getOwnOccupant(); expect(occupant.get('role')).toBe('moderator'); @@ -580,7 +580,7 @@ describe("Message Retractions", function () { const muc_jid = 'lounge@montague.lit'; const features = [...mock.default_muc_features, Strophe.NS.MODERATE]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const occupant = view.model.getOwnOccupant(); expect(occupant.get('role')).toBe('moderator'); occupant.save('role', 'member'); @@ -636,7 +636,7 @@ describe("Message Retractions", function () { const muc_jid = 'lounge@montague.lit'; const features = [...mock.default_muc_features, Strophe.NS.MODERATE]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const occupant = view.model.getOwnOccupant(); expect(occupant.get('role')).toBe('moderator'); occupant.save('role', 'member'); @@ -685,7 +685,7 @@ describe("Message Retractions", function () { const muc_jid = 'lounge@montague.lit'; const features = [...mock.default_muc_features, Strophe.NS.MODERATE]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const occupant = view.model.getOwnOccupant(); expect(occupant.get('role')).toBe('moderator'); occupant.save('role', 'member'); @@ -716,7 +716,7 @@ describe("Message Retractions", function () { const muc_jid = 'lounge@montague.lit'; const features = [...mock.default_muc_features, Strophe.NS.MODERATE]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const occupant = view.model.getOwnOccupant(); expect(occupant.get('role')).toBe('moderator'); @@ -766,7 +766,7 @@ describe("Message Retractions", function () { const muc_jid = 'lounge@montague.lit'; const features = [...mock.default_muc_features, Strophe.NS.MODERATE]; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo', features); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const occupant = view.model.getOwnOccupant(); expect(occupant.get('role')).toBe('moderator'); diff --git a/src/plugins/muc-views/tests/styling.js b/src/plugins/muc-views/tests/styling.js index 6025f1290..81c78e388 100644 --- a/src/plugins/muc-views/tests/styling.js +++ b/src/plugins/muc-views/tests/styling.js @@ -10,7 +10,7 @@ describe("An incoming groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const msg_text = "This *message mentions romeo*"; const msg = $msg({ from: 'lounge@montague.lit/gibson', @@ -36,7 +36,7 @@ describe("An incoming groupchat Message", function () { const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo'); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const msg_text = "x_y_z_ hello"; const msg = $msg({ from: 'lounge@montague.lit/gibson', diff --git a/src/plugins/muc-views/tests/unfurls.js b/src/plugins/muc-views/tests/unfurls.js index 7a3cce084..746b11d05 100644 --- a/src/plugins/muc-views/tests/unfurls.js +++ b/src/plugins/muc-views/tests/unfurls.js @@ -8,7 +8,7 @@ describe("A Groupchat Message", function () { const nick = 'romeo'; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const message_stanza = u.toStanza(` @@ -53,7 +53,7 @@ describe("A Groupchat Message", function () { const nick = 'romeo'; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const message_stanza = u.toStanza(` @@ -89,7 +89,7 @@ describe("A Groupchat Message", function () { const nick = 'romeo'; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const message_stanza = u.toStanza(` @@ -144,7 +144,7 @@ describe("A Groupchat Message", function () { const nick = 'romeo'; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const message_stanza = u.toStanza(` @@ -185,7 +185,7 @@ describe("A Groupchat Message", function () { const nick = 'romeo'; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const message_stanza = u.toStanza(` @@ -224,7 +224,7 @@ describe("A Groupchat Message", function () { const nick = 'romeo'; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const message_stanza = u.toStanza(` @@ -268,7 +268,7 @@ describe("A Groupchat Message", function () { const nick = 'romeo'; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const message_stanza = u.toStanza(` @@ -307,7 +307,7 @@ describe("A Groupchat Message", function () { const nick = 'romeo'; const muc_jid = 'lounge@montague.lit'; await mock.openAndEnterChatRoom(_converse, muc_jid, nick); - const view = _converse.api.chatviews.get(muc_jid); + const view = _converse.chatboxviews.get(muc_jid); const message_stanza = u.toStanza(` diff --git a/src/plugins/notifications/tests/notification.js b/src/plugins/notifications/tests/notification.js index b88678174..9833c3b02 100644 --- a/src/plugins/notifications/tests/notification.js +++ b/src/plugins/notifications/tests/notification.js @@ -28,7 +28,7 @@ describe("Notifications", function () { }).c('body').t(message).up() .c('active', {'xmlns': 'http://jabber.org/protocol/chatstates'}).tree(); await _converse.handleMessageStanza(msg); // This will emit 'message' - await u.waitUntil(() => _converse.api.chatviews.get(sender_jid)); + await u.waitUntil(() => _converse.chatboxviews.get(sender_jid)); expect(window.Notification).toHaveBeenCalled(); done(); })); @@ -38,7 +38,7 @@ describe("Notifications", function () { await mock.waitForRoster(_converse, 'current'); await mock.openAndEnterChatRoom(_converse, 'lounge@montague.lit', 'romeo'); - const view = _converse.api.chatviews.get('lounge@montague.lit'); + const view = _converse.chatboxviews.get('lounge@montague.lit'); if (!view.querySelectorAll('.chat-area').length) { view.renderChatArea(); } diff --git a/src/shared/chat/baseview.js b/src/shared/chat/baseview.js index f56a8b1d6..586bb7203 100644 --- a/src/shared/chat/baseview.js +++ b/src/shared/chat/baseview.js @@ -20,6 +20,7 @@ export default class BaseChatView extends CustomElement { updated () { if (this.model && this.jid !== this.model.get('jid')) { this.stopListening(); + _converse.chatboxviews.remove(this.model.get('jid'), this); delete this.model; this.requestUpdate(); this.initialize(); diff --git a/src/shared/chat/tests/styling.js b/src/shared/chat/tests/styling.js index 675dc28d9..865dd08c2 100644 --- a/src/shared/chat/tests/styling.js +++ b/src/shared/chat/tests/styling.js @@ -24,7 +24,7 @@ describe("An incoming chat Message", function () { .c('unstyled', {'xmlns': 'urn:xmpp:styling:0'}).tree(); await _converse.handleMessageStanza(msg); - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); await u.waitUntil(() => view.model.messages.length); expect(view.model.messages.models[0].get('is_unstyled')).toBe(true); @@ -55,7 +55,7 @@ describe("An incoming chat Message", function () { }).c('body').t(msg_text).tree(); await _converse.handleMessageStanza(msg); - const view = _converse.api.chatviews.get(sender_jid); + const view = _converse.chatboxviews.get(sender_jid); await u.waitUntil(() => view.model.messages.length); expect(view.model.messages.models[0].get('is_unstyled')).toBe(false); @@ -74,7 +74,7 @@ describe("An incoming chat Message", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); msg_text = "This *message _contains_* styling hints! \`Here's *some* code\`"; msg = mock.createChatMessage(_converse, contact_jid, msg_text) @@ -199,7 +199,7 @@ describe("An incoming chat Message", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); msg_text = `Here's a code block: \n\`\`\`\nInside the code-block, hello we don't enable *styling hints* like ~these~\n\`\`\``; msg = mock.createChatMessage(_converse, contact_jid, msg_text) @@ -247,7 +247,7 @@ describe("An incoming chat Message", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); msg_text = `> This is quoted text\n>This is also quoted\nThis is not quoted`; msg = mock.createChatMessage(_converse, contact_jid, msg_text) @@ -394,7 +394,7 @@ describe("An incoming chat Message", function () { await mock.waitForRoster(_converse, 'current', 1); const contact_jid = mock.cur_names[0].replace(/ /g,'.').toLowerCase() + '@montague.lit'; await mock.openChatBoxFor(_converse, contact_jid); - const view = _converse.api.chatviews.get(contact_jid); + const view = _converse.chatboxviews.get(contact_jid); const msg_text = '```\ncode```'; const msg = $msg({ from: contact_jid,