refactor: extract numeric shortcut runtime service

This commit is contained in:
2026-02-10 01:14:26 -08:00
parent 073f84b03e
commit f1cf13b59c
4 changed files with 92 additions and 16 deletions

View File

@@ -0,0 +1,48 @@
import test from "node:test";
import assert from "node:assert/strict";
import { createNumericShortcutRuntimeService } from "./numeric-shortcut-runtime-service";
test("createNumericShortcutRuntimeService creates sessions wired to globalShortcut", () => {
const registered: string[] = [];
const unregistered: string[] = [];
const osd: string[] = [];
const handlers = new Map<string, () => void>();
const runtime = createNumericShortcutRuntimeService({
globalShortcut: {
register: (accelerator, callback) => {
registered.push(accelerator);
handlers.set(accelerator, callback);
return true;
},
unregister: (accelerator) => {
unregistered.push(accelerator);
handlers.delete(accelerator);
},
},
showMpvOsd: (text) => {
osd.push(text);
},
setTimer: () => setTimeout(() => {}, 1000),
clearTimer: (timer) => clearTimeout(timer),
});
const session = runtime.createSession();
session.start({
timeoutMs: 5000,
onDigit: () => {},
messages: {
prompt: "Select count",
timeout: "Timed out",
},
});
assert.equal(session.isActive(), true);
assert.ok(registered.includes("1"));
assert.ok(registered.includes("Escape"));
assert.equal(osd[0], "Select count");
handlers.get("Escape")?.();
assert.equal(session.isActive(), false);
assert.ok(unregistered.includes("Escape"));
});

View File

@@ -0,0 +1,37 @@
import {
createNumericShortcutSessionService,
} from "./numeric-shortcut-session-service";
interface GlobalShortcutLike {
register: (accelerator: string, callback: () => void) => boolean;
unregister: (accelerator: string) => void;
}
export interface NumericShortcutRuntimeOptions {
globalShortcut: GlobalShortcutLike;
showMpvOsd: (text: string) => void;
setTimer: (
handler: () => void,
timeoutMs: number,
) => ReturnType<typeof setTimeout>;
clearTimer: (timer: ReturnType<typeof setTimeout>) => void;
}
export function createNumericShortcutRuntimeService(
options: NumericShortcutRuntimeOptions,
) {
const createSession = () =>
createNumericShortcutSessionService({
registerShortcut: (accelerator, handler) =>
options.globalShortcut.register(accelerator, handler),
unregisterShortcut: (accelerator) =>
options.globalShortcut.unregister(accelerator),
setTimer: options.setTimer,
clearTimer: options.clearTimer,
showMpvOsd: options.showMpvOsd,
});
return {
createSession,
};
}

View File

@@ -112,7 +112,6 @@ import {
} from "./core/services/overlay-shortcut-service";
import { runOverlayShortcutLocalFallback } from "./core/services/overlay-shortcut-fallback-runner";
import { createOverlayShortcutRuntimeHandlers } from "./core/services/overlay-shortcut-runtime-service";
import { createNumericShortcutSessionService } from "./core/services/numeric-shortcut-session-service";
import { handleCliCommandService } from "./core/services/cli-command-service";
import { cycleSecondarySubModeService } from "./core/services/secondary-subtitle-service";
import {
@@ -205,6 +204,7 @@ import { createIpcDepsRuntimeService } from "./core/services/ipc-deps-runtime-se
import { createAnkiJimakuIpcDepsRuntimeService } from "./core/services/anki-jimaku-ipc-deps-runtime-service";
import { createFieldGroupingOverlayRuntimeService } from "./core/services/field-grouping-overlay-runtime-service";
import { createSubsyncRuntimeDepsService } from "./core/services/subsync-deps-runtime-service";
import { createNumericShortcutRuntimeService } from "./core/services/numeric-shortcut-runtime-service";
import { createRuntimeOptionsManagerRuntimeService } from "./core/services/runtime-options-manager-runtime-service";
import { createAppLoggingRuntimeService } from "./core/services/app-logging-runtime-service";
import {
@@ -959,23 +959,14 @@ function showMpvOsd(text: string): void {
);
}
const multiCopySession = createNumericShortcutSessionService({
registerShortcut: (accelerator, handler) =>
globalShortcut.register(accelerator, handler),
unregisterShortcut: (accelerator) => globalShortcut.unregister(accelerator),
const numericShortcutRuntime = createNumericShortcutRuntimeService({
globalShortcut,
showMpvOsd: (text) => showMpvOsd(text),
setTimer: (handler, timeoutMs) => setTimeout(handler, timeoutMs),
clearTimer: (timer) => clearTimeout(timer),
showMpvOsd: (text) => showMpvOsd(text),
});
const mineSentenceSession = createNumericShortcutSessionService({
registerShortcut: (accelerator, handler) =>
globalShortcut.register(accelerator, handler),
unregisterShortcut: (accelerator) => globalShortcut.unregister(accelerator),
setTimer: (handler, timeoutMs) => setTimeout(handler, timeoutMs),
clearTimer: (timer) => clearTimeout(timer),
showMpvOsd: (text) => showMpvOsd(text),
});
const multiCopySession = numericShortcutRuntime.createSession();
const mineSentenceSession = numericShortcutRuntime.createSession();
function getSubsyncRuntimeDeps() {
return createSubsyncRuntimeDepsService({