mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-11-05 10:10:36 +00:00
* fix(composer): keep IME-composition Enter out of the slash-skill catalog `handlePromptTextareaKeyDown` called `handleSkillSuggestionKeyDown` with no composition guard, unlike its two siblings: the inline-skill editor wraps the same call in `isIMEComposing(...)` with a comment naming this exact hazard, and `handlePromptHistoryKeyDown` checks it too. `PromptInputTextarea` calls the prop's `onKeyDown` *before* its own `isIMEComposing` check, so the suggestion handler won the event. With an IME active and the `/` catalog open, pressing Enter to commit the composition instead ran `event.preventDefault()` and applied the highlighted suggestion — discarding the text still being composed and selecting a skill the user never chose. The catalog opens from the live `textInput.value`, and React `onChange` fires during composition, so a CJK user typing `/res` to reach a skill hits it directly. Guard the main composer's call site the same way the inline-skill editor does, and pin it with a happy-dom regression test: `keyCode: 229` (the keydown a browser reports for a key an active IME consumed) must leave both the catalog and the draft untouched, while a plain Enter still selects the highlighted skill. Verified: - new test `tests/unit/components/workspace/input-box-skill-suggestion-ime.dom.test.tsx` fails on main (the IME case applies the skill) and passes here; the plain-Enter control case passes on both - `rstest run --pool threads tests/unit/components/workspace` -> 69 files / 448 tests passed - `tsc --noEmit`, `eslint`, `prettier --check` clean on the touched files * fix(composer): ignore the Enter that follows IME compositionend Safari emits the confirming Enter after compositionend, with neither isComposing nor keyCode 229. Drop that Enter in PromptInputTextarea for a short window, before the skill catalog or prompt history can treat it as a plain key. --------- Co-authored-by: Shxiao101 <Shxiao101@users.noreply.github.com>
28 lines
863 B
TypeScript
28 lines
863 B
TypeScript
import type { KeyboardEvent } from "react";
|
|
|
|
type IMEKeyboardEvent = KeyboardEvent<HTMLElement>;
|
|
|
|
export function isIMEComposing(
|
|
event: IMEKeyboardEvent,
|
|
isComposing = false,
|
|
): boolean {
|
|
return isComposing || event.nativeEvent.isComposing || event.keyCode === 229;
|
|
}
|
|
|
|
// Safari emits the Enter that confirms a composition after compositionend,
|
|
// with isComposing false and keyCode 13. React has already flushed the
|
|
// composing state by the time that keydown runs.
|
|
export const COMPOSITION_CONFIRM_ENTER_MS = 50;
|
|
|
|
export function isCompositionConfirmEnter(
|
|
event: IMEKeyboardEvent,
|
|
compositionEndedAt: number,
|
|
now = Date.now(),
|
|
): boolean {
|
|
if (event.key !== "Enter" || event.shiftKey || isIMEComposing(event)) {
|
|
return false;
|
|
}
|
|
const elapsed = now - compositionEndedAt;
|
|
return elapsed >= 0 && elapsed < COMPOSITION_CONFIRM_ENTER_MS;
|
|
}
|