Bluesky app fork with some witchin' additions 馃挮
witchsky.app
bluesky
fork
client
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}