diff --git a/src/components/launch/HudControls.tsx b/src/components/launch/HudControls.tsx index 78ef09a76..c417b754c 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" }); + const user = userEvent.setup(); + + keep.focus(); + await user.keyboard("{Enter}"); + + expect(i18nState.value.dismissSystemLocaleSuggestion).toHaveBeenCalledTimes(1); + 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 }); + 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(); + }); + + 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 0bad565d7..50df3e645 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} /> )}