Files
bsky-social-app/src/state/queries/actor-search.ts
T
2026-08-13 12:26:16 -07:00

94 lines
2.0 KiB
TypeScript

import {
type InfiniteData,
keepPreviousData,
type QueryClient,
type QueryKey,
useInfiniteQuery,
} from '@tanstack/react-query'
import {STALE} from '#/state/queries'
import {useAppviewClient} from '#/state/session'
import {app} from '#/lexicons'
export const RQKEY_ROOT = 'actor-search'
export const RQKEY = (query: string, limit?: number) => [
RQKEY_ROOT,
query,
limit,
]
export function useActorSearch({
query,
enabled,
maintainData,
limit = 25,
}: {
query: string
enabled?: boolean
maintainData?: boolean
limit?: number
}) {
const client = useAppviewClient()
return useInfiniteQuery<
app.bsky.actor.searchActors.$OutputBody,
Error,
InfiniteData<app.bsky.actor.searchActors.$OutputBody>,
QueryKey,
string | undefined
>({
staleTime: STALE.MINUTES.FIVE,
queryKey: RQKEY(query, limit),
queryFn: async ({pageParam}) => {
return await client.call(app.bsky.actor.searchActors, {
q: query,
limit,
cursor: pageParam,
})
},
enabled: enabled && !!query,
initialPageParam: undefined,
getNextPageParam: lastPage => lastPage.cursor,
placeholderData: maintainData ? keepPreviousData : undefined,
select,
})
}
function select(data: InfiniteData<app.bsky.actor.searchActors.$OutputBody>) {
// enforce uniqueness
const dids = new Set()
return {
...data,
pages: data.pages.map(page => ({
actors: page.actors.filter(actor => {
if (dids.has(actor.did)) {
return false
}
dids.add(actor.did)
return true
}),
})),
}
}
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
) {
const queryDatas = queryClient.getQueriesData<
InfiniteData<app.bsky.actor.searchActors.$OutputBody>
>({
queryKey: [RQKEY_ROOT],
})
for (const [_queryKey, queryData] of queryDatas) {
if (!queryData) {
continue
}
for (const actor of queryData.pages.flatMap(page => page.actors)) {
if (actor.did === did) {
yield actor
}
}
}
}