parent
55bb1826ea
commit
f64fdb8088
98
dist/converse.js
vendored
98
dist/converse.js
vendored
@ -56433,13 +56433,6 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||
|
||||
this.model.on('change:omemo_active', this.renderOMEMOToolbarButton, this);
|
||||
this.model.on('change:omemo_supported', this.onOMEMOSupportedDetermined, this);
|
||||
this.checkOMEMOSupported();
|
||||
},
|
||||
|
||||
async checkOMEMOSupported() {
|
||||
const _converse = this.__super__._converse;
|
||||
const supported = await _converse.contactHasOMEMOSupport(this.model.get('jid'));
|
||||
this.model.set('omemo_supported', supported);
|
||||
},
|
||||
|
||||
showMessage(message) {
|
||||
@ -56486,6 +56479,33 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||
});
|
||||
}
|
||||
|
||||
},
|
||||
ChatRoomView: {
|
||||
events: {
|
||||
'click .toggle-omemo': 'toggleOMEMO'
|
||||
},
|
||||
|
||||
initialize() {
|
||||
this.__super__.initialize.apply(this, arguments);
|
||||
|
||||
this.model.on('change:omemo_active', this.renderOMEMOToolbarButton, this);
|
||||
this.model.on('change:omemo_supported', this.onOMEMOSupportedDetermined, this);
|
||||
},
|
||||
|
||||
toggleOMEMO(ev) {
|
||||
const _converse = this.__super__._converse,
|
||||
__ = _converse.__;
|
||||
|
||||
if (!this.model.get('omemo_supported')) {
|
||||
return _converse.api.alert.show(Strophe.LogLevel.ERROR, __('Error'), [__('Cannot use end-to-end encryption in this groupchat, ' + 'either the groupchat has some anonymity or not all participants support OMEMO.')]);
|
||||
}
|
||||
|
||||
ev.preventDefault();
|
||||
this.model.save({
|
||||
'omemo_active': !this.model.get('omemo_active')
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
|
||||
@ -56493,7 +56513,8 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||
/* The initialize function gets called as soon as the plugin is
|
||||
* loaded by Converse.js's plugin machinery.
|
||||
*/
|
||||
const _converse = this._converse;
|
||||
const _converse = this._converse,
|
||||
__ = _converse.__;
|
||||
|
||||
_converse.api.promises.add(['OMEMOInitialized']);
|
||||
|
||||
@ -57134,6 +57155,49 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_0__["default"].plugins
|
||||
fetchOwnDevices().then(() => restoreOMEMOSession()).then(() => _converse.omemo_store.publishBundle()).then(() => _converse.emit('OMEMOInitialized')).catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||
}
|
||||
|
||||
async function onOccupantAdded(chatroom, occupant) {
|
||||
if (occupant.isSelf() || !chatroom.get('nonanonymous')) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (chatroom.get('omemo_active')) {
|
||||
const supported = await _converse.contactHasOMEMOSupport(occupant.get('jid'));
|
||||
|
||||
if (!supported) {
|
||||
chatroom.messages.create({
|
||||
'message': __("%1$s doesn't appear to have a client that supports OMEMO. " + "Encrypted chat will no longer be possible in this grouchat.", occupant.get('nick')),
|
||||
'type': 'error'
|
||||
});
|
||||
chatroom.save({
|
||||
'omemo_active': false,
|
||||
'omemo_supported': false
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function checkOMEMOSupported(chatbox) {
|
||||
let supported;
|
||||
|
||||
if (chatbox.get('type') === _converse.CHATROOMS_TYPE) {
|
||||
supported = chatbox.get('nonanonymous') && chatbox.get('membersonly');
|
||||
} else if (chatbox.get('type') === _converse.PRIVATE_CHAT_TYPE) {
|
||||
supported = await _converse.contactHasOMEMOSupport(chatbox.get('jid'));
|
||||
}
|
||||
|
||||
chatbox.set('omemo_supported', supported);
|
||||
}
|
||||
|
||||
_converse.api.waitUntil('chatBoxesInitialized').then(() => _converse.chatboxes.on('add', chatbox => {
|
||||
checkOMEMOSupported(chatbox);
|
||||
|
||||
if (chatbox.get('type') === _converse.CHATROOMS_TYPE) {
|
||||
chatbox.occupants.on('add', o => onOccupantAdded(chatbox, o));
|
||||
chatbox.on('change:nonanonymous', checkOMEMOSupported);
|
||||
chatbox.on('change:membersonly', checkOMEMOSupported);
|
||||
}
|
||||
}));
|
||||
|
||||
_converse.api.listen.on('afterTearDown', () => {
|
||||
if (_converse.devicelists) {
|
||||
_converse.devicelists.reset();
|
||||
@ -65885,7 +65949,23 @@ Strophe.addNamespace('MUC_REGISTER', "jabber:iq:register");
|
||||
Strophe.addNamespace('MUC_ROOMCONF', Strophe.NS.MUC + "#roomconfig");
|
||||
Strophe.addNamespace('MUC_USER', Strophe.NS.MUC + "#user");
|
||||
_converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].MUC_NICK_CHANGED_CODE = "303";
|
||||
_converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].ROOM_FEATURES = ['passwordprotected', 'unsecured', 'hidden', 'publicroom', 'membersonly', 'open', 'persistent', 'temporary', 'nonanonymous', 'semianonymous', 'moderated', 'unmoderated', 'mam_enabled'];
|
||||
_converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].ROOM_FEATURES = ['passwordprotected', 'unsecured', 'hidden', 'publicroom', 'membersonly', 'open', 'persistent', 'temporary', 'nonanonymous', 'semianonymous', 'moderated', 'unmoderated', 'mam_enabled']; // No longer used in code, but useful as reference.
|
||||
//
|
||||
// const ROOM_FEATURES_MAP = {
|
||||
// 'passwordprotected': 'unsecured',
|
||||
// 'unsecured': 'passwordprotected',
|
||||
// 'hidden': 'publicroom',
|
||||
// 'publicroom': 'hidden',
|
||||
// 'membersonly': 'open',
|
||||
// 'open': 'membersonly',
|
||||
// 'persistent': 'temporary',
|
||||
// 'temporary': 'persistent',
|
||||
// 'nonanonymous': 'semianonymous',
|
||||
// 'semianonymous': 'nonanonymous',
|
||||
// 'moderated': 'unmoderated',
|
||||
// 'unmoderated': 'moderated'
|
||||
// };
|
||||
|
||||
_converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].ROOMSTATUS = {
|
||||
CONNECTED: 0,
|
||||
CONNECTING: 1,
|
||||
|
190
spec/omemo.js
190
spec/omemo.js
@ -1,12 +1,8 @@
|
||||
(function (root, factory) {
|
||||
define(["jasmine", "mock", "test-utils"], factory);
|
||||
} (this, function (jasmine, mock, test_utils) {
|
||||
var Strophe = converse.env.Strophe;
|
||||
var b64_sha1 = converse.env.b64_sha1;
|
||||
var $iq = converse.env.$iq;
|
||||
var $msg = converse.env.$msg;
|
||||
var _ = converse.env._;
|
||||
var u = converse.env.utils;
|
||||
const { $iq, $pres, $msg, _, Strophe } = converse.env;
|
||||
const u = converse.env.utils;
|
||||
|
||||
|
||||
function deviceListFetched (_converse, jid) {
|
||||
@ -229,7 +225,6 @@
|
||||
done();
|
||||
}));
|
||||
|
||||
|
||||
it("can receive a PreKeySignalMessage",
|
||||
mock.initConverseWithPromises(
|
||||
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {},
|
||||
@ -824,6 +819,187 @@
|
||||
done();
|
||||
}));
|
||||
|
||||
it("adds a toolbar button for starting an encrypted groupchat session",
|
||||
mock.initConverseWithPromises(
|
||||
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {'view_mode': 'fullscreen'},
|
||||
async function (done, _converse) {
|
||||
|
||||
// MEMO encryption works only in members-only conferences that are non-anonymous.
|
||||
const features = [
|
||||
'http://jabber.org/protocol/muc',
|
||||
'jabber:iq:register',
|
||||
'muc_passwordprotected',
|
||||
'muc_hidden',
|
||||
'muc_temporary',
|
||||
'muc_membersonly',
|
||||
'muc_unmoderated',
|
||||
'muc_nonanonymous'
|
||||
];
|
||||
await test_utils.openAndEnterChatRoom(_converse, 'lounge', 'localhost', 'dummy', features);
|
||||
const view = _converse.chatboxviews.get('lounge@localhost');
|
||||
await test_utils.waitUntil(() => initializedOMEMO(_converse));
|
||||
|
||||
const toolbar = view.el.querySelector('.chat-toolbar');
|
||||
let toggle = toolbar.querySelector('.toggle-omemo');
|
||||
expect(view.model.get('omemo_active')).toBe(undefined);
|
||||
expect(_.isNull(toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
||||
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
||||
expect(u.hasClass('disabled', toggle)).toBe(false);
|
||||
expect(view.model.get('omemo_supported')).toBe(true);
|
||||
|
||||
toggle.click();
|
||||
toggle = toolbar.querySelector('.toggle-omemo');
|
||||
expect(view.model.get('omemo_active')).toBe(true);
|
||||
expect(u.hasClass('fa-unlock', toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-lock', toggle)).toBe(true);
|
||||
expect(u.hasClass('disabled', toggle)).toBe(false);
|
||||
expect(view.model.get('omemo_supported')).toBe(true);
|
||||
|
||||
let contact_jid = 'newguy@localhost';
|
||||
let stanza = $pres({
|
||||
to: 'dummy@localhost/resource',
|
||||
from: 'lounge@localhost/newguy'
|
||||
})
|
||||
.c('x', {xmlns: Strophe.NS.MUC_USER})
|
||||
.c('item', {
|
||||
'affiliation': 'none',
|
||||
'jid': 'newguy@localhost/_converse.js-290929789',
|
||||
'role': 'participant'
|
||||
}).tree();
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
|
||||
let iq_stanza = await test_utils.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
||||
expect(iq_stanza.toLocaleString()).toBe(
|
||||
`<iq from="dummy@localhost" id="${iq_stanza.nodeTree.getAttribute("id")}" to="${contact_jid}" type="get" xmlns="jabber:client">`+
|
||||
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
||||
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
||||
`</pubsub>`+
|
||||
`</iq>`);
|
||||
|
||||
stanza = $iq({
|
||||
'from': contact_jid,
|
||||
'id': iq_stanza.nodeTree.getAttribute('id'),
|
||||
'to': _converse.bare_jid,
|
||||
'type': 'result',
|
||||
}).c('pubsub', {'xmlns': "http://jabber.org/protocol/pubsub"})
|
||||
.c('items', {'node': "eu.siacs.conversations.axolotl.devicelist"})
|
||||
.c('item', {'xmlns': "http://jabber.org/protocol/pubsub"}) // TODO: must have an id attribute
|
||||
.c('list', {'xmlns': "eu.siacs.conversations.axolotl"})
|
||||
.c('device', {'id': '4e30f35051b7b8b42abe083742187228'}).up()
|
||||
.c('device', {'id': 'ae890ac52d0df67ed7cfdf51b644e901'});
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
await test_utils.waitUntil(() => _converse.omemo_store);
|
||||
expect(_converse.devicelists.length).toBe(2);
|
||||
|
||||
const devicelist = _converse.devicelists.get(contact_jid);
|
||||
expect(devicelist.devices.length).toBe(2);
|
||||
expect(devicelist.devices.at(0).get('id')).toBe('4e30f35051b7b8b42abe083742187228');
|
||||
expect(devicelist.devices.at(1).get('id')).toBe('ae890ac52d0df67ed7cfdf51b644e901');
|
||||
|
||||
expect(view.model.get('omemo_active')).toBe(true);
|
||||
toggle = toolbar.querySelector('.toggle-omemo');
|
||||
expect(_.isNull(toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-unlock', toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-lock', toggle)).toBe(true);
|
||||
expect(u.hasClass('disabled', toggle)).toBe(false);
|
||||
expect(view.model.get('omemo_supported')).toBe(true);
|
||||
|
||||
// Test that the button gets disabled when the room becomes
|
||||
// anonymous or semi-anonymous
|
||||
view.model.save({'nonanonymous': false, 'semianonymous': true});
|
||||
await test_utils.waitUntil(() => !view.model.get('omemo_supported'));
|
||||
toggle = toolbar.querySelector('.toggle-omemo');
|
||||
expect(_.isNull(toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
||||
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
||||
expect(u.hasClass('disabled', toggle)).toBe(true);
|
||||
expect(view.model.get('omemo_supported')).toBe(false);
|
||||
|
||||
view.model.save({'nonanonymous': true, 'semianonymous': false});
|
||||
await test_utils.waitUntil(() => view.model.get('omemo_supported'));
|
||||
toggle = toolbar.querySelector('.toggle-omemo');
|
||||
expect(_.isNull(toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
||||
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
||||
expect(u.hasClass('disabled', toggle)).toBe(false);
|
||||
|
||||
// Test that the button gets disabled when the room becomes open
|
||||
view.model.save({'membersonly': false, 'open': true});
|
||||
await test_utils.waitUntil(() => !view.model.get('omemo_supported'));
|
||||
toggle = toolbar.querySelector('.toggle-omemo');
|
||||
expect(_.isNull(toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
||||
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
||||
expect(u.hasClass('disabled', toggle)).toBe(true);
|
||||
expect(view.model.get('omemo_supported')).toBe(false);
|
||||
|
||||
view.model.save({'membersonly': true, 'open': false});
|
||||
await test_utils.waitUntil(() => view.model.get('omemo_supported'));
|
||||
toggle = toolbar.querySelector('.toggle-omemo');
|
||||
expect(_.isNull(toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
||||
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
||||
expect(u.hasClass('disabled', toggle)).toBe(false);
|
||||
expect(view.model.get('omemo_supported')).toBe(true);
|
||||
expect(view.model.get('omemo_active')).toBe(false);
|
||||
|
||||
toggle.click();
|
||||
expect(view.model.get('omemo_active')).toBe(true);
|
||||
|
||||
// Someone enters the room who doesn't have OMEMO support, while we
|
||||
// have OMEMO activated...
|
||||
contact_jid = 'oldguy@localhost';
|
||||
stanza = $pres({
|
||||
to: 'dummy@localhost/resource',
|
||||
from: 'lounge@localhost/oldguy'
|
||||
})
|
||||
.c('x', {xmlns: Strophe.NS.MUC_USER})
|
||||
.c('item', {
|
||||
'affiliation': 'none',
|
||||
'jid': `${contact_jid}/_converse.js-290929788`,
|
||||
'role': 'participant'
|
||||
}).tree();
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
iq_stanza = await test_utils.waitUntil(() => deviceListFetched(_converse, contact_jid));
|
||||
expect(iq_stanza.toLocaleString()).toBe(
|
||||
`<iq from="dummy@localhost" id="${iq_stanza.nodeTree.getAttribute("id")}" to="${contact_jid}" type="get" xmlns="jabber:client">`+
|
||||
`<pubsub xmlns="http://jabber.org/protocol/pubsub">`+
|
||||
`<items node="eu.siacs.conversations.axolotl.devicelist"/>`+
|
||||
`</pubsub>`+
|
||||
`</iq>`);
|
||||
|
||||
stanza = $iq({
|
||||
'from': contact_jid,
|
||||
'id': iq_stanza.nodeTree.getAttribute('id'),
|
||||
'to': _converse.bare_jid,
|
||||
'type': 'error'
|
||||
}).c('error', {'type': 'cancel'})
|
||||
.c('item-not-found', {'xmlns': "urn:ietf:params:xml:ns:xmpp-stanzas"});
|
||||
_converse.connection._dataRecv(test_utils.createRequest(stanza));
|
||||
|
||||
await test_utils.waitUntil(() => !view.model.get('omemo_supported'));
|
||||
|
||||
expect(view.el.querySelector('.chat-error').textContent).toBe(
|
||||
"oldguy doesn't appear to have a client that supports OMEMO. "+
|
||||
"Encrypted chat will no longer be possible in this grouchat."
|
||||
);
|
||||
|
||||
toggle = toolbar.querySelector('.toggle-omemo');
|
||||
expect(_.isNull(toggle)).toBe(false);
|
||||
expect(u.hasClass('fa-unlock', toggle)).toBe(true);
|
||||
expect(u.hasClass('fa-lock', toggle)).toBe(false);
|
||||
expect(u.hasClass('disabled', toggle)).toBe(true);
|
||||
|
||||
expect( _converse.chatboxviews.el.querySelector('.modal-body p')).toBe(null);
|
||||
toggle.click();
|
||||
const msg = _converse.chatboxviews.el.querySelector('.modal-body p');
|
||||
expect(msg.textContent).toBe(
|
||||
'Cannot use end-to-end encryption in this groupchat, '+
|
||||
'either the groupchat has some anonymity or not all participants support OMEMO.');
|
||||
done();
|
||||
}));
|
||||
|
||||
|
||||
it("shows OMEMO device fingerprints in the user details modal",
|
||||
mock.initConverseWithPromises(
|
||||
|
@ -87,7 +87,7 @@ converse.plugins.add('converse-omemo', {
|
||||
beforeRender () {
|
||||
const { _converse } = this.__super__,
|
||||
device_id = _converse.omemo_store.get('device_id');
|
||||
|
||||
|
||||
if (device_id) {
|
||||
this.current_device = this.devicelist.devices.get(device_id);
|
||||
}
|
||||
@ -458,14 +458,8 @@ converse.plugins.add('converse-omemo', {
|
||||
this.__super__.initialize.apply(this, arguments);
|
||||
this.model.on('change:omemo_active', this.renderOMEMOToolbarButton, this);
|
||||
this.model.on('change:omemo_supported', this.onOMEMOSupportedDetermined, this);
|
||||
this.checkOMEMOSupported();
|
||||
},
|
||||
|
||||
async checkOMEMOSupported () {
|
||||
const { _converse } = this.__super__;
|
||||
const supported = await _converse.contactHasOMEMOSupport(this.model.get('jid'));
|
||||
this.model.set('omemo_supported', supported);
|
||||
},
|
||||
|
||||
showMessage (message) {
|
||||
// We don't show a message if it's only keying material
|
||||
@ -503,12 +497,38 @@ converse.plugins.add('converse-omemo', {
|
||||
__('Error'),
|
||||
[__("Cannot use end-to-end encryption because %1$s uses a client that doesn't support OMEMO.",
|
||||
this.model.contact.getDisplayName()
|
||||
)]
|
||||
)]
|
||||
)
|
||||
}
|
||||
ev.preventDefault();
|
||||
this.model.save({'omemo_active': !this.model.get('omemo_active')});
|
||||
}
|
||||
},
|
||||
|
||||
ChatRoomView: {
|
||||
events: {
|
||||
'click .toggle-omemo': 'toggleOMEMO'
|
||||
},
|
||||
|
||||
initialize () {
|
||||
this.__super__.initialize.apply(this, arguments);
|
||||
this.model.on('change:omemo_active', this.renderOMEMOToolbarButton, this);
|
||||
this.model.on('change:omemo_supported', this.onOMEMOSupportedDetermined, this);
|
||||
},
|
||||
|
||||
toggleOMEMO (ev) {
|
||||
const { _converse } = this.__super__, { __ } = _converse;
|
||||
if (!this.model.get('omemo_supported')) {
|
||||
return _converse.api.alert.show(
|
||||
Strophe.LogLevel.ERROR,
|
||||
__('Error'),
|
||||
[__('Cannot use end-to-end encryption in this groupchat, '+
|
||||
'either the groupchat has some anonymity or not all participants support OMEMO.')]
|
||||
);
|
||||
}
|
||||
ev.preventDefault();
|
||||
this.model.save({'omemo_active': !this.model.get('omemo_active')});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@ -516,7 +536,8 @@ converse.plugins.add('converse-omemo', {
|
||||
/* The initialize function gets called as soon as the plugin is
|
||||
* loaded by Converse.js's plugin machinery.
|
||||
*/
|
||||
const { _converse } = this;
|
||||
const { _converse } = this,
|
||||
{ __ } = _converse;
|
||||
|
||||
_converse.api.promises.add(['OMEMOInitialized']);
|
||||
|
||||
@ -1070,6 +1091,45 @@ converse.plugins.add('converse-omemo', {
|
||||
.catch(_.partial(_converse.log, _, Strophe.LogLevel.ERROR));
|
||||
}
|
||||
|
||||
async function onOccupantAdded (chatroom, occupant) {
|
||||
if (occupant.isSelf() || !chatroom.get('nonanonymous')) {
|
||||
return;
|
||||
}
|
||||
if (chatroom.get('omemo_active')) {
|
||||
const supported = await _converse.contactHasOMEMOSupport(occupant.get('jid'));
|
||||
if (!supported) {
|
||||
chatroom.messages.create({
|
||||
'message': __("%1$s doesn't appear to have a client that supports OMEMO. " +
|
||||
"Encrypted chat will no longer be possible in this grouchat.", occupant.get('nick')),
|
||||
'type': 'error'
|
||||
});
|
||||
chatroom.save({'omemo_active': false, 'omemo_supported': false});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function checkOMEMOSupported (chatbox) {
|
||||
let supported;
|
||||
if (chatbox.get('type') === _converse.CHATROOMS_TYPE) {
|
||||
supported = chatbox.get('nonanonymous') && chatbox.get('membersonly');
|
||||
} else if (chatbox.get('type') === _converse.PRIVATE_CHAT_TYPE) {
|
||||
supported = await _converse.contactHasOMEMOSupport(chatbox.get('jid'));
|
||||
}
|
||||
chatbox.set('omemo_supported', supported);
|
||||
}
|
||||
|
||||
_converse.api.waitUntil('chatBoxesInitialized').then(() =>
|
||||
_converse.chatboxes.on('add', chatbox => {
|
||||
checkOMEMOSupported(chatbox);
|
||||
if (chatbox.get('type') === _converse.CHATROOMS_TYPE) {
|
||||
chatbox.occupants.on('add', o => onOccupantAdded(chatbox, o));
|
||||
chatbox.on('change:nonanonymous', checkOMEMOSupported);
|
||||
chatbox.on('change:membersonly', checkOMEMOSupported);
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
_converse.api.listen.on('afterTearDown', () => {
|
||||
if (_converse.devicelists) {
|
||||
_converse.devicelists.reset();
|
||||
|
@ -38,6 +38,23 @@ converse.ROOM_FEATURES = [
|
||||
'moderated', 'unmoderated', 'mam_enabled'
|
||||
];
|
||||
|
||||
// No longer used in code, but useful as reference.
|
||||
//
|
||||
// const ROOM_FEATURES_MAP = {
|
||||
// 'passwordprotected': 'unsecured',
|
||||
// 'unsecured': 'passwordprotected',
|
||||
// 'hidden': 'publicroom',
|
||||
// 'publicroom': 'hidden',
|
||||
// 'membersonly': 'open',
|
||||
// 'open': 'membersonly',
|
||||
// 'persistent': 'temporary',
|
||||
// 'temporary': 'persistent',
|
||||
// 'nonanonymous': 'semianonymous',
|
||||
// 'semianonymous': 'nonanonymous',
|
||||
// 'moderated': 'unmoderated',
|
||||
// 'unmoderated': 'moderated'
|
||||
// };
|
||||
|
||||
converse.ROOMSTATUS = {
|
||||
CONNECTED: 0,
|
||||
CONNECTING: 1,
|
||||
|
Loading…
Reference in New Issue
Block a user