An ATproto social media client -- with an independent Appview.
at main 114 lines 2.8 kB view raw
1import { 2 type $Typed, 3 type AppBskyBookmarkGetBookmarks, 4 type AppBskyFeedDefs, 5} from '@atproto/api' 6import { 7 type InfiniteData, 8 type QueryClient, 9 type QueryKey, 10 useInfiniteQuery, 11} from '@tanstack/react-query' 12 13import {useAgent} from '#/state/session' 14 15export const bookmarksQueryKeyRoot = 'bookmarks' 16export const createBookmarksQueryKey = () => [bookmarksQueryKeyRoot] 17 18export function useBookmarksQuery() { 19 const agent = useAgent() 20 21 return useInfiniteQuery< 22 AppBskyBookmarkGetBookmarks.OutputSchema, 23 Error, 24 InfiniteData<AppBskyBookmarkGetBookmarks.OutputSchema>, 25 QueryKey, 26 string | undefined 27 >({ 28 queryKey: createBookmarksQueryKey(), 29 async queryFn({pageParam}) { 30 const res = await agent.app.bsky.bookmark.getBookmarks({ 31 cursor: pageParam, 32 }) 33 return res.data 34 }, 35 initialPageParam: undefined, 36 getNextPageParam: lastPage => lastPage.cursor, 37 }) 38} 39 40export async function truncateAndInvalidate(qc: QueryClient) { 41 qc.setQueriesData<InfiniteData<AppBskyBookmarkGetBookmarks.OutputSchema>>( 42 {queryKey: [bookmarksQueryKeyRoot]}, 43 data => { 44 if (data) { 45 return { 46 pageParams: data.pageParams.slice(0, 1), 47 pages: data.pages.slice(0, 1), 48 } 49 } 50 return data 51 }, 52 ) 53 return qc.invalidateQueries({queryKey: [bookmarksQueryKeyRoot]}) 54} 55 56export async function optimisticallySaveBookmark( 57 qc: QueryClient, 58 post: AppBskyFeedDefs.PostView, 59) { 60 qc.setQueriesData<InfiniteData<AppBskyBookmarkGetBookmarks.OutputSchema>>( 61 { 62 queryKey: [bookmarksQueryKeyRoot], 63 }, 64 data => { 65 if (!data) return data 66 return { 67 ...data, 68 pages: data.pages.map((page, index) => { 69 if (index === 0) { 70 post.$type = 'app.bsky.feed.defs#postView' 71 return { 72 ...page, 73 bookmarks: [ 74 { 75 createdAt: new Date().toISOString(), 76 subject: { 77 uri: post.uri, 78 cid: post.cid, 79 }, 80 item: post as $Typed<AppBskyFeedDefs.PostView>, 81 }, 82 ...page.bookmarks, 83 ], 84 } 85 } 86 return page 87 }), 88 } 89 }, 90 ) 91} 92 93export async function optimisticallyDeleteBookmark( 94 qc: QueryClient, 95 {uri}: {uri: string}, 96) { 97 qc.setQueriesData<InfiniteData<AppBskyBookmarkGetBookmarks.OutputSchema>>( 98 { 99 queryKey: [bookmarksQueryKeyRoot], 100 }, 101 data => { 102 if (!data) return data 103 return { 104 ...data, 105 pages: data.pages.map(page => { 106 return { 107 ...page, 108 bookmarks: page.bookmarks.filter(b => b.subject.uri !== uri), 109 } 110 }), 111 } 112 }, 113 ) 114}