From c63fdec9168e257c55365f80c645561942ddf627 Mon Sep 17 00:00:00 2001 From: Justin Date: Wed, 31 Aug 2022 13:20:37 -0400 Subject: [PATCH] Reset state on failure --- .../features/chats/components/chat-box.tsx | 34 +++++++++++-------- .../chats/components/chat-message-list.tsx | 5 +-- app/soapbox/queries/chats.ts | 1 + 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/app/soapbox/features/chats/components/chat-box.tsx b/app/soapbox/features/chats/components/chat-box.tsx index f3923d2e3..9553dec34 100644 --- a/app/soapbox/features/chats/components/chat-box.tsx +++ b/app/soapbox/features/chats/components/chat-box.tsx @@ -14,7 +14,7 @@ import { Avatar, Button, HStack, Icon, IconButton, Input, Stack, Text, Textarea import UploadProgress from 'soapbox/components/upload-progress'; import UploadButton from 'soapbox/features/compose/components/upload_button'; import { useAppSelector, useAppDispatch, useOwnAccount } from 'soapbox/hooks'; -import { IChat, useChat } from 'soapbox/queries/chats'; +import { IChat, IChatMessage, useChat } from 'soapbox/queries/chats'; import { queryClient } from 'soapbox/queries/client'; import { truncateFilename } from 'soapbox/utils/media'; @@ -56,22 +56,23 @@ const ChatBox: React.FC = ({ chat, onSetInputRef, autosize, inputRef } const isSubmitDisabled = content.length === 0 && !attachment; - const submitMessage = useMutation(({ chatId, content }: any) => { - return createChatMessage(chatId, content); - }, { - onMutate: async (newMessage) => { - clearState(); - + const submitMessage = useMutation(({ chatId, content }: any) => createChatMessage(chatId, content), { + retry: false, + onMutate: async(newMessage: any) => { // Cancel any outgoing refetches (so they don't overwrite our optimistic update) await queryClient.cancelQueries(['chats', 'messages', chat.id]); // Snapshot the previous value - const previousChatMessages = queryClient.getQueryData(['chats', 'messages', chat.id]); + const prevChatMessages = queryClient.getQueryData(['chats', 'messages', chat.id]); + const prevContent = content; + + // Clear state (content, attachment, etc) + clearState(); // Optimistically update to the new value queryClient.setQueryData(['chats', 'messages', chat.id], (prevResult: any) => { - const newResult = prevResult; - newResult.pages = prevResult.pages.map((page: any, idx: number) => { + const newResult = { ...prevResult }; + newResult.pages = newResult.pages.map((page: any, idx: number) => { if (idx === 0) { return { ...page, @@ -92,14 +93,15 @@ const ChatBox: React.FC = ({ chat, onSetInputRef, autosize, inputRef } }); // Return a context object with the snapshotted value - return { previousChatMessages }; + return { prevChatMessages, prevContent }; }, // If the mutation fails, use the context returned from onMutate to roll back - onError: (err, newTodo, context: any) => { - queryClient.setQueryData(['chats', 'messages', chat.id], context.previousChatMessages); + onError: (_error: any, _newData: any, context: any) => { + setContent(context.prevContent); + queryClient.setQueryData(['chats', 'messages', chat.id], context.prevChatMessages); }, // Always refetch after error or success: - onSettled: () => { + onSuccess: () => { queryClient.invalidateQueries(['chats', 'messages', chat.id]); }, }); @@ -120,7 +122,9 @@ const ChatBox: React.FC = ({ chat, onSetInputRef, autosize, inputRef } }; submitMessage.mutate({ chatId: chat.id, content }); - acceptChat.mutate(); + if (!chat.accepted) { + acceptChat.mutate(); + } } }; diff --git a/app/soapbox/features/chats/components/chat-message-list.tsx b/app/soapbox/features/chats/components/chat-message-list.tsx index 2369d1252..dc20c9467 100644 --- a/app/soapbox/features/chats/components/chat-message-list.tsx +++ b/app/soapbox/features/chats/components/chat-message-list.tsx @@ -359,9 +359,10 @@ const ChatMessageList: React.FC = ({ chat, autosize }) => { }, [formattedChatMessages.length]); useEffect(() => { - const lastMessageId = formattedChatMessages.pop()?.id; + const lastMessage = formattedChatMessages.pop(); + const lastMessageId = lastMessage?.id; - if (lastMessageId) { + if (lastMessageId && !lastMessage.pending) { markChatAsRead(lastMessageId); } }, [formattedChatMessages.length]); diff --git a/app/soapbox/queries/chats.ts b/app/soapbox/queries/chats.ts index 4c7352a7e..8c7e214b6 100644 --- a/app/soapbox/queries/chats.ts +++ b/app/soapbox/queries/chats.ts @@ -34,6 +34,7 @@ export interface IChatMessage { created_at: Date id: string unread: boolean + pending?: boolean } const reverseOrder = (a: IChat, b: IChat): number => {