From 06e0c7d1a9b25b9c19c518d339f0a2c98b516515 Mon Sep 17 00:00:00 2001 From: Omar Leonardo Sanchez Granados Date: Fri, 28 Feb 2025 05:05:50 -0500 Subject: [PATCH] Feat: multiline text input for chat (#5317) ### What problem does this PR solve? Improves the chat interface by adding a multiline chat area that grows when multiple lines exists. Some images: * Empty: image * With multiple lines and documents: image ### Type of change - [X] New Feature (non-breaking change which adds functionality) --- web/src/components/message-input/index.less | 49 ++-- web/src/components/message-input/index.tsx | 246 +++++++++++--------- 2 files changed, 162 insertions(+), 133 deletions(-) diff --git a/web/src/components/message-input/index.less b/web/src/components/message-input/index.less index 41f382d90..89ed1b742 100644 --- a/web/src/components/message-input/index.less +++ b/web/src/components/message-input/index.less @@ -1,29 +1,38 @@ .messageInputWrapper { margin-right: 20px; - background-color: rgba(255, 255, 255, 0.1); + padding: '0px 0px 10px 0px'; + background-color: #ffffff; + border: 1px solid #d9d9d9; + &:hover { + border-color: #40a9ff; + box-shadow: #40a9ff; + } border-radius: 8px; :global(.ant-input-affix-wrapper) { border-bottom-right-radius: 0; border-bottom-left-radius: 0; } - .documentCard { - :global(.ant-card-body) { - padding: 10px; - position: relative; - } - } - .listWrapper { - padding: 0 10px; - overflow: auto; - max-height: 170px; - } - .inputWrapper { - border-radius: 8px; - } - .deleteIcon { - position: absolute; - right: -4px; - top: -4px; - color: #d92d20; +} + +.documentCard { + :global(.ant-card-body) { + padding: 10px; + position: relative; + width: 100%; } } +.listWrapper { + padding: 0 10px; + overflow: auto; + max-height: 170px; + width: 100%; +} +.inputWrapper { + border-radius: 8px; +} +.deleteIcon { + position: absolute; + right: -4px; + top: -4px; + color: #d92d20; +} diff --git a/web/src/components/message-input/index.tsx b/web/src/components/message-input/index.tsx index 4f3de100d..6e3427171 100644 --- a/web/src/components/message-input/index.tsx +++ b/web/src/components/message-input/index.tsx @@ -11,11 +11,14 @@ import { CloseCircleOutlined, InfoCircleOutlined, LoadingOutlined, + PaperClipOutlined, + SendOutlined, } from '@ant-design/icons'; import type { GetProp, UploadFile } from 'antd'; import { Button, Card, + Divider, Flex, Input, List, @@ -25,12 +28,9 @@ import { Upload, UploadProps, } from 'antd'; -import classNames from 'classnames'; import get from 'lodash/get'; -import { Paperclip } from 'lucide-react'; import { ChangeEventHandler, - KeyboardEventHandler, memo, useCallback, useEffect, @@ -43,6 +43,8 @@ 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[]) => { @@ -99,6 +101,7 @@ const MessageInput = ({ const { data: documentInfos, setDocumentIds } = useFetchDocumentInfosByIds(); const { uploadAndParseDocument } = useUploadAndParseDocument(uploadMethod); const conversationIdRef = useRef(conversationId); + const [fileList, setFileList] = useState([]); const handlePreview = async (file: UploadFile) => { @@ -128,7 +131,6 @@ const MessageInput = ({ }); return [...list]; }); - const ret = await uploadAndParseDocument({ conversationId: nextConversationId, fileList: [file], @@ -148,6 +150,19 @@ const MessageInput = ({ const isUploadingFile = fileList.some((x) => x.status === 'uploading'); + 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(); + }, + [fileList, onPressEnter, isUploadingFile], + ); + const handlePressEnter = useCallback(async () => { if (isUploadingFile) return; const ids = getFileIds(fileList.filter((x) => isUploadSuccess(x))); @@ -161,14 +176,6 @@ const MessageInput = ({ const handleCompositionStart = () => setIsComposing(true); const handleCompositionEnd = () => setIsComposing(false); - const handleInputKeyDown: KeyboardEventHandler = (e) => { - if (e.key === 'Enter' && !e.nativeEvent.shiftKey) { - if (isComposing || sendLoading) return; - e.preventDefault(); - handlePressEnter(); - } - }; - const handleRemove = useCallback( async (file: UploadFile) => { const ids = get(file, 'response.data', []); @@ -215,23 +222,114 @@ const MessageInput = ({ }, [conversationId, setFileList]); return ( - - - - + +