diff options
| author | Chris Yang <[email protected]> | 2026-03-12 03:40:06 +0900 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-03-11 13:40:06 -0500 |
| commit | cf7ca9b2f7f13fabd87e2ff41264d12ddd4f85ff (patch) | |
| tree | 48c4d82c31d08a676df67466631ef841621afe04 /packages/app | |
| parent | 981c7b9e375b7d9ac57d2d6a3179451139b2b99b (diff) | |
| download | opencode-cf7ca9b2f7f13fabd87e2ff41264d12ddd4f85ff.tar.gz opencode-cf7ca9b2f7f13fabd87e2ff41264d12ddd4f85ff.zip | |
fix(app): skip editor reconcile during IME composition (#17041)
Diffstat (limited to 'packages/app')
| -rw-r--r-- | packages/app/src/components/prompt-input.tsx | 47 |
1 files changed, 31 insertions, 16 deletions
diff --git a/packages/app/src/components/prompt-input.tsx b/packages/app/src/components/prompt-input.tsx index 532edd3bc..3ee8f4351 100644 --- a/packages/app/src/components/prompt-input.tsx +++ b/packages/app/src/components/prompt-input.tsx @@ -490,6 +490,18 @@ export const PromptInput: Component<PromptInputProps> = (props) => { setComposing(false) } + const handleCompositionStart = () => { + setComposing(true) + } + + const handleCompositionEnd = () => { + setComposing(false) + requestAnimationFrame(() => { + if (composing()) return + reconcile(prompt.current().filter((part) => part.type !== "image")) + }) + } + const agentList = createMemo(() => sync.data.agent .filter((agent) => !agent.hidden && agent.mode !== "primary") @@ -680,24 +692,27 @@ export const PromptInput: Component<PromptInputProps> = (props) => { } } - createEffect( - on( - () => prompt.current(), - (currentParts) => { - const inputParts = currentParts.filter((part) => part.type !== "image") + const reconcile = (input: Prompt) => { + if (mirror.input) { + mirror.input = false + if (isNormalizedEditor()) return - if (mirror.input) { - mirror.input = false - if (isNormalizedEditor()) return + renderEditorWithCursor(input) + return + } - renderEditorWithCursor(inputParts) - return - } + const dom = parseFromDOM() + if (isNormalizedEditor() && isPromptEqual(input, dom)) return - const domParts = parseFromDOM() - if (isNormalizedEditor() && isPromptEqual(inputParts, domParts)) return + renderEditorWithCursor(input) + } - renderEditorWithCursor(inputParts) + createEffect( + on( + () => prompt.current(), + (parts) => { + if (composing()) return + reconcile(parts.filter((part) => part.type !== "image")) }, ), ) @@ -1208,8 +1223,8 @@ export const PromptInput: Component<PromptInputProps> = (props) => { spellcheck={store.mode === "normal"} onInput={handleInput} onPaste={handlePaste} - onCompositionStart={() => setComposing(true)} - onCompositionEnd={() => setComposing(false)} + onCompositionStart={handleCompositionStart} + onCompositionEnd={handleCompositionEnd} onBlur={handleBlur} onKeyDown={handleKeyDown} classList={{ |
