From f87efcff8cef8836fb74c0786d6bc7f19c266c53 Mon Sep 17 00:00:00 2001 From: Anastasiia Solop <35258279+anastasiya1155@users.noreply.github.com> Date: Wed, 21 Feb 2024 06:35:34 -0600 Subject: [PATCH] Fix Chinese duplicated characters in chat input (#1237) * detach input value from chat persistent state * fix ts error --- .../ChatTab/ChatPersistentState.tsx | 43 ++++--------------- .../ChatTab/Input/ReactMentions/index.tsx | 29 ++++++++----- .../CurrentTabContent/ChatTab/Input/index.tsx | 43 +++++++++++++------ client/src/context/chatsContext.tsx | 2 +- 4 files changed, 59 insertions(+), 58 deletions(-) diff --git a/client/src/Project/CurrentTabContent/ChatTab/ChatPersistentState.tsx b/client/src/Project/CurrentTabContent/ChatTab/ChatPersistentState.tsx index 2472b870b0..1ca1804dfb 100644 --- a/client/src/Project/CurrentTabContent/ChatTab/ChatPersistentState.tsx +++ b/client/src/Project/CurrentTabContent/ChatTab/ChatPersistentState.tsx @@ -147,10 +147,8 @@ const ChatPersistentState = ({ }); }, [queryIdToEdit]); - const [inputImperativeValue, setInputImperativeValue] = useState | null>(null); + const [inputImperativeValue, setInputImperativeValue] = + useState({ plain: '', parsed: [] }); useEffect(() => { setChats((prev) => { return { ...prev, [tabKey]: { ...prev[tabKey], inputImperativeValue } }; @@ -199,34 +197,11 @@ const ChatPersistentState = ({ ? { plain: value, parsed: splitUserInputAfterAutocomplete(value) } : { parsed: value, plain: concatenateParsedQuery(value) }, ); - setInputImperativeValue({ - type: 'paragraph', - content: - typeof value === 'string' - ? [ - { - type: 'text', - text: value, - }, - ] - : value - .filter((pq) => - ['path', 'lang', 'text', 'repo'].includes(pq.type), - ) - .map((pq) => - pq.type === 'text' - ? { type: 'text', text: pq.text } - : { - type: 'mention', - attrs: { - id: pq.text, - display: pq.text, - type: pq.type, - isFirst: false, - }, - }, - ), - }); + setInputImperativeValue( + typeof value === 'string' + ? { plain: value, parsed: splitUserInputAfterAutocomplete(value) } + : { parsed: value, plain: concatenateParsedQuery(value) }, + ); focusInput(); }, [], @@ -247,7 +222,7 @@ const ChatPersistentState = ({ } eventSource.current?.close(); setInputValue({ plain: '', parsed: [] }); - setInputImperativeValue(null); + setInputImperativeValue({ plain: '', parsed: [] }); setLoading(true); setQueryIdToEdit(''); setHideMessagesFrom(null); @@ -584,7 +559,7 @@ const ChatPersistentState = ({ const onMessageEditCancel = useCallback(() => { setQueryIdToEdit(''); setInputValue({ plain: '', parsed: [] }); - setInputImperativeValue(null); + setInputImperativeValue({ plain: '', parsed: [] }); setHideMessagesFrom(null); }, []); useEffect(() => { diff --git a/client/src/Project/CurrentTabContent/ChatTab/Input/ReactMentions/index.tsx b/client/src/Project/CurrentTabContent/ChatTab/Input/ReactMentions/index.tsx index f27e8f3a3e..e36eea3ed2 100644 --- a/client/src/Project/CurrentTabContent/ChatTab/Input/ReactMentions/index.tsx +++ b/client/src/Project/CurrentTabContent/ChatTab/Input/ReactMentions/index.tsx @@ -16,7 +16,7 @@ import { Trans, useTranslation } from 'react-i18next'; import { getFileExtensionForLang, splitPath } from '../../../../../utils'; import FileIcon from '../../../../../components/FileIcon'; import { FolderIcon, RepositoryIcon } from '../../../../../icons'; -import { ParsedQueryType } from '../../../../../types/general'; +import { InputValueType } from '../../../../../types/general'; import { blurInput } from '../../../../../utils/domUtils'; import { MentionOptionType } from '../../../../../types/results'; @@ -25,10 +25,11 @@ type Props = { getDataLang: (s: string) => Promise; getDataPath: (s: string) => Promise; getDataRepo: (s: string) => Promise; - value?: { parsed: ParsedQueryType[]; plain: string }; + value?: InputValueType; onChange: (v: string) => void; - onSubmit: (v: { parsed: ParsedQueryType[]; plain: string }) => void; + onSubmit: (v: InputValueType) => void; isDisabled?: boolean; + initialValue?: InputValueType; }; const inputStyle = { @@ -67,10 +68,18 @@ const ReactMentionsInput = ({ getDataLang, value, isDisabled, + initialValue, }: Props) => { const { t } = useTranslation(); const inputRef = useRef(null); const [isComposing, setComposition] = useState(false); + const [inputValue, setInputValue] = useState(''); + + useEffect(() => { + if (initialValue) { + setInputValue(initialValue.plain); + } + }, [initialValue]); useEffect(() => { if (inputRef.current) { @@ -126,12 +135,12 @@ const ReactMentionsInput = ({ setTimeout(() => setComposition(false), 10); }, []); - const handleChange = useCallback( - (e) => { - onChange(e.target.value); - }, - [onChange], - ); + const handleChange = useCallback((e) => { + setInputValue(e.target.value); + }, []); + useEffect(() => { + onChange(inputValue); + }, [inputValue]); const renderRepoSuggestion = useCallback( ( @@ -245,7 +254,7 @@ const ReactMentionsInput = ({ return (
| null; + value?: InputValueType; + valueToEdit?: InputValueType; generationInProgress?: boolean; isStoppable?: boolean; onStop?: () => void; - setInputValue: Dispatch< - SetStateAction<{ parsed: ParsedQueryType[]; plain: string }> - >; + setInputValue: Dispatch>; selectedLines?: [number, number] | null; setSelectedLines?: (l: [number, number] | null) => void; queryIdToEdit?: string; @@ -48,10 +47,8 @@ type Props = { conversation: ChatMessage[]; hideMessagesFrom: number | null; setConversation: Dispatch>; - setSubmittedQuery: Dispatch< - SetStateAction<{ parsed: ParsedQueryType[]; plain: string }> - >; - submittedQuery: { parsed: ParsedQueryType[]; plain: string }; + setSubmittedQuery: Dispatch>; + submittedQuery: InputValueType; isInputAtBottom?: boolean; projectId: string; }; @@ -80,7 +77,7 @@ const ConversationInput = ({ const { isVisible } = useContext(CommandBarContext.General); const { chatInputType } = useContext(UIContext.ChatInputType); const { setIsLeftSidebarFocused } = useContext(UIContext.Focus); - const [initialValue, setInitialValue] = useState< + const [initialProseValue, setInitialProseValue] = useState< Record | null | undefined >({ type: 'paragraph', @@ -100,6 +97,7 @@ const ConversationInput = ({ }, ), }); + const [initialMentionsValue, setInitialMentionsValue] = useState(value); const [hasRendered, setHasRendered] = useState(false); const containerRef = useRef(null); @@ -109,8 +107,26 @@ const ConversationInput = ({ }, []); useEffect(() => { - if (hasRendered) { - setInitialValue(valueToEdit); + if (hasRendered && valueToEdit) { + setInitialProseValue({ + type: 'paragraph', + content: valueToEdit?.parsed + .filter((pq) => ['path', 'lang', 'text', 'repo'].includes(pq.type)) + .map((pq) => + pq.type === 'text' + ? { type: 'text', text: pq.text } + : { + type: 'mention', + attrs: { + id: pq.text, + display: pq.text, + type: pq.type, + isFirst: false, + }, + }, + ), + }); + setInitialMentionsValue(valueToEdit); } }, [valueToEdit]); @@ -314,6 +330,7 @@ const ConversationInput = ({ getDataLang={getDataLang} getDataPath={getDataPath} getDataRepo={getDataRepo} + initialValue={initialMentionsValue} /> ) : generationInProgress ? (
@@ -324,7 +341,7 @@ const ConversationInput = ({ getDataLang={getDataLang} getDataPath={getDataPath} getDataRepo={getDataRepo} - initialValue={initialValue} + initialValue={initialProseValue} onChange={onChangeProseMirrorInput} onSubmit={onSubmit} placeholder={t( diff --git a/client/src/context/chatsContext.tsx b/client/src/context/chatsContext.tsx index 98a4f7f949..8750417b6c 100644 --- a/client/src/context/chatsContext.tsx +++ b/client/src/context/chatsContext.tsx @@ -13,7 +13,7 @@ export type ChatContext = { isLoading: boolean; hideMessagesFrom: null | number; queryIdToEdit: string; - inputImperativeValue: Record | null; + inputImperativeValue: InputValueType; threadId: string; setThreadId: Dispatch>; stopGenerating: () => void;