about summary refs log tree commit diff
path: root/src/state/queries/bookmarks/useBookmarkMutation.ts
blob: c6e745aa047246c248c9bc2e681f0d0b06321559 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import {type AppBskyFeedDefs} from '@atproto/api'
import {useMutation, useQueryClient} from '@tanstack/react-query'

import {isNetworkError} from '#/lib/strings/errors'
import {logger} from '#/logger'
import {updatePostShadow} from '#/state/cache/post-shadow'
import {
  optimisticallyDeleteBookmark,
  optimisticallySaveBookmark,
} from '#/state/queries/bookmarks/useBookmarksQuery'
import {useAgent} from '#/state/session'

type MutationArgs =
  | {action: 'create'; post: AppBskyFeedDefs.PostView}
  | {
      action: 'delete'
      /**
       * For deletions, we only need to URI. Plus, in some cases we only know the
       * URI, such as when a post was deleted by the author.
       */
      uri: string
    }

export function useBookmarkMutation() {
  const qc = useQueryClient()
  const agent = useAgent()

  return useMutation({
    async mutationFn(args: MutationArgs) {
      if (args.action === 'create') {
        updatePostShadow(qc, args.post.uri, {bookmarked: true})
        await agent.app.bsky.bookmark.createBookmark({
          uri: args.post.uri,
          cid: args.post.cid,
        })
      } else if (args.action === 'delete') {
        updatePostShadow(qc, args.uri, {bookmarked: false})
        await agent.app.bsky.bookmark.deleteBookmark({
          uri: args.uri,
        })
      }
    },
    onSuccess(_, args) {
      if (args.action === 'create') {
        optimisticallySaveBookmark(qc, args.post)
      } else if (args.action === 'delete') {
        optimisticallyDeleteBookmark(qc, {uri: args.uri})
      }
    },
    onError(e, args) {
      if (args.action === 'create') {
        updatePostShadow(qc, args.post.uri, {bookmarked: false})
      } else if (args.action === 'delete') {
        updatePostShadow(qc, args.uri, {bookmarked: true})
      }

      if (!isNetworkError(e)) {
        logger.error('bookmark mutation failed', {
          bookmarkAction: args.action,
          safeMessage: e,
        })
      }
    },
  })
}