Bluesky app fork with some witchin' additions 馃挮 witchsky.app
bluesky fork client
at feat/custom-appview 87 lines 2.9 kB view raw
1import {msg} from '@lingui/core/macro' 2import {useLingui} from '@lingui/react' 3import {useMutation, useQueryClient} from '@tanstack/react-query' 4 5import {logger} from '#/logger' 6import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed' 7import * as Toast from '#/view/com/util/Toast' 8import {updatePostShadow} from '../cache/post-shadow' 9import {useAgent, useSession} from '../session' 10import {useProfileUpdateMutation} from './profile' 11 12export function usePinnedPostMutation() { 13 const {_} = useLingui() 14 const {currentAccount} = useSession() 15 const agent = useAgent() 16 const queryClient = useQueryClient() 17 const {mutateAsync: profileUpdateMutate} = useProfileUpdateMutation() 18 19 return useMutation({ 20 mutationFn: async ({ 21 postUri, 22 postCid, 23 action, 24 }: { 25 postUri: string 26 postCid: string 27 action: 'pin' | 'unpin' 28 }) => { 29 const pinCurrentPost = action === 'pin' 30 let prevPinnedPost: string | undefined 31 try { 32 updatePostShadow(queryClient, postUri, {pinned: pinCurrentPost}) 33 34 // get the currently pinned post so we can optimistically remove the pin from it 35 if (!currentAccount) throw new Error('Not signed in') 36 const {data: profile} = await agent.getProfile({ 37 actor: currentAccount.did, 38 }) 39 prevPinnedPost = profile.pinnedPost?.uri 40 if (prevPinnedPost && prevPinnedPost !== postUri) { 41 updatePostShadow(queryClient, prevPinnedPost, {pinned: false}) 42 } 43 44 await profileUpdateMutate({ 45 profile, 46 updates: existing => { 47 existing.pinnedPost = pinCurrentPost 48 ? {uri: postUri, cid: postCid} 49 : undefined 50 return existing 51 }, 52 checkCommitted: res => 53 pinCurrentPost 54 ? res.data.pinnedPost?.uri === postUri 55 : !res.data.pinnedPost, 56 }) 57 58 if (pinCurrentPost) { 59 Toast.show(_(msg({message: 'Post pinned', context: 'toast'}))) 60 } else { 61 Toast.show(_(msg({message: 'Post unpinned', context: 'toast'}))) 62 } 63 64 queryClient.invalidateQueries({ 65 queryKey: FEED_RQKEY( 66 `author|${currentAccount.did}|posts_and_author_threads`, 67 ), 68 }) 69 queryClient.invalidateQueries({ 70 queryKey: FEED_RQKEY( 71 `author|${currentAccount.did}|posts_with_replies`, 72 ), 73 }) 74 } catch (e: any) { 75 Toast.show(_(msg`Failed to pin post`)) 76 logger.error('Failed to pin post', {message: String(e)}) 77 // revert optimistic update 78 updatePostShadow(queryClient, postUri, { 79 pinned: !pinCurrentPost, 80 }) 81 if (prevPinnedPost && prevPinnedPost !== postUri) { 82 updatePostShadow(queryClient, prevPinnedPost, {pinned: true}) 83 } 84 } 85 }, 86 }) 87}