Explorar o código

roster: Treat undefined `subscription` as indicator of unsaved contact.

Instead of `'none'` since you can have saved contacts with that value.
JC Brand hai 2 meses
pai
achega
3f31c5033f

+ 1 - 1
src/headless/plugins/chat/model.js

@@ -164,7 +164,7 @@ class ChatBox extends ModelWithVCard(ModelWithMessages(ModelWithContact(ColorAwa
 
         if (attrs.is_markable) {
             if (this.contact &&
-                    !['none', 'to'].includes(this.contact.get('subscription')) &&
+                    !['none', 'to', undefined].includes(this.contact.get('subscription')) &&
                     !attrs.is_archived &&
                     !attrs.is_carbon) {
                 sendMarker(attrs.from, attrs.msgid, 'received');

+ 1 - 1
src/headless/plugins/roster/contact.js

@@ -8,7 +8,7 @@ import ColorAwareModel from '../../shared/color.js';
 import ModelWithVCard from '../../shared/model-with-vcard.js';
 import { rejectPresenceSubscription } from './utils.js';
 
-const { Strophe, $iq, $pres, stx } = converse.env;
+const { Strophe, $pres, stx } = converse.env;
 
 class RosterContact extends ModelWithVCard(ColorAwareModel(Model)) {
     get idAttribute () {

+ 2 - 1
src/headless/plugins/roster/contacts.js

@@ -191,7 +191,7 @@ class RosterContacts extends Collection {
                     nickname: name,
                     groups: [],
                     requesting: false,
-                    subscription: subscribe ? 'to' : 'none',
+                    subscription: persist ? 'none' : undefined,
                 },
                 ...attributes,
             },
@@ -265,6 +265,7 @@ class RosterContacts extends Collection {
             log.warn('Received a roster push stanza without an "item" element.');
             return;
         }
+
         this.updateContact(items.pop());
         /**
          * When the roster receives a push event from server (i.e. new entry in your contacts roster).

+ 5 - 4
src/headless/shared/api/public.js

@@ -7,7 +7,7 @@ import sizzle from 'sizzle';
 import { Stanza, Strophe, $build, $iq, $msg, $pres, stx } from 'strophe.js';
 import { Collection, Model } from "@converse/skeletor";
 import { filesize } from 'filesize';
-import { css, html, render } from 'lit';
+import { css, html, render, nothing } from 'lit';
 
 import api from './index.js';
 import _converse from '../_converse.js';
@@ -36,24 +36,25 @@ const env = /** @type {import('./types').ConverseEnv} */ {
     $iq,
     $msg,
     $pres,
-    utils: u,
     Collection,
     Model,
     Stanza,
     Strophe,
     TimeoutError,
     VERSION_NAME,
+    css,
     dayjs,
     errors,
     filesize,
     html,
-    css,
-    render,
     log,
+    nothing,
+    render,
     sizzle,
     sprintf,
     stx,
     u,
+    utils: u,
 }
 
 /**

+ 1 - 1
src/headless/shared/model-with-contact.js

@@ -38,7 +38,7 @@ export default function ModelWithContact(BaseModel) {
             } else {
                 contact = await api.contacts.get(jid);
                 if (!contact && !(await api.blocklist.get()).get(jid)) {
-                    await api.contacts.add({ jid, subscription: 'none' }, false, false);
+                    contact = await api.contacts.add({ jid }, false, false);
                 }
             }
 

+ 1 - 1
src/headless/tests/converse.js

@@ -215,7 +215,7 @@ describe("Converse", function() {
             const contacts = await api.contacts.get()
             expect(contacts.length).toBe(1);
             expect(contacts[0].get('jid')).toBe("newcontact@example.org");
-            expect(contacts[0].get('subscription')).toBe("none");
+            expect(contacts[0].get('subscription')).toBe(undefined);
             expect(contacts[0].get('ask')).toBeUndefined();
             expect(contacts[0].get('groups').length).toBe(0);
         }));

+ 13 - 0
src/headless/utils/jid.js

@@ -1,4 +1,5 @@
 import { Strophe } from 'strophe.js';
+import _converse from "../shared/_converse";
 
 /**
  * @param {string|null} [jid]
@@ -55,3 +56,15 @@ export function isSameDomain(jid1, jid2) {
 export function getJIDFromURI(jid) {
     return jid.startsWith('xmpp:') && jid.endsWith('?join') ? jid.replace(/^xmpp:/, '').replace(/\?join$/, '') : jid;
 }
+
+/**
+ * @param {string} jid
+ * @param {boolean} [include_resource=false]
+ * @returns {boolean}
+ */
+export function isOwnJID(jid, include_resource = false) {
+    if (include_resource) {
+        return jid === _converse.session.get('full_jid');
+    }
+    return Strophe.getBareJidFromJid(jid) === _converse.session.get('bare_jid');
+}

+ 17 - 8
src/plugins/chatview/tests/markers.js

@@ -1,11 +1,12 @@
 /*global mock, converse */
 // See: https://xmpp.org/rfcs/rfc3921.html
-
 const { Strophe, u, stx } = converse.env;
 
 
 describe("A XEP-0333 Chat Marker", function () {
 
+    beforeEach(() => jasmine.addMatchers({ toEqualStanza: jasmine.toEqualStanza }));
+
     it("is sent when a markable message is received from a roster contact",
             mock.initConverse([], {}, async function (_converse) {
 
@@ -59,14 +60,22 @@ describe("A XEP-0333 Chat Marker", function () {
             .map(s => s?.nodeTree ?? s)
             .filter(e => e.nodeName === 'message');
 
-        await u.waitUntil(() => sent_messages.length === 1);
-        expect(Strophe.serialize(sent_messages[0])).toBe(
-            `<message id="${sent_messages[0].getAttribute('id')}" to="${contact_jid}" type="chat" xmlns="jabber:client">`+
-                `<active xmlns="http://jabber.org/protocol/chatstates"/>`+
-                `<no-store xmlns="urn:xmpp:hints"/>`+
-                `<no-permanent-store xmlns="urn:xmpp:hints"/>`+
-            `</message>`
+        await u.waitUntil(() => sent_messages.length === 2);
+        expect(sent_messages[0]).toEqualStanza(stx`
+            <message id="${sent_messages[0].getAttribute('id')}" to="${contact_jid}" type="chat" xmlns="jabber:client">
+                <active xmlns="http://jabber.org/protocol/chatstates"/>
+                <no-store xmlns="urn:xmpp:hints"/>
+                <no-permanent-store xmlns="urn:xmpp:hints"/>
+            </message>`
         );
+
+        expect(sent_messages[1]).toEqualStanza(stx`
+            <message xmlns="jabber:client"
+                    from="romeo@montague.lit/orchard"
+                    id="${sent_messages[1].getAttribute('id')}"
+                    to="someone@montague.lit" type="chat">
+                <displayed xmlns="urn:xmpp:chat-markers:0" id="${sent_messages[1].querySelector('displayed')?.getAttribute('id')}"/>
+            </message>`);
     }));
 
     it("is ignored if it's a carbon copy of one that I sent from a different client",

+ 11 - 8
src/plugins/rosterview/utils.js

@@ -207,12 +207,13 @@ export function shouldShowGroup(group, model) {
  */
 export function populateContactsMap(contacts_map, contact) {
     const { labels } = _converse;
-
     const contact_groups = /** @type {string[]} */ (u.unique(contact.get('groups') ?? []));
 
-    if (contact.get('requesting')) {
+    if (u.isOwnJID(contact.get('jid')) && !contact_groups.length) {
+        contact_groups.push(/** @type {string} */ (labels.HEADER_UNGROUPED));
+    } else if (contact.get('requesting')) {
         contact_groups.push(/** @type {string} */ (labels.HEADER_REQUESTING_CONTACTS));
-    } else if (contact.get('subscription') === 'none') {
+    } else if (contact.get('subscription') === undefined) {
         contact_groups.push(/** @type {string} */ (labels.HEADER_UNSAVED_CONTACTS));
     } else if (!api.settings.get('roster_groups')) {
         contact_groups.push(/** @type {string} */ (labels.HEADER_CURRENT_CONTACTS));
@@ -258,16 +259,18 @@ export function contactsComparator(contact1, contact2) {
 export function groupsComparator(a, b) {
     const HEADER_WEIGHTS = {};
     const {
-        HEADER_UNREAD,
-        HEADER_REQUESTING_CONTACTS,
         HEADER_CURRENT_CONTACTS,
+        HEADER_REQUESTING_CONTACTS,
         HEADER_UNGROUPED,
+        HEADER_UNREAD,
+        HEADER_UNSAVED_CONTACTS,
     } = _converse.labels;
 
     HEADER_WEIGHTS[HEADER_UNREAD] = 0;
-    HEADER_WEIGHTS[HEADER_REQUESTING_CONTACTS] = 1;
-    HEADER_WEIGHTS[HEADER_CURRENT_CONTACTS] = 2;
-    HEADER_WEIGHTS[HEADER_UNGROUPED] = 3;
+    HEADER_WEIGHTS[HEADER_UNSAVED_CONTACTS] = 1;
+    HEADER_WEIGHTS[HEADER_REQUESTING_CONTACTS] = 2;
+    HEADER_WEIGHTS[HEADER_CURRENT_CONTACTS] = 3;
+    HEADER_WEIGHTS[HEADER_UNGROUPED] = 4;
 
     const WEIGHTS = HEADER_WEIGHTS;
     const special_groups = Object.keys(HEADER_WEIGHTS);