2
0
Эх сурвалжийг харах

Updates #2781

Only send presence status update when a MUC is entered, and when joining
a MUC, include the `<show>` element.
JC Brand 3 жил өмнө
parent
commit
beb220f188

+ 1 - 0
CHANGES.md

@@ -11,6 +11,7 @@
 - #2733: Fix OMEMO race condition related to automatic reconnection and SMACKS
 - #2733: Wait for decrypted/parsed message before queuing to UI
 - #2751: Media not rendered when Converse runs in a browser extension
+- #2781: Flashing error when connecting to a room
 - #2786: Fix webpack configuration not working on Windows OS
 - #2788: `TypeError` when trying to use `@converse/headless`
 - #2789: Implement new hook `parseMessageForCommands` for plugins to add custom commands

+ 30 - 15
src/headless/plugins/muc/muc.js

@@ -175,7 +175,7 @@ const ChatRoomMixin = {
             }
             return this;
         }
-        api.send(await this.constructPresence(password));
+        api.send(await this.constructJoinPresence(password));
         return this;
     },
 
@@ -191,7 +191,7 @@ const ChatRoomMixin = {
         return this.join();
     },
 
-    async constructPresence (password) {
+    async constructJoinPresence (password) {
         let stanza = $pres({
             'id': getUniqueId(),
             'from': _converse.connection.jid,
@@ -205,6 +205,17 @@ const ChatRoomMixin = {
         if (password) {
             stanza.cnode(Strophe.xmlElement('password', [], password));
         }
+        stanza.up(); // Go one level up, out of the `x` element.
+
+        const status = _converse.xmppstatus.get('status');
+        if (['away', 'chat', 'dnd', 'online', 'xa'].includes(status)) {
+            stanza.c('show').t(status).up();
+        }
+        const status_message = _converse.xmppstatus.get('status_message');
+        if (status_message) {
+            stanza.c('status').t(status_message).up();
+        }
+
         stanza = await api.hook('constructedMUCPresence', null, stanza);
         return stanza;
     },
@@ -271,10 +282,9 @@ const ChatRoomMixin = {
             if (conn_status === roomstatus.ENTERED &&
                     api.settings.get('muc_subscribe_to_rai') &&
                     this.getOwnAffiliation() !== 'none') {
-                if (conn_status !== roomstatus.DISCONNECTED && conn_status !== roomstatus.CLOSING) {
-                    this.sendMarkerForLastMessage('received', true);
-                    await this.leave();
-                }
+
+                this.sendMarkerForLastMessage('received', true);
+                await this.leave();
                 this.enableRAI();
             }
         } else {
@@ -869,7 +879,7 @@ const ChatRoomMixin = {
             await new Promise(resolve =>
                 this.features.destroy({
                     'success': resolve,
-                    'error': (m, e) => { log.error(e); resolve(); }
+                    'error': (_, e) => { log.error(e); resolve(); }
                 })
             );
         }
@@ -878,7 +888,7 @@ const ChatRoomMixin = {
         if (disco_entity) {
             await new Promise(resolve => disco_entity.destroy({
                 'success': resolve,
-                'error': (m, e) => { log.error(e); resolve(); }
+                'error': (_, e) => { log.error(e); resolve(); }
             }));
         }
         u.safeSave(this.session, { 'connection_status': converse.ROOMSTATUS.DISCONNECTED });
@@ -899,7 +909,7 @@ const ChatRoomMixin = {
         await new Promise(resolve =>
             this.session.destroy({
                 'success': resolve,
-                'error': (m, e) => { log.error(e); resolve(); }
+                'error': (_, e) => { log.error(e); resolve(); }
             })
         );
         return _converse.ChatBox.prototype.close.call(this);
@@ -1918,14 +1928,19 @@ const ChatRoomMixin = {
     },
 
     /**
-     * When sending a status update presence (i.e. based on the `<show>`
-     * element), we need to first make sure that the MUC is connected,
-     * otherwise we will get an error from the MUC service.
+     * Sends a status update presence (i.e. based on the `<show>` element)
      * @method _converse.ChatRoom#sendStatusPresence
+     * @param { String } type
+     * @param { String } [status] - An optional status message
+     * @param { Element[]|Strophe.Builder[]|Element|Strophe.Builder } [child_nodes]
+     *  Nodes(s) to be added as child nodes of the `presence` XML element.
      */
-    async sendStatusPresence (presence) {
-        await this.rejoinIfNecessary();
-        api.send(presence);
+    async sendStatusPresence (type, status, child_nodes) {
+        if (this.session.get('connection_status') === converse.ROOMSTATUS.ENTERED) {
+            const presence = await _converse.xmppstatus.constructPresence(type, this.getRoomJIDAndNick(), status);
+            child_nodes?.map(c => c?.tree() ?? c).forEach(c => presence.cnode(c).up());
+            api.send(presence);
+        }
     },
 
     /**

+ 54 - 1
src/headless/plugins/muc/tests/muc.js

@@ -37,7 +37,59 @@ describe("Groupchats", function () {
         expect(model.get('num_unread')).toBe(0);
     }));
 
-    describe("An groupchat", function () {
+    describe("A groupchat", function () {
+
+        it("sends the user status when joining and when it changes",
+                mock.initConverse(['statusInitialized'], {}, async function (_converse) {
+
+            const muc_jid = 'coven@chat.shakespeare.lit';
+            _converse.xmppstatus.set('status', 'away');
+
+            const sent_stanzas = _converse.connection.sent_stanzas;
+            while (sent_stanzas.length) sent_stanzas.pop();
+
+            const muc = await mock.openAndEnterChatRoom(_converse, muc_jid, 'romeo');
+
+            let pres = await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'presence').pop());
+            expect(Strophe.serialize(pres)).toBe(
+                `<presence from="${_converse.jid}" id="${pres.getAttribute('id')}" to="${muc_jid}/romeo" xmlns="jabber:client">`+
+                    `<x xmlns="http://jabber.org/protocol/muc"><history maxstanzas="0"/></x>`+
+                    `<show>away</show>`+
+                    `<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
+                `</presence>`);
+
+            expect(muc.getOwnOccupant().get('show')).toBe('away');
+
+            while (sent_stanzas.length) sent_stanzas.pop();
+
+            _converse.xmppstatus.set('status', 'xa');
+            pres = await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'presence').pop());
+            expect(Strophe.serialize(pres)).toBe(
+                `<presence to="${muc_jid}/romeo" xmlns="jabber:client">`+
+                    `<show>xa</show>`+
+                    `<priority>0</priority>`+
+                    `<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
+                `</presence>`)
+
+            _converse.xmppstatus.set('status', 'dnd');
+            _converse.xmppstatus.set('status_message', 'Do not disturb');
+            while (sent_stanzas.length) sent_stanzas.pop();
+
+            const muc2_jid = 'cave@chat.shakespeare.lit';
+            const muc2 = await mock.openAndEnterChatRoom(_converse, muc2_jid, 'romeo');
+
+            pres = await u.waitUntil(() => sent_stanzas.filter(s => s.nodeName === 'presence').pop());
+            expect(Strophe.serialize(pres)).toBe(
+                `<presence from="${_converse.jid}" id="${pres.getAttribute('id')}" to="${muc2_jid}/romeo" xmlns="jabber:client">`+
+                    `<x xmlns="http://jabber.org/protocol/muc"><history maxstanzas="0"/></x>`+
+                    `<show>dnd</show>`+
+                    `<status>Do not disturb</status>`+
+                    `<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
+                `</presence>`);
+
+            expect(muc2.getOwnOccupant().get('show')).toBe('dnd');
+
+        }));
 
         it("reconnects when no-acceptable error is returned when sending a message",
                 mock.initConverse([], {}, async function (_converse) {
@@ -87,6 +139,7 @@ describe("Groupchats", function () {
             expect(Strophe.serialize(pres)).toBe(
                 `<presence from="${_converse.jid}" id="${pres.getAttribute('id')}" to="coven@chat.shakespeare.lit/romeo" xmlns="jabber:client">`+
                     `<x xmlns="http://jabber.org/protocol/muc"><history maxstanzas="0"/></x>`+
+                    `<show>online</show>`+
                     `<c hash="sha-1" node="https://conversejs.org" ver="TfHz9vOOfqIG0Z9lW5CuPaWGnrQ=" xmlns="http://jabber.org/protocol/caps"/>`+
                 `</presence>`);
         }));

+ 2 - 6
src/headless/plugins/status/api.js

@@ -21,18 +21,14 @@ export default {
             if (child_nodes && !Array.isArray(child_nodes)) {
                 child_nodes = [child_nodes];
             }
-            const model= _converse.xmppstatus
+            const model = _converse.xmppstatus
             const presence = await model.constructPresence(type, to, status);
             child_nodes?.map(c => c?.tree() ?? c).forEach(c => presence.cnode(c).up());
             api.send(presence);
 
             if (['away', 'chat', 'dnd', 'online', 'xa', undefined].includes(type)) {
                 const mucs = await api.rooms.get();
-                mucs.forEach(async muc => {
-                    const presence = await model.constructPresence(type, muc.getRoomJIDAndNick(), status);
-                    child_nodes?.map(c => c?.tree() ?? c).forEach(c => presence.cnode(c).up());
-                    muc.sendStatusPresence(presence);
-                });
+                mucs.forEach(muc => muc.sendStatusPresence(type, status, child_nodes));
             }
         }
     },

+ 5 - 1
src/shared/tests/mock.js

@@ -292,7 +292,11 @@ async function receiveOwnMUCPresence (_converse, muc_jid, nick, affiliation='own
             id: u.getUniqueId()
     }).c('x').attrs({xmlns:'http://jabber.org/protocol/muc#user'})
         .c('item').attrs({ affiliation, role, 'jid': _converse.bare_jid }).up()
-        .c('status').attrs({code:'110'});
+        .c('status').attrs({code:'110'}).up().up()
+
+    if (_converse.xmppstatus.get('status')) {
+       presence.c('show').t(_converse.xmppstatus.get('status'));
+    }
     _converse.connection._dataRecv(createRequest(presence));
 }