From f8acd69d0bcfcaa34e49899be95b996d0dd10138 Mon Sep 17 00:00:00 2001 From: Takashi Fujita Date: Wed, 3 Jun 2026 16:15:17 +0900 Subject: [PATCH] fix(desktop): ignore IME composition enter --- .../desktop/src/app/chat/composer/ime.test.ts | 32 +++++++++++++++++++ apps/desktop/src/app/chat/composer/ime.ts | 12 +++++++ apps/desktop/src/app/chat/composer/index.tsx | 7 +++- 3 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 apps/desktop/src/app/chat/composer/ime.test.ts create mode 100644 apps/desktop/src/app/chat/composer/ime.ts diff --git a/apps/desktop/src/app/chat/composer/ime.test.ts b/apps/desktop/src/app/chat/composer/ime.test.ts new file mode 100644 index 000000000000..4eed011f11b5 --- /dev/null +++ b/apps/desktop/src/app/chat/composer/ime.test.ts @@ -0,0 +1,32 @@ +import { describe, expect, it } from 'vitest' + +import { isImeCompositionKeyEvent } from './ime' + +describe('isImeCompositionKeyEvent', () => { + it('treats Enter keydown during IME composition as composing so it does not submit', () => { + const event = { + key: 'Enter', + nativeEvent: { isComposing: true } + } + + expect(isImeCompositionKeyEvent(event)).toBe(true) + }) + + it('treats macOS IME composition Enter with keyCode 229 as composing', () => { + const event = { + key: 'Enter', + nativeEvent: { isComposing: false, keyCode: 229 } + } + + expect(isImeCompositionKeyEvent(event)).toBe(true) + }) + + it('does not treat normal Enter as composing', () => { + const event = { + key: 'Enter', + nativeEvent: { isComposing: false, keyCode: 13 } + } + + expect(isImeCompositionKeyEvent(event)).toBe(false) + }) +}) diff --git a/apps/desktop/src/app/chat/composer/ime.ts b/apps/desktop/src/app/chat/composer/ime.ts new file mode 100644 index 000000000000..472a3c05e715 --- /dev/null +++ b/apps/desktop/src/app/chat/composer/ime.ts @@ -0,0 +1,12 @@ +interface ImeCompositionKeyEvent { + nativeEvent?: { + isComposing?: boolean + keyCode?: number + } +} + +const IME_PROCESSING_KEY_CODE = 229 + +export function isImeCompositionKeyEvent(event: ImeCompositionKeyEvent) { + return Boolean(event.nativeEvent?.isComposing || event.nativeEvent?.keyCode === IME_PROCESSING_KEY_CODE) +} diff --git a/apps/desktop/src/app/chat/composer/index.tsx b/apps/desktop/src/app/chat/composer/index.tsx index 2a9580af3fdc..21b38d58a8b0 100644 --- a/apps/desktop/src/app/chat/composer/index.tsx +++ b/apps/desktop/src/app/chat/composer/index.tsx @@ -54,6 +54,7 @@ import { useAtCompletions } from './hooks/use-at-completions' import { useSlashCompletions } from './hooks/use-slash-completions' import { useVoiceConversation } from './hooks/use-voice-conversation' import { useVoiceRecorder } from './hooks/use-voice-recorder' +import { isImeCompositionKeyEvent } from './ime' import { dragHasAttachments, droppedFileInlineRef, insertInlineRefsIntoEditor } from './inline-refs' import { QueuePanel } from './queue-panel' import { @@ -545,6 +546,10 @@ export function ChatBar({ } const handleEditorKeyDown = (event: KeyboardEvent) => { + if (isImeCompositionKeyEvent(event)) { + return + } + if ((event.metaKey || event.ctrlKey) && !event.altKey && !event.shiftKey && event.key.toLowerCase() === 'k') { event.preventDefault() @@ -1024,8 +1029,8 @@ export function ChatBar({