diff --git a/desk/desk.docket-0 b/desk/desk.docket-0 index e7f2d697fc..20753214c9 100644 --- a/desk/desk.docket-0 +++ b/desk/desk.docket-0 @@ -2,7 +2,7 @@ info+'Start, host, and cultivate communities. Own your communications, organize your resources, and share documents. Tlon is a decentralized platform that offers a full, communal suite of tools for messaging, writing and sharing media with others.' color+0xde.dede image+'https://bootstrap.urbit.org/tlon.svg?v=1' - glob-http+['https://bootstrap.urbit.org/glob-0v1.71qpt.066p8.ig25t.if94m.d9hsb.glob' 0v1.71qpt.066p8.ig25t.if94m.d9hsb] + glob-http+['https://bootstrap.urbit.org/glob-0vjij3q.upm2l.l5jts.6o74u.2a67q.glob' 0vjij3q.upm2l.l5jts.6o74u.2a67q] base+'groups' version+[6 1 0] website+'https://tlon.io' diff --git a/packages/ui/src/components/ChatList.tsx b/packages/ui/src/components/ChatList.tsx index bf00211a3c..a9f945df5c 100644 --- a/packages/ui/src/components/ChatList.tsx +++ b/packages/ui/src/components/ChatList.tsx @@ -1,7 +1,7 @@ import * as db from '@tloncorp/shared/dist/db'; import * as logic from '@tloncorp/shared/dist/logic'; import * as store from '@tloncorp/shared/dist/store'; -import fuzzy from 'fuzzy'; +import Fuse from 'fuse.js'; import { debounce } from 'lodash'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { @@ -93,57 +93,73 @@ export function ChatList({ ]; }, [filteredData, pendingChats]); - const extractForFuzzy = useCallback((item: db.Channel) => { - if (logic.isGroupChannelId(item.id)) { - return item.group?.title || ''; - } - if (item.type === 'dm' && item.contact) { - return item.contact.nickname - ? `${item.contact.nickname}-${item.id}` - : item.id; - } - if (item.type === 'groupDm') { - return (item.members || []) - .map((m) => - m.contact - ? m.contact.nickname - ? `${m.contact.nickname}-${m.contact.id}` - : m.contact.id - : '' - ) - .join(' '); - } - return item.id; + const getFuseOptions = useCallback(() => { + return { + keys: [ + 'id', + 'group.title', + 'contact.nickname', + 'members.contact.nickname', + 'members.contact.id', + ], + threshold: 0.3, + }; }, []); - const debouncedFuzzySearch = useMemo( + const fuse = useMemo(() => { + const allData = [...pinned, ...unpinned]; + return new Fuse(allData, getFuseOptions()); + }, [pinned, unpinned, getFuseOptions]); + + const performSearch = useCallback( + (query: string) => { + if (query.trim() === '') { + return []; + } + return fuse.search(query).map((result) => result.item); + }, + [fuse] + ); + + const debouncedSearch = useMemo( () => - debounce((query) => { - const results = fuzzy.filter( - query.trim(), - [...filteredData.filteredPinned, ...filteredData.filteredUnpinned], - { extract: extractForFuzzy } - ); - return results.map((result) => result.original); + debounce((query: string, callback: (results: Chat[]) => void) => { + const results = performSearch(query); + callback(results); }, DEBOUNCE_DELAY), - [filteredData, extractForFuzzy] + [performSearch] ); - const searchResults = useMemo(() => { + const [searchResults, setSearchResults] = useState([]); + + useEffect(() => { + if (searchQuery.trim() !== '') { + debouncedSearch(searchQuery, setSearchResults); + } else { + setSearchResults([]); + } + return () => { + debouncedSearch.cancel(); + }; + }, [searchQuery, debouncedSearch]); + + const filteredSearchResults = useMemo(() => { + return searchResults.filter((chat) => { + if (logic.isGroupChannelId(chat.id)) { + return activeTab === 'all' || activeTab === 'groups'; + } + return activeTab === 'all' || activeTab === 'messages'; + }); + }, [searchResults, activeTab]); + + const displayData = useMemo(() => { if (searchQuery.trim() === '') { return sectionedData; } - const results = debouncedFuzzySearch(searchQuery); - - return results && results.length > 0 - ? [ - { - title: 'Search', - data: results, - }, - ] + return filteredSearchResults.length > 0 + ? [{ title: 'Search', data: filteredSearchResults }] : [{ title: 'Search', data: [] }]; - }, [searchQuery, sectionedData, debouncedFuzzySearch]); + }, [searchQuery, sectionedData, filteredSearchResults]); const contentContainerStyle = useStyle( { @@ -342,7 +358,7 @@ export function ChatList({ - {searchQuery !== '' && searchResults.length === 0 ? ( + {searchQuery !== '' && filteredSearchResults.length === 0 ? ( ) : (