From 866cf4ef7338ab217b7421ae6035f338e4676346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sleepy=20Ranx=20=F0=9F=8C=99?= Date: Sun, 29 Mar 2026 22:36:38 +0800 Subject: [PATCH] fix(frontend): prevent submit during IME composition (#1562) --- frontend/src/app/workspace/agents/new/page.tsx | 3 ++- frontend/src/components/ai-elements/prompt-input.tsx | 3 ++- frontend/src/components/workspace/recent-chat-list.tsx | 4 +++- frontend/src/lib/ime.ts | 10 ++++++++++ 4 files changed, 17 insertions(+), 3 deletions(-) create mode 100644 frontend/src/lib/ime.ts diff --git a/frontend/src/app/workspace/agents/new/page.tsx b/frontend/src/app/workspace/agents/new/page.tsx index 9424a5f5d..865416f7f 100644 --- a/frontend/src/app/workspace/agents/new/page.tsx +++ b/frontend/src/app/workspace/agents/new/page.tsx @@ -20,6 +20,7 @@ import { checkAgentName, getAgent } from "@/core/agents/api"; import { useI18n } from "@/core/i18n/hooks"; import { useThreadStream } from "@/core/threads/hooks"; import { uuid } from "@/core/utils/uuid"; +import { isIMEComposing } from "@/lib/ime"; import { cn } from "@/lib/utils"; type Step = "name" | "chat"; @@ -98,7 +99,7 @@ export default function NewAgentPage() { ]); const handleNameKeyDown = (e: React.KeyboardEvent) => { - if (e.key === "Enter") { + if (e.key === "Enter" && !isIMEComposing(e)) { e.preventDefault(); void handleConfirmName(); } diff --git a/frontend/src/components/ai-elements/prompt-input.tsx b/frontend/src/components/ai-elements/prompt-input.tsx index b95779f87..c178a5b8f 100644 --- a/frontend/src/components/ai-elements/prompt-input.tsx +++ b/frontend/src/components/ai-elements/prompt-input.tsx @@ -34,6 +34,7 @@ import { SelectTrigger, SelectValue, } from "@/components/ui/select"; +import { isIMEComposing } from "@/lib/ime"; import { cn } from "@/lib/utils"; import type { ChatStatus, FileUIPart } from "ai"; import { @@ -833,7 +834,7 @@ export const PromptInputTextarea = ({ const handleKeyDown: KeyboardEventHandler = (e) => { if (e.key === "Enter") { - if (isComposing || e.nativeEvent.isComposing) { + if (isIMEComposing(e, isComposing)) { return; } if (e.shiftKey) { diff --git a/frontend/src/components/workspace/recent-chat-list.tsx b/frontend/src/components/workspace/recent-chat-list.tsx index 09f0b3433..a0c00d298 100644 --- a/frontend/src/components/workspace/recent-chat-list.tsx +++ b/frontend/src/components/workspace/recent-chat-list.tsx @@ -56,6 +56,7 @@ import { import type { AgentThread, AgentThreadState } from "@/core/threads/types"; import { pathOfThread, titleOfThread } from "@/core/threads/utils"; import { env } from "@/env"; +import { isIMEComposing } from "@/lib/ime"; export function RecentChatList() { const { t } = useI18n(); @@ -271,7 +272,8 @@ export function RecentChatList() { onChange={(e) => setRenameValue(e.target.value)} placeholder={t.common.rename} onKeyDown={(e) => { - if (e.key === "Enter") { + if (e.key === "Enter" && !isIMEComposing(e)) { + e.preventDefault(); handleRenameSubmit(); } }} diff --git a/frontend/src/lib/ime.ts b/frontend/src/lib/ime.ts new file mode 100644 index 000000000..0c6f26f55 --- /dev/null +++ b/frontend/src/lib/ime.ts @@ -0,0 +1,10 @@ +import type { KeyboardEvent } from "react"; + +type IMEKeyboardEvent = KeyboardEvent; + +export function isIMEComposing( + event: IMEKeyboardEvent, + isComposing = false, +): boolean { + return isComposing || event.nativeEvent.isComposing || event.keyCode === 229; +}