Files
dbx/apps/desktop/src/lib/shortcutRegistry.ts
T
二丫讲梵 178a800ce8 ✨ feat(shortcuts): 添加打开设置的键盘快捷键
新增 openSettings 快捷键,默认绑定 Mod+,,用于触发设置对话框。

包含所有语言包的翻译、键盘快捷键文档更新,以及测试用例。
2026-06-08 21:52:26 +08:00

183 lines
4.3 KiB
TypeScript

export type ShortcutActionId =
| "executeSql"
| "saveSql"
| "acceptCompletion"
| "copyCurrentRow"
| "deleteCurrentRow"
| "newQuery"
| "openSettings"
| "closeTab"
| "focusSearch"
| "zoomInUi"
| "zoomOutUi"
| "resetUiZoom"
| "find"
| "replace"
| "refreshData"
| "toggleTranspose"
| "cancelSearch";
export type ShortcutScope = "global" | "editor" | "grid" | "search";
export interface ShortcutDefinition {
id: ShortcutActionId;
labelKey: string;
scope: ShortcutScope;
defaultShortcut: string;
}
export type ShortcutSettings = Record<ShortcutActionId, string>;
export const SHORTCUT_DEFINITIONS: ShortcutDefinition[] = [
{
id: "executeSql",
labelKey: "settings.shortcutExecuteSql",
scope: "editor",
defaultShortcut: "Mod+Enter",
},
{
id: "saveSql",
labelKey: "settings.shortcutSaveSql",
scope: "editor",
defaultShortcut: "Mod+S",
},
{
id: "acceptCompletion",
labelKey: "settings.shortcutAcceptCompletion",
scope: "editor",
defaultShortcut: "Tab",
},
{
id: "copyCurrentRow",
labelKey: "settings.shortcutCopyCurrentRow",
scope: "grid",
defaultShortcut: "Mod+D",
},
{
id: "deleteCurrentRow",
labelKey: "settings.shortcutDeleteCurrentRow",
scope: "grid",
defaultShortcut: "Delete",
},
{
id: "newQuery",
labelKey: "settings.shortcutNewQuery",
scope: "global",
defaultShortcut: "Mod+T",
},
{
id: "openSettings",
labelKey: "settings.shortcutOpenSettings",
scope: "global",
defaultShortcut: "Mod+,",
},
{
id: "closeTab",
labelKey: "settings.shortcutCloseTab",
scope: "global",
defaultShortcut: "Meta+W",
},
{
id: "focusSearch",
labelKey: "settings.shortcutFocusSearch",
scope: "global",
defaultShortcut: "Mod+F",
},
{
id: "zoomInUi",
labelKey: "settings.shortcutZoomInUi",
scope: "global",
defaultShortcut: "Mod+=",
},
{
id: "zoomOutUi",
labelKey: "settings.shortcutZoomOutUi",
scope: "global",
defaultShortcut: "Mod+-",
},
{
id: "resetUiZoom",
labelKey: "settings.shortcutResetUiZoom",
scope: "global",
defaultShortcut: "Mod+0",
},
{
id: "find",
labelKey: "settings.shortcutFind",
scope: "editor",
defaultShortcut: "Mod+F",
},
{
id: "replace",
labelKey: "settings.shortcutReplace",
scope: "editor",
defaultShortcut: "Mod+R",
},
{
id: "refreshData",
labelKey: "settings.shortcutRefreshData",
scope: "global",
defaultShortcut: "F5",
},
{
id: "toggleTranspose",
labelKey: "settings.shortcutToggleTranspose",
scope: "grid",
defaultShortcut: "Tab",
},
{
id: "cancelSearch",
labelKey: "settings.shortcutCancelSearch",
scope: "search",
defaultShortcut: "Escape",
},
];
export const DEFAULT_SHORTCUT_SETTINGS: ShortcutSettings = Object.fromEntries(
SHORTCUT_DEFINITIONS.map((definition) => [definition.id, definition.defaultShortcut]),
) as ShortcutSettings;
export function normalizeShortcutSettings(settings?: Partial<ShortcutSettings>): ShortcutSettings {
return Object.fromEntries(
SHORTCUT_DEFINITIONS.map((definition) => [
definition.id,
typeof settings?.[definition.id] === "string" && settings[definition.id]?.trim()
? settings[definition.id]
: definition.defaultShortcut,
]),
) as ShortcutSettings;
}
export function shortcutToCodeMirrorKey(shortcut: string): string {
return shortcut
.split("+")
.map((part) => (part.length === 1 ? part.toLowerCase() : part))
.join("-");
}
export function formatShortcut(shortcut: string, platform = globalThis.navigator?.platform || ""): string {
const isMac = platform.toLowerCase().includes("mac");
return shortcut
.split("+")
.map((part) => {
if (part === "Mod") return isMac ? "Cmd" : "Ctrl";
if (part === "Meta") return isMac ? "Cmd" : "Meta";
return part;
})
.join("+");
}
export function findShortcutConflict(
actionId: ShortcutActionId,
shortcut: string,
shortcuts: ShortcutSettings,
): ShortcutActionId | null {
const definition = SHORTCUT_DEFINITIONS.find((item) => item.id === actionId);
if (!definition) return null;
const conflict = SHORTCUT_DEFINITIONS.find(
(item) => item.id !== actionId && item.scope === definition.scope && shortcuts[item.id] === shortcut,
);
return conflict?.id ?? null;
}