mirror of
https://github.com/mountain-loop/yaak.git
synced 2026-03-25 19:01:38 +01:00
63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
import type { ActionInvocation, ActionMetadata } from "@yaakapp-internal/proxy-lib";
|
|
import { rpc } from "./rpc";
|
|
|
|
type ActionBinding = {
|
|
invocation: ActionInvocation;
|
|
meta: ActionMetadata;
|
|
keys: { key: string; ctrl: boolean; shift: boolean; alt: boolean; meta: boolean };
|
|
};
|
|
|
|
/** Parse a hotkey string like "Ctrl+Shift+P" into its parts. */
|
|
function parseHotkey(hotkey: string): ActionBinding["keys"] {
|
|
const parts = hotkey.split("+").map((p) => p.trim().toLowerCase());
|
|
return {
|
|
ctrl: parts.includes("ctrl") || parts.includes("control"),
|
|
shift: parts.includes("shift"),
|
|
alt: parts.includes("alt"),
|
|
meta: parts.includes("meta") || parts.includes("cmd") || parts.includes("command"),
|
|
key:
|
|
parts.filter(
|
|
(p) => !["ctrl", "control", "shift", "alt", "meta", "cmd", "command"].includes(p),
|
|
)[0] ?? "",
|
|
};
|
|
}
|
|
|
|
function matchesEvent(binding: ActionBinding["keys"], e: KeyboardEvent): boolean {
|
|
return (
|
|
e.ctrlKey === binding.ctrl &&
|
|
e.shiftKey === binding.shift &&
|
|
e.altKey === binding.alt &&
|
|
e.metaKey === binding.meta &&
|
|
e.key.toLowerCase() === binding.key
|
|
);
|
|
}
|
|
|
|
/** Fetch all actions from Rust and register a global keydown listener. */
|
|
export async function initHotkeys(): Promise<() => void> {
|
|
const { actions } = await rpc("list_actions", {});
|
|
|
|
const bindings: ActionBinding[] = actions
|
|
.filter(
|
|
(entry): entry is [ActionInvocation, ActionMetadata & { defaultHotkey: string }] =>
|
|
entry[1].defaultHotkey != null,
|
|
)
|
|
.map(([invocation, meta]) => ({
|
|
invocation,
|
|
meta,
|
|
keys: parseHotkey(meta.defaultHotkey),
|
|
}));
|
|
|
|
function onKeyDown(e: KeyboardEvent) {
|
|
for (const binding of bindings) {
|
|
if (matchesEvent(binding.keys, e)) {
|
|
e.preventDefault();
|
|
rpc("execute_action", binding.invocation);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
window.addEventListener("keydown", onKeyDown);
|
|
return () => window.removeEventListener("keydown", onKeyDown);
|
|
}
|