From 234556793f38c8609a63913bb8006eadd9d1532b Mon Sep 17 00:00:00 2001 From: JC Brand Date: Wed, 10 Apr 2019 22:03:00 +0200 Subject: [PATCH] Provide a more user-friendly error message to muted users --- dist/converse.js | 39 +++++++++++++++++--------- spec/muc.js | 33 ++++++++++++++++++++++ src/headless/converse-chatboxes.js | 31 +++++++++++--------- src/headless/converse-core.js | 1 + src/headless/converse-muc.js | 8 ++++++ src/headless/dist/converse-headless.js | 39 +++++++++++++++++--------- 6 files changed, 112 insertions(+), 39 deletions(-) diff --git a/dist/converse.js b/dist/converse.js index fe5f66c4f..ab17369ca 100644 --- a/dist/converse.js +++ b/dist/converse.js @@ -62126,7 +62126,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha const older_versions = message.get('older_versions') || []; older_versions.push(message.get('message')); message.save({ - 'message': _converse.chatboxes.getMessageBody(stanza), + 'message': this.getMessageBody(stanza), 'references': this.getReferencesFromStanza(stanza), 'older_versions': older_versions, 'edited': moment().format() @@ -62529,6 +62529,18 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha return !_.isNil(sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop()); }, + getMessageBody(stanza) { + /* Given a message stanza, return the text contained in its body. + */ + const type = stanza.getAttribute('type'); + + if (type === 'error') { + return this.getErrorMessage(stanza); + } else { + return _.propertyOf(stanza.querySelector('body'))('textContent'); + } + }, + /** * Parses a passed in message stanza and returns an object * of attributes. @@ -62542,7 +62554,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha getMessageAttributesFromStanza(stanza, original_stanza) { const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(), delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(), - text = _converse.chatboxes.getMessageBody(stanza) || undefined, + text = this.getMessageBody(stanza) || undefined, chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE; const attrs = _.extend({ @@ -62737,17 +62749,9 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha chatbox.messages.create(attrs); }, - getMessageBody(stanza) { - /* Given a message stanza, return the text contained in its body. - */ - const type = stanza.getAttribute('type'); - - if (type === 'error') { - const error = stanza.querySelector('error'); - return _.propertyOf(error.querySelector('text'))('textContent') || __('Sorry, an error occurred:') + ' ' + error.innerHTML; - } else { - return _.propertyOf(stanza.querySelector('body'))('textContent'); - } + getErrorMessage(stanza) { + const error = stanza.querySelector('error'); + return _.propertyOf(error.querySelector('text'))('textContent') || __('Sorry, an error occurred:') + ' ' + error.innerHTML; }, /** @@ -63172,6 +63176,7 @@ strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('ROSTERX', 'http strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('RSM', 'http://jabber.org/protocol/rsm'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('SID', 'urn:xmpp:sid:0'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('SPOILER', 'urn:xmpp:spoiler:0'); +strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('STANZAS', 'urn:ietf:params:xml:ns:xmpp-stanzas'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('VCARD', 'vcard-temp'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('VCARDUPDATE', 'vcard-temp:x:update'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('XFORM', 'jabber:x:data'); // Use Mustache style syntax for variable interpolation @@ -67663,6 +67668,14 @@ _converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins.add('converse-muc return attrs; }, + getErrorMessage(stanza) { + if (sizzle(`forbidden[xmlns="${Strophe.NS.STANZAS}"]`, stanza).length) { + return __("Your message was not delivered because you're not allowed to send messages in this groupchat."); + } else { + return _converse.ChatBox.prototype.getErrorMessage.apply(this, arguments); + } + }, + /** * Handler for all MUC messages sent to this groupchat. * @private diff --git a/spec/muc.js b/spec/muc.js index 12ad2f5b5..cdb241978 100644 --- a/spec/muc.js +++ b/spec/muc.js @@ -4636,5 +4636,38 @@ })); }); }); + + describe("A muted user", function () { + + it("will receive a user-friendly error message when trying to send a message", + mock.initConverse( + null, ['rosterGroupsFetched', 'chatBoxesFetched'], {}, + async function (done, _converse) { + + await test_utils.openAndEnterChatRoom(_converse, 'trollbox', 'localhost', 'troll'); + var sent_IQ, IQ_id; + var sendIQ = _converse.connection.sendIQ; + spyOn(_converse.connection, 'sendIQ').and.callFake(function (iq, callback, errback) { + sent_IQ = iq; + IQ_id = sendIQ.bind(this)(iq, callback, errback); + }); + const view = _converse.chatboxviews.get('trollbox@localhost'); + + const textarea = view.el.querySelector('.chat-textarea'); + textarea.value = 'Hello world'; + view.onFormSubmitted(new Event('submit')); + + const stanza = u.toStanza(` + + + `); + _converse.connection._dataRecv(test_utils.createRequest(stanza)); + + await new Promise((resolve, reject) => view.once('messageInserted', resolve)); + expect(view.el.querySelector('.chat-error').textContent).toBe( + "Your message was not delivered because you're not allowed to send messages in this groupchat."); + done(); + })); + }); }); })); diff --git a/src/headless/converse-chatboxes.js b/src/headless/converse-chatboxes.js index a3093f57b..00f9cab42 100644 --- a/src/headless/converse-chatboxes.js +++ b/src/headless/converse-chatboxes.js @@ -361,7 +361,7 @@ converse.plugins.add('converse-chatboxes', { const older_versions = message.get('older_versions') || []; older_versions.push(message.get('message')); message.save({ - 'message': _converse.chatboxes.getMessageBody(stanza), + 'message': this.getMessageBody(stanza), 'references': this.getReferencesFromStanza(stanza), 'older_versions': older_versions, 'edited': moment().format() @@ -696,6 +696,18 @@ converse.plugins.add('converse-chatboxes', { return !_.isNil(sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop()); }, + getMessageBody (stanza) { + /* Given a message stanza, return the text contained in its body. + */ + const type = stanza.getAttribute('type'); + if (type === 'error') { + return this.getErrorMessage(stanza); + } else { + return _.propertyOf(stanza.querySelector('body'))('textContent'); + } + }, + + /** * Parses a passed in message stanza and returns an object * of attributes. @@ -709,7 +721,7 @@ converse.plugins.add('converse-chatboxes', { getMessageAttributesFromStanza (stanza, original_stanza) { const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(), delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(), - text = _converse.chatboxes.getMessageBody(stanza) || undefined, + text = this.getMessageBody(stanza) || undefined, chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || @@ -887,17 +899,10 @@ converse.plugins.add('converse-chatboxes', { chatbox.messages.create(attrs); }, - getMessageBody (stanza) { - /* Given a message stanza, return the text contained in its body. - */ - const type = stanza.getAttribute('type'); - if (type === 'error') { - const error = stanza.querySelector('error'); - return _.propertyOf(error.querySelector('text'))('textContent') || - __('Sorry, an error occurred:') + ' ' + error.innerHTML; - } else { - return _.propertyOf(stanza.querySelector('body'))('textContent'); - } + getErrorMessage (stanza) { + const error = stanza.querySelector('error'); + return _.propertyOf(error.querySelector('text'))('textContent') || + __('Sorry, an error occurred:') + ' ' + error.innerHTML; }, /** diff --git a/src/headless/converse-core.js b/src/headless/converse-core.js index fff615b16..cbadf2b19 100644 --- a/src/headless/converse-core.js +++ b/src/headless/converse-core.js @@ -41,6 +41,7 @@ Strophe.addNamespace('ROSTERX', 'http://jabber.org/protocol/rosterx'); Strophe.addNamespace('RSM', 'http://jabber.org/protocol/rsm'); Strophe.addNamespace('SID', 'urn:xmpp:sid:0'); Strophe.addNamespace('SPOILER', 'urn:xmpp:spoiler:0'); +Strophe.addNamespace('STANZAS', 'urn:ietf:params:xml:ns:xmpp-stanzas'); Strophe.addNamespace('VCARD', 'vcard-temp'); Strophe.addNamespace('VCARDUPDATE', 'vcard-temp:x:update'); Strophe.addNamespace('XFORM', 'jabber:x:data'); diff --git a/src/headless/converse-muc.js b/src/headless/converse-muc.js index 88e1bb3e8..e06d338b2 100644 --- a/src/headless/converse-muc.js +++ b/src/headless/converse-muc.js @@ -1040,6 +1040,14 @@ converse.plugins.add('converse-muc', { return attrs; }, + getErrorMessage (stanza) { + if (sizzle(`forbidden[xmlns="${Strophe.NS.STANZAS}"]`, stanza).length) { + return __("Your message was not delivered because you're not allowed to send messages in this groupchat."); + } else { + return _converse.ChatBox.prototype.getErrorMessage.apply(this, arguments); + } + }, + /** * Handler for all MUC messages sent to this groupchat. * @private diff --git a/src/headless/dist/converse-headless.js b/src/headless/dist/converse-headless.js index 8551c8de9..3cbf0169e 100644 --- a/src/headless/dist/converse-headless.js +++ b/src/headless/dist/converse-headless.js @@ -40643,7 +40643,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha const older_versions = message.get('older_versions') || []; older_versions.push(message.get('message')); message.save({ - 'message': _converse.chatboxes.getMessageBody(stanza), + 'message': this.getMessageBody(stanza), 'references': this.getReferencesFromStanza(stanza), 'older_versions': older_versions, 'edited': moment().format() @@ -41046,6 +41046,18 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha return !_.isNil(sizzle(`result[xmlns="${Strophe.NS.MAM}"]`, original_stanza).pop()); }, + getMessageBody(stanza) { + /* Given a message stanza, return the text contained in its body. + */ + const type = stanza.getAttribute('type'); + + if (type === 'error') { + return this.getErrorMessage(stanza); + } else { + return _.propertyOf(stanza.querySelector('body'))('textContent'); + } + }, + /** * Parses a passed in message stanza and returns an object * of attributes. @@ -41059,7 +41071,7 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha getMessageAttributesFromStanza(stanza, original_stanza) { const spoiler = sizzle(`spoiler[xmlns="${Strophe.NS.SPOILER}"]`, original_stanza).pop(), delay = sizzle(`delay[xmlns="${Strophe.NS.DELAY}"]`, original_stanza).pop(), - text = _converse.chatboxes.getMessageBody(stanza) || undefined, + text = this.getMessageBody(stanza) || undefined, chat_state = stanza.getElementsByTagName(_converse.COMPOSING).length && _converse.COMPOSING || stanza.getElementsByTagName(_converse.PAUSED).length && _converse.PAUSED || stanza.getElementsByTagName(_converse.INACTIVE).length && _converse.INACTIVE || stanza.getElementsByTagName(_converse.ACTIVE).length && _converse.ACTIVE || stanza.getElementsByTagName(_converse.GONE).length && _converse.GONE; const attrs = _.extend({ @@ -41254,17 +41266,9 @@ _converse_core__WEBPACK_IMPORTED_MODULE_2__["default"].plugins.add('converse-cha chatbox.messages.create(attrs); }, - getMessageBody(stanza) { - /* Given a message stanza, return the text contained in its body. - */ - const type = stanza.getAttribute('type'); - - if (type === 'error') { - const error = stanza.querySelector('error'); - return _.propertyOf(error.querySelector('text'))('textContent') || __('Sorry, an error occurred:') + ' ' + error.innerHTML; - } else { - return _.propertyOf(stanza.querySelector('body'))('textContent'); - } + getErrorMessage(stanza) { + const error = stanza.querySelector('error'); + return _.propertyOf(error.querySelector('text'))('textContent') || __('Sorry, an error occurred:') + ' ' + error.innerHTML; }, /** @@ -41689,6 +41693,7 @@ strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('ROSTERX', 'http strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('RSM', 'http://jabber.org/protocol/rsm'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('SID', 'urn:xmpp:sid:0'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('SPOILER', 'urn:xmpp:spoiler:0'); +strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('STANZAS', 'urn:ietf:params:xml:ns:xmpp-stanzas'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('VCARD', 'vcard-temp'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('VCARDUPDATE', 'vcard-temp:x:update'); strophe_js__WEBPACK_IMPORTED_MODULE_0__["Strophe"].addNamespace('XFORM', 'jabber:x:data'); // Use Mustache style syntax for variable interpolation @@ -46180,6 +46185,14 @@ _converse_core__WEBPACK_IMPORTED_MODULE_3__["default"].plugins.add('converse-muc return attrs; }, + getErrorMessage(stanza) { + if (sizzle(`forbidden[xmlns="${Strophe.NS.STANZAS}"]`, stanza).length) { + return __("Your message was not delivered because you're not allowed to send messages in this groupchat."); + } else { + return _converse.ChatBox.prototype.getErrorMessage.apply(this, arguments); + } + }, + /** * Handler for all MUC messages sent to this groupchat. * @private