kopia lustrzana https://gitlab.com/soapbox-pub/soapbox
Error handling for bad sends
rodzic
6b38e37019
commit
c48b4adc81
|
@ -1,5 +1,5 @@
|
|||
import { Map as ImmutableMap } from 'immutable';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import React, { useEffect } from 'react';
|
||||
|
||||
import { fetchChat, markChatRead } from 'soapbox/actions/chats';
|
||||
import { Column } from 'soapbox/components/ui';
|
||||
|
@ -22,22 +22,12 @@ interface IChatRoom {
|
|||
const ChatRoom: React.FC<IChatRoom> = ({ params }) => {
|
||||
const dispatch = useAppDispatch();
|
||||
const displayFqn = useAppSelector(getDisplayFqn);
|
||||
const inputElem = useRef<HTMLTextAreaElement | null>(null);
|
||||
|
||||
const chat = useAppSelector(state => {
|
||||
const chat = state.chats.items.get(params.chatId, ImmutableMap()).toJS() as any;
|
||||
return getChat(state, chat);
|
||||
});
|
||||
|
||||
const focusInput = () => {
|
||||
inputElem.current?.focus();
|
||||
};
|
||||
|
||||
const handleInputRef = (el: HTMLTextAreaElement) => {
|
||||
inputElem.current = el;
|
||||
focusInput();
|
||||
};
|
||||
|
||||
const markRead = () => {
|
||||
if (!chat) return;
|
||||
dispatch(markChatRead(chat.id));
|
||||
|
@ -57,11 +47,7 @@ const ChatRoom: React.FC<IChatRoom> = ({ params }) => {
|
|||
|
||||
return (
|
||||
<Column label={`@${getAcct(chat.account as any, displayFqn)}`}>
|
||||
<ChatBox
|
||||
chat={chat as any}
|
||||
onSetInputRef={handleInputRef}
|
||||
autosize
|
||||
/>
|
||||
<ChatBox chat={chat as any} autosize />
|
||||
</Column>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
import { useMutation } from '@tanstack/react-query';
|
||||
import { OrderedSet as ImmutableOrderedSet } from 'immutable';
|
||||
import React, { MutableRefObject, useEffect, useRef, useState } from 'react';
|
||||
import React, { MutableRefObject, useState } from 'react';
|
||||
import { useIntl, defineMessages } from 'react-intl';
|
||||
|
||||
import {
|
||||
sendChatMessage,
|
||||
markChatRead,
|
||||
} from 'soapbox/actions/chats';
|
||||
import { uploadMedia } from 'soapbox/actions/media';
|
||||
import { openModal } from 'soapbox/actions/modals';
|
||||
import { initReport } from 'soapbox/actions/reports';
|
||||
import { Avatar, Button, HStack, Icon, IconButton, Input, Stack, Text, Textarea } from 'soapbox/components/ui';
|
||||
import { HStack, IconButton, Stack, Text, Textarea } from 'soapbox/components/ui';
|
||||
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, IChatMessage, useChat } from 'soapbox/queries/chats';
|
||||
import { IChat, useChat } from 'soapbox/queries/chats';
|
||||
import { queryClient } from 'soapbox/queries/client';
|
||||
import { truncateFilename } from 'soapbox/utils/media';
|
||||
|
||||
|
@ -29,7 +22,6 @@ const fileKeyGen = (): number => Math.floor((Math.random() * 0x10000));
|
|||
|
||||
interface IChatBox {
|
||||
chat: IChat,
|
||||
onSetInputRef: (el: HTMLTextAreaElement) => void,
|
||||
autosize?: boolean,
|
||||
inputRef?: MutableRefObject<HTMLTextAreaElement>
|
||||
}
|
||||
|
@ -38,21 +30,19 @@ interface IChatBox {
|
|||
* Chat UI with just the messages and textarea.
|
||||
* Reused between floating desktop chats and fullscreen/mobile chats.
|
||||
*/
|
||||
const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize, inputRef }) => {
|
||||
const ChatBox: React.FC<IChatBox> = ({ chat, autosize, inputRef }) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const chatMessageIds = useAppSelector(state => state.chat_message_lists.get(chat.id, ImmutableOrderedSet<string>()));
|
||||
const account = useOwnAccount();
|
||||
|
||||
const { createChatMessage, markChatAsRead, acceptChat } = useChat(chat.id);
|
||||
const { createChatMessage, acceptChat } = useChat(chat.id);
|
||||
|
||||
const [content, setContent] = useState<string>('');
|
||||
const [attachment, setAttachment] = useState<any>(undefined);
|
||||
const [isUploading, setIsUploading] = useState(false);
|
||||
const [uploadProgress, setUploadProgress] = useState(0);
|
||||
const [resetFileKey, setResetFileKey] = useState<number>(fileKeyGen());
|
||||
|
||||
const inputElem = useRef<HTMLTextAreaElement | null>(null);
|
||||
const [hasErrorSubmittingMessage, setErrorSubmittingMessage] = useState<boolean>(false);
|
||||
|
||||
const isSubmitDisabled = content.length === 0 && !attachment;
|
||||
|
||||
|
@ -99,6 +89,7 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize, inputRef }
|
|||
onError: (_error: any, _newData: any, context: any) => {
|
||||
setContent(context.prevContent);
|
||||
queryClient.setQueryData(['chats', 'messages', chat.id], context.prevChatMessages);
|
||||
setErrorSubmittingMessage(true);
|
||||
},
|
||||
// Always refetch after error or success:
|
||||
onSuccess: () => {
|
||||
|
@ -112,6 +103,7 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize, inputRef }
|
|||
setIsUploading(false);
|
||||
setUploadProgress(0);
|
||||
setResetFileKey(fileKeyGen());
|
||||
setErrorSubmittingMessage(false);
|
||||
};
|
||||
|
||||
const sendMessage = () => {
|
||||
|
@ -217,11 +209,11 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize, inputRef }
|
|||
<Stack className='overflow-hidden flex flex-grow' onMouseOver={handleMouseOver}>
|
||||
<div className='flex-grow h-full overflow-hidden flex justify-center'>
|
||||
<ChatMessageList chat={chat} autosize />
|
||||
</div >
|
||||
</div>
|
||||
|
||||
<div className='mt-auto p-4 shadow-3xl'>
|
||||
<div className='mt-auto pt-4 px-4 shadow-3xl'>
|
||||
<HStack alignItems='center' justifyContent='between' space={4}>
|
||||
<div className='flex-grow'>
|
||||
<Stack grow>
|
||||
<Textarea
|
||||
autoFocus
|
||||
ref={inputRef}
|
||||
|
@ -233,7 +225,7 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize, inputRef }
|
|||
autoGrow
|
||||
maxRows={5}
|
||||
/>
|
||||
</div>
|
||||
</Stack>
|
||||
|
||||
<IconButton
|
||||
src={require('@tabler/icons/send.svg')}
|
||||
|
@ -243,8 +235,24 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize, inputRef }
|
|||
onClick={sendMessage}
|
||||
/>
|
||||
</HStack>
|
||||
|
||||
<HStack alignItems='center' className='h-5' space={1}>
|
||||
{hasErrorSubmittingMessage && (
|
||||
<>
|
||||
<Text theme='danger' size='xs'>
|
||||
Message failed to send.
|
||||
</Text>
|
||||
|
||||
<button onClick={sendMessage} className='flex hover:underline'>
|
||||
<Text theme='primary' size='xs' tag='span'>
|
||||
Retry?
|
||||
</Text>
|
||||
</button>
|
||||
</>
|
||||
)}
|
||||
</HStack>
|
||||
</div>
|
||||
</Stack >
|
||||
</Stack>
|
||||
// {renderAttachment()}
|
||||
// {isUploading && (
|
||||
// <UploadProgress progress={uploadProgress * 100} />
|
||||
|
|
|
@ -74,7 +74,7 @@ const ChatWindow = () => {
|
|||
/>
|
||||
|
||||
<Stack className='overflow-hidden flex-grow h-full' space={2}>
|
||||
<ChatBox chat={chat} inputRef={inputRef as any} onSetInputRef={() => null} />
|
||||
<ChatBox chat={chat} inputRef={inputRef as any} />
|
||||
</Stack>
|
||||
</>
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
|
||||
import RelativeTimestamp from 'soapbox/components/relative_timestamp';
|
||||
import RelativeTimestamp from 'soapbox/components/relative-timestamp';
|
||||
import { Avatar, HStack, Stack, Text } from 'soapbox/components/ui';
|
||||
import VerificationBadge from 'soapbox/components/verification_badge';
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue