Account for API validation errors

This commit is contained in:
Chewbacca 2022-11-14 11:22:45 -05:00
parent d5fc6fe252
commit caa3873821
2 changed files with 39 additions and 14 deletions

View File

@ -10,7 +10,6 @@ import { useAppDispatch, useAppSelector } from 'soapbox/hooks';
const messages = defineMessages({
placeholder: { id: 'chat.input.placeholder', defaultMessage: 'Type a message' },
send: { id: 'chat.actions.send', defaultMessage: 'Send' },
failedToSend: { id: 'chat.failed_to_send', defaultMessage: 'Message failed to send.' },
retry: { id: 'chat.retry', defaultMessage: 'Retry?' },
blocked: { id: 'chat_message_list.blocked', defaultMessage: 'You blocked this user' },
unblock: { id: 'chat_composer.unblock', defaultMessage: 'Unblock' },
@ -20,9 +19,9 @@ const messages = defineMessages({
});
interface IChatComposer extends Pick<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'onKeyDown' | 'onChange' | 'disabled'> {
value: string,
onSubmit: () => void,
hasErrorSubmittingMessage?: boolean,
value: string
onSubmit: () => void
errorMessage: string | undefined
}
/** Textarea input for chats. */
@ -31,7 +30,7 @@ const ChatComposer = React.forwardRef<HTMLTextAreaElement | null, IChatComposer>
onChange,
value,
onSubmit,
hasErrorSubmittingMessage = false,
errorMessage = false,
disabled = false,
}, ref) => {
const dispatch = useAppDispatch();
@ -102,10 +101,10 @@ const ChatComposer = React.forwardRef<HTMLTextAreaElement | null, IChatComposer>
</HStack>
<HStack alignItems='center' className='h-5' space={1}>
{hasErrorSubmittingMessage && (
{errorMessage && (
<>
<Text theme='danger' size='xs'>
{intl.formatMessage(messages.failedToSend)}
{errorMessage}
</Text>
<button onClick={onSubmit} className='flex hover:underline'>

View File

@ -1,5 +1,7 @@
import { AxiosError } from 'axios';
import classNames from 'clsx';
import React, { MutableRefObject, useEffect, useState } from 'react';
import { defineMessages, useIntl } from 'react-intl';
import { Stack } from 'soapbox/components/ui';
// import UploadProgress from 'soapbox/components/upload-progress';
@ -12,17 +14,39 @@ import ChatMessageList from './chat-message-list';
// const fileKeyGen = (): number => Math.floor((Math.random() * 0x10000));
const messages = defineMessages({
failedToSend: { id: 'chat.failed_to_send', defaultMessage: 'Message failed to send.' },
});
interface ChatInterface {
chat: IChat,
inputRef?: MutableRefObject<HTMLTextAreaElement | null>,
className?: string,
}
/**
* Clears the value of the input while dispatching the `onChange` function
* which allows the <Textarea> to resize itself (this is important)
* because we autoGrow the element as the user inputs text that spans
* beyond one line
*/
const clearNativeInputValue = (element: HTMLTextAreaElement) => {
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLTextAreaElement.prototype, 'value')?.set;
if (nativeInputValueSetter) {
nativeInputValueSetter.call(element, '');
const ev2 = new Event('input', { bubbles: true });
element.dispatchEvent(ev2);
}
};
/**
* Chat UI with just the messages and textarea.
* Reused between floating desktop chats and fullscreen/mobile chats.
*/
const Chat: React.FC<ChatInterface> = ({ chat, inputRef, className }) => {
const intl = useIntl();
const { createChatMessage, acceptChat } = useChatActions(chat.id);
const [content, setContent] = useState<string>('');
@ -30,20 +54,19 @@ const Chat: React.FC<ChatInterface> = ({ chat, inputRef, className }) => {
// const [isUploading, setIsUploading] = useState(false);
// const [uploadProgress, setUploadProgress] = useState(0);
// const [resetFileKey, setResetFileKey] = useState<number>(fileKeyGen());
const [hasErrorSubmittingMessage, setErrorSubmittingMessage] = useState<boolean>(false);
const [errorMessage, setErrorMessage] = useState<string>();
const isSubmitDisabled = content.length === 0 && !attachment;
const submitMessage = () => {
createChatMessage.mutate({ chatId: chat.id, content }, {
onSuccess: () => {
setErrorSubmittingMessage(false);
setErrorMessage(undefined);
},
onError: (error, _variables, context: any) => {
console.log(context);
onError: (error: AxiosError<{ error: string }>, _variables, context) => {
const message = error.response?.data?.error;
setErrorMessage(message || intl.formatMessage(messages.failedToSend));
setContent(context.prevContent as string);
setErrorSubmittingMessage(true);
},
});
@ -51,6 +74,9 @@ const Chat: React.FC<ChatInterface> = ({ chat, inputRef, className }) => {
};
const clearState = () => {
if (inputRef?.current) {
clearNativeInputValue(inputRef.current);
}
setContent('');
setAttachment(undefined);
// setIsUploading(false);
@ -172,7 +198,7 @@ const Chat: React.FC<ChatInterface> = ({ chat, inputRef, className }) => {
value={content}
onChange={handleContentChange}
onSubmit={sendMessage}
hasErrorSubmittingMessage={hasErrorSubmittingMessage}
errorMessage={errorMessage}
/>
</Stack>
// {renderAttachment()}