From dffcc13dea632a298633d0dc2b0a9f5a6901ab6b Mon Sep 17 00:00:00 2001 From: JC Brand Date: Wed, 10 Oct 2018 22:28:32 +0200 Subject: [PATCH] Fixes #1140 Add support for destroyed chatrooms --- CHANGES.md | 1 + dist/converse.js | 76 ++++++++++++++++++++++++++- spec/chatroom.js | 33 ++++++++++++ src/converse-muc-views.js | 42 +++++++++++++++ src/templates/chatroom_destroyed.html | 12 +++++ 5 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 src/templates/chatroom_destroyed.html diff --git a/CHANGES.md b/CHANGES.md index bb6ec0dd9f..76d79b74d7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -5,6 +5,7 @@ - Bugfix. Handler not triggered when submitting MUC password form 2nd time - Bugfix. MUC features weren't being refreshed when saving the config form - #1063 URLs in the topic / subject are not clickable +- #1140 Add support for destroyed chatrooms - #1190 MUC Participants column disappears in certain viewport widths - #1199 Can't get back from to login screen from registration screen - #1204 Link encoding issue diff --git a/dist/converse.js b/dist/converse.js index 8b6847c499..ae57045da5 100644 --- a/dist/converse.js +++ b/dist/converse.js @@ -68193,11 +68193,11 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ // Copyright (c) 2013-2018, the Converse.js developers // Licensed under the Mozilla Public License (MPLv2) (function (root, factory) { - !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! formdata-polyfill */ "./node_modules/formdata-polyfill/FormData.js"), __webpack_require__(/*! utils/muc */ "./src/utils/muc.js"), __webpack_require__(/*! xss */ "./node_modules/xss/dist/xss.js"), __webpack_require__(/*! templates/add_chatroom_modal.html */ "./src/templates/add_chatroom_modal.html"), __webpack_require__(/*! templates/chatarea.html */ "./src/templates/chatarea.html"), __webpack_require__(/*! templates/chatroom.html */ "./src/templates/chatroom.html"), __webpack_require__(/*! templates/chatroom_details_modal.html */ "./src/templates/chatroom_details_modal.html"), __webpack_require__(/*! templates/chatroom_disconnect.html */ "./src/templates/chatroom_disconnect.html"), __webpack_require__(/*! templates/chatroom_features.html */ "./src/templates/chatroom_features.html"), __webpack_require__(/*! templates/chatroom_form.html */ "./src/templates/chatroom_form.html"), __webpack_require__(/*! templates/chatroom_head.html */ "./src/templates/chatroom_head.html"), __webpack_require__(/*! templates/chatroom_invite.html */ "./src/templates/chatroom_invite.html"), __webpack_require__(/*! templates/chatroom_nickname_form.html */ "./src/templates/chatroom_nickname_form.html"), __webpack_require__(/*! templates/chatroom_password_form.html */ "./src/templates/chatroom_password_form.html"), __webpack_require__(/*! templates/chatroom_sidebar.html */ "./src/templates/chatroom_sidebar.html"), __webpack_require__(/*! templates/info.html */ "./src/templates/info.html"), __webpack_require__(/*! templates/list_chatrooms_modal.html */ "./src/templates/list_chatrooms_modal.html"), __webpack_require__(/*! templates/occupant.html */ "./src/templates/occupant.html"), __webpack_require__(/*! templates/room_description.html */ "./src/templates/room_description.html"), __webpack_require__(/*! templates/room_item.html */ "./src/templates/room_item.html"), __webpack_require__(/*! templates/room_panel.html */ "./src/templates/room_panel.html"), __webpack_require__(/*! templates/rooms_results.html */ "./src/templates/rooms_results.html"), __webpack_require__(/*! templates/spinner.html */ "./src/templates/spinner.html"), __webpack_require__(/*! awesomplete */ "./node_modules/awesomplete-avoid-xss/awesomplete.js"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), + !(__WEBPACK_AMD_DEFINE_ARRAY__ = [__webpack_require__(/*! converse-core */ "./src/converse-core.js"), __webpack_require__(/*! formdata-polyfill */ "./node_modules/formdata-polyfill/FormData.js"), __webpack_require__(/*! utils/muc */ "./src/utils/muc.js"), __webpack_require__(/*! xss */ "./node_modules/xss/dist/xss.js"), __webpack_require__(/*! templates/add_chatroom_modal.html */ "./src/templates/add_chatroom_modal.html"), __webpack_require__(/*! templates/chatarea.html */ "./src/templates/chatarea.html"), __webpack_require__(/*! templates/chatroom.html */ "./src/templates/chatroom.html"), __webpack_require__(/*! templates/chatroom_details_modal.html */ "./src/templates/chatroom_details_modal.html"), __webpack_require__(/*! templates/chatroom_destroyed.html */ "./src/templates/chatroom_destroyed.html"), __webpack_require__(/*! templates/chatroom_disconnect.html */ "./src/templates/chatroom_disconnect.html"), __webpack_require__(/*! templates/chatroom_features.html */ "./src/templates/chatroom_features.html"), __webpack_require__(/*! templates/chatroom_form.html */ "./src/templates/chatroom_form.html"), __webpack_require__(/*! templates/chatroom_head.html */ "./src/templates/chatroom_head.html"), __webpack_require__(/*! templates/chatroom_invite.html */ "./src/templates/chatroom_invite.html"), __webpack_require__(/*! templates/chatroom_nickname_form.html */ "./src/templates/chatroom_nickname_form.html"), __webpack_require__(/*! templates/chatroom_password_form.html */ "./src/templates/chatroom_password_form.html"), __webpack_require__(/*! templates/chatroom_sidebar.html */ "./src/templates/chatroom_sidebar.html"), __webpack_require__(/*! templates/info.html */ "./src/templates/info.html"), __webpack_require__(/*! templates/list_chatrooms_modal.html */ "./src/templates/list_chatrooms_modal.html"), __webpack_require__(/*! templates/occupant.html */ "./src/templates/occupant.html"), __webpack_require__(/*! templates/room_description.html */ "./src/templates/room_description.html"), __webpack_require__(/*! templates/room_item.html */ "./src/templates/room_item.html"), __webpack_require__(/*! templates/room_panel.html */ "./src/templates/room_panel.html"), __webpack_require__(/*! templates/rooms_results.html */ "./src/templates/rooms_results.html"), __webpack_require__(/*! templates/spinner.html */ "./src/templates/spinner.html"), __webpack_require__(/*! awesomplete */ "./node_modules/awesomplete-avoid-xss/awesomplete.js"), __webpack_require__(/*! converse-modal */ "./src/converse-modal.js")], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory), __WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ? (__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__), __WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__)); -})(void 0, function (converse, _FormData, muc_utils, xss, tpl_add_chatroom_modal, tpl_chatarea, tpl_chatroom, tpl_chatroom_details_modal, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_info, tpl_list_chatrooms_modal, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) { +})(void 0, function (converse, _FormData, muc_utils, xss, tpl_add_chatroom_modal, tpl_chatarea, tpl_chatroom, tpl_chatroom_details_modal, tpl_chatroom_destroyed, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, tpl_chatroom_head, tpl_chatroom_invite, tpl_chatroom_nickname_form, tpl_chatroom_password_form, tpl_chatroom_sidebar, tpl_info, tpl_list_chatrooms_modal, tpl_occupant, tpl_room_description, tpl_room_item, tpl_room_panel, tpl_rooms_results, tpl_spinner, Awesomplete) { "use strict"; const _converse$env = converse.env, @@ -68674,6 +68674,7 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ this.model.messages.on('rendered', this.scrollDown, this); this.model.on('change:affiliation', this.renderHeading, this); this.model.on('change:connection_status', this.afterConnected, this); + this.model.on('change:jid', this.renderHeading, this); this.model.on('change:name', this.renderHeading, this); this.model.on('change:subject', this.renderHeading, this); this.model.on('change:subject', this.setChatRoomSubject, this); @@ -68689,6 +68690,13 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ this.createOccupantsView(); this.render().insertIntoDOM(); this.registerHandlers(); + this.enterRoom(); + }, + + enterRoom(ev) { + if (ev) { + ev.preventDefault(); + } if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) { const handler = () => { @@ -69511,6 +69519,39 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ this.el.querySelector('.chatroom-form').addEventListener('submit', ev => this.submitPassword(ev), false); }, + showDestroyedMessage(error) { + u.hideElement(this.el.querySelector('.chat-area')); + u.hideElement(this.el.querySelector('.occupants')); + + _.each(this.el.querySelectorAll('.spinner'), u.removeElement); + + const container = this.el.querySelector('.disconnect-container'); + + const moved_jid = _.get(sizzle('gone[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', error).pop(), 'textContent').replace(/^xmpp:/, '').replace(/\?join$/, ''); + + const reason = _.get(sizzle('text[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', error).pop(), 'textContent'); + + container.innerHTML = tpl_chatroom_destroyed({ + '_': _, + '__': __, + 'jid': moved_jid, + 'reason': reason ? `"${reason}"` : null + }); + const switch_el = container.querySelector('a.switch-chat'); + + if (switch_el) { + switch_el.addEventListener('click', ev => { + ev.preventDefault(); + this.model.save('jid', moved_jid); + container.innerHTML = ''; + this.showSpinner(); + this.enterRoom(); + }); + } + + u.showElement(container); + }, + showDisconnectMessages(msgs) { if (_.isString(msgs)) { msgs = [msgs]; @@ -69812,6 +69853,8 @@ var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_ this.showDisconnectMessages(__('You are not allowed to create new groupchats.')); } else if (!_.isNull(error.querySelector('not-acceptable'))) { this.showDisconnectMessages(__("Your nickname doesn't conform to this groupchat's policies.")); + } else if (sizzle('gone[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', error).length) { + this.showDestroyedMessage(error); } else if (!_.isNull(error.querySelector('conflict'))) { this.onNicknameClash(presence); } else if (!_.isNull(error.querySelector('item-not-found'))) { @@ -78634,6 +78677,35 @@ return __p /***/ }), +/***/ "./src/templates/chatroom_destroyed.html": +/*!***********************************************!*\ + !*** ./src/templates/chatroom_destroyed.html ***! + \***********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { + +var _ = {escape:__webpack_require__(/*! ./node_modules/lodash/escape.js */ "./node_modules/lodash/escape.js")}; +module.exports = function(o) { +var __t, __p = '', __e = _.escape, __j = Array.prototype.join; +function print() { __p += __j.call(arguments, '') } +__p += '\n
\n

' + +__e(o.__('This room no longer exists')) + +'

\n\n

' + +__e(o.reason) + +'

\n\n '; + if (o.jid) { ; +__p += '\n

\n ' + +__e(o.__('The conversation has moved. Click below to enter.') ) + +'\n

\n \n '; + } ; +__p += '\n
\n'; +return __p +}; + +/***/ }), + /***/ "./src/templates/chatroom_details_modal.html": /*!***************************************************!*\ !*** ./src/templates/chatroom_details_modal.html ***! diff --git a/spec/chatroom.js b/spec/chatroom.js index df0c5165cc..e611d1bf03 100644 --- a/spec/chatroom.js +++ b/spec/chatroom.js @@ -1245,6 +1245,39 @@ }).catch(_.partial(console.error, _)); })); + it("properly handles notification that a room has been destroyed", + mock.initConverseWithPromises( + null, ['rosterGroupsFetched'], {}, + function (done, _converse) { + + test_utils.openChatRoomViaModal(_converse, 'problematic@muc.localhost', 'dummy') + .then(function () { + const presence = $pres().attrs({ + from:'problematic@muc.localhost', + id:'n13mt3l', + to:'dummy@localhost/pda', + type:'error'}) + .c('error').attrs({'type':'cancel'}) + .c('gone').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'}) + .t('xmpp:other-room@chat.jabberfr.org?join').up() + .c('text').attrs({'xmlns':'urn:ietf:params:xml:ns:xmpp-stanzas'}) + .t("We didn't like the name").nodeTree; + + const view = _converse.chatboxviews.get('problematic@muc.localhost'); + spyOn(view, 'showErrorMessage').and.callThrough(); + _converse.connection._dataRecv(test_utils.createRequest(presence)); + expect(view.el.querySelector('.chatroom-body .disconnect-msg').textContent) + .toBe('This room no longer exists'); + expect(view.el.querySelector('.chatroom-body .destroyed-reason').textContent) + .toBe(`"We didn't like the name"`); + expect(view.el.querySelector('.chatroom-body .moved-label').textContent.trim()) + .toBe('The conversation has moved. Click below to enter.'); + expect(view.el.querySelector('.chatroom-body .moved-link').textContent.trim()) + .toBe(`other-room@chat.jabberfr.org`); + done(); + }).catch(_.partial(console.error, _)); + })); + it("will use the user's reserved nickname, if it exists", mock.initConverseWithPromises( null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, diff --git a/src/converse-muc-views.js b/src/converse-muc-views.js index 825d21d684..a4c6a3b0c9 100644 --- a/src/converse-muc-views.js +++ b/src/converse-muc-views.js @@ -14,6 +14,7 @@ "templates/chatarea.html", "templates/chatroom.html", "templates/chatroom_details_modal.html", + "templates/chatroom_destroyed.html", "templates/chatroom_disconnect.html", "templates/chatroom_features.html", "templates/chatroom_form.html", @@ -42,6 +43,7 @@ tpl_chatarea, tpl_chatroom, tpl_chatroom_details_modal, + tpl_chatroom_destroyed, tpl_chatroom_disconnect, tpl_chatroom_features, tpl_chatroom_form, @@ -530,6 +532,7 @@ this.model.on('change:affiliation', this.renderHeading, this); this.model.on('change:connection_status', this.afterConnected, this); + this.model.on('change:jid', this.renderHeading, this); this.model.on('change:name', this.renderHeading, this); this.model.on('change:subject', this.renderHeading, this); this.model.on('change:subject', this.setChatRoomSubject, this); @@ -547,7 +550,11 @@ this.createOccupantsView(); this.render().insertIntoDOM(); this.registerHandlers(); + this.enterRoom(); + }, + enterRoom (ev) { + if (ev) { ev.preventDefault(); } if (this.model.get('connection_status') !== converse.ROOMSTATUS.ENTERED) { const handler = () => { if (!u.isPersistableModel(this.model)) { @@ -1316,6 +1323,39 @@ .addEventListener('submit', ev => this.submitPassword(ev), false); }, + showDestroyedMessage (error) { + u.hideElement(this.el.querySelector('.chat-area')); + u.hideElement(this.el.querySelector('.occupants')); + _.each(this.el.querySelectorAll('.spinner'), u.removeElement); + const container = this.el.querySelector('.disconnect-container'); + const moved_jid = _.get( + sizzle('gone[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', error).pop(), + 'textContent' + ).replace(/^xmpp:/, '').replace(/\?join$/, ''); + const reason = _.get( + sizzle('text[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', error).pop(), + 'textContent' + ); + container.innerHTML = tpl_chatroom_destroyed({ + '_': _, + '__':__, + 'jid': moved_jid, + 'reason': reason ? `"${reason}"` : null + }); + + const switch_el = container.querySelector('a.switch-chat'); + if (switch_el) { + switch_el.addEventListener('click', ev => { + ev.preventDefault(); + this.model.save('jid', moved_jid); + container.innerHTML = ''; + this.showSpinner(); + this.enterRoom(); + }); + } + u.showElement(container); + }, + showDisconnectMessages (msgs) { if (_.isString(msgs)) { msgs = [msgs]; @@ -1585,6 +1625,8 @@ this.showDisconnectMessages(__('You are not allowed to create new groupchats.')); } else if (!_.isNull(error.querySelector('not-acceptable'))) { this.showDisconnectMessages(__("Your nickname doesn't conform to this groupchat's policies.")); + } else if (sizzle('gone[xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"]', error).length) { + this.showDestroyedMessage(error); } else if (!_.isNull(error.querySelector('conflict'))) { this.onNicknameClash(presence); } else if (!_.isNull(error.querySelector('item-not-found'))) { diff --git a/src/templates/chatroom_destroyed.html b/src/templates/chatroom_destroyed.html new file mode 100644 index 0000000000..7fcd3d6a0e --- /dev/null +++ b/src/templates/chatroom_destroyed.html @@ -0,0 +1,12 @@ +
+

{{{o.__('This room no longer exists')}}}

+ +

{{{o.reason}}}

+ + {[ if (o.jid) { ]} +

+ {{{o.__('The conversation has moved. Click below to enter.') }}} +

+ + {[ } ]} +