parent
2ddd918f6a
commit
d3a4555165
@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
## 4.1.3 (Unreleased)
|
## 4.1.3 (Unreleased)
|
||||||
|
|
||||||
|
- New config setting [locked_muc_domain](https://conversejs.org/docs/html/configuration.html#locked-muc-domain)
|
||||||
|
- #1373: Re-add support for the [muc_domain](https://conversejs.org/docs/html/configuration.html#muc-domain) setting
|
||||||
- #1437: List of groupchats in modal doesn't scroll
|
- #1437: List of groupchats in modal doesn't scroll
|
||||||
|
|
||||||
## 4.1.2 (2019-02-22)
|
## 4.1.2 (2019-02-22)
|
||||||
@ -23,7 +25,7 @@
|
|||||||
- Bugfix: MUC invite form not appearing
|
- Bugfix: MUC invite form not appearing
|
||||||
- #1369 Don't wrongly interpret message with `subject` as a topic change.
|
- #1369 Don't wrongly interpret message with `subject` as a topic change.
|
||||||
- #1405 Status of contacts list are not displayed properly
|
- #1405 Status of contacts list are not displayed properly
|
||||||
- #1408 New config option `roomconfig_whitelist`
|
- #1408 New config option [roomconfig_whitelist](https://conversejs.org/docs/html/configuration.html#roomconfig-whitelist)
|
||||||
- #1410 HTTP upload not working if conversations push proxy is used
|
- #1410 HTTP upload not working if conversations push proxy is used
|
||||||
- #1412 MUC moderator commands can be disabled selectively by config
|
- #1412 MUC moderator commands can be disabled selectively by config
|
||||||
- #1413 Fix moderator commands that change affiliation
|
- #1413 Fix moderator commands that change affiliation
|
||||||
|
67
dist/converse.js
vendored
67
dist/converse.js
vendored
@ -53303,6 +53303,8 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
|
|||||||
_converse.api.settings.update({
|
_converse.api.settings.update({
|
||||||
'auto_list_rooms': false,
|
'auto_list_rooms': false,
|
||||||
'muc_disable_moderator_commands': false,
|
'muc_disable_moderator_commands': false,
|
||||||
|
'muc_domain': undefined,
|
||||||
|
'locked_muc_domain': undefined,
|
||||||
'muc_show_join_leave': true,
|
'muc_show_join_leave': true,
|
||||||
'roomconfig_whitelist': [],
|
'roomconfig_whitelist': [],
|
||||||
'visible_toolbar_buttons': {
|
'visible_toolbar_buttons': {
|
||||||
@ -53310,6 +53312,10 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (_converse.locked_muc_domain && !_.isString(_converse.muc_domain)) {
|
||||||
|
throw new Error("Config Error: it makes no sense to set locked_muc_domain " + "to true when muc_domain is not set");
|
||||||
|
}
|
||||||
|
|
||||||
function ___(str) {
|
function ___(str) {
|
||||||
/* This is part of a hack to get gettext to scan strings to be
|
/* This is part of a hack to get gettext to scan strings to be
|
||||||
* translated. Strings we cannot send to the function above because
|
* translated. Strings we cannot send to the function above because
|
||||||
@ -53459,22 +53465,31 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
|
|||||||
initialize() {
|
initialize() {
|
||||||
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
|
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
|
if (_converse.muc_domain && !this.model.get('muc_domain')) {
|
||||||
|
this.model.save('muc_domain', _converse.muc_domain);
|
||||||
|
}
|
||||||
|
|
||||||
this.model.on('change:muc_domain', this.onDomainChange, this);
|
this.model.on('change:muc_domain', this.onDomainChange, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
toHTML() {
|
toHTML() {
|
||||||
|
const muc_domain = this.model.get('muc_domain') || _converse.muc_domain;
|
||||||
|
|
||||||
return templates_list_chatrooms_modal_html__WEBPACK_IMPORTED_MODULE_19___default()(_.extend(this.model.toJSON(), {
|
return templates_list_chatrooms_modal_html__WEBPACK_IMPORTED_MODULE_19___default()(_.extend(this.model.toJSON(), {
|
||||||
'heading_list_chatrooms': __('Query for Groupchats'),
|
'heading_list_chatrooms': __('Query for Groupchats'),
|
||||||
'label_server_address': __('Server address'),
|
'label_server_address': __('Server address'),
|
||||||
'label_query': __('Show groupchats'),
|
'label_query': __('Show groupchats'),
|
||||||
'server_placeholder': __('conference.example.org')
|
'show_form': !_converse.locked_muc_domain,
|
||||||
|
'server_placeholder': muc_domain ? muc_domain : __('conference.example.org')
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
afterRender() {
|
afterRender() {
|
||||||
this.el.addEventListener('shown.bs.modal', () => {
|
if (_converse.locked_muc_domain) {
|
||||||
this.el.querySelector('input[name="server"]').focus();
|
this.updateRoomsList();
|
||||||
}, false);
|
} else {
|
||||||
|
this.el.addEventListener('shown.bs.modal', () => this.el.querySelector('input[name="server"]').focus(), false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
openRoom(ev) {
|
openRoom(ev) {
|
||||||
@ -53588,12 +53603,26 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
|
|||||||
'submit form.add-chatroom': 'openChatRoom'
|
'submit form.add-chatroom': 'openChatRoom'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initialize() {
|
||||||
|
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
|
||||||
|
|
||||||
|
this.model.on('change:muc_domain', this.render, this);
|
||||||
|
},
|
||||||
|
|
||||||
toHTML() {
|
toHTML() {
|
||||||
|
let placeholder = '';
|
||||||
|
|
||||||
|
if (!_converse.locked_muc_domain) {
|
||||||
|
const muc_domain = this.model.get('muc_domain') || _converse.muc_domain;
|
||||||
|
|
||||||
|
placeholder = muc_domain ? `name@${muc_domain}` : __('name@conference.example.org');
|
||||||
|
}
|
||||||
|
|
||||||
return templates_add_chatroom_modal_html__WEBPACK_IMPORTED_MODULE_5___default()(_.extend(this.model.toJSON(), {
|
return templates_add_chatroom_modal_html__WEBPACK_IMPORTED_MODULE_5___default()(_.extend(this.model.toJSON(), {
|
||||||
'heading_new_chatroom': __('Enter a new Groupchat'),
|
'heading_new_chatroom': __('Enter a new Groupchat'),
|
||||||
'label_room_address': __('Groupchat address'),
|
'label_room_address': _converse.muc_domain ? __('Groupchat name') : __('Groupchat address'),
|
||||||
'label_nickname': __('Optional nickname'),
|
'label_nickname': __('Optional nickname'),
|
||||||
'chatroom_placeholder': __('name@conference.example.org'),
|
'chatroom_placeholder': placeholder,
|
||||||
'label_join': __('Join')
|
'label_join': __('Join')
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@ -53623,7 +53652,17 @@ _converse_headless_converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins
|
|||||||
data.nick = undefined;
|
data.nick = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
_converse.api.rooms.open(data.jid, data);
|
let jid;
|
||||||
|
|
||||||
|
if (_converse.locked_muc_domain || _converse.muc_domain && !u.isValidJID(data.jid)) {
|
||||||
|
jid = `${Strophe.escapeNode(data.jid)}@${_converse.muc_domain}`;
|
||||||
|
} else {
|
||||||
|
jid = data.jid;
|
||||||
|
}
|
||||||
|
|
||||||
|
_converse.api.rooms.open(jid, _.extend(data, {
|
||||||
|
jid
|
||||||
|
}));
|
||||||
|
|
||||||
this.modal.hide();
|
this.modal.hide();
|
||||||
ev.target.reset();
|
ev.target.reset();
|
||||||
@ -66093,7 +66132,6 @@ _converse_core__WEBPACK_IMPORTED_MODULE_6__["default"].plugins.add('converse-muc
|
|||||||
auto_join_on_invite: false,
|
auto_join_on_invite: false,
|
||||||
auto_join_rooms: [],
|
auto_join_rooms: [],
|
||||||
auto_register_muc_nickname: false,
|
auto_register_muc_nickname: false,
|
||||||
muc_domain: undefined,
|
|
||||||
muc_history_max_stanzas: undefined,
|
muc_history_max_stanzas: undefined,
|
||||||
muc_instant_rooms: true,
|
muc_instant_rooms: true,
|
||||||
muc_nickname_from_jid: false
|
muc_nickname_from_jid: false
|
||||||
@ -93667,18 +93705,23 @@ return __p
|
|||||||
|
|
||||||
var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")};
|
var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")};
|
||||||
module.exports = function(o) {
|
module.exports = function(o) {
|
||||||
var __t, __p = '', __e = _.escape;
|
var __t, __p = '', __e = _.escape, __j = Array.prototype.join;
|
||||||
|
function print() { __p += __j.call(arguments, '') }
|
||||||
__p += '<!-- src/templates/list_chatrooms_modal.html -->\n<div class="modal fade" id="list-chatrooms-modal" tabindex="-1" role="dialog" aria-labelledby="list-chatrooms-modal-label" aria-hidden="true">\n <div class="modal-dialog" role="document">\n <div class="modal-content">\n <div class="modal-header">\n <h5 class="modal-title"\n id="list-chatrooms-modal-label">' +
|
__p += '<!-- src/templates/list_chatrooms_modal.html -->\n<div class="modal fade" id="list-chatrooms-modal" tabindex="-1" role="dialog" aria-labelledby="list-chatrooms-modal-label" aria-hidden="true">\n <div class="modal-dialog" role="document">\n <div class="modal-content">\n <div class="modal-header">\n <h5 class="modal-title"\n id="list-chatrooms-modal-label">' +
|
||||||
__e(o.heading_list_chatrooms) +
|
__e(o.heading_list_chatrooms) +
|
||||||
'</h5>\n <button type="button" class="close" data-dismiss="modal" aria-label="Close">\n <span aria-hidden="true">×</span>\n </button>\n </div>\n <div class="modal-body d-flex flex-column">\n <form class="converse-form list-chatrooms">\n <div class="form-group">\n <label for="chatroom">' +
|
'</h5>\n <button type="button" class="close" data-dismiss="modal" aria-label="Close">\n <span aria-hidden="true">×</span>\n </button>\n </div>\n <div class="modal-body d-flex flex-column">\n ';
|
||||||
|
if (o.show_form) { ;
|
||||||
|
__p += '\n <form class="converse-form list-chatrooms">\n <div class="form-group">\n <label for="chatroom">' +
|
||||||
__e(o.label_server_address) +
|
__e(o.label_server_address) +
|
||||||
':</label>\n <input type="text" value="' +
|
':</label>\n <input type="text" value="' +
|
||||||
__e(o.muc_domain) +
|
__e(o.muc_domain) +
|
||||||
'" required="required" name="server" class="form-control" placeholder="' +
|
'" required="required" name="server" class="form-control" placeholder="' +
|
||||||
__e(o.server_placeholder) +
|
__e(o.server_placeholder) +
|
||||||
'"/>\n </div>\n <input type="submit" class="btn btn-primary" name="join" value="' +
|
'"/>\n </div>\n <input type="submit" class="btn btn-primary" name="list" value="' +
|
||||||
__e(o.label_query) +
|
__e(o.label_query) +
|
||||||
'"/>\n </form>\n <ul class="available-chatrooms list-group"></ul>\n </div>\n </div>\n </div>\n</div>\n';
|
'"/>\n </form>\n ';
|
||||||
|
} ;
|
||||||
|
__p += '\n <ul class="available-chatrooms list-group"></ul>\n </div>\n </div>\n </div>\n</div>\n';
|
||||||
return __p
|
return __p
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -256,7 +256,8 @@ auto_list_rooms
|
|||||||
* Default: ``false``
|
* Default: ``false``
|
||||||
|
|
||||||
If true, and the XMPP server on which the current user is logged in supports
|
If true, and the XMPP server on which the current user is logged in supports
|
||||||
multi-user chat, then a list of rooms on that server will be fetched.
|
multi-user chat, then a list of rooms on that server will be fetched in the
|
||||||
|
"Query for Groupchats" modal.
|
||||||
|
|
||||||
Not recommended for servers with lots of chatrooms.
|
Not recommended for servers with lots of chatrooms.
|
||||||
|
|
||||||
@ -264,6 +265,10 @@ For each room on the server a query is made to fetch further details (e.g.
|
|||||||
features, number of occupants etc.), so on servers with many rooms this
|
features, number of occupants etc.), so on servers with many rooms this
|
||||||
option will create lots of extra connection traffic.
|
option will create lots of extra connection traffic.
|
||||||
|
|
||||||
|
If the `muc_domain`_ is locked with the `locked_muc_domain`_ setting, then
|
||||||
|
rooms will automatically be fetched in the "Query for Groupchats" modal,
|
||||||
|
regardless of the value of this setting.
|
||||||
|
|
||||||
.. _`auto_login`:
|
.. _`auto_login`:
|
||||||
|
|
||||||
auto_login
|
auto_login
|
||||||
@ -869,6 +874,15 @@ For example, if ``locked_domain`` is set to ``example.org``, then the user
|
|||||||
Additionally, only users registered on the ``example.org`` host can log in, no
|
Additionally, only users registered on the ``example.org`` host can log in, no
|
||||||
other users are allowed to log in.
|
other users are allowed to log in.
|
||||||
|
|
||||||
|
locked_muc_domain
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* Default: ``false``
|
||||||
|
|
||||||
|
This setting allows you to restrict the multi-user chat (MUC) domain to only the value
|
||||||
|
specified in `muc_domain`_.
|
||||||
|
|
||||||
|
|
||||||
message_archiving
|
message_archiving
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
@ -941,11 +955,16 @@ muc_domain
|
|||||||
|
|
||||||
* Default: ``undefined``
|
* Default: ``undefined``
|
||||||
|
|
||||||
The MUC (multi-user chat) domain that should be used. By default Converse
|
The default MUC (multi-user chat) domain that should be used.
|
||||||
will attempt to get the MUC domain from the XMPP host of the currently logged in
|
|
||||||
user.
|
|
||||||
|
|
||||||
This setting will override that.
|
When setting this value, users can only enter the name when opening a new MUC,
|
||||||
|
and don't have to add the whole address (i.e. including the domain part).
|
||||||
|
|
||||||
|
Users can however still enter the domain and they can still open MUCs with
|
||||||
|
other domains.
|
||||||
|
|
||||||
|
If you want to restrict MUCs to only this domain, then set `locked_domain`_ to
|
||||||
|
``true``.
|
||||||
|
|
||||||
muc_history_max_stanzas
|
muc_history_max_stanzas
|
||||||
-----------------------
|
-----------------------
|
||||||
|
166
spec/muc.js
166
spec/muc.js
@ -3958,13 +3958,19 @@
|
|||||||
async function (done, _converse) {
|
async function (done, _converse) {
|
||||||
|
|
||||||
test_utils.openControlBox();
|
test_utils.openControlBox();
|
||||||
_converse.emit('rosterContactsFetched');
|
await test_utils.waitForRoster(_converse, 'current', 0);
|
||||||
|
|
||||||
const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||||
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
||||||
test_utils.closeControlBox(_converse);
|
test_utils.closeControlBox(_converse);
|
||||||
const modal = roomspanel.add_room_modal;
|
const modal = roomspanel.add_room_modal;
|
||||||
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000)
|
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000)
|
||||||
|
|
||||||
|
let label_name = modal.el.querySelector('label[for="chatroom"]');
|
||||||
|
expect(label_name.textContent).toBe('Groupchat address:');
|
||||||
|
let name_input = modal.el.querySelector('input[name="chatroom"]');
|
||||||
|
expect(name_input.placeholder).toBe('name@conference.example.org');
|
||||||
|
|
||||||
expect(modal.el.querySelector('.modal-title').textContent).toBe('Enter a new Groupchat');
|
expect(modal.el.querySelector('.modal-title').textContent).toBe('Enter a new Groupchat');
|
||||||
spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(() => Promise.resolve());
|
spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(() => Promise.resolve());
|
||||||
roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||||
@ -3972,6 +3978,83 @@
|
|||||||
modal.el.querySelector('form input[type="submit"]').click();
|
modal.el.querySelector('form input[type="submit"]').click();
|
||||||
await test_utils.waitUntil(() => _converse.chatboxes.length);
|
await test_utils.waitUntil(() => _converse.chatboxes.length);
|
||||||
await test_utils.waitUntil(() => sizzle('.chatroom', _converse.el).filter(u.isVisible).length === 1);
|
await test_utils.waitUntil(() => sizzle('.chatroom', _converse.el).filter(u.isVisible).length === 1);
|
||||||
|
|
||||||
|
roomspanel.model.set('muc_domain', 'muc.example.org');
|
||||||
|
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
||||||
|
label_name = modal.el.querySelector('label[for="chatroom"]');
|
||||||
|
expect(label_name.textContent).toBe('Groupchat address:');
|
||||||
|
name_input = modal.el.querySelector('input[name="chatroom"]');
|
||||||
|
expect(name_input.placeholder).toBe('name@muc.example.org');
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("doesn't require the domain when muc_domain is set",
|
||||||
|
mock.initConverse(
|
||||||
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {'muc_domain': 'muc.example.org'},
|
||||||
|
async function (done, _converse) {
|
||||||
|
|
||||||
|
test_utils.openControlBox();
|
||||||
|
const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||||
|
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
||||||
|
const modal = roomspanel.add_room_modal;
|
||||||
|
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000)
|
||||||
|
expect(modal.el.querySelector('.modal-title').textContent).toBe('Enter a new Groupchat');
|
||||||
|
spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(() => Promise.resolve());
|
||||||
|
roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||||
|
const label_name = modal.el.querySelector('label[for="chatroom"]');
|
||||||
|
expect(label_name.textContent).toBe('Groupchat name:');
|
||||||
|
let name_input = modal.el.querySelector('input[name="chatroom"]');
|
||||||
|
expect(name_input.placeholder).toBe('name@muc.example.org');
|
||||||
|
name_input.value = 'lounge';
|
||||||
|
modal.el.querySelector('form input[type="submit"]').click();
|
||||||
|
await test_utils.waitUntil(() => _converse.chatboxes.length);
|
||||||
|
await test_utils.waitUntil(() => sizzle('.chatroom', _converse.el).filter(u.isVisible).length === 1);
|
||||||
|
expect(_.includes(_converse.chatboxes.models.map(m => m.get('id')), 'lounge@muc.example.org')).toBe(true);
|
||||||
|
|
||||||
|
// However, you can still open MUCs with different domains
|
||||||
|
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
||||||
|
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000);
|
||||||
|
name_input = modal.el.querySelector('input[name="chatroom"]');
|
||||||
|
name_input.value = 'lounge@conference.example.org';
|
||||||
|
modal.el.querySelector('form input[type="submit"]').click();
|
||||||
|
await test_utils.waitUntil(() => _converse.chatboxes.models.filter(c => c.get('type') === 'chatroom').length === 2);
|
||||||
|
await test_utils.waitUntil(() => sizzle('.chatroom', _converse.el).filter(u.isVisible).length === 2);
|
||||||
|
expect(_.includes(_converse.chatboxes.models.map(m => m.get('id')), 'lounge@conference.example.org')).toBe(true);
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("only uses the muc_domain is locked_muc_domain is true",
|
||||||
|
mock.initConverse(
|
||||||
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'], {'muc_domain': 'muc.example.org', 'locked_muc_domain': true},
|
||||||
|
async function (done, _converse) {
|
||||||
|
|
||||||
|
test_utils.openControlBox();
|
||||||
|
const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||||
|
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
||||||
|
const modal = roomspanel.add_room_modal;
|
||||||
|
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000)
|
||||||
|
expect(modal.el.querySelector('.modal-title').textContent).toBe('Enter a new Groupchat');
|
||||||
|
spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(() => Promise.resolve());
|
||||||
|
roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||||
|
const label_name = modal.el.querySelector('label[for="chatroom"]');
|
||||||
|
expect(label_name.textContent).toBe('Groupchat name:');
|
||||||
|
let name_input = modal.el.querySelector('input[name="chatroom"]');
|
||||||
|
expect(name_input.placeholder).toBe('');
|
||||||
|
name_input.value = 'lounge';
|
||||||
|
modal.el.querySelector('form input[type="submit"]').click();
|
||||||
|
await test_utils.waitUntil(() => _converse.chatboxes.length);
|
||||||
|
await test_utils.waitUntil(() => sizzle('.chatroom', _converse.el).filter(u.isVisible).length === 1);
|
||||||
|
expect(_.includes(_converse.chatboxes.models.map(m => m.get('id')), 'lounge@muc.example.org')).toBe(true);
|
||||||
|
|
||||||
|
// However, you can still open MUCs with different domains
|
||||||
|
roomspanel.el.querySelector('.show-add-muc-modal').click();
|
||||||
|
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000);
|
||||||
|
name_input = modal.el.querySelector('input[name="chatroom"]');
|
||||||
|
name_input.value = 'lounge@conference';
|
||||||
|
modal.el.querySelector('form input[type="submit"]').click();
|
||||||
|
await test_utils.waitUntil(() => _converse.chatboxes.models.filter(c => c.get('type') === 'chatroom').length === 2);
|
||||||
|
await test_utils.waitUntil(() => sizzle('.chatroom', _converse.el).filter(u.isVisible).length === 2);
|
||||||
|
expect(_.includes(_converse.chatboxes.models.map(m => m.get('id')), 'lounge\\40conference@muc.example.org')).toBe(true);
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
});
|
});
|
||||||
@ -4002,7 +4085,9 @@
|
|||||||
// See: http://xmpp.org/extensions/xep-0045.html#disco-rooms
|
// See: http://xmpp.org/extensions/xep-0045.html#disco-rooms
|
||||||
expect(modal.el.querySelectorAll('.available-chatrooms li').length).toBe(0);
|
expect(modal.el.querySelectorAll('.available-chatrooms li').length).toBe(0);
|
||||||
|
|
||||||
const input = modal.el.querySelector('input[name="server"]').value = 'chat.shakespear.lit';
|
const server_input = modal.el.querySelector('input[name="server"]');
|
||||||
|
expect(server_input.placeholder).toBe('conference.example.org');
|
||||||
|
const input = server_input.value = 'chat.shakespear.lit';
|
||||||
modal.el.querySelector('input[type="submit"]').click();
|
modal.el.querySelector('input[type="submit"]').click();
|
||||||
await test_utils.waitUntil(() => _converse.chatboxes.length);
|
await test_utils.waitUntil(() => _converse.chatboxes.length);
|
||||||
expect(sent_stanza.toLocaleString()).toBe(
|
expect(sent_stanza.toLocaleString()).toBe(
|
||||||
@ -4010,7 +4095,6 @@
|
|||||||
`<query xmlns="http://jabber.org/protocol/disco#items"/>`+
|
`<query xmlns="http://jabber.org/protocol/disco#items"/>`+
|
||||||
`</iq>`
|
`</iq>`
|
||||||
);
|
);
|
||||||
|
|
||||||
const iq = $iq({
|
const iq = $iq({
|
||||||
from:'muc.localhost',
|
from:'muc.localhost',
|
||||||
to:'dummy@localhost/pda',
|
to:'dummy@localhost/pda',
|
||||||
@ -4029,13 +4113,19 @@
|
|||||||
.c('item', { jid:'street@chat.shakespeare.lit', name:'A street'}).nodeTree;
|
.c('item', { jid:'street@chat.shakespeare.lit', name:'A street'}).nodeTree;
|
||||||
_converse.connection._dataRecv(test_utils.createRequest(iq));
|
_converse.connection._dataRecv(test_utils.createRequest(iq));
|
||||||
|
|
||||||
await test_utils.waitUntil(() => modal.el.querySelectorAll('.available-chatrooms li').length === 5);
|
await test_utils.waitUntil(() => modal.el.querySelectorAll('.available-chatrooms li').length === 11);
|
||||||
const rooms = modal.el.querySelectorAll('.available-chatrooms li');
|
const rooms = modal.el.querySelectorAll('.available-chatrooms li');
|
||||||
expect(rooms[0].textContent.trim()).toBe("Groupchats found:");
|
expect(rooms[0].textContent.trim()).toBe("Groupchats found:");
|
||||||
expect(rooms[1].textContent.trim()).toBe("A Lonely Heath");
|
expect(rooms[1].textContent.trim()).toBe("A Lonely Heath");
|
||||||
expect(rooms[2].textContent.trim()).toBe("A Dark Cave");
|
expect(rooms[2].textContent.trim()).toBe("A Dark Cave");
|
||||||
expect(rooms[3].textContent.trim()).toBe("The Palace");
|
expect(rooms[3].textContent.trim()).toBe("The Palace");
|
||||||
expect(rooms[4].textContent.trim()).toBe("Macbeth's Castle");
|
expect(rooms[4].textContent.trim()).toBe("Macbeth's Castle");
|
||||||
|
expect(rooms[5].textContent.trim()).toBe('Capulet\'s Orchard');
|
||||||
|
expect(rooms[6].textContent.trim()).toBe('Friar Laurence\'s cell');
|
||||||
|
expect(rooms[7].textContent.trim()).toBe('Hall in Capulet\'s house');
|
||||||
|
expect(rooms[8].textContent.trim()).toBe('Juliet\'s chamber');
|
||||||
|
expect(rooms[9].textContent.trim()).toBe('A public place');
|
||||||
|
expect(rooms[10].textContent.trim()).toBe('A street');
|
||||||
|
|
||||||
rooms[4].querySelector('.open-room').click();
|
rooms[4].querySelector('.open-room').click();
|
||||||
await test_utils.waitUntil(() => _converse.chatboxes.length > 1);
|
await test_utils.waitUntil(() => _converse.chatboxes.length > 1);
|
||||||
@ -4044,6 +4134,71 @@
|
|||||||
expect(view.el.querySelector('.chat-head-chatroom').textContent.trim()).toBe("Macbeth's Castle");
|
expect(view.el.querySelector('.chat-head-chatroom').textContent.trim()).toBe("Macbeth's Castle");
|
||||||
done();
|
done();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
it("is pre-filled with the muc_domain",
|
||||||
|
mock.initConverse(
|
||||||
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'],
|
||||||
|
{'muc_domain': 'muc.example.org'},
|
||||||
|
async function (done, _converse) {
|
||||||
|
|
||||||
|
test_utils.openControlBox();
|
||||||
|
const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||||
|
roomspanel.el.querySelector('.show-list-muc-modal').click();
|
||||||
|
test_utils.closeControlBox(_converse);
|
||||||
|
const modal = roomspanel.list_rooms_modal;
|
||||||
|
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000);
|
||||||
|
const server_input = modal.el.querySelector('input[name="server"]');
|
||||||
|
expect(server_input.value).toBe('muc.example.org');
|
||||||
|
done();
|
||||||
|
}));
|
||||||
|
|
||||||
|
it("doesn't let you set the MUC domain if it's locked",
|
||||||
|
mock.initConverse(
|
||||||
|
null, ['rosterGroupsFetched', 'chatBoxesFetched'],
|
||||||
|
{'muc_domain': 'chat.shakespeare.lit', 'locked_muc_domain': true},
|
||||||
|
async function (done, _converse) {
|
||||||
|
|
||||||
|
test_utils.openControlBox();
|
||||||
|
const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||||
|
roomspanel.el.querySelector('.show-list-muc-modal').click();
|
||||||
|
test_utils.closeControlBox(_converse);
|
||||||
|
const modal = roomspanel.list_rooms_modal;
|
||||||
|
await test_utils.waitUntil(() => u.isVisible(modal.el), 1000);
|
||||||
|
spyOn(_converse.ChatRoom.prototype, 'getRoomFeatures').and.callFake(() => Promise.resolve());
|
||||||
|
roomspanel.delegateEvents(); // We need to rebind all events otherwise our spy won't be called
|
||||||
|
|
||||||
|
expect(modal.el.querySelector('input[name="server"]')).toBe(null);
|
||||||
|
expect(modal.el.querySelector('input[type="submit"]')).toBe(null);
|
||||||
|
await test_utils.waitUntil(() => _converse.chatboxes.length);
|
||||||
|
const sent_stanza = await test_utils.waitUntil(() =>
|
||||||
|
_converse.connection.sent_stanzas.filter(
|
||||||
|
s => sizzle(`query[xmlns="http://jabber.org/protocol/disco#items"]`, s).length).pop()
|
||||||
|
);
|
||||||
|
expect(Strophe.serialize(sent_stanza)).toBe(
|
||||||
|
`<iq from="dummy@localhost/resource" id="${sent_stanza.getAttribute('id')}" `+
|
||||||
|
`to="chat.shakespeare.lit" type="get" xmlns="jabber:client">`+
|
||||||
|
`<query xmlns="http://jabber.org/protocol/disco#items"/>`+
|
||||||
|
`</iq>`
|
||||||
|
);
|
||||||
|
const iq = $iq({
|
||||||
|
from:'muc.localhost',
|
||||||
|
to:'dummy@localhost/pda',
|
||||||
|
id: sent_stanza.getAttribute('id'),
|
||||||
|
type:'result'
|
||||||
|
}).c('query')
|
||||||
|
.c('item', { jid:'heath@chat.shakespeare.lit', name:'A Lonely Heath'}).up()
|
||||||
|
.c('item', { jid:'coven@chat.shakespeare.lit', name:'A Dark Cave'}).up()
|
||||||
|
.c('item', { jid:'forres@chat.shakespeare.lit', name:'The Palace'}).up()
|
||||||
|
_converse.connection._dataRecv(test_utils.createRequest(iq));
|
||||||
|
|
||||||
|
await test_utils.waitUntil(() => modal.el.querySelectorAll('.available-chatrooms li').length === 4);
|
||||||
|
const rooms = modal.el.querySelectorAll('.available-chatrooms li');
|
||||||
|
expect(rooms[0].textContent.trim()).toBe("Groupchats found:");
|
||||||
|
expect(rooms[1].textContent.trim()).toBe("A Lonely Heath");
|
||||||
|
expect(rooms[2].textContent.trim()).toBe("A Dark Cave");
|
||||||
|
expect(rooms[3].textContent.trim()).toBe("The Palace");
|
||||||
|
done();
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("The \"Groupchats\" section", function () {
|
describe("The \"Groupchats\" section", function () {
|
||||||
@ -4052,9 +4207,6 @@
|
|||||||
mock.initConverse(
|
mock.initConverse(
|
||||||
null, ['rosterGroupsFetched'], {'allow_bookmarks': false},
|
null, ['rosterGroupsFetched'], {'allow_bookmarks': false},
|
||||||
async function (done, _converse) {
|
async function (done, _converse) {
|
||||||
// XXX: we set `allow_bookmarks` to false, so that the groupchats
|
|
||||||
// list gets rendered. Otherwise we would have to mock
|
|
||||||
// the bookmark stanza exchange.
|
|
||||||
|
|
||||||
test_utils.openControlBox();
|
test_utils.openControlBox();
|
||||||
const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
const roomspanel = _converse.chatboxviews.get('controlbox').roomspanel;
|
||||||
|
@ -103,6 +103,8 @@ converse.plugins.add('converse-muc-views', {
|
|||||||
_converse.api.settings.update({
|
_converse.api.settings.update({
|
||||||
'auto_list_rooms': false,
|
'auto_list_rooms': false,
|
||||||
'muc_disable_moderator_commands': false,
|
'muc_disable_moderator_commands': false,
|
||||||
|
'muc_domain': undefined,
|
||||||
|
'locked_muc_domain': undefined,
|
||||||
'muc_show_join_leave': true,
|
'muc_show_join_leave': true,
|
||||||
'roomconfig_whitelist': [],
|
'roomconfig_whitelist': [],
|
||||||
'visible_toolbar_buttons': {
|
'visible_toolbar_buttons': {
|
||||||
@ -110,6 +112,10 @@ converse.plugins.add('converse-muc-views', {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (_converse.locked_muc_domain && !_.isString(_converse.muc_domain)) {
|
||||||
|
throw new Error("Config Error: it makes no sense to set locked_muc_domain "+
|
||||||
|
"to true when muc_domain is not set");
|
||||||
|
}
|
||||||
|
|
||||||
function ___ (str) {
|
function ___ (str) {
|
||||||
/* This is part of a hack to get gettext to scan strings to be
|
/* This is part of a hack to get gettext to scan strings to be
|
||||||
@ -266,22 +272,32 @@ converse.plugins.add('converse-muc-views', {
|
|||||||
|
|
||||||
initialize () {
|
initialize () {
|
||||||
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
|
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
|
||||||
|
if (_converse.muc_domain && !this.model.get('muc_domain')) {
|
||||||
|
this.model.save('muc_domain', _converse.muc_domain);
|
||||||
|
}
|
||||||
this.model.on('change:muc_domain', this.onDomainChange, this);
|
this.model.on('change:muc_domain', this.onDomainChange, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
toHTML () {
|
toHTML () {
|
||||||
|
const muc_domain = this.model.get('muc_domain') || _converse.muc_domain;
|
||||||
return tpl_list_chatrooms_modal(_.extend(this.model.toJSON(), {
|
return tpl_list_chatrooms_modal(_.extend(this.model.toJSON(), {
|
||||||
'heading_list_chatrooms': __('Query for Groupchats'),
|
'heading_list_chatrooms': __('Query for Groupchats'),
|
||||||
'label_server_address': __('Server address'),
|
'label_server_address': __('Server address'),
|
||||||
'label_query': __('Show groupchats'),
|
'label_query': __('Show groupchats'),
|
||||||
'server_placeholder': __('conference.example.org')
|
'show_form': !_converse.locked_muc_domain,
|
||||||
|
'server_placeholder': muc_domain ? muc_domain : __('conference.example.org')
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
afterRender () {
|
afterRender () {
|
||||||
this.el.addEventListener('shown.bs.modal', () => {
|
if (_converse.locked_muc_domain) {
|
||||||
this.el.querySelector('input[name="server"]').focus();
|
this.updateRoomsList();
|
||||||
}, false);
|
} else {
|
||||||
|
this.el.addEventListener('shown.bs.modal',
|
||||||
|
() => this.el.querySelector('input[name="server"]').focus(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
openRoom (ev) {
|
openRoom (ev) {
|
||||||
@ -384,12 +400,22 @@ converse.plugins.add('converse-muc-views', {
|
|||||||
'submit form.add-chatroom': 'openChatRoom'
|
'submit form.add-chatroom': 'openChatRoom'
|
||||||
},
|
},
|
||||||
|
|
||||||
|
initialize () {
|
||||||
|
_converse.BootstrapModal.prototype.initialize.apply(this, arguments);
|
||||||
|
this.model.on('change:muc_domain', this.render, this);
|
||||||
|
},
|
||||||
|
|
||||||
toHTML () {
|
toHTML () {
|
||||||
|
let placeholder = '';
|
||||||
|
if (!_converse.locked_muc_domain) {
|
||||||
|
const muc_domain = this.model.get('muc_domain') || _converse.muc_domain;
|
||||||
|
placeholder = muc_domain ? `name@${muc_domain}` : __('name@conference.example.org');
|
||||||
|
}
|
||||||
return tpl_add_chatroom_modal(_.extend(this.model.toJSON(), {
|
return tpl_add_chatroom_modal(_.extend(this.model.toJSON(), {
|
||||||
'heading_new_chatroom': __('Enter a new Groupchat'),
|
'heading_new_chatroom': __('Enter a new Groupchat'),
|
||||||
'label_room_address': __('Groupchat address'),
|
'label_room_address': _converse.muc_domain ? __('Groupchat name') : __('Groupchat address'),
|
||||||
'label_nickname': __('Optional nickname'),
|
'label_nickname': __('Optional nickname'),
|
||||||
'chatroom_placeholder': __('name@conference.example.org'),
|
'chatroom_placeholder': placeholder,
|
||||||
'label_join': __('Join'),
|
'label_join': __('Join'),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
@ -417,7 +443,13 @@ converse.plugins.add('converse-muc-views', {
|
|||||||
// Make sure defaults apply if no nick is provided.
|
// Make sure defaults apply if no nick is provided.
|
||||||
data.nick = undefined;
|
data.nick = undefined;
|
||||||
}
|
}
|
||||||
_converse.api.rooms.open(data.jid, data);
|
let jid;
|
||||||
|
if (_converse.locked_muc_domain || (_converse.muc_domain && !u.isValidJID(data.jid))) {
|
||||||
|
jid = `${Strophe.escapeNode(data.jid)}@${_converse.muc_domain}`;
|
||||||
|
} else {
|
||||||
|
jid = data.jid
|
||||||
|
}
|
||||||
|
_converse.api.rooms.open(jid, _.extend(data, {jid}));
|
||||||
this.modal.hide();
|
this.modal.hide();
|
||||||
ev.target.reset();
|
ev.target.reset();
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,6 @@ converse.plugins.add('converse-muc', {
|
|||||||
auto_join_on_invite: false,
|
auto_join_on_invite: false,
|
||||||
auto_join_rooms: [],
|
auto_join_rooms: [],
|
||||||
auto_register_muc_nickname: false,
|
auto_register_muc_nickname: false,
|
||||||
muc_domain: undefined,
|
|
||||||
muc_history_max_stanzas: undefined,
|
muc_history_max_stanzas: undefined,
|
||||||
muc_instant_rooms: true,
|
muc_instant_rooms: true,
|
||||||
muc_nickname_from_jid: false
|
muc_nickname_from_jid: false
|
||||||
|
@ -9,13 +9,15 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body d-flex flex-column">
|
<div class="modal-body d-flex flex-column">
|
||||||
|
{[ if (o.show_form) { ]}
|
||||||
<form class="converse-form list-chatrooms">
|
<form class="converse-form list-chatrooms">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="chatroom">{{{o.label_server_address}}}:</label>
|
<label for="chatroom">{{{o.label_server_address}}}:</label>
|
||||||
<input type="text" value="{{{o.muc_domain}}}" required="required" name="server" class="form-control" placeholder="{{{o.server_placeholder}}}"/>
|
<input type="text" value="{{{o.muc_domain}}}" required="required" name="server" class="form-control" placeholder="{{{o.server_placeholder}}}"/>
|
||||||
</div>
|
</div>
|
||||||
<input type="submit" class="btn btn-primary" name="join" value="{{{o.label_query}}}"/>
|
<input type="submit" class="btn btn-primary" name="list" value="{{{o.label_query}}}"/>
|
||||||
</form>
|
</form>
|
||||||
|
{[ } ]}
|
||||||
<ul class="available-chatrooms list-group"></ul>
|
<ul class="available-chatrooms list-group"></ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user