diff options
author | Eric Bailey <git@esb.lol> | 2023-11-14 19:51:23 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-14 17:51:23 -0800 |
commit | d1cb74febea9725b028dca372e1b7d7e157ad24d (patch) | |
tree | 6d08f29a709c024e01b543b179bf33b28859eb3c /src/state/queries | |
parent | ab1ce078ec16866c691eac81f7b1517bb26399c9 (diff) | |
download | voidsky-d1cb74febea9725b028dca372e1b7d7e157ad24d.tar.zst |
Desktop user autocomplete search (#1906)
* Fix notification provider order, add comments * Remove log * Add actor typeahead handling * Trim down desktop search styles and hooks * Clean up moderation
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 |