// Copyright 2023 Signal Messenger, LLC // SPDX-License-Identifier: AGPL-3.0-only import type Fuse from 'fuse.js'; import type { ConversationType } from '../state/ducks/conversations'; import { fuseGetFnRemoveDiacritics, getCachedFuseIndex } from './fuse'; const CONVERSATION_TITLE = 'title'; const MIN_SEARCH_TERM_LENGTH = 2; const segmenter = new Intl.Segmenter([], { granularity: 'word' }); const FUSE_OPTIONS: Fuse.IFuseOptions = { keys: [CONVERSATION_TITLE], getFn: (...args) => { const text = fuseGetFnRemoveDiacritics(...args); return [ ...segmenter.segment(typeof text === 'string' ? text : text.join(' ')), ].map(word => word.segment); }, isCaseSensitive: false, includeScore: false, shouldSort: true, // Setting location, distance, and threshold to zero returns only exact prefix matches // i.e. matches that start at index 0 and where every character matches the query location: 0, distance: 0, threshold: 0, }; export function searchConversationTitles( conversations: ReadonlyArray, searchTerms: Array ): Array { // Searches all conversation titles where const index = getCachedFuseIndex(conversations, FUSE_OPTIONS); const searchQuery: Fuse.Expression = { $or: searchTerms .filter(term => term.length >= MIN_SEARCH_TERM_LENGTH) .map(term => ({ [CONVERSATION_TITLE]: term })), }; return index.search(searchQuery).map(result => result.item); }