From e1e1cfb8920bf7c2820b95d267a38f56a4fd933a Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Thu, 7 Apr 2022 11:47:12 -0700 Subject: [PATCH] Use fuse.js for regular contact search --- ts/sql/Client.ts | 7 ------ ts/sql/Interface.ts | 4 ---- ts/sql/Server.ts | 28 ----------------------- ts/state/ducks/search.ts | 35 ++++++++++++++++++++--------- ts/state/selectors/conversations.ts | 2 +- 5 files changed, 26 insertions(+), 50 deletions(-) diff --git a/ts/sql/Client.ts b/ts/sql/Client.ts index 2fa2eae1e9..f7a892c0fb 100644 --- a/ts/sql/Client.ts +++ b/ts/sql/Client.ts @@ -207,7 +207,6 @@ const dataInterface: ClientInterface = { getAllConversationIds, getAllGroupsInvolvingUuid, - searchConversations, searchMessages, searchMessagesInConversation, @@ -1031,12 +1030,6 @@ async function getAllGroupsInvolvingUuid(uuid: UUIDStringType) { return channels.getAllGroupsInvolvingUuid(uuid); } -async function searchConversations(query: string) { - const conversations = await channels.searchConversations(query); - - return conversations; -} - function handleSearchMessageJSON( messages: Array ): Array { diff --git a/ts/sql/Interface.ts b/ts/sql/Interface.ts index fd14e219e0..411d743988 100644 --- a/ts/sql/Interface.ts +++ b/ts/sql/Interface.ts @@ -363,10 +363,6 @@ export type DataInterface = { id: UUIDStringType ) => Promise>; - searchConversations: ( - query: string, - options?: { limit?: number } - ) => Promise>; // searchMessages is JSON on server, full message on Client // searchMessagesInConversation is JSON on server, full message on Client diff --git a/ts/sql/Server.ts b/ts/sql/Server.ts index 330fb7d9f0..ad917324cd 100644 --- a/ts/sql/Server.ts +++ b/ts/sql/Server.ts @@ -203,7 +203,6 @@ const dataInterface: ServerInterface = { getAllConversationIds, getAllGroupsInvolvingUuid, - searchConversations, searchMessages, searchMessagesInConversation, @@ -1526,33 +1525,6 @@ async function getAllGroupsInvolvingUuid( return rows.map(row => rowToConversation(row)); } -async function searchConversations( - query: string, - { limit }: { limit?: number } = {} -): Promise> { - const db = getInstance(); - const rows: ConversationRows = db - .prepare( - ` - SELECT json, profileLastFetchedAt - FROM conversations WHERE - ( - e164 LIKE $query OR - name LIKE $query OR - profileFullName LIKE $query - ) - ORDER BY active_at DESC - LIMIT $limit - ` - ) - .all({ - query: `%${query}%`, - limit: limit || 100, - }); - - return rows.map(row => rowToConversation(row)); -} - async function searchMessages( query: string, params: { limit?: number; conversationId?: string } = {} diff --git a/ts/state/ducks/search.ts b/ts/state/ducks/search.ts index 32816da8c5..2fa82686ac 100644 --- a/ts/state/ducks/search.ts +++ b/ts/state/ducks/search.ts @@ -6,6 +6,7 @@ import { debounce, omit, reject } from 'lodash'; import type { StateType as RootStateType } from '../reducer'; import { cleanSearchTerm } from '../../util/cleanSearchTerm'; +import { filterAndSortConversationsByRecent } from '../../util/filterAndSortConversations'; import type { ClientSearchResultMessageType, ClientInterface, @@ -14,8 +15,8 @@ import dataInterface from '../../sql/Client'; import { makeLookup } from '../../util/makeLookup'; import type { + ConversationType, ConversationUnloadedActionType, - DBConversationType, MessageDeletedActionType, MessageType, RemoveAllConversationsActionType, @@ -23,11 +24,15 @@ import type { ShowArchivedConversationsActionType, } from './conversations'; import { getQuery, getSearchConversation } from '../selectors/search'; -import { getIntl, getUserConversationId } from '../selectors/user'; +import { getAllConversations } from '../selectors/conversations'; +import { + getIntl, + getRegionCode, + getUserConversationId, +} from '../selectors/user'; import { strictAssert } from '../../util/assert'; const { - searchConversations: dataSearchConversations, searchMessages: dataSearchMessages, searchMessagesInConversation, }: ClientInterface = dataInterface; @@ -166,6 +171,8 @@ function updateSearchTerm( doSearch({ dispatch, + allConversations: getAllConversations(state), + regionCode: getRegionCode(state), noteToSelf: getIntl(state)('noteToSelf').toLowerCase(), ourConversationId, query: getQuery(state), @@ -177,6 +184,8 @@ function updateSearchTerm( const doSearch = debounce( ({ dispatch, + allConversations, + regionCode, noteToSelf, ourConversationId, query, @@ -188,7 +197,9 @@ const doSearch = debounce( | SearchMessagesResultsFulfilledActionType | SearchDiscussionsResultsFulfilledActionType >; + allConversations: ReadonlyArray; noteToSelf: string; + regionCode: string | undefined; ourConversationId: string; query: string; searchConversationId: undefined | string; @@ -213,6 +224,8 @@ const doSearch = debounce( await queryConversationsAndContacts(query, { ourConversationId, noteToSelf, + regionCode, + allConversations, }); dispatch({ @@ -250,20 +263,22 @@ async function queryMessages( } async function queryConversationsAndContacts( - providedQuery: string, + query: string, options: { ourConversationId: string; noteToSelf: string; + regionCode: string | undefined; + allConversations: ReadonlyArray; } ): Promise<{ contactIds: Array; conversationIds: Array; }> { - const { ourConversationId, noteToSelf } = options; - const query = providedQuery.replace(/[+.()]*/g, ''); + const { ourConversationId, noteToSelf, regionCode, allConversations } = + options; - const searchResults: Array = - await dataSearchConversations(query); + const searchResults: Array = + filterAndSortConversationsByRecent(allConversations, query, regionCode); // Split into two groups - active conversations and items just from address book let conversationIds: Array = []; @@ -272,7 +287,7 @@ async function queryConversationsAndContacts( for (let i = 0; i < max; i += 1) { const conversation = searchResults[i]; - if (conversation.type === 'private' && !conversation.lastMessage) { + if (conversation.type === 'direct' && !conversation.lastMessage) { contactIds.push(conversation.id); } else { conversationIds.push(conversation.id); @@ -280,7 +295,7 @@ async function queryConversationsAndContacts( } // Inject synthetic Note to Self entry if query matches localized 'Note to Self' - if (noteToSelf.indexOf(providedQuery.toLowerCase()) !== -1) { + if (noteToSelf.indexOf(query.toLowerCase()) !== -1) { // ensure that we don't have duplicates in our results contactIds = contactIds.filter(id => id !== ourConversationId); conversationIds = conversationIds.filter(id => id !== ourConversationId); diff --git a/ts/state/selectors/conversations.ts b/ts/state/selectors/conversations.ts index ea23ef73be..d5177a7837 100644 --- a/ts/state/selectors/conversations.ts +++ b/ts/state/selectors/conversations.ts @@ -121,7 +121,7 @@ export const getConversationsByUsername = createSelector( } ); -const getAllConversations = createSelector( +export const getAllConversations = createSelector( getConversationLookup, (lookup): Array => Object.values(lookup) );