Improve how the `muc_domain` setting is populated via disco
Remove brittle code that uses `querySelector` to get the rooms list model. This code was causing a TypeError due to a race condition.
This commit is contained in:
parent
99ae9a9850
commit
8e1c3e47df
|
@ -3,6 +3,7 @@
|
|||
## 9.1.1 (Unreleased)
|
||||
|
||||
- GIFs don't render inside unfurls and cause a TypeError
|
||||
- Improve how the `muc_domain` setting is populated via service discovery
|
||||
- #2746: Always reply to all iqs, even those not understood
|
||||
- #2868: Selected emoji is inserted into all open chat boxes
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ module.exports = function(config) {
|
|||
{ pattern: "src/plugins/muc-views/tests/autocomplete.js", type: 'module' },
|
||||
{ pattern: "src/plugins/muc-views/tests/component.js", type: 'module' },
|
||||
{ pattern: "src/plugins/muc-views/tests/corrections.js", type: 'module' },
|
||||
{ pattern: "src/plugins/muc-views/tests/disco.js", type: 'module' },
|
||||
{ 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' },
|
||||
|
|
|
@ -8,7 +8,9 @@ import 'plugins/modal/index.js';
|
|||
import './adhoc-commands.js';
|
||||
import MUCView from './muc.js';
|
||||
import { api, converse } from '@converse/headless/core';
|
||||
import { clearHistory, fetchAndSetMUCDomain, parseMessageForMUCCommands } from './utils.js';
|
||||
import { clearHistory, parseMessageForMUCCommands } from './utils.js';
|
||||
|
||||
const { Strophe } = converse.env;
|
||||
|
||||
import './styles/index.scss';
|
||||
|
||||
|
@ -58,6 +60,22 @@ converse.plugins.add('converse-muc-views', {
|
|||
|
||||
_converse.ChatRoomView = MUCView;
|
||||
|
||||
if (!api.settings.get('muc_domain')) {
|
||||
// Use service discovery to get the default MUC domain
|
||||
api.listen.on('serviceDiscovered', async (feature) => {
|
||||
if (feature?.get('var') === Strophe.NS.MUC) {
|
||||
if (feature.entity.get('jid').includes('@')) {
|
||||
// Ignore full JIDs, we're only looking for a MUC service, not a room
|
||||
return;
|
||||
}
|
||||
const identity = await feature.entity.getIdentity('conference', 'text');
|
||||
if (identity) {
|
||||
api.settings.set('muc_domain', Strophe.getDomainFromJid(feature.get('from')));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
api.listen.on('clearsession', () => {
|
||||
const view = _converse.chatboxviews.get('controlbox');
|
||||
if (view && view.roomspanel) {
|
||||
|
@ -67,14 +85,6 @@ converse.plugins.add('converse-muc-views', {
|
|||
}
|
||||
});
|
||||
|
||||
api.listen.on('controlBoxInitialized', view => {
|
||||
if (!api.settings.get('allow_muc')) {
|
||||
return;
|
||||
}
|
||||
fetchAndSetMUCDomain(view);
|
||||
view.model.on('change:connected', () => fetchAndSetMUCDomain(view));
|
||||
});
|
||||
|
||||
api.listen.on('chatBoxClosed', (model) => {
|
||||
if (model.get('type') === _converse.CHATROOMS_TYPE) {
|
||||
clearHistory(model.get('jid'));
|
||||
|
|
|
@ -74,23 +74,23 @@ export default BootstrapModal.extend({
|
|||
this.loading_items = false;
|
||||
|
||||
BootstrapModal.prototype.initialize.apply(this, arguments);
|
||||
if (api.settings.get('muc_domain') && !this.model.get('muc_domain')) {
|
||||
this.model.save('muc_domain', api.settings.get('muc_domain'));
|
||||
}
|
||||
this.listenTo(this.model, 'change:muc_domain', this.onDomainChange);
|
||||
this.listenTo(this.model, 'change:feedback_text', () => this.render());
|
||||
|
||||
|
||||
this.el.addEventListener('shown.bs.modal', () => api.settings.get('locked_muc_domain')
|
||||
? this.updateRoomsList()
|
||||
: this.el.querySelector('input[name="server"]').focus()
|
||||
);
|
||||
|
||||
this.model.save('feedback_text', '');
|
||||
},
|
||||
|
||||
toHTML () {
|
||||
const muc_domain = this.model.get('muc_domain') || api.settings.get('muc_domain');
|
||||
return tpl_muc_list(
|
||||
Object.assign(this.model.toJSON(), {
|
||||
'show_form': !api.settings.get('locked_muc_domain'),
|
||||
'server_placeholder': muc_domain ? muc_domain : __('conference.example.org'),
|
||||
'server_placeholder': this.model.get('muc_domain') || __('conference.example.org'),
|
||||
'items': this.items,
|
||||
'loading_items': this.loading_items,
|
||||
'openRoom': ev => this.openRoom(ev),
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
/*global mock, converse */
|
||||
|
||||
describe("Service Discovery", function () {
|
||||
|
||||
it("can be used to set the muc_domain", mock.initConverse( ['discoInitialized'], {}, async function (_converse) {
|
||||
const { u, $iq } = converse.env;
|
||||
const IQ_stanzas = _converse.connection.IQ_stanzas;
|
||||
const IQ_ids = _converse.connection.IQ_ids;
|
||||
const { api } = _converse;
|
||||
|
||||
expect(api.settings.get('muc_domain')).toBe(undefined);
|
||||
|
||||
await u.waitUntil(() => IQ_stanzas.filter(
|
||||
(iq) => iq.querySelector(`iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]`)).length > 0
|
||||
);
|
||||
|
||||
let stanza = IQ_stanzas.find((iq) => iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]'));
|
||||
const info_IQ_id = IQ_ids[IQ_stanzas.indexOf(stanza)];
|
||||
stanza = $iq({
|
||||
'type': 'result',
|
||||
'from': 'montague.lit',
|
||||
'to': 'romeo@montague.lit/orchard',
|
||||
'id': info_IQ_id
|
||||
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
|
||||
.c('identity', { 'category': 'server', 'type': 'im'}).up()
|
||||
.c('identity', { 'category': 'conference', 'name': 'Play-Specific Chatrooms'}).up()
|
||||
.c('feature', { 'var': 'http://jabber.org/protocol/disco#info'}).up()
|
||||
.c('feature', { 'var': 'http://jabber.org/protocol/disco#items'}).up();
|
||||
_converse.connection._dataRecv(mock.createRequest(stanza));
|
||||
|
||||
const entities = await _converse.api.disco.entities.get();
|
||||
expect(entities.length).toBe(2); // We have an extra entity, which is the user's JID
|
||||
expect(entities.get(_converse.domain).identities.length).toBe(2);
|
||||
expect(entities.get('montague.lit').features.where(
|
||||
{'var': 'http://jabber.org/protocol/disco#items'}).length).toBe(1);
|
||||
expect(entities.get('montague.lit').features.where(
|
||||
{'var': 'http://jabber.org/protocol/disco#info'}).length).toBe(1);
|
||||
|
||||
stanza = await u.waitUntil(() => IQ_stanzas.filter(
|
||||
iq => iq.querySelector('iq[to="montague.lit"] query[xmlns="http://jabber.org/protocol/disco#items"]')).pop()
|
||||
);
|
||||
|
||||
_converse.connection._dataRecv(mock.createRequest($iq({
|
||||
'type': 'result',
|
||||
'from': 'montague.lit',
|
||||
'to': 'romeo@montague.lit/orchard',
|
||||
'id': IQ_ids[IQ_stanzas.indexOf(stanza)]
|
||||
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#items'})
|
||||
.c('item', { 'jid': 'chat.shakespeare.lit', 'name': 'Chatroom Service'})));
|
||||
|
||||
stanza = await u.waitUntil(() => IQ_stanzas.filter(
|
||||
iq => iq.querySelector('iq[to="chat.shakespeare.lit"] query[xmlns="http://jabber.org/protocol/disco#info"]')).pop()
|
||||
);
|
||||
_converse.connection._dataRecv(mock.createRequest($iq({
|
||||
'type': 'result',
|
||||
'from': 'chat.shakespeare.lit',
|
||||
'to': 'romeo@montague.lit/orchard',
|
||||
'id': IQ_ids[IQ_stanzas.indexOf(stanza)]
|
||||
}).c('query', {'xmlns': 'http://jabber.org/protocol/disco#info'})
|
||||
.c('identity', { 'category': 'conference', 'name': 'Play-Specific Chatrooms', 'type': 'text'}).up()
|
||||
.c('feature', { 'var': 'http://jabber.org/protocol/muc'}).up()));
|
||||
|
||||
await u.waitUntil(() => _converse.api.settings.get('muc_domain') === 'chat.shakespeare.lit');
|
||||
}));
|
||||
});
|
|
@ -61,51 +61,6 @@ export async function destroyMUC (model) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function setMUCDomain (domain, controlboxview) {
|
||||
controlboxview.querySelector('converse-rooms-list')
|
||||
.model.save('muc_domain', Strophe.getDomainFromJid(domain));
|
||||
}
|
||||
|
||||
function setMUCDomainFromDisco (controlboxview) {
|
||||
/* Check whether service discovery for the user's domain
|
||||
* returned MUC information and use that to automatically
|
||||
* set the MUC domain in the "Add groupchat" modal.
|
||||
*/
|
||||
function featureAdded (feature) {
|
||||
if (!feature) {
|
||||
return;
|
||||
}
|
||||
if (feature.get('var') === Strophe.NS.MUC) {
|
||||
feature.entity.getIdentity('conference', 'text').then(identity => {
|
||||
if (identity) {
|
||||
setMUCDomain(feature.get('from'), controlboxview);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
api.waitUntil('discoInitialized')
|
||||
.then(() => {
|
||||
api.listen.on('serviceDiscovered', featureAdded);
|
||||
// Features could have been added before the controlbox was
|
||||
// initialized. We're only interested in MUC
|
||||
_converse.disco_entities.each(entity => featureAdded(entity.features.findWhere({ 'var': Strophe.NS.MUC })));
|
||||
})
|
||||
.catch(e => log.error(e));
|
||||
}
|
||||
|
||||
export function fetchAndSetMUCDomain (controlboxview) {
|
||||
if (controlboxview.model.get('connected')) {
|
||||
if (!controlboxview.querySelector('converse-rooms-list').model.get('muc_domain')) {
|
||||
if (api.settings.get('muc_domain') === undefined) {
|
||||
setMUCDomainFromDisco(controlboxview);
|
||||
} else {
|
||||
setMUCDomain(api.settings.get('muc_domain'), controlboxview);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function getNicknameRequiredTemplate (model) {
|
||||
const jid = model.get('jid');
|
||||
if (api.settings.get('muc_show_logs_before_join')) {
|
||||
|
|
|
@ -7,23 +7,17 @@
|
|||
*/
|
||||
import "@converse/headless/plugins/muc/index.js";
|
||||
import './view.js';
|
||||
import { api, converse } from "@converse/headless/core";
|
||||
import { converse } from "@converse/headless/core";
|
||||
|
||||
|
||||
converse.plugins.add('converse-roomslist', {
|
||||
|
||||
dependencies: ["converse-singleton", "converse-controlbox", "converse-muc", "converse-bookmarks"],
|
||||
dependencies: [
|
||||
"converse-singleton",
|
||||
"converse-controlbox",
|
||||
"converse-muc",
|
||||
"converse-bookmarks"
|
||||
],
|
||||
|
||||
initialize () {
|
||||
// Event handlers
|
||||
api.listen.on('connected', async () => {
|
||||
if (api.settings.get('allow_bookmarks')) {
|
||||
await api.waitUntil('bookmarksInitialized');
|
||||
} else {
|
||||
await Promise.all([
|
||||
api.waitUntil('chatBoxesFetched'),
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
initialize () { }
|
||||
});
|
||||
|
|
|
@ -4,6 +4,7 @@ import { _converse, api, converse } from "@converse/headless/core";
|
|||
const { Strophe } = converse.env;
|
||||
|
||||
const RoomsListModel = Model.extend({
|
||||
|
||||
defaults: function () {
|
||||
return {
|
||||
'muc_domain': api.settings.get('muc_domain'),
|
||||
|
@ -12,6 +13,10 @@ const RoomsListModel = Model.extend({
|
|||
};
|
||||
},
|
||||
|
||||
initialize () {
|
||||
api.settings.listen.on('change:muc_domain', (muc_domain) => this.setDomain(muc_domain));
|
||||
},
|
||||
|
||||
setDomain (jid) {
|
||||
if (!api.settings.get('locked_muc_domain')) {
|
||||
this.save('muc_domain', Strophe.getDomainFromJid(jid));
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
// connection_options: { 'worker': '/dist/shared-connection-worker.js' },
|
||||
// persistent_store: 'IndexedDB',
|
||||
message_archiving: 'always',
|
||||
muc_domain: 'conference.chat.example.org',
|
||||
// muc_domain: 'conference.chat.example.org',
|
||||
muc_respect_autojoin: true,
|
||||
view_mode: 'fullscreen',
|
||||
websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
|
||||
|
|
Loading…
Reference in New Issue