138 lines
4.1 KiB
TypeScript
138 lines
4.1 KiB
TypeScript
import {
|
|
type ChatBskyActorDefs,
|
|
ChatBskyConvoDefs,
|
|
type ChatBskyConvoListConvos,
|
|
type ChatBskyGroupRemoveMembers,
|
|
} from '@atproto/api'
|
|
import {
|
|
type InfiniteData,
|
|
useMutation,
|
|
useQueryClient,
|
|
} from '@tanstack/react-query'
|
|
|
|
import {DM_SERVICE_HEADERS} from '#/lib/constants'
|
|
import {logger} from '#/logger'
|
|
import {useAgent} from '#/state/session'
|
|
import {RQKEY as CONVO_KEY} from './conversation'
|
|
import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations'
|
|
import {listConvoMembersQueryKey} from './list-convo-members'
|
|
|
|
export function useRemoveFromGroupChat(
|
|
convoId: string | undefined,
|
|
{
|
|
onSuccess,
|
|
onError,
|
|
}: {
|
|
onSuccess?: (data: ChatBskyGroupRemoveMembers.OutputSchema) => void
|
|
onError?: (error: Error) => void
|
|
},
|
|
) {
|
|
const queryClient = useQueryClient()
|
|
const agent = useAgent()
|
|
|
|
return useMutation({
|
|
mutationFn: async ({members}: {members: string[]}) => {
|
|
if (!convoId) throw new Error('No convoId provided')
|
|
const {data} = await agent.chat.bsky.group.removeMembers(
|
|
{convoId, members},
|
|
{headers: DM_SERVICE_HEADERS, encoding: 'application/json'},
|
|
)
|
|
return data
|
|
},
|
|
onMutate: ({members}) => {
|
|
if (!convoId) return
|
|
|
|
const prevConvo = queryClient.getQueryData<ChatBskyConvoDefs.ConvoView>(
|
|
CONVO_KEY(convoId),
|
|
)
|
|
const prevListEntries = queryClient.getQueriesData<
|
|
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
|
|
>({queryKey: [CONVO_LIST_KEY]})
|
|
const prevMemberList = queryClient.getQueryData<
|
|
ChatBskyActorDefs.ProfileViewBasic[]
|
|
>(listConvoMembersQueryKey(convoId))
|
|
|
|
queryClient.setQueryData<ChatBskyConvoDefs.ConvoView>(
|
|
CONVO_KEY(convoId),
|
|
prev => {
|
|
if (!prev) return
|
|
const nextMembers = prev.members.filter(m => !members.includes(m.did))
|
|
const removed = prev.members.length - nextMembers.length
|
|
if (!ChatBskyConvoDefs.isGroupConvo(prev.kind)) {
|
|
return {...prev, members: nextMembers}
|
|
}
|
|
return {
|
|
...prev,
|
|
members: nextMembers,
|
|
kind: {
|
|
...prev.kind,
|
|
memberCount: Math.max(0, prev.kind.memberCount - removed),
|
|
},
|
|
}
|
|
},
|
|
)
|
|
|
|
queryClient.setQueriesData<
|
|
InfiniteData<ChatBskyConvoListConvos.OutputSchema>
|
|
>({queryKey: [CONVO_LIST_KEY]}, prev => {
|
|
if (!prev?.pages) return
|
|
return {
|
|
...prev,
|
|
pages: prev.pages.map(page => ({
|
|
...page,
|
|
convos: page.convos.map(convo => {
|
|
if (convo.id !== convoId) return convo
|
|
const nextMembers = convo.members.filter(
|
|
m => !members.includes(m.did),
|
|
)
|
|
const removed = convo.members.length - nextMembers.length
|
|
if (!ChatBskyConvoDefs.isGroupConvo(convo.kind)) {
|
|
return {...convo, members: nextMembers}
|
|
}
|
|
return {
|
|
...convo,
|
|
members: nextMembers,
|
|
kind: {
|
|
...convo.kind,
|
|
memberCount: Math.max(0, convo.kind.memberCount - removed),
|
|
},
|
|
}
|
|
}),
|
|
})),
|
|
}
|
|
})
|
|
|
|
queryClient.setQueryData<ChatBskyActorDefs.ProfileViewBasic[]>(
|
|
listConvoMembersQueryKey(convoId),
|
|
prev => {
|
|
if (!prev) return
|
|
return prev.filter(m => !members.includes(m.did))
|
|
},
|
|
)
|
|
|
|
return {prevConvo, prevListEntries, prevMemberList}
|
|
},
|
|
onSuccess: data => {
|
|
onSuccess?.(data)
|
|
},
|
|
onError: (e, _variables, context) => {
|
|
logger.error(e)
|
|
if (context?.prevConvo && convoId) {
|
|
queryClient.setQueryData(CONVO_KEY(convoId), context.prevConvo)
|
|
}
|
|
if (context?.prevListEntries) {
|
|
for (const [key, data] of context.prevListEntries) {
|
|
queryClient.setQueryData(key, data)
|
|
}
|
|
}
|
|
if (context?.prevMemberList && convoId) {
|
|
queryClient.setQueryData(
|
|
listConvoMembersQueryKey(convoId),
|
|
context.prevMemberList,
|
|
)
|
|
}
|
|
onError?.(e)
|
|
},
|
|
})
|
|
}
|