diff --git a/src/screens/Messages/ChatList.tsx b/src/screens/Messages/ChatList.tsx index f08d155e06..f2dff0c6d6 100644 --- a/src/screens/Messages/ChatList.tsx +++ b/src/screens/Messages/ChatList.tsx @@ -16,7 +16,6 @@ import {listenSoftReset} from '#/state/events' import {MESSAGE_SCREEN_POLL_INTERVAL} from '#/state/messages/convo/const' import {useMessagesEventBus} from '#/state/messages/events' import {useChatActorStatusQuery} from '#/state/queries/messages/get-status' -import {useLeftConvos} from '#/state/queries/messages/leave-conversation' import {useListConvosQuery} from '#/state/queries/messages/list-conversations' import {EmptyState} from '#/view/com/util/EmptyState' import {List, type ListRef} from '#/view/com/util/List' @@ -237,14 +236,9 @@ export function ChatList({ useRefreshOnFocus(refetch) useRefreshOnFocus(refetchInbox) - const leftConvos = useLeftConvos() - const conversations = useMemo(() => { if (data?.pages) { - const conversations = data.pages - .flatMap(page => page.convos) - // filter out convos that are actively being left - .filter(convo => !leftConvos.includes(convo.id)) + const conversations = data.pages.flatMap(page => page.convos) return conversations.map( convo => @@ -256,7 +250,7 @@ export function ChatList({ ) satisfies ListItem[] } return [] - }, [data, leftConvos, selectedChat]) + }, [data, selectedChat]) const onRefresh = useCallback(async () => { setIsPTRing(true) @@ -453,7 +447,6 @@ export function Header({ const {gtMobile} = useBreakpoints() const aa = useAgeAssurance() const requireEmailVerification = useRequireEmailVerification() - const leftConvos = useLeftConvos() const {isWithinSplitView} = useIsWithinSplitView() // In split view, the left column (and this header) stays mounted while the @@ -473,7 +466,6 @@ export function Header({ .flatMap(page => page.convos) .filter( convo => - !leftConvos.includes(convo.id) && !convo.muted && convo.members.every(member => member.handle !== 'missing.invalid') && (ChatBskyConvoDefs.isGroupConvo(convo.kind) diff --git a/src/screens/Messages/Inbox.tsx b/src/screens/Messages/Inbox.tsx index 60891c3c11..2fb58253a5 100644 --- a/src/screens/Messages/Inbox.tsx +++ b/src/screens/Messages/Inbox.tsx @@ -23,7 +23,6 @@ import {cleanError} from '#/lib/strings/errors' import {logger} from '#/logger' import {MESSAGE_SCREEN_POLL_INTERVAL} from '#/state/messages/convo/const' import {useMessagesEventBus} from '#/state/messages/events' -import {useLeftConvos} from '#/state/queries/messages/leave-conversation' import {useListConvoRequests} from '#/state/queries/messages/list-conversation-requests' import {useUpdateAllRead} from '#/state/queries/messages/update-all-read' import {EmptyState} from '#/view/com/util/EmptyState' @@ -70,16 +69,12 @@ export function MessagesInboxScreenInner({}: Props) { const listConvosQuery = useListConvoRequests() const {data} = listConvosQuery - const leftConvos = useLeftConvos() - const conversations = useMemo(() => { if (!data?.pages) return [] const items: RequestItem[] = [] for (const page of data.pages) { for (const item of page.requests) { if (ChatBskyConvoDefs.isConvoView(item)) { - // filter out convos that are actively being left - if (leftConvos.includes(item.id)) continue items.push({type: 'incoming', view: item}) } else if (ChatBskyGroupDefs.isJoinRequestConvoView(item)) { items.push({type: 'outgoing', view: item}) @@ -87,7 +82,7 @@ export function MessagesInboxScreenInner({}: Props) { } } return items - }, [data, leftConvos]) + }, [data]) const hasUnreadConvos = useMemo(() => { return conversations.some( diff --git a/src/state/queries/messages/leave-conversation.ts b/src/state/queries/messages/leave-conversation.ts index a9614981e5..51b51bde80 100644 --- a/src/state/queries/messages/leave-conversation.ts +++ b/src/state/queries/messages/leave-conversation.ts @@ -1,18 +1,18 @@ -import {useMemo} from 'react' import { type ChatBskyConvoLeaveConvo, type ChatBskyConvoListConvos, } from '@atproto/api' -import { - useMutation, - useMutationState, - useQueryClient, -} from '@tanstack/react-query' +import {useMutation, useQueryClient} from '@tanstack/react-query' import {DM_SERVICE_HEADERS} from '#/lib/constants' import {logger} from '#/logger' import {invalidateJoinLinkPreviewsForConvo} from '#/state/queries/join-links' import {useAgent} from '#/state/session' +import { + type ConvoRequestListQueryData, + optimisticDelete as optimisticDeleteRequest, + RQKEY_ROOT as REQUESTS_RQKEY_ROOT, +} from './list-conversation-requests' import {RQKEY_ROOT as CONVO_LIST_KEY} from './list-conversations' const RQKEY_ROOT = 'leave-convo' @@ -20,6 +20,11 @@ export function RQKEY(convoId: string | undefined) { return [RQKEY_ROOT, convoId] } +type ConvoListQueryData = { + pageParams: Array + pages: Array +} + export function useLeaveConvo( convoId: string | undefined, { @@ -48,31 +53,37 @@ export function useLeaveConvo( return data }, onMutate: () => { - let prevPages: ChatBskyConvoListConvos.OutputSchema[] = [] - queryClient.setQueryData( - [CONVO_LIST_KEY], - (old?: { - pageParams: Array - pages: Array - }) => { + const prevConvoListQueries = + queryClient.getQueriesData({ + queryKey: [CONVO_LIST_KEY], + }) + queryClient.setQueriesData( + {queryKey: [CONVO_LIST_KEY]}, + old => { if (!old) return old - prevPages = old.pages return { ...old, - pages: old.pages.map(page => { - return { - ...page, - convos: page.convos.filter(convo => convo.id !== convoId), - } - }), + pages: old.pages.map(page => ({ + ...page, + convos: page.convos.filter(convo => convo.id !== convoId), + })), } }, ) + const prevRequestsQueries = + queryClient.getQueriesData({ + queryKey: [REQUESTS_RQKEY_ROOT], + }) + queryClient.setQueriesData( + {queryKey: [REQUESTS_RQKEY_ROOT]}, + old => (convoId ? optimisticDeleteRequest(convoId, old) : old), + ) onMutate?.() - return {prevPages} + return {prevConvoListQueries, prevRequestsQueries} }, onSuccess: data => { void queryClient.invalidateQueries({queryKey: [CONVO_LIST_KEY]}) + void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]}) if (convoId) { void invalidateJoinLinkPreviewsForConvo(queryClient, convoId) } @@ -80,41 +91,19 @@ export function useLeaveConvo( }, onError: (error, _, context) => { logger.error(error) - queryClient.setQueryData( - [CONVO_LIST_KEY], - (old?: { - pageParams: Array - pages: Array - }) => { - if (!old) return old - return { - ...old, - pages: context?.prevPages || old.pages, - } - }, - ) + if (context?.prevConvoListQueries) { + for (const [queryKey, prevData] of context.prevConvoListQueries) { + queryClient.setQueryData(queryKey, prevData) + } + } + if (context?.prevRequestsQueries) { + for (const [queryKey, prevData] of context.prevRequestsQueries) { + queryClient.setQueryData(queryKey, prevData) + } + } void queryClient.invalidateQueries({queryKey: [CONVO_LIST_KEY]}) + void queryClient.invalidateQueries({queryKey: [REQUESTS_RQKEY_ROOT]}) onError?.(error) }, }) } - -/** - * Gets currently pending and successful leave convo mutations - * - * @returns Array of `convoId` - */ -export function useLeftConvos() { - const pending = useMutationState({ - filters: {mutationKey: [RQKEY_ROOT], status: 'pending'}, - select: mutation => mutation.options.mutationKey?.[1] as string | undefined, - }) - const success = useMutationState({ - filters: {mutationKey: [RQKEY_ROOT], status: 'success'}, - select: mutation => mutation.options.mutationKey?.[1] as string | undefined, - }) - return useMemo( - () => [...pending, ...success].filter(id => id !== undefined), - [pending, success], - ) -} diff --git a/src/state/queries/messages/list-conversations.tsx b/src/state/queries/messages/list-conversations.tsx index 9cb4e59603..8072a4eaf6 100644 --- a/src/state/queries/messages/list-conversations.tsx +++ b/src/state/queries/messages/list-conversations.tsx @@ -25,7 +25,6 @@ import {useAgeAssurance} from '#/ageAssurance' import {type AgeAssuranceFlags} from '#/ageAssurance/types' import * as bsky from '#/types/bsky' import {RQKEY as CONVO_KEY} from './conversation' -import {useLeftConvos} from './leave-conversation' import { type ConvoRequestListQueryData, optimisticDelete as optimisticDeleteRequest, @@ -136,7 +135,6 @@ export function ListConvosProviderInner({ const queryClient = useQueryClient() const {currentConvoId} = useCurrentConvoId() const {currentAccount} = useSession() - const leftConvos = useLeftConvos() const debouncedRefetch = useMemo(() => { const refetchAndInvalidate = () => { @@ -664,15 +662,12 @@ export function ListConvosProviderInner({ ]) const ctx = useMemo(() => { - const convos = - data?.pages - .flatMap(page => page.convos) - .filter(convo => !leftConvos.includes(convo.id)) ?? [] + const convos = data?.pages.flatMap(page => page.convos) ?? [] return { accepted: convos.filter(conv => conv.status === 'accepted'), request: convos.filter(conv => conv.status === 'request'), } - }, [data, leftConvos]) + }, [data]) return (