fix(keymap): match remaining letter shortcuts by typed character (#292)

#291 named letter keys by the typed character (e.key) when Alt is not held, so AZERTY Ctrl+Z is no longer Ctrl+W. Hard-coded handlers still compared the physical KeyboardEvent.code. A shared letterOf(e) in platform/keymap.ts now backs strokeOf and those handlers:

- terminal Ctrl+Shift+C / V / T (copy, paste, new tab) and Ctrl+letter control codes
- Run/Debug Configurations Ctrl/Cmd+N
- browser shortcut guards (blocked reload/print etc.)

Alt combos keep the physical key (Option / AltGr type symbols).
Цей коміт міститься в:
l0ng-ai authored and GitHub committed 2026-10-29 23:05:26 +08:00
1 джерело d1a597898d
коміт aeec0e6759
8 files changed
+64 -18

No files matched your search

+3 -1
Переглянути файл
@@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef, useState, type DragEvent, type KeyboardEven
import clsx from "clsx";
import { executeAction } from "@/platform/actions";
import { call, commands, isTauri, type RunConfig } from "@/platform/ipc";
import { letterOf } from "@/platform/keymap";
import { useWorkflowSettings } from "@/platform/workflowSettings";
import { Button, Dialog, Icon, IconButton, Input, T } from "@/ui";
import {
@@ -312,7 +313,8 @@ function EditConfigsDialog() {
// IDEA: ⌘N / Alt+Insert adds a configuration, ⌥M opens "Modify options".
const onKeyDown = (e: KeyboardEvent) => {
const add =
(e.code === "KeyN" && (isMac() ? e.metaKey || e.ctrlKey : e.ctrlKey)) || (e.altKey && e.key === "Insert");
(letterOf(e) === "N" && !e.altKey && (isMac() ? e.metaKey || e.ctrlKey : e.ctrlKey)) ||
(e.altKey && e.key === "Insert");
if (add && mode === "configs") {
e.preventDefault();
openAdd();
+11
Переглянути файл
@@ -318,6 +318,17 @@ describe("Run/Debug Configurations tree", () => {
fireEvent.click(await screen.findByText("Redirect input"));
expect(screen.getByLabelText("Redirect input from")).toBeTruthy();
});
it("opens Add New Configuration on Ctrl+N by typed letter", () => {
useRun.setState({ configs: [], loaded: true, editorOpen: true });
render(<EditConfigsOverlay />);
const tree = screen.getByRole("tree", { name: "Run configurations" });
// Dvorak: physical KeyN types "b", physical KeyL types "n".
fireEvent.keyDown(tree, { key: "b", code: "KeyN", ctrlKey: true });
expect(screen.queryByLabelText("Search configuration types")).toBeNull();
fireEvent.keyDown(tree, { key: "n", code: "KeyL", ctrlKey: true });
expect(screen.getByLabelText("Search configuration types")).toBeTruthy();
});
});
describe("debug-only types (Remote JVM Debug)", () => {