Commit 3cca2fdb authored by JC Brand's avatar JC Brand

roster: Filter contacts via all available information

parent a6129eeb
...@@ -24,6 +24,7 @@ Soon we'll deprecate the latter, so prepare now. ...@@ -24,6 +24,7 @@ Soon we'll deprecate the latter, so prepare now.
- #1999: Demarcate first unread message - #1999: Demarcate first unread message
- #2002: fix rendering of `muc_roomid_policy_hint` - #2002: fix rendering of `muc_roomid_policy_hint`
- #2006: fix rendering of emojis in case `use_system_emojis == false` - #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` - 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 - Bugfix. Handle stanza that clears the MUC subject
- Replace Backbone with [Skeletor](https://github.com/skeletorjs/skeletor) - Replace Backbone with [Skeletor](https://github.com/skeletorjs/skeletor)
......
...@@ -610,8 +610,8 @@ converse.plugins.add('converse-rosterview', { ...@@ -610,8 +610,8 @@ converse.plugins.add('converse-rosterview', {
if (q.length === 0) { if (q.length === 0) {
return []; return [];
} }
let matches;
q = q.toLowerCase(); q = q.toLowerCase();
const contacts = this.model.contacts;
if (type === 'state') { if (type === 'state') {
const sticky_groups = [_converse.HEADER_REQUESTING_CONTACTS, _converse.HEADER_UNREAD]; const sticky_groups = [_converse.HEADER_REQUESTING_CONTACTS, _converse.HEADER_UNREAD];
if (sticky_groups.includes(this.model.get('name'))) { if (sticky_groups.includes(this.model.get('name'))) {
...@@ -620,18 +620,15 @@ converse.plugins.add('converse-rosterview', { ...@@ -620,18 +620,15 @@ converse.plugins.add('converse-rosterview', {
// match the state in question. // match the state in question.
return []; return [];
} else if (q === 'unread_messages') { } else if (q === 'unread_messages') {
matches = this.model.contacts.filter({'num_unread': 0}); return contacts.filter({'num_unread': 0});
} else if (q === 'online') { } 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 { } else {
matches = this.model.contacts.filter(c => !c.presence.get('show').includes(q)); return contacts.filter(c => !c.presence.get('show').includes(q));
} }
} else { } else {
matches = this.model.contacts.filter((contact) => { return contacts.filter(c => !c.getFilterCriteria().includes(q));
return !contact.getDisplayName().toLowerCase().includes(q.toLowerCase());
});
} }
return matches;
}, },
/** /**
...@@ -784,14 +781,14 @@ converse.plugins.add('converse-rosterview', { ...@@ -784,14 +781,14 @@ converse.plugins.add('converse-rosterview', {
this.filter_view.model.fetch(); 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 () { 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'); const type = this.filter_view.model.get('filter_type');
if (type === 'state') { if (type === 'state') {
this.filter(this.filter_view.model.get('chat_state'), type); this.filter(this.filter_view.model.get('chat_state'), type);
......
...@@ -253,6 +253,23 @@ converse.plugins.add('converse-roster', { ...@@ -253,6 +253,23 @@ converse.plugins.add('converse-roster', {
api.chats.open(attrs.jid, attrs, true); 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 () { getDisplayName () {
// Gets overridden in converse-vcard where the fullname is may be returned // Gets overridden in converse-vcard where the fullname is may be returned
if (this.get('nickname')) { if (this.get('nickname')) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment