mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-28 06:22:45 -08:00
refactor: extract shortcut and mining runtime deps
This commit is contained in:
65
src/core/services/mining-runtime-deps-service.test.ts
Normal file
65
src/core/services/mining-runtime-deps-service.test.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
createCopyCurrentSubtitleDepsRuntimeService,
|
||||
createHandleMineSentenceDigitDepsRuntimeService,
|
||||
createHandleMultiCopyDigitDepsRuntimeService,
|
||||
createMarkLastCardAsAudioCardDepsRuntimeService,
|
||||
createMineSentenceCardDepsRuntimeService,
|
||||
createTriggerFieldGroupingDepsRuntimeService,
|
||||
createUpdateLastCardFromClipboardDepsRuntimeService,
|
||||
} from "./mining-runtime-deps-service";
|
||||
|
||||
test("mining runtime deps builders preserve references", () => {
|
||||
const showMpvOsd = (_text: string) => {};
|
||||
const writeClipboardText = (_text: string) => {};
|
||||
const readClipboardText = () => "x";
|
||||
const logError = (_message: string, _err: unknown) => {};
|
||||
const subtitleTimingTracker = null;
|
||||
const ankiIntegration = null;
|
||||
const mpvClient = null;
|
||||
|
||||
const multiCopy = createHandleMultiCopyDigitDepsRuntimeService({
|
||||
subtitleTimingTracker,
|
||||
writeClipboardText,
|
||||
showMpvOsd,
|
||||
});
|
||||
const copyCurrent = createCopyCurrentSubtitleDepsRuntimeService({
|
||||
subtitleTimingTracker,
|
||||
writeClipboardText,
|
||||
showMpvOsd,
|
||||
});
|
||||
const updateLast = createUpdateLastCardFromClipboardDepsRuntimeService({
|
||||
ankiIntegration,
|
||||
readClipboardText,
|
||||
showMpvOsd,
|
||||
});
|
||||
const fieldGrouping = createTriggerFieldGroupingDepsRuntimeService({
|
||||
ankiIntegration,
|
||||
showMpvOsd,
|
||||
});
|
||||
const markAudio = createMarkLastCardAsAudioCardDepsRuntimeService({
|
||||
ankiIntegration,
|
||||
showMpvOsd,
|
||||
});
|
||||
const mineCard = createMineSentenceCardDepsRuntimeService({
|
||||
ankiIntegration,
|
||||
mpvClient,
|
||||
showMpvOsd,
|
||||
});
|
||||
const mineDigit = createHandleMineSentenceDigitDepsRuntimeService({
|
||||
subtitleTimingTracker,
|
||||
ankiIntegration,
|
||||
getCurrentSecondarySubText: () => undefined,
|
||||
showMpvOsd,
|
||||
logError,
|
||||
});
|
||||
|
||||
assert.equal(multiCopy.writeClipboardText, writeClipboardText);
|
||||
assert.equal(copyCurrent.showMpvOsd, showMpvOsd);
|
||||
assert.equal(updateLast.readClipboardText, readClipboardText);
|
||||
assert.equal(fieldGrouping.ankiIntegration, ankiIntegration);
|
||||
assert.equal(markAudio.showMpvOsd, showMpvOsd);
|
||||
assert.equal(mineCard.mpvClient, mpvClient);
|
||||
assert.equal(mineDigit.logError, logError);
|
||||
});
|
||||
107
src/core/services/mining-runtime-deps-service.ts
Normal file
107
src/core/services/mining-runtime-deps-service.ts
Normal file
@@ -0,0 +1,107 @@
|
||||
import {
|
||||
copyCurrentSubtitleService,
|
||||
handleMineSentenceDigitService,
|
||||
handleMultiCopyDigitService,
|
||||
markLastCardAsAudioCardService,
|
||||
mineSentenceCardService,
|
||||
triggerFieldGroupingService,
|
||||
updateLastCardFromClipboardService,
|
||||
} from "./mining-runtime-service";
|
||||
|
||||
export function createHandleMultiCopyDigitDepsRuntimeService(
|
||||
options: {
|
||||
subtitleTimingTracker: Parameters<typeof handleMultiCopyDigitService>[1]["subtitleTimingTracker"];
|
||||
writeClipboardText: Parameters<typeof handleMultiCopyDigitService>[1]["writeClipboardText"];
|
||||
showMpvOsd: Parameters<typeof handleMultiCopyDigitService>[1]["showMpvOsd"];
|
||||
},
|
||||
): Parameters<typeof handleMultiCopyDigitService>[1] {
|
||||
return {
|
||||
subtitleTimingTracker: options.subtitleTimingTracker,
|
||||
writeClipboardText: options.writeClipboardText,
|
||||
showMpvOsd: options.showMpvOsd,
|
||||
};
|
||||
}
|
||||
|
||||
export function createCopyCurrentSubtitleDepsRuntimeService(
|
||||
options: {
|
||||
subtitleTimingTracker: Parameters<typeof copyCurrentSubtitleService>[0]["subtitleTimingTracker"];
|
||||
writeClipboardText: Parameters<typeof copyCurrentSubtitleService>[0]["writeClipboardText"];
|
||||
showMpvOsd: Parameters<typeof copyCurrentSubtitleService>[0]["showMpvOsd"];
|
||||
},
|
||||
): Parameters<typeof copyCurrentSubtitleService>[0] {
|
||||
return {
|
||||
subtitleTimingTracker: options.subtitleTimingTracker,
|
||||
writeClipboardText: options.writeClipboardText,
|
||||
showMpvOsd: options.showMpvOsd,
|
||||
};
|
||||
}
|
||||
|
||||
export function createUpdateLastCardFromClipboardDepsRuntimeService(
|
||||
options: {
|
||||
ankiIntegration: Parameters<typeof updateLastCardFromClipboardService>[0]["ankiIntegration"];
|
||||
readClipboardText: Parameters<typeof updateLastCardFromClipboardService>[0]["readClipboardText"];
|
||||
showMpvOsd: Parameters<typeof updateLastCardFromClipboardService>[0]["showMpvOsd"];
|
||||
},
|
||||
): Parameters<typeof updateLastCardFromClipboardService>[0] {
|
||||
return {
|
||||
ankiIntegration: options.ankiIntegration,
|
||||
readClipboardText: options.readClipboardText,
|
||||
showMpvOsd: options.showMpvOsd,
|
||||
};
|
||||
}
|
||||
|
||||
export function createTriggerFieldGroupingDepsRuntimeService(
|
||||
options: {
|
||||
ankiIntegration: Parameters<typeof triggerFieldGroupingService>[0]["ankiIntegration"];
|
||||
showMpvOsd: Parameters<typeof triggerFieldGroupingService>[0]["showMpvOsd"];
|
||||
},
|
||||
): Parameters<typeof triggerFieldGroupingService>[0] {
|
||||
return {
|
||||
ankiIntegration: options.ankiIntegration,
|
||||
showMpvOsd: options.showMpvOsd,
|
||||
};
|
||||
}
|
||||
|
||||
export function createMarkLastCardAsAudioCardDepsRuntimeService(
|
||||
options: {
|
||||
ankiIntegration: Parameters<typeof markLastCardAsAudioCardService>[0]["ankiIntegration"];
|
||||
showMpvOsd: Parameters<typeof markLastCardAsAudioCardService>[0]["showMpvOsd"];
|
||||
},
|
||||
): Parameters<typeof markLastCardAsAudioCardService>[0] {
|
||||
return {
|
||||
ankiIntegration: options.ankiIntegration,
|
||||
showMpvOsd: options.showMpvOsd,
|
||||
};
|
||||
}
|
||||
|
||||
export function createMineSentenceCardDepsRuntimeService(
|
||||
options: {
|
||||
ankiIntegration: Parameters<typeof mineSentenceCardService>[0]["ankiIntegration"];
|
||||
mpvClient: Parameters<typeof mineSentenceCardService>[0]["mpvClient"];
|
||||
showMpvOsd: Parameters<typeof mineSentenceCardService>[0]["showMpvOsd"];
|
||||
},
|
||||
): Parameters<typeof mineSentenceCardService>[0] {
|
||||
return {
|
||||
ankiIntegration: options.ankiIntegration,
|
||||
mpvClient: options.mpvClient,
|
||||
showMpvOsd: options.showMpvOsd,
|
||||
};
|
||||
}
|
||||
|
||||
export function createHandleMineSentenceDigitDepsRuntimeService(
|
||||
options: {
|
||||
subtitleTimingTracker: Parameters<typeof handleMineSentenceDigitService>[1]["subtitleTimingTracker"];
|
||||
ankiIntegration: Parameters<typeof handleMineSentenceDigitService>[1]["ankiIntegration"];
|
||||
getCurrentSecondarySubText: Parameters<typeof handleMineSentenceDigitService>[1]["getCurrentSecondarySubText"];
|
||||
showMpvOsd: Parameters<typeof handleMineSentenceDigitService>[1]["showMpvOsd"];
|
||||
logError: Parameters<typeof handleMineSentenceDigitService>[1]["logError"];
|
||||
},
|
||||
): Parameters<typeof handleMineSentenceDigitService>[1] {
|
||||
return {
|
||||
subtitleTimingTracker: options.subtitleTimingTracker,
|
||||
ankiIntegration: options.ankiIntegration,
|
||||
getCurrentSecondarySubText: options.getCurrentSecondarySubText,
|
||||
showMpvOsd: options.showMpvOsd,
|
||||
logError: options.logError,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
import test from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
import {
|
||||
createOverlayShortcutLifecycleDepsRuntimeService,
|
||||
createOverlayShortcutRuntimeDepsService,
|
||||
} from "./overlay-shortcut-runtime-deps-service";
|
||||
|
||||
test("createOverlayShortcutRuntimeDepsService returns callable runtime deps", async () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createOverlayShortcutRuntimeDepsService({
|
||||
showMpvOsd: () => calls.push("showMpvOsd"),
|
||||
openRuntimeOptions: () => calls.push("openRuntimeOptions"),
|
||||
openJimaku: () => calls.push("openJimaku"),
|
||||
markAudioCard: async () => {
|
||||
calls.push("markAudioCard");
|
||||
},
|
||||
copySubtitleMultiple: () => calls.push("copySubtitleMultiple"),
|
||||
copySubtitle: () => calls.push("copySubtitle"),
|
||||
toggleSecondarySub: () => calls.push("toggleSecondarySub"),
|
||||
updateLastCardFromClipboard: async () => {
|
||||
calls.push("updateLastCardFromClipboard");
|
||||
},
|
||||
triggerFieldGrouping: async () => {
|
||||
calls.push("triggerFieldGrouping");
|
||||
},
|
||||
triggerSubsync: async () => {
|
||||
calls.push("triggerSubsync");
|
||||
},
|
||||
mineSentence: async () => {
|
||||
calls.push("mineSentence");
|
||||
},
|
||||
mineSentenceMultiple: () => calls.push("mineSentenceMultiple"),
|
||||
});
|
||||
|
||||
deps.copySubtitle();
|
||||
await deps.mineSentence();
|
||||
deps.mineSentenceMultiple(2);
|
||||
|
||||
assert.deepEqual(calls, ["copySubtitle", "mineSentence", "mineSentenceMultiple"]);
|
||||
});
|
||||
|
||||
test("createOverlayShortcutLifecycleDepsRuntimeService returns lifecycle passthrough", () => {
|
||||
const deps = createOverlayShortcutLifecycleDepsRuntimeService({
|
||||
getConfiguredShortcuts: () => ({ actions: [] } as never),
|
||||
getOverlayHandlers: () => ({} as never),
|
||||
cancelPendingMultiCopy: () => {},
|
||||
cancelPendingMineSentenceMultiple: () => {},
|
||||
});
|
||||
|
||||
assert.ok(deps.getConfiguredShortcuts());
|
||||
assert.ok(deps.getOverlayHandlers());
|
||||
});
|
||||
59
src/core/services/overlay-shortcut-runtime-deps-service.ts
Normal file
59
src/core/services/overlay-shortcut-runtime-deps-service.ts
Normal file
@@ -0,0 +1,59 @@
|
||||
import {
|
||||
OverlayShortcutLifecycleDeps,
|
||||
} from "./overlay-shortcut-lifecycle-service";
|
||||
import {
|
||||
OverlayShortcutRuntimeDeps,
|
||||
} from "./overlay-shortcut-runtime-service";
|
||||
|
||||
export interface OverlayShortcutRuntimeDepsOptions {
|
||||
showMpvOsd: (text: string) => void;
|
||||
openRuntimeOptions: () => void;
|
||||
openJimaku: () => void;
|
||||
markAudioCard: () => Promise<void>;
|
||||
copySubtitleMultiple: (timeoutMs: number) => void;
|
||||
copySubtitle: () => void;
|
||||
toggleSecondarySub: () => void;
|
||||
updateLastCardFromClipboard: () => Promise<void>;
|
||||
triggerFieldGrouping: () => Promise<void>;
|
||||
triggerSubsync: () => Promise<void>;
|
||||
mineSentence: () => Promise<void>;
|
||||
mineSentenceMultiple: (timeoutMs: number) => void;
|
||||
}
|
||||
|
||||
export interface OverlayShortcutLifecycleDepsOptions {
|
||||
getConfiguredShortcuts: OverlayShortcutLifecycleDeps["getConfiguredShortcuts"];
|
||||
getOverlayHandlers: OverlayShortcutLifecycleDeps["getOverlayHandlers"];
|
||||
cancelPendingMultiCopy: () => void;
|
||||
cancelPendingMineSentenceMultiple: () => void;
|
||||
}
|
||||
|
||||
export function createOverlayShortcutRuntimeDepsService(
|
||||
options: OverlayShortcutRuntimeDepsOptions,
|
||||
): OverlayShortcutRuntimeDeps {
|
||||
return {
|
||||
showMpvOsd: options.showMpvOsd,
|
||||
openRuntimeOptions: options.openRuntimeOptions,
|
||||
openJimaku: options.openJimaku,
|
||||
markAudioCard: options.markAudioCard,
|
||||
copySubtitleMultiple: options.copySubtitleMultiple,
|
||||
copySubtitle: options.copySubtitle,
|
||||
toggleSecondarySub: options.toggleSecondarySub,
|
||||
updateLastCardFromClipboard: options.updateLastCardFromClipboard,
|
||||
triggerFieldGrouping: options.triggerFieldGrouping,
|
||||
triggerSubsync: options.triggerSubsync,
|
||||
mineSentence: options.mineSentence,
|
||||
mineSentenceMultiple: options.mineSentenceMultiple,
|
||||
};
|
||||
}
|
||||
|
||||
export function createOverlayShortcutLifecycleDepsRuntimeService(
|
||||
options: OverlayShortcutLifecycleDepsOptions,
|
||||
): OverlayShortcutLifecycleDeps {
|
||||
return {
|
||||
getConfiguredShortcuts: options.getConfiguredShortcuts,
|
||||
getOverlayHandlers: options.getOverlayHandlers,
|
||||
cancelPendingMultiCopy: options.cancelPendingMultiCopy,
|
||||
cancelPendingMineSentenceMultiple:
|
||||
options.cancelPendingMineSentenceMultiple,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user