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).
This commit is contained in:
JC Brand 2021-06-14 15:44:50 +02:00
parent ba1b712fee
commit 9fb92080f2
29 changed files with 199 additions and 291 deletions

View File

@ -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

View File

@ -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' },

View File

@ -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');
}

View File

@ -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));
}
}
}

View File

@ -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));
}

View File

@ -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?';

View File

@ -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, '') ===
'<img class="emoji" draggable="false" title=":innocent:" alt="😇" src="https://twemoji.maxcdn.com/v/12.1.6//72x72/1f607.png">');
@ -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();

View File

@ -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(`
<message xmlns="jabber:client"
@ -114,67 +114,4 @@ describe("A XEP-0333 Chat Marker", function () {
expect(view.model.messages.length).toBe(1);
done();
}));
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.api.chatviews.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(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<received xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_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(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<displayed xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_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(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<acknowledged xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_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(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<body>'tis I!</body>
<stanza-id xmlns='urn:xmpp:sid:0' id='stanza-id-1' by='${muc_jid}'/>
<markable xmlns="urn:xmpp:chat-markers:0"/>
</message>`);
_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();
}));
});

View File

@ -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);

View File

@ -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 = '<p>This message contains <em>some</em> <b>markup</b></p>';
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(`
<message from="${contact_jid}"
@ -1407,7 +1407,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 url = base_url+"/logo/conversejs-filled.svg";

View File

@ -103,7 +103,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);
spyOn(_converse.connection, 'send');
await u.waitUntil(() => 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');

View File

@ -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 = "<img src=x onerror=alert('XSS');>";
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 = "<svg onload=alert(1)>";
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*(',

View File

@ -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();

View File

@ -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())))
}
}
}

View File

@ -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) {

View File

@ -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');

View File

@ -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(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<received xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_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(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<displayed xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_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(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<acknowledged xmlns="urn:xmpp:chat-markers:0" id="${msg_obj.get('msgid')}"/>
</message>`);
_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(`
<message xml:lang="en" to="romeo@montague.lit/orchard"
from="lounge@montague.lit/some1" type="groupchat" xmlns="jabber:client">
<body>'tis I!</body>
<stanza-id xmlns='urn:xmpp:sid:0' id='stanza-id-1' by='${muc_jid}'/>
<markable xmlns="urn:xmpp:chat-markers:0"/>
</message>`);
_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();
}));
});

View File

@ -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 = {

View File

@ -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();

View File

@ -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(`
<presence xmlns="jabber:client" to="${_converse.jid}" from="${muc_jid}/romeo">
<x xmlns="http://jabber.org/protocol/muc#user">
@ -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(`
<presence xmlns="jabber:client" to="${_converse.jid}" from="${muc_jid}/romeo">
<x xmlns="http://jabber.org/protocol/muc#user">
@ -145,7 +145,7 @@ describe("A Groupchat Message", function () {
</forwarded>
</message>
`);
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(`
<message xmlns="jabber:client"
@ -262,7 +262,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, 'getStanzaIdQueryAttrs').and.callThrough();
let stanza = u.toStanza(`
<message xmlns="jabber:client"
@ -348,7 +348,7 @@ describe("A Groupchat Message", function () {
'to': muc_jid,
'type': 'groupchat'
}).c('body').t('I am groot').tree();
const view = _converse.api.chatviews.get(muc_jid);
const view = _converse.chatboxviews.get(muc_jid);
spyOn(converse.env.log, 'error');
await _converse.handleMAMResult(view.model, { 'messages': [msg] });
await u.waitUntil(() => 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');

View File

@ -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(`

View File

@ -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));

View File

@ -49,7 +49,7 @@ describe("Message Retractions", function () {
<stanza-id xmlns='urn:xmpp:sid:0' id='stanza-id-1' by='${muc_jid}'/>
</message>
`);
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 () {
</apply-to>
</message>
`);
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 () {
</apply-to>
</message>
`);
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 () {
<origin-id xmlns='urn:xmpp:sid:0' id='origin-id-1' by='${muc_jid}'/>
</message>
`);
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');

View File

@ -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',

View File

@ -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(`
<message xmlns="jabber:client" type="groupchat" from="${muc_jid}/arzu" xml:lang="en" to="${_converse.jid}" id="eda6c790-b4f3-4c07-b5e2-13fff99e6c04">
@ -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(`
<message xmlns="jabber:client" type="groupchat" from="${muc_jid}/arzu" xml:lang="en" to="${_converse.jid}" id="eda6c790-b4f3-4c07-b5e2-13fff99e6c04">
@ -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(`
<message xmlns="jabber:client" type="groupchat" from="${muc_jid}/arzu" xml:lang="en" to="${_converse.jid}" id="eda6c790-b4f3-4c07-b5e2-13fff99e6c04">
@ -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(`
<message xmlns="jabber:client" type="groupchat" from="${muc_jid}/arzu" xml:lang="en" to="${_converse.jid}" id="eda6c790-b4f3-4c07-b5e2-13fff99e6c04">
@ -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(`
<message xmlns="jabber:client" type="groupchat" from="${muc_jid}/arzu" xml:lang="en" to="${_converse.jid}" id="eda6c790-b4f3-4c07-b5e2-13fff99e6c04">
@ -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(`
<message xmlns="jabber:client" type="groupchat" from="${muc_jid}/arzu" xml:lang="en" to="${_converse.jid}" id="eda6c790-b4f3-4c07-b5e2-13fff99e6c04">
@ -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(`
<message xmlns="jabber:client" type="groupchat" from="${muc_jid}/arzu" xml:lang="en" to="${_converse.jid}" id="eda6c790-b4f3-4c07-b5e2-13fff99e6c04">
@ -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(`
<message xmlns="jabber:client" type="groupchat" from="${muc_jid}/arzu" xml:lang="en" to="${_converse.jid}" id="eda6c790-b4f3-4c07-b5e2-13fff99e6c04">

View File

@ -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();
}

View File

@ -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();

View File

@ -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, <code>hello</code> 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,