Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions src/components/launch/HudControls.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -746,14 +746,28 @@ export const HudNotice = memo(function HudNotice({
confirmLabel,
onDismiss,
onConfirm,
confirmOnEnter = false,
}: {
title: string;
description: string;
dismissLabel: string;
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 (
<div
data-hud-interactive="true"
Expand Down
69 changes: 69 additions & 0 deletions src/components/launch/LaunchWindow.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2239,6 +2239,75 @@ describe("LaunchWindow software encoder fallback notice", () => {
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
Expand Down
1 change: 1 addition & 0 deletions src/components/launch/LaunchWindow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1450,6 +1450,7 @@ export function LaunchWindow() {
})}
onDismiss={dismissSystemLocaleSuggestion}
onConfirm={acceptSystemLocaleSuggestion}
confirmOnEnter={!isPopoverOpen}
/>
)}

Expand Down
Loading