diff --git a/ts/test-both/util/filterAndSortContacts_test.ts b/ts/test-both/util/filterAndSortContacts_test.ts index 870d773567..dbd7bcb208 100644 --- a/ts/test-both/util/filterAndSortContacts_test.ts +++ b/ts/test-both/util/filterAndSortContacts_test.ts @@ -10,32 +10,53 @@ describe('filterAndSortContacts', () => { const conversations = [ getDefaultConversation({ title: '+16505551234', - firstName: undefined, + e164: '+16505551234', + name: undefined, profileName: undefined, }), - getDefaultConversation({ title: 'Carlos Santana' }), - getDefaultConversation({ title: 'Aaron Aardvark' }), - getDefaultConversation({ title: 'Belinda Beetle' }), - getDefaultConversation({ title: 'Belinda Zephyr' }), + getDefaultConversation({ + name: 'Carlos Santana', + title: 'Carlos Santana', + e164: '+16505559876', + }), + getDefaultConversation({ + name: 'Aaron Aardvark', + title: 'Aaron Aardvark', + }), + getDefaultConversation({ + name: 'Belinda Beetle', + title: 'Belinda Beetle', + }), + getDefaultConversation({ + name: 'Belinda Zephyr', + title: 'Belinda Zephyr', + }), ]; - it('without a search term, sorts conversations by title', () => { + it('without a search term, sorts conversations by title (but puts no-name contacts at the bottom)', () => { const titles = filterAndSortContacts(conversations, '').map( contact => contact.title ); assert.deepEqual(titles, [ - '+16505551234', 'Aaron Aardvark', 'Belinda Beetle', 'Belinda Zephyr', 'Carlos Santana', + '+16505551234', ]); }); - it('filters conversations a search terms', () => { + it('can search for contacts by title', () => { const titles = filterAndSortContacts(conversations, 'belind').map( contact => contact.title ); - assert.deepEqual(titles, ['Belinda Beetle', 'Belinda Zephyr']); + assert.sameMembers(titles, ['Belinda Beetle', 'Belinda Zephyr']); + }); + + it('can search for contacts by phone number (and puts no-name contacts at the bottom)', () => { + const titles = filterAndSortContacts(conversations, '650555').map( + contact => contact.title + ); + assert.sameMembers(titles, ['Carlos Santana', '+16505551234']); }); }); diff --git a/ts/util/filterAndSortContacts.ts b/ts/util/filterAndSortContacts.ts index ddf398b0cb..c47cc3219b 100644 --- a/ts/util/filterAndSortContacts.ts +++ b/ts/util/filterAndSortContacts.ts @@ -9,7 +9,20 @@ const FUSE_OPTIONS: FuseOptions = { // A small-but-nonzero threshold lets us match parts of E164s better, and makes the // search a little more forgiving. threshold: 0.05, - keys: ['title', 'name', 'e164'], + keys: [ + { + name: 'title', + weight: 1, + }, + { + name: 'name', + weight: 1, + }, + { + name: 'e164', + weight: 0.5, + }, + ], }; const collator = new Intl.Collator(); @@ -23,5 +36,19 @@ export function filterAndSortContacts( searchTerm ); } - return contacts.concat().sort((a, b) => collator.compare(a.title, b.title)); + + return contacts.concat().sort((a, b) => { + const aHasName = hasName(a); + const bHasName = hasName(b); + + if (aHasName === bHasName) { + return collator.compare(a.title, b.title); + } + + return aHasName && !bHasName ? -1 : 1; + }); +} + +function hasName(contact: Readonly): boolean { + return Boolean(contact.name || contact.profileName); }