import { type AppBskyActorDefs, type AppBskyGraphGetFollowers, } from '@atproto/api' import { type InfiniteData, type QueryClient, type QueryKey, useInfiniteQuery, } from '@tanstack/react-query' import {useAgent} from '#/state/session' import {useAnalytics} from '#/analytics' import {useAutoPagination} from './util' const DEFAULT_SORT = 'latest' const PAGE_SIZE = 30 type RQPageParam = string | undefined const RQKEY_ROOT = 'profile-followers' export const RQKEY = (did: string, sort: 'latest' | 'top' = DEFAULT_SORT) => [ RQKEY_ROOT, did, sort, ] export function useProfileFollowersQuery( did?: string, { sort, }: { sort?: 'latest' | 'top' } = {}, ) { const ax = useAnalytics() const isSortEnabled = ax.features.enabled(ax.features.FollowSortEnable) const agent = useAgent() const sortParam = isSortEnabled ? sort || DEFAULT_SORT : undefined const query = useInfiniteQuery< AppBskyGraphGetFollowers.OutputSchema, Error, InfiniteData, QueryKey, RQPageParam >({ queryKey: RQKEY(did || '', sortParam), async queryFn({pageParam}: {pageParam: RQPageParam}) { const res = await agent.app.bsky.graph.getFollowers({ actor: did || '', limit: PAGE_SIZE, cursor: pageParam, sort: sortParam, }) return res.data }, initialPageParam: undefined, getNextPageParam: lastPage => lastPage.cursor, enabled: !!did, }) const itemCount = query.data?.pages.reduce( (count, page) => count + page.followers.length, 0, ) ?? 0 useAutoPagination(query, itemCount, PAGE_SIZE) return query } export function* findAllProfilesInQueryData( queryClient: QueryClient, did: string, ): Generator { const queryDatas = queryClient.getQueriesData< InfiniteData >({ queryKey: [RQKEY_ROOT], }) for (const [_queryKey, queryData] of queryDatas) { if (!queryData?.pages) { continue } for (const page of queryData?.pages) { for (const follower of page.followers) { if (follower.did === did) { yield follower } } } } }