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