소스 검색

roster: Filter contacts via all available information

JC Brand 5 년 전
부모
커밋
3cca2fdb7f
3개의 변경된 파일30개의 추가작업 그리고 15개의 파일을 삭제
  1. 1 0
      CHANGES.md
  2. 12 15
      src/converse-rosterview.js
  3. 17 0
      src/headless/converse-roster.js

+ 1 - 0
CHANGES.md

@@ -24,6 +24,7 @@ Soon we'll deprecate the latter, so prepare now.
 - #1999: Demarcate first unread message
 - #2002: fix rendering of `muc_roomid_policy_hint`
 - #2006: fix rendering of emojis in case `use_system_emojis == false`
+- Filter roster contacts via all available information (JID, nickname and VCard full name).
 - Allow ignoring of bootstrap modules at build using environment variable. For xample: `export BOOTSTRAP_IGNORE_MODULES="Modal,Dropdown" && make dist`
 - Bugfix. Handle stanza that clears the MUC subject
 - Replace Backbone with [Skeletor](https://github.com/skeletorjs/skeletor)

+ 12 - 15
src/converse-rosterview.js

@@ -610,8 +610,8 @@ converse.plugins.add('converse-rosterview', {
                 if (q.length === 0) {
                     return [];
                 }
-                let matches;
                 q = q.toLowerCase();
+                const contacts = this.model.contacts;
                 if (type === 'state') {
                     const sticky_groups = [_converse.HEADER_REQUESTING_CONTACTS, _converse.HEADER_UNREAD];
                     if (sticky_groups.includes(this.model.get('name'))) {
@@ -620,18 +620,15 @@ converse.plugins.add('converse-rosterview', {
                         // match the state in question.
                         return [];
                     } else if (q === 'unread_messages') {
-                        matches = this.model.contacts.filter({'num_unread': 0});
+                        return contacts.filter({'num_unread': 0});
                     } else if (q === 'online') {
-                        matches = this.model.contacts.filter(c => ["offline", "unavailable"].includes(c.presence.get('show')));
+                        return contacts.filter(c => ["offline", "unavailable"].includes(c.presence.get('show')));
                     } else {
-                        matches = this.model.contacts.filter(c => !c.presence.get('show').includes(q));
+                        return contacts.filter(c => !c.presence.get('show').includes(q));
                     }
                 } else  {
-                    matches = this.model.contacts.filter((contact) => {
-                        return !contact.getDisplayName().toLowerCase().includes(q.toLowerCase());
-                    });
+                    return contacts.filter(c => !c.getFilterCriteria().includes(q));
                 }
-                return matches;
             },
 
             /**
@@ -784,14 +781,14 @@ converse.plugins.add('converse-rosterview', {
                 this.filter_view.model.fetch();
             },
 
+            /**
+             * Called whenever the filter settings have been changed or
+             * when contacts have been added, removed or changed.
+             *
+             * Debounced for 100ms so that it doesn't get called for every
+             * contact fetched from browser storage.
+             */
             updateFilter: debounce(function () {
-                /* Filter the roster again.
-                 * Called whenever the filter settings have been changed or
-                 * when contacts have been added, removed or changed.
-                 *
-                 * Debounced so that it doesn't get called for every
-                 * contact fetched from browser storage.
-                 */
                 const type = this.filter_view.model.get('filter_type');
                 if (type === 'state') {
                     this.filter(this.filter_view.model.get('chat_state'), type);

+ 17 - 0
src/headless/converse-roster.js

@@ -253,6 +253,23 @@ converse.plugins.add('converse-roster', {
                 api.chats.open(attrs.jid, attrs, true);
             },
 
+            /**
+             * Return a string of tab-separated values that are to be used when
+             * matching against filter text.
+             *
+             * The goal is to be able to filter against the VCard fullname,
+             * roster nickname and JID.
+             * @returns { String } Lower-cased, tab-separated values
+             */
+            getFilterCriteria () {
+                const nick = this.get('nickname');
+                const jid = this.get('jid');
+                let criteria = this.getDisplayName();
+                criteria = !criteria.includes(jid) ? criteria.concat(`   ${jid}`) : criteria;
+                criteria = !criteria.includes(nick) ? criteria.concat(`   ${nick}`) : criteria;
+                return criteria.toLowerCase();
+            },
+
             getDisplayName () {
                 // Gets overridden in converse-vcard where the fullname is may be returned
                 if (this.get('nickname')) {