diff --git a/web/src/components/message-input/index.tsx b/web/src/components/message-input/index.tsx deleted file mode 100644 index 95a4ee195..000000000 --- a/web/src/components/message-input/index.tsx +++ /dev/null @@ -1,372 +0,0 @@ -import { useTranslate } from '@/hooks/common-hooks'; -import { - useDeleteDocument, - useFetchDocumentInfosByIds, - useRemoveNextDocument, - useUploadAndParseDocument, -} from '@/hooks/document-hooks'; -import { cn } from '@/lib/utils'; -import { getExtension } from '@/utils/document-util'; -import { formatBytes } from '@/utils/file-util'; -import { - CloseCircleOutlined, - InfoCircleOutlined, - LoadingOutlined, -} from '@ant-design/icons'; -import type { GetProp, UploadFile } from 'antd'; -import { - Button, - Card, - Divider, - Flex, - Input, - List, - Space, - Spin, - Typography, - Upload, - UploadProps, -} from 'antd'; -import get from 'lodash/get'; -import { CircleStop, Paperclip, SendHorizontal } from 'lucide-react'; -import { - ChangeEventHandler, - memo, - useCallback, - useEffect, - useRef, - useState, -} from 'react'; -import FileIcon from '../file-icon'; -import styles from './index.less'; - -type FileType = Parameters>[0]; -const { Text } = Typography; - -const { TextArea } = Input; - -const getFileId = (file: UploadFile) => get(file, 'response.data.0'); - -const getFileIds = (fileList: UploadFile[]) => { - const ids = fileList.reduce((pre, cur) => { - return pre.concat(get(cur, 'response.data', [])); - }, []); - - return ids; -}; - -const isUploadSuccess = (file: UploadFile) => { - const code = get(file, 'response.code'); - return typeof code === 'number' && code === 0; -}; - -interface IProps { - disabled: boolean; - value: string; - sendDisabled: boolean; - sendLoading: boolean; - onPressEnter(documentIds: string[]): void; - onInputChange: ChangeEventHandler; - conversationId: string; - uploadMethod?: string; - isShared?: boolean; - showUploadIcon?: boolean; - createConversationBeforeUploadDocument?(message: string): Promise; - stopOutputMessage?(): void; -} - -const getBase64 = (file: FileType): Promise => - new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.readAsDataURL(file as any); - reader.onload = () => resolve(reader.result as string); - reader.onerror = (error) => reject(error); - }); - -const MessageInput = ({ - isShared = false, - disabled, - value, - onPressEnter, - sendDisabled, - sendLoading, - onInputChange, - conversationId, - showUploadIcon = true, - createConversationBeforeUploadDocument, - uploadMethod = 'upload_and_parse', - stopOutputMessage, -}: IProps) => { - const { t } = useTranslate('chat'); - const { removeDocument } = useRemoveNextDocument(); - const { deleteDocument } = useDeleteDocument(); - const { data: documentInfos, setDocumentIds } = useFetchDocumentInfosByIds(); - const { uploadAndParseDocument } = useUploadAndParseDocument(uploadMethod); - const conversationIdRef = useRef(conversationId); - - const [fileList, setFileList] = useState([]); - - const handlePreview = async (file: UploadFile) => { - if (!file.url && !file.preview) { - file.preview = await getBase64(file.originFileObj as FileType); - } - }; - - const handleChange: UploadProps['onChange'] = async ({ - // fileList: newFileList, - file, - }) => { - let nextConversationId: string = conversationId; - if (createConversationBeforeUploadDocument) { - const creatingRet = await createConversationBeforeUploadDocument( - file.name, - ); - if (creatingRet?.code === 0) { - nextConversationId = creatingRet.data.id; - } - } - setFileList((list) => { - list.push({ - ...file, - status: 'uploading', - originFileObj: file as any, - }); - return [...list]; - }); - const ret = await uploadAndParseDocument({ - conversationId: nextConversationId, - fileList: [file], - }); - setFileList((list) => { - const nextList = list.filter((x) => x.uid !== file.uid); - nextList.push({ - ...file, - originFileObj: file as any, - response: ret, - percent: 100, - status: ret?.code === 0 ? 'done' : 'error', - }); - return nextList; - }); - }; - - const isUploadingFile = fileList.some((x) => x.status === 'uploading'); - - const handlePressEnter = useCallback(async () => { - if (isUploadingFile) return; - const ids = getFileIds(fileList.filter((x) => isUploadSuccess(x))); - - onPressEnter(ids); - setFileList([]); - }, [fileList, onPressEnter, isUploadingFile]); - - const handleKeyDown = useCallback( - async (event: React.KeyboardEvent) => { - // check if it was shift + enter - if (event.key === 'Enter' && event.shiftKey) return; - if (event.key !== 'Enter') return; - if (sendDisabled || isUploadingFile || sendLoading) return; - - event.preventDefault(); - handlePressEnter(); - }, - [sendDisabled, isUploadingFile, sendLoading, handlePressEnter], - ); - - const handleRemove = useCallback( - async (file: UploadFile) => { - const ids = get(file, 'response.data', []); - // Upload Successfully - if (Array.isArray(ids) && ids.length) { - if (isShared) { - await deleteDocument(ids); - } else { - await removeDocument(ids[0]); - } - setFileList((preList) => { - return preList.filter((x) => getFileId(x) !== ids[0]); - }); - } else { - // Upload failed - setFileList((preList) => { - return preList.filter((x) => x.uid !== file.uid); - }); - } - }, - [removeDocument, deleteDocument, isShared], - ); - - const handleStopOutputMessage = useCallback(() => { - stopOutputMessage?.(); - }, [stopOutputMessage]); - - const getDocumentInfoById = useCallback( - (id: string) => { - return documentInfos.find((x) => x.id === id); - }, - [documentInfos], - ); - - useEffect(() => { - const ids = getFileIds(fileList); - setDocumentIds(ids); - }, [fileList, setDocumentIds]); - - useEffect(() => { - if ( - conversationIdRef.current && - conversationId !== conversationIdRef.current - ) { - setFileList([]); - } - conversationIdRef.current = conversationId; - }, [conversationId, setFileList]); - - return ( - -