From ee8c71bd87b157f2c17e0c982a2680d369acada8 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Sun, 1 Mar 2026 06:09:48 +0800 Subject: [PATCH] fix(web): prevent enter newline in ime guard window --- .../components/base/chat/chat/question.spec.tsx | 11 ++++++++--- web/app/components/base/chat/chat/question.tsx | 17 ++++++++++++++++- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/web/app/components/base/chat/chat/question.spec.tsx b/web/app/components/base/chat/chat/question.spec.tsx index f12f15ffba4..99c25f56599 100644 --- a/web/app/components/base/chat/chat/question.spec.tsx +++ b/web/app/components/base/chat/chat/question.spec.tsx @@ -257,9 +257,10 @@ describe('Question component', () => { fireEvent.keyDown(textbox, { key: 'Enter', code: 'Enter' }) expect(onRegenerate).not.toHaveBeenCalled() + expect(textbox).toHaveValue('This is the question content') }) - it('should keep Enter suppressed if a new composition starts before previous composition-end timer finishes', () => { + it('should keep text unchanged and suppress Enter if a new composition starts before previous composition-end timer finishes', async () => { vi.useFakeTimers() try { @@ -268,6 +269,7 @@ describe('Question component', () => { fireEvent.click(screen.getByTestId('edit-btn')) const textbox = screen.getByRole('textbox') + fireEvent.change(textbox, { target: { value: 'IME guard text' } }) fireEvent.compositionStart(textbox) fireEvent.compositionEnd(textbox) @@ -275,14 +277,17 @@ describe('Question component', () => { vi.advanceTimersByTime(50) - fireEvent.keyDown(textbox, { key: 'Enter', code: 'Enter' }) + const blockedEnterEvent = new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', bubbles: true, cancelable: true }) + textbox.dispatchEvent(blockedEnterEvent) expect(onRegenerate).not.toHaveBeenCalled() + expect(blockedEnterEvent.defaultPrevented).toBe(true) + expect(textbox).toHaveValue('IME guard text') fireEvent.compositionEnd(textbox) vi.advanceTimersByTime(50) fireEvent.keyDown(textbox, { key: 'Enter', code: 'Enter' }) - expect(onRegenerate).toHaveBeenCalledTimes(1) + expect(onRegenerate).toHaveBeenCalledWith(makeItem(), { message: 'IME guard text', files: [] }) } finally { vi.useRealTimers() diff --git a/web/app/components/base/chat/chat/question.tsx b/web/app/components/base/chat/chat/question.tsx index cb9332dea19..6eceadf6ea5 100644 --- a/web/app/components/base/chat/chat/question.tsx +++ b/web/app/components/base/chat/chat/question.tsx @@ -65,11 +65,21 @@ const Question: FC = ({ }, [content]) const handleResend = useCallback(() => { + if (compositionEndTimerRef.current) { + clearTimeout(compositionEndTimerRef.current) + compositionEndTimerRef.current = null + } + isComposingRef.current = false setIsEditing(false) onRegenerate?.(item, { message: editedContent, files: message_files }) }, [editedContent, message_files, item, onRegenerate]) const handleCancelEditing = useCallback(() => { + if (compositionEndTimerRef.current) { + clearTimeout(compositionEndTimerRef.current) + compositionEndTimerRef.current = null + } + isComposingRef.current = false setIsEditing(false) setEditedContent(content) }, [content]) @@ -78,9 +88,14 @@ const Question: FC = ({ if (e.key !== 'Enter' || e.shiftKey) return - if (e.nativeEvent.isComposing || isComposingRef.current) + if (e.nativeEvent.isComposing) return + if (isComposingRef.current) { + e.preventDefault() + return + } + e.preventDefault() handleResend() }, [handleResend])