1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
import {
type AppBskyActorDefs,
type AppBskyGraphDefs,
type AppBskyGraphGetList,
type BskyAgent,
} from '@atproto/api'
import {
type InfiniteData,
type QueryClient,
type QueryKey,
useInfiniteQuery,
useQuery,
} from '@tanstack/react-query'
import {STALE} from '#/state/queries'
import {useAgent} from '#/state/session'
const PAGE_SIZE = 30
type RQPageParam = string | undefined
const RQKEY_ROOT = 'list-members'
const RQKEY_ROOT_ALL = 'list-members-all'
export const RQKEY = (uri: string) => [RQKEY_ROOT, uri]
export const RQKEY_ALL = (uri: string) => [RQKEY_ROOT_ALL, uri]
export function useListMembersQuery(uri?: string, limit: number = PAGE_SIZE) {
const agent = useAgent()
return useInfiniteQuery<
AppBskyGraphGetList.OutputSchema,
Error,
InfiniteData<AppBskyGraphGetList.OutputSchema>,
QueryKey,
RQPageParam
>({
staleTime: STALE.MINUTES.ONE,
queryKey: RQKEY(uri ?? ''),
async queryFn({pageParam}: {pageParam: RQPageParam}) {
const res = await agent.app.bsky.graph.getList({
list: uri!, // the enabled flag will prevent this from running until uri is set
limit,
cursor: pageParam,
})
return res.data
},
initialPageParam: undefined,
getNextPageParam: lastPage => lastPage.cursor,
enabled: Boolean(uri),
})
}
export function useAllListMembersQuery(uri?: string) {
const agent = useAgent()
return useQuery({
staleTime: STALE.MINUTES.ONE,
queryKey: RQKEY_ALL(uri ?? ''),
queryFn: async () => {
return getAllListMembers(agent, uri!)
},
enabled: Boolean(uri),
})
}
export async function getAllListMembers(agent: BskyAgent, uri: string) {
let hasMore = true
let cursor: string | undefined
const listItems: AppBskyGraphDefs.ListItemView[] = []
// We want to cap this at 6 pages, just for anything weird happening with the api
let i = 0
while (hasMore && i < 6) {
const res = await agent.app.bsky.graph.getList({
list: uri,
limit: 50,
cursor,
})
listItems.push(...res.data.items)
hasMore = Boolean(res.data.cursor)
cursor = res.data.cursor
i++
}
return listItems
}
export async function invalidateListMembersQuery({
queryClient,
uri,
}: {
queryClient: QueryClient
uri: string
}) {
await queryClient.invalidateQueries({queryKey: RQKEY(uri)})
}
export function* findAllProfilesInQueryData(
queryClient: QueryClient,
did: string,
): Generator<AppBskyActorDefs.ProfileView, void> {
const queryDatas = queryClient.getQueriesData<
InfiniteData<AppBskyGraphGetList.OutputSchema>
>({
queryKey: [RQKEY_ROOT],
})
for (const [_queryKey, queryData] of queryDatas) {
if (!queryData?.pages) {
continue
}
for (const page of queryData?.pages) {
if (page.list.creator.did === did) {
yield page.list.creator
}
for (const item of page.items) {
if (item.subject.did === did) {
yield item.subject
}
}
}
}
const allQueryData = queryClient.getQueriesData<
AppBskyGraphDefs.ListItemView[]
>({
queryKey: [RQKEY_ROOT_ALL],
})
for (const [_queryKey, queryData] of allQueryData) {
if (!queryData) {
continue
}
for (const item of queryData) {
if (item.subject.did === did) {
yield item.subject
}
}
}
}
|