ソースを参照

MUC: create references for nicks gathered from messages

JC Brand 5 年 前
コミット
3c9ec96350
3 ファイル変更53 行追加26 行削除
  1. 18 1
      spec/muc_messages.js
  2. 1 6
      src/converse-muc-views.js
  3. 34 19
      src/headless/converse-muc.js

+ 18 - 1
spec/muc_messages.js

@@ -652,7 +652,7 @@
                          from="${msg_obj.get('from')}"
                          to="${_converse.connection.jid}"
                          type="groupchat">
-                    <msg_body>${msg_obj.get('message')}</msg_body>
+                    <body>${msg_obj.get('message')}</body>
                     <stanza-id xmlns="urn:xmpp:sid:0"
                                id="5f3dbc5e-e1d3-4077-a492-693f3769c7ad"
                                by="lounge@montague.lit"/>
@@ -878,6 +878,17 @@
                         })));
                 });
 
+                // Also check that nicks from received messages, (but for which
+                // we don't have occupant objects) can be mentioned.
+                const stanza = u.toStanza(`
+                    <message xmlns="jabber:client"
+                            from="${muc_jid}/gh0st"
+                            to="${_converse.connection.bare_jid}"
+                            type="groupchat">
+                        <body>Boo!</body>
+                    </message>`);
+                await view.model.onMessage(stanza);
+
                 // Run a few unit tests for the parseTextForReferences method
                 let [text, references] = view.model.parseTextForReferences('hello z3r0')
                 expect(references.length).toBe(0);
@@ -935,6 +946,12 @@
                 expect(references.length).toBe(0);
                 expect(JSON.stringify(references))
                     .toBe('[]');
+
+                [text, references] = view.model.parseTextForReferences('@gh0st where are you?')
+                expect(text).toBe('gh0st where are you?');
+                expect(references.length).toBe(1);
+                expect(JSON.stringify(references))
+                    .toBe('[{"begin":0,"end":5,"value":"gh0st","type":"mention","uri":"xmpp:lounge@montague.lit/gh0st"}]');
                 done();
             }));
 

+ 1 - 6
src/converse-muc-views.js

@@ -845,12 +845,7 @@ converse.plugins.add('converse-muc-views', {
             },
 
             getAutoCompleteList () {
-                // Create an array of unique nicknames based on the occupants and messages.
-                const nicks = [...new Set([
-                    ...this.model.occupants.map(o => o.get('nick')),
-                    ...this.model.messages.map(m => m.get('nick'))
-                ])].filter(n => n);
-                return nicks.map(nick => ({'label': nick, 'value': `@${nick}`}));
+                return this.model.getAllKnownNicknames().map(nick => ({'label': nick, 'value': `@${nick}`}));
             },
 
             getAutoCompleteListItem(text, input) {

+ 34 - 19
src/headless/converse-muc.js

@@ -829,11 +829,22 @@ converse.plugins.add('converse-muc', {
                 _converse.connection.sendPresence(presence);
             },
 
+            /**
+             * Return an array of unique nicknames based on all occupants and messages in this MUC.
+             * @private
+             * @method _converse.ChatRoom#getAllKnownNicknames
+             * @returns { String[] }
+             */
+            getAllKnownNicknames () {
+                return [...new Set([
+                    ...this.occupants.map(o => o.get('nick')),
+                    ...this.messages.map(m => m.get('nick'))
+                ])].filter(n => n);
+            },
+
             getReferenceForMention (mention, index) {
-                const longest_match = u.getLongestSubstring(
-                    mention,
-                    this.occupants.map(o => o.getDisplayName())
-                );
+                const nicknames = this.getAllKnownNicknames();
+                const longest_match = u.getLongestSubstring(mention, nicknames);
                 if (!longest_match) {
                     return null;
                 }
@@ -843,22 +854,26 @@ converse.plugins.add('converse-muc', {
                     // match.
                     return null;
                 }
+
+                let uri;
                 const occupant = this.occupants.findOccupant({'nick': longest_match}) ||
-                        this.occupants.findOccupant({'jid': longest_match});
-                if (!occupant) {
-                    return null;
+                        u.isValidJID(longest_match) && this.occupants.findOccupant({'jid': longest_match});
+
+                if (occupant) {
+                    uri = occupant.get('jid') || `${this.get('jid')}/${occupant.get('nick')}`;
+                } else if (nicknames.includes(longest_match)) {
+                    // TODO: show a warning to the user that the person is not currently in the chat
+                    uri = `${this.get('jid')}/${longest_match}`;
+                } else {
+                    return;
                 }
                 const obj = {
                     'begin': index,
                     'end': index + longest_match.length,
                     'value': longest_match,
-                    'type': 'mention'
+                    'type': 'mention',
+                    'uri': encodeURI(`xmpp:${uri}`)
                 };
-                if (occupant.get('jid')) {
-                    obj.uri = encodeURI(`xmpp:${occupant.get('jid')}`);
-                } else {
-                    obj.uri = encodeURI(`xmpp:${this.get('jid')}/${occupant.get('nick')}`);
-                }
                 return obj;
             },
 
@@ -898,16 +913,16 @@ converse.plugins.add('converse-muc', {
                 const origin_id = u.getUniqueId();
 
                 return {
+                    is_spoiler,
+                    origin_id,
+                    references,
                     'id': origin_id,
                     'msgid': origin_id,
-                    'origin_id': origin_id,
                     'from': `${this.get('jid')}/${this.get('nick')}`,
                     'fullname': this.get('nick'),
                     'is_only_emojis': text ? u.isOnlyEmojis(text) : false,
-                    'is_spoiler': is_spoiler,
                     'message': text ? u.httpToGeoUri(u.shortnameToUnicode(text), _converse) : undefined,
                     'nick': this.get('nick'),
-                    'references': references,
                     'sender': 'me',
                     'spoiler_hint': is_spoiler ? spoiler_hint : undefined,
                     'type': 'groupchat'
@@ -915,9 +930,9 @@ converse.plugins.add('converse-muc', {
             },
 
             /**
-             * Utility method to construct the JID for the current user
-             * as occupant of the groupchat.
-             *
+             * Utility method to construct the JID for the current user as occupant of the groupchat.
+             * @private
+             * @method _converse.ChatRoom#getRoomJIDAndNick
              * @returns {string} - The groupchat JID with the user's nickname added at the end.
              * @example groupchat@conference.example.org/nickname
              */