From 7fda7c30f15925bc91ef7f3ff66d4a7b0e10ee8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E8=B6=85=E8=B6=85=E8=B6=85=E8=B6=85=E7=BA=A7?= =?UTF-8?q?=E5=96=9C=E6=AC=A2=E4=BD=A0=E7=9A=84=E8=BE=BE=E5=A6=AE=E5=A8=85?= <176143450+My-Denia@users.noreply.github.com> Date: Sat, 31 Oct 2026 14:53:28 +0800 Subject: [PATCH 1/3] fix(hud): accept the system language prompt on Enter --- src/components/launch/HudControls.tsx | 14 +++++ src/components/launch/LaunchWindow.test.tsx | 63 +++++++++++++++++++++ src/components/launch/LaunchWindow.tsx | 1 + 3 files changed, 78 insertions(+) diff --git a/src/components/launch/HudControls.tsx b/src/components/launch/HudControls.tsx index 78ef09a763..c417b754c2 100644 --- a/src/components/launch/HudControls.tsx +++ b/src/components/launch/HudControls.tsx @@ -746,6 +746,7 @@ export const HudNotice = memo(function HudNotice({ confirmLabel, onDismiss, onConfirm, + confirmOnEnter = false, }: { title: string; description: string; @@ -753,7 +754,20 @@ export const HudNotice = memo(function HudNotice({ confirmLabel: string; onDismiss: () => void; onConfirm: () => void; + /** Enter confirms while no control has focus; a focused control keeps its own Enter. */ + confirmOnEnter?: boolean; }) { + useEffect(() => { + if (!confirmOnEnter) return; + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key !== "Enter" || event.repeat || event.target !== document.body) return; + if (event.ctrlKey || event.altKey || event.shiftKey || event.metaKey) return; + onConfirm(); + }; + window.addEventListener("keydown", handleKeyDown); + return () => window.removeEventListener("keydown", handleKeyDown); + }, [confirmOnEnter, onConfirm]); + return (
{ expect(recorderState.value.dismissSoftwareEncoderFallbackNotice).toHaveBeenCalledTimes(1); expect(recorderState.value.dismissSoftwareEncoderFallbackNotice).toHaveBeenCalledWith(true); }); + + it("leaves Enter alone", async () => { + recorderState.value.softwareEncoderFallbackNoticeVisible = true; + + renderLaunchWindow(); + await screen.findByRole("button", { name: "Got it" }); + fireEvent.keyDown(document.body, { key: "Enter" }); + + expect(recorderState.value.dismissSoftwareEncoderFallbackNotice).not.toHaveBeenCalled(); + }); +}); + +// #1428: the prompt's buttons need the mouse, and a window with nothing focused took Enter nowhere. +describe("LaunchWindow system language prompt", () => { + beforeEach(() => { + platformState.value = "win32"; + resetLaunchMocks(); + i18nState.value.systemLocaleSuggestion = "zh-CN"; + }); + + afterEach(() => { + cleanup(); + vi.unstubAllGlobals(); + }); + + it("accepts the suggestion on Enter while no control has focus", async () => { + renderLaunchWindow(); + await screen.findByRole("button", { name: "Switch to English" }); + + fireEvent.keyDown(document.body, { key: "Enter" }); + + expect(i18nState.value.acceptSystemLocaleSuggestion).toHaveBeenCalledTimes(1); + expect(i18nState.value.dismissSystemLocaleSuggestion).not.toHaveBeenCalled(); + }); + + it("leaves Enter to a control that has focus", async () => { + renderLaunchWindow(); + const keep = await screen.findByRole("button", { name: "Keep current language" }); + + fireEvent.keyDown(keep, { key: "Enter" }); + + expect(i18nState.value.acceptSystemLocaleSuggestion).not.toHaveBeenCalled(); + }); + + it("ignores a held Enter, and other keys", async () => { + renderLaunchWindow(); + await screen.findByRole("button", { name: "Switch to English" }); + + fireEvent.keyDown(document.body, { key: "Enter", repeat: true }); + fireEvent.keyDown(document.body, { key: " " }); + fireEvent.keyDown(document.body, { key: "Enter", ctrlKey: true }); + + expect(i18nState.value.acceptSystemLocaleSuggestion).not.toHaveBeenCalled(); + }); + + it("leaves Enter alone while a popover is open", async () => { + renderLaunchWindow(); + fireEvent.click(await screen.findByRole("button", { name: "Language: English" })); + + fireEvent.keyDown(document.body, { key: "Enter" }); + + expect(i18nState.value.acceptSystemLocaleSuggestion).not.toHaveBeenCalled(); + }); }); // #1149: sonner's default corner of the HUD window is where the bar is, so a toast covered diff --git a/src/components/launch/LaunchWindow.tsx b/src/components/launch/LaunchWindow.tsx index 0bad565d75..50df3e6450 100644 --- a/src/components/launch/LaunchWindow.tsx +++ b/src/components/launch/LaunchWindow.tsx @@ -1450,6 +1450,7 @@ export function LaunchWindow() { })} onDismiss={dismissSystemLocaleSuggestion} onConfirm={acceptSystemLocaleSuggestion} + confirmOnEnter={!isPopoverOpen} /> )} From 3af33042df75739bc073fe3a594d798a3f0b6aaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E8=B6=85=E8=B6=85=E8=B6=85=E8=B6=85=E7=BA=A7?= =?UTF-8?q?=E5=96=9C=E6=AC=A2=E4=BD=A0=E7=9A=84=E8=BE=BE=E5=A6=AE=E5=A8=85?= <176143450+My-Denia@users.noreply.github.com> Date: Sat, 31 Oct 2026 15:53:41 +0800 Subject: [PATCH 2/3] test(hud): press Enter on the focused Keep button --- src/components/launch/LaunchWindow.test.tsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/launch/LaunchWindow.test.tsx b/src/components/launch/LaunchWindow.test.tsx index 231b94f273..ff8cb47935 100644 --- a/src/components/launch/LaunchWindow.test.tsx +++ b/src/components/launch/LaunchWindow.test.tsx @@ -2277,9 +2277,12 @@ describe("LaunchWindow system language prompt", () => { it("leaves Enter to a control that has focus", async () => { renderLaunchWindow(); const keep = await screen.findByRole("button", { name: "Keep current language" }); + const user = userEvent.setup(); - fireEvent.keyDown(keep, { key: "Enter" }); + keep.focus(); + await user.keyboard("{Enter}"); + expect(i18nState.value.dismissSystemLocaleSuggestion).toHaveBeenCalledTimes(1); expect(i18nState.value.acceptSystemLocaleSuggestion).not.toHaveBeenCalled(); }); From 4cc2d878ed7768656285bcf478fd4fce5740547d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E8=B6=85=E8=B6=85=E8=B6=85=E8=B6=85=E7=BA=A7?= =?UTF-8?q?=E5=96=9C=E6=AC=A2=E4=BD=A0=E7=9A=84=E8=BE=BE=E5=A6=AE=E5=A8=85?= <176143450+My-Denia@users.noreply.github.com> Date: Sat, 31 Oct 2026 18:42:33 +0800 Subject: [PATCH 3/3] test(hud): cover Alt, Shift and Meta on the language prompt's Enter --- src/components/launch/LaunchWindow.test.tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/components/launch/LaunchWindow.test.tsx b/src/components/launch/LaunchWindow.test.tsx index ff8cb47935..fffc58d538 100644 --- a/src/components/launch/LaunchWindow.test.tsx +++ b/src/components/launch/LaunchWindow.test.tsx @@ -2293,6 +2293,9 @@ describe("LaunchWindow system language prompt", () => { fireEvent.keyDown(document.body, { key: "Enter", repeat: true }); fireEvent.keyDown(document.body, { key: " " }); fireEvent.keyDown(document.body, { key: "Enter", ctrlKey: true }); + fireEvent.keyDown(document.body, { key: "Enter", altKey: true }); + fireEvent.keyDown(document.body, { key: "Enter", shiftKey: true }); + fireEvent.keyDown(document.body, { key: "Enter", metaKey: true }); expect(i18nState.value.acceptSystemLocaleSuggestion).not.toHaveBeenCalled(); });