An ATproto social media client -- with an independent Appview.
1import {
2 type AppBskyActorDefs,
3 type AppBskyUnspeccedGetSuggestedUsers,
4} from '@atproto/api'
5import {type QueryClient, useQuery} from '@tanstack/react-query'
6
7import {
8 aggregateUserInterests,
9 createBskyTopicsHeader,
10} from '#/lib/api/feed/utils'
11import {getContentLanguages} from '#/state/preferences/languages'
12import {STALE} from '#/state/queries'
13import {usePreferencesQuery} from '#/state/queries/preferences'
14import {useAgent} from '#/state/session'
15
16export type QueryProps = {
17 category?: string | null
18 limit?: number
19 enabled?: boolean
20 overrideInterests?: string[]
21}
22
23export const getSuggestedUsersQueryKeyRoot = 'unspecced-suggested-users'
24export const createGetSuggestedUsersQueryKey = (props: QueryProps) => [
25 getSuggestedUsersQueryKeyRoot,
26 props.category,
27 props.limit,
28 props.overrideInterests?.join(','),
29]
30
31export function useGetSuggestedUsersQuery(props: QueryProps) {
32 const agent = useAgent()
33 const {data: preferences} = usePreferencesQuery()
34
35 return useQuery({
36 enabled: !!preferences && props.enabled !== false,
37 staleTime: STALE.MINUTES.THREE,
38 queryKey: createGetSuggestedUsersQueryKey(props),
39 queryFn: async () => {
40 const contentLangs = getContentLanguages().join(',')
41 const interests = aggregateUserInterests(preferences)
42 const {data} = await agent.app.bsky.unspecced.getSuggestedUsers(
43 {
44 category: props.category ?? undefined,
45 limit: props.limit || 10,
46 },
47 {
48 headers: {
49 ...createBskyTopicsHeader(
50 props.overrideInterests && props.overrideInterests.length > 0
51 ? props.overrideInterests.join(',')
52 : interests,
53 ),
54 'Accept-Language': contentLangs,
55 },
56 },
57 )
58
59 return data
60 },
61 })
62}
63
64export function* findAllProfilesInQueryData(
65 queryClient: QueryClient,
66 did: string,
67): Generator<AppBskyActorDefs.ProfileView, void> {
68 const responses =
69 queryClient.getQueriesData<AppBskyUnspeccedGetSuggestedUsers.OutputSchema>({
70 queryKey: [getSuggestedUsersQueryKeyRoot],
71 })
72 for (const [_key, response] of responses) {
73 if (!response) {
74 continue
75 }
76
77 for (const actor of response.actors) {
78 if (actor.did === did) {
79 yield actor
80 }
81 }
82 }
83}