diff options
Diffstat (limited to 'src/state/queries')
-rw-r--r-- | src/state/queries/actor-autocomplete.ts | 62 |
1 files changed, 59 insertions, 3 deletions
diff --git a/src/state/queries/actor-autocomplete.ts b/src/state/queries/actor-autocomplete.ts index 62c4781c4..1bfa13f81 100644 --- a/src/state/queries/actor-autocomplete.ts +++ b/src/state/queries/actor-autocomplete.ts @@ -1,8 +1,12 @@ +import React from 'react' import {AppBskyActorDefs, BskyAgent} from '@atproto/api' -import {useQuery} from '@tanstack/react-query' -import {useSession} from '../session' -import {useMyFollowsQuery} from './my-follows' +import {useQuery, useQueryClient} from '@tanstack/react-query' import AwaitLock from 'await-lock' +import Fuse from 'fuse.js' + +import {logger} from '#/logger' +import {useSession} from '#/state/session' +import {useMyFollowsQuery} from '#/state/queries/my-follows' export const RQKEY = (prefix: string) => ['actor-autocomplete', prefix] @@ -22,6 +26,58 @@ export function useActorAutocompleteQuery(prefix: string) { }) } +export function useActorSearch() { + const queryClient = useQueryClient() + const {agent} = useSession() + const {data: follows} = useMyFollowsQuery() + + const followsSearch = React.useMemo(() => { + if (!follows) return undefined + + return new Fuse(follows, { + includeScore: true, + keys: ['displayName', 'handle'], + }) + }, [follows]) + + return React.useCallback( + async ({query}: {query: string}) => { + let searchResults: AppBskyActorDefs.ProfileViewBasic[] = [] + + if (followsSearch) { + const results = followsSearch.search(query) + searchResults = results.map(({item}) => item) + } + + try { + const res = await queryClient.fetchQuery({ + // cached for 1 min + staleTime: 60 * 1000, + queryKey: ['search', query], + queryFn: () => + agent.searchActorsTypeahead({ + term: query, + limit: 8, + }), + }) + + if (res.data.actors) { + for (const actor of res.data.actors) { + if (!searchResults.find(item => item.handle === actor.handle)) { + searchResults.push(actor) + } + } + } + } catch (e) { + logger.error('useActorSearch: searchActorsTypeahead failed', {error: e}) + } + + return searchResults + }, + [agent, followsSearch, queryClient], + ) +} + export class ActorAutocomplete { // state isLoading = false |