about summary refs log tree commit diff
path: root/src/state/queries/messages/conversation.ts
blob: 393bf9e52021c4589ca579b908a9d0741b7cd8c2 (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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import {type ChatBskyConvoDefs} from '@atproto/api'
import {
  type QueryClient,
  useMutation,
  useQuery,
  useQueryClient,
} from '@tanstack/react-query'

import {DM_SERVICE_HEADERS} from '#/lib/constants'
import {STALE} from '#/state/queries'
import {useOnMarkAsRead} from '#/state/queries/messages/list-conversations'
import {useAgent} from '#/state/session'
import {
  type ConvoListQueryData,
  getConvoFromQueryData,
  RQKEY_ROOT as LIST_CONVOS_KEY,
} from './list-conversations'

const RQKEY_ROOT = 'convo'
export const RQKEY = (convoId: string) => [RQKEY_ROOT, convoId]

export function useConvoQuery(convo: ChatBskyConvoDefs.ConvoView) {
  const agent = useAgent()

  return useQuery({
    queryKey: RQKEY(convo.id),
    queryFn: async () => {
      const {data} = await agent.chat.bsky.convo.getConvo(
        {convoId: convo.id},
        {headers: DM_SERVICE_HEADERS},
      )
      return data.convo
    },
    initialData: convo,
    staleTime: STALE.INFINITY,
  })
}

export function precacheConvoQuery(
  queryClient: QueryClient,
  convo: ChatBskyConvoDefs.ConvoView,
) {
  queryClient.setQueryData(RQKEY(convo.id), convo)
}

export function useMarkAsReadMutation() {
  const optimisticUpdate = useOnMarkAsRead()
  const queryClient = useQueryClient()
  const agent = useAgent()

  return useMutation({
    mutationFn: async ({
      convoId,
      messageId,
    }: {
      convoId?: string
      messageId?: string
    }) => {
      if (!convoId) throw new Error('No convoId provided')

      await agent.api.chat.bsky.convo.updateRead(
        {
          convoId,
          messageId,
        },
        {
          encoding: 'application/json',
          headers: DM_SERVICE_HEADERS,
        },
      )
    },
    onMutate({convoId}) {
      if (!convoId) throw new Error('No convoId provided')
      optimisticUpdate(convoId)
    },
    onSuccess(_, {convoId}) {
      if (!convoId) return

      queryClient.setQueriesData(
        {queryKey: [LIST_CONVOS_KEY]},
        (old?: ConvoListQueryData) => {
          if (!old) return old

          const existingConvo = getConvoFromQueryData(convoId, old)

          if (existingConvo) {
            return {
              ...old,
              pages: old.pages.map(page => {
                return {
                  ...page,
                  convos: page.convos.map(convo => {
                    if (convo.id === convoId) {
                      return {
                        ...convo,
                        unreadCount: 0,
                      }
                    }
                    return convo
                  }),
                }
              }),
            }
          } else {
            // If we somehow marked a convo as read that doesn't exist in the
            // list, then we don't need to do anything.
          }
        },
      )
    },
  })
}