* Swap in new package, update usages * Remove uneccessary patch * Override type in safe place
142 lines
3.6 KiB
TypeScript
142 lines
3.6 KiB
TypeScript
import {useCallback, useMemo} from 'react'
|
|
import {ChatBskyConvoDefs, ChatBskyConvoListConvos} from '@atproto/api'
|
|
import {useInfiniteQuery, useQueryClient} from '@tanstack/react-query'
|
|
|
|
import {useCurrentConvoId} from '#/state/messages/current-convo-id'
|
|
import {DM_SERVICE_HEADERS} from '#/state/queries/messages/const'
|
|
import {useAgent} from '#/state/session'
|
|
|
|
export const RQKEY = ['convo-list']
|
|
type RQPageParam = string | undefined
|
|
|
|
export function useListConvos({refetchInterval}: {refetchInterval: number}) {
|
|
const {getAgent} = useAgent()
|
|
|
|
return useInfiniteQuery({
|
|
queryKey: RQKEY,
|
|
queryFn: async ({pageParam}) => {
|
|
const {data} = await getAgent().api.chat.bsky.convo.listConvos(
|
|
{cursor: pageParam},
|
|
{headers: DM_SERVICE_HEADERS},
|
|
)
|
|
|
|
return data
|
|
},
|
|
initialPageParam: undefined as RQPageParam,
|
|
getNextPageParam: lastPage => lastPage.cursor,
|
|
refetchInterval,
|
|
})
|
|
}
|
|
|
|
export function useUnreadMessageCount() {
|
|
const {currentConvoId} = useCurrentConvoId()
|
|
const convos = useListConvos({
|
|
refetchInterval: 30_000,
|
|
})
|
|
|
|
const count =
|
|
convos.data?.pages
|
|
.flatMap(page => page.convos)
|
|
.filter(convo => convo.id !== currentConvoId)
|
|
.reduce((acc, convo) => {
|
|
return acc + (!convo.muted && convo.unreadCount > 0 ? 1 : 0)
|
|
}, 0) ?? 0
|
|
|
|
return useMemo(() => {
|
|
return {
|
|
count,
|
|
numUnread: count > 0 ? (count > 30 ? '30+' : String(count)) : undefined,
|
|
}
|
|
}, [count])
|
|
}
|
|
|
|
type ConvoListQueryData = {
|
|
pageParams: Array<string | undefined>
|
|
pages: Array<ChatBskyConvoListConvos.OutputSchema>
|
|
}
|
|
|
|
export function useOnDeleteMessage() {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useCallback(
|
|
(chatId: string, messageId: string) => {
|
|
queryClient.setQueryData(RQKEY, (old: ConvoListQueryData) => {
|
|
return optimisticUpdate(chatId, old, convo =>
|
|
messageId === convo.lastMessage?.id
|
|
? {
|
|
...convo,
|
|
lastMessage: {
|
|
$type: 'chat.bsky.convo.defs#deletedMessageView',
|
|
id: messageId,
|
|
rev: '',
|
|
},
|
|
}
|
|
: convo,
|
|
)
|
|
})
|
|
},
|
|
[queryClient],
|
|
)
|
|
}
|
|
|
|
export function useOnNewMessage() {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useCallback(
|
|
(chatId: string, message: ChatBskyConvoDefs.MessageView) => {
|
|
queryClient.setQueryData(RQKEY, (old: ConvoListQueryData) => {
|
|
return optimisticUpdate(chatId, old, convo => ({
|
|
...convo,
|
|
lastMessage: message,
|
|
unreadCount: convo.unreadCount + 1,
|
|
}))
|
|
})
|
|
queryClient.invalidateQueries({queryKey: RQKEY})
|
|
},
|
|
[queryClient],
|
|
)
|
|
}
|
|
|
|
export function useOnCreateConvo() {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useCallback(() => {
|
|
queryClient.invalidateQueries({queryKey: RQKEY})
|
|
}, [queryClient])
|
|
}
|
|
|
|
export function useOnMarkAsRead() {
|
|
const queryClient = useQueryClient()
|
|
|
|
return useCallback(
|
|
(chatId: string) => {
|
|
queryClient.setQueryData(RQKEY, (old: ConvoListQueryData) => {
|
|
return optimisticUpdate(chatId, old, convo => ({
|
|
...convo,
|
|
unreadCount: 0,
|
|
}))
|
|
})
|
|
},
|
|
[queryClient],
|
|
)
|
|
}
|
|
|
|
function optimisticUpdate(
|
|
chatId: string,
|
|
old: ConvoListQueryData,
|
|
updateFn: (convo: ChatBskyConvoDefs.ConvoView) => ChatBskyConvoDefs.ConvoView,
|
|
) {
|
|
if (!old) {
|
|
return old
|
|
}
|
|
|
|
return {
|
|
...old,
|
|
pages: old.pages.map(page => ({
|
|
...page,
|
|
convos: page.convos.map(convo =>
|
|
chatId === convo.id ? updateFn(convo) : convo,
|
|
),
|
|
})),
|
|
}
|
|
}
|