An ATproto social media client -- with an independent Appview.
at main 130 lines 3.5 kB view raw
1import { 2 type AppBskyActorDefs, 3 type AppBskyNotificationDeclaration, 4 type AppBskyNotificationListActivitySubscriptions, 5} from '@atproto/api' 6import {t} from '@lingui/macro' 7import { 8 type InfiniteData, 9 type QueryClient, 10 useInfiniteQuery, 11 useMutation, 12 useQuery, 13 useQueryClient, 14} from '@tanstack/react-query' 15 16import {useAgent, useSession} from '#/state/session' 17import * as Toast from '#/view/com/util/Toast' 18 19export const RQKEY_getActivitySubscriptions = ['activity-subscriptions'] 20export const RQKEY_getNotificationDeclaration = ['notification-declaration'] 21 22export function useActivitySubscriptionsQuery() { 23 const agent = useAgent() 24 25 return useInfiniteQuery({ 26 queryKey: RQKEY_getActivitySubscriptions, 27 queryFn: async ({pageParam}) => { 28 const response = 29 await agent.app.bsky.notification.listActivitySubscriptions({ 30 cursor: pageParam, 31 }) 32 return response.data 33 }, 34 initialPageParam: undefined as string | undefined, 35 getNextPageParam: prev => prev.cursor, 36 }) 37} 38 39export function useNotificationDeclarationQuery() { 40 const agent = useAgent() 41 const {currentAccount} = useSession() 42 return useQuery({ 43 queryKey: RQKEY_getNotificationDeclaration, 44 queryFn: async () => { 45 try { 46 const response = await agent.app.bsky.notification.declaration.get({ 47 repo: currentAccount!.did, 48 rkey: 'self', 49 }) 50 return response 51 } catch (err) { 52 if ( 53 err instanceof Error && 54 err.message.startsWith('Could not locate record') 55 ) { 56 return { 57 value: { 58 $type: 'app.bsky.notification.declaration', 59 allowSubscriptions: 'followers', 60 } satisfies AppBskyNotificationDeclaration.Record, 61 } 62 } else { 63 throw err 64 } 65 } 66 }, 67 }) 68} 69 70export function useNotificationDeclarationMutation() { 71 const agent = useAgent() 72 const {currentAccount} = useSession() 73 const queryClient = useQueryClient() 74 return useMutation({ 75 mutationFn: async (record: AppBskyNotificationDeclaration.Record) => { 76 const response = await agent.app.bsky.notification.declaration.put( 77 { 78 repo: currentAccount!.did, 79 rkey: 'self', 80 }, 81 record, 82 ) 83 return response 84 }, 85 onMutate: value => { 86 queryClient.setQueryData( 87 RQKEY_getNotificationDeclaration, 88 (old?: { 89 uri: string 90 cid: string 91 value: AppBskyNotificationDeclaration.Record 92 }) => { 93 if (!old) return old 94 return { 95 value, 96 } 97 }, 98 ) 99 }, 100 onError: () => { 101 Toast.show(t`Failed to update notification declaration`) 102 queryClient.invalidateQueries({ 103 queryKey: RQKEY_getNotificationDeclaration, 104 }) 105 }, 106 }) 107} 108 109export function* findAllProfilesInQueryData( 110 queryClient: QueryClient, 111 did: string, 112): Generator<AppBskyActorDefs.ProfileView, void> { 113 const queryDatas = queryClient.getQueriesData< 114 InfiniteData<AppBskyNotificationListActivitySubscriptions.OutputSchema> 115 >({ 116 queryKey: RQKEY_getActivitySubscriptions, 117 }) 118 for (const [_queryKey, queryData] of queryDatas) { 119 if (!queryData?.pages) { 120 continue 121 } 122 for (const page of queryData.pages) { 123 for (const subscription of page.subscriptions) { 124 if (subscription.did === did) { 125 yield subscription 126 } 127 } 128 } 129 } 130}