mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
refactor: extract anki jimaku ipc deps runtime service
This commit is contained in:
@@ -16,7 +16,7 @@
|
|||||||
"docs:build": "vitepress build docs",
|
"docs:build": "vitepress build docs",
|
||||||
"docs:preview": "vitepress preview docs --host 0.0.0.0 --port 4173 --strictPort",
|
"docs:preview": "vitepress preview docs --host 0.0.0.0 --port 4173 --strictPort",
|
||||||
"test:config": "pnpm run build && node --test dist/config/config.test.js",
|
"test:config": "pnpm run build && node --test dist/config/config.test.js",
|
||||||
"test:core": "pnpm run build && node --test dist/cli/args.test.js dist/cli/help.test.js dist/core/services/cli-command-service.test.js dist/core/services/cli-command-deps-runtime-service.test.js dist/core/services/ipc-deps-runtime-service.test.js dist/core/services/numeric-shortcut-session-service.test.js dist/core/services/secondary-subtitle-service.test.js dist/core/services/mpv-render-metrics-service.test.js dist/core/services/mpv-runtime-service.test.js dist/core/services/runtime-options-runtime-service.test.js dist/core/services/overlay-modal-restore-service.test.js dist/core/services/runtime-config-service.test.js dist/core/services/overlay-bridge-runtime-service.test.js dist/core/services/overlay-visibility-facade-service.test.js dist/core/services/overlay-broadcast-runtime-service.test.js dist/core/services/app-ready-runtime-service.test.js dist/core/services/app-shutdown-runtime-service.test.js dist/core/services/mpv-client-deps-runtime-service.test.js dist/core/services/app-lifecycle-deps-runtime-service.test.js dist/core/services/runtime-options-manager-runtime-service.test.js dist/core/services/config-warning-runtime-service.test.js dist/core/services/app-logging-runtime-service.test.js dist/core/services/startup-resource-runtime-service.test.js dist/core/services/config-generation-runtime-service.test.js",
|
"test:core": "pnpm run build && node --test dist/cli/args.test.js dist/cli/help.test.js dist/core/services/cli-command-service.test.js dist/core/services/cli-command-deps-runtime-service.test.js dist/core/services/ipc-deps-runtime-service.test.js dist/core/services/anki-jimaku-ipc-deps-runtime-service.test.js dist/core/services/numeric-shortcut-session-service.test.js dist/core/services/secondary-subtitle-service.test.js dist/core/services/mpv-render-metrics-service.test.js dist/core/services/mpv-runtime-service.test.js dist/core/services/runtime-options-runtime-service.test.js dist/core/services/overlay-modal-restore-service.test.js dist/core/services/runtime-config-service.test.js dist/core/services/overlay-bridge-runtime-service.test.js dist/core/services/overlay-visibility-facade-service.test.js dist/core/services/overlay-broadcast-runtime-service.test.js dist/core/services/app-ready-runtime-service.test.js dist/core/services/app-shutdown-runtime-service.test.js dist/core/services/mpv-client-deps-runtime-service.test.js dist/core/services/app-lifecycle-deps-runtime-service.test.js dist/core/services/runtime-options-manager-runtime-service.test.js dist/core/services/config-warning-runtime-service.test.js dist/core/services/app-logging-runtime-service.test.js dist/core/services/startup-resource-runtime-service.test.js dist/core/services/config-generation-runtime-service.test.js",
|
||||||
"test:subtitle": "pnpm run build && node --test dist/subtitle/stages.test.js dist/subtitle/pipeline.test.js",
|
"test:subtitle": "pnpm run build && node --test dist/subtitle/stages.test.js dist/subtitle/pipeline.test.js",
|
||||||
"generate:config-example": "pnpm run build && node dist/generate-config-example.js",
|
"generate:config-example": "pnpm run build && node dist/generate-config-example.js",
|
||||||
"start": "pnpm run build && electron . --start",
|
"start": "pnpm run build && electron . --start",
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import test from "node:test";
|
||||||
|
import assert from "node:assert/strict";
|
||||||
|
import {
|
||||||
|
AnkiJimakuIpcDepsRuntimeOptions,
|
||||||
|
createAnkiJimakuIpcDepsRuntimeService,
|
||||||
|
} from "./anki-jimaku-ipc-deps-runtime-service";
|
||||||
|
|
||||||
|
test("createAnkiJimakuIpcDepsRuntimeService returns passthrough runtime options", async () => {
|
||||||
|
const calls: string[] = [];
|
||||||
|
const options = {
|
||||||
|
patchAnkiConnectEnabled: () => calls.push("patch"),
|
||||||
|
getResolvedConfig: () => ({ ankiConnect: undefined }),
|
||||||
|
getRuntimeOptionsManager: () => null,
|
||||||
|
getSubtitleTimingTracker: () => null,
|
||||||
|
getMpvClient: () => null,
|
||||||
|
getAnkiIntegration: () => null,
|
||||||
|
setAnkiIntegration: () => calls.push("set-integration"),
|
||||||
|
showDesktopNotification: () => calls.push("notify"),
|
||||||
|
createFieldGroupingCallback: () => async () => ({
|
||||||
|
keepNoteId: 0,
|
||||||
|
deleteNoteId: 0,
|
||||||
|
deleteDuplicate: false,
|
||||||
|
cancelled: true,
|
||||||
|
}),
|
||||||
|
broadcastRuntimeOptionsChanged: () => calls.push("broadcast"),
|
||||||
|
getFieldGroupingResolver: () => null,
|
||||||
|
setFieldGroupingResolver: () => calls.push("set-resolver"),
|
||||||
|
parseMediaInfo: () => ({ mediaPath: null, baseName: null, episode: null }),
|
||||||
|
getCurrentMediaPath: () => "/tmp/a.mp4",
|
||||||
|
jimakuFetchJson: async () => ({ ok: true, data: [] }),
|
||||||
|
getJimakuMaxEntryResults: () => 100,
|
||||||
|
getJimakuLanguagePreference: () => "prefer-japanese",
|
||||||
|
resolveJimakuApiKey: async () => "abc",
|
||||||
|
isRemoteMediaPath: () => false,
|
||||||
|
downloadToFile: async () => ({ ok: true, path: "/tmp/a.srt" }),
|
||||||
|
} as unknown as AnkiJimakuIpcDepsRuntimeOptions;
|
||||||
|
|
||||||
|
const runtime = createAnkiJimakuIpcDepsRuntimeService(options);
|
||||||
|
|
||||||
|
runtime.patchAnkiConnectEnabled(true);
|
||||||
|
runtime.broadcastRuntimeOptionsChanged();
|
||||||
|
runtime.setFieldGroupingResolver(null);
|
||||||
|
|
||||||
|
assert.deepEqual(calls, ["patch", "broadcast", "set-resolver"]);
|
||||||
|
assert.equal(runtime.getCurrentMediaPath(), "/tmp/a.mp4");
|
||||||
|
assert.equal(runtime.getJimakuMaxEntryResults(), 100);
|
||||||
|
assert.equal(await runtime.resolveJimakuApiKey(), "abc");
|
||||||
|
});
|
||||||
32
src/core/services/anki-jimaku-ipc-deps-runtime-service.ts
Normal file
32
src/core/services/anki-jimaku-ipc-deps-runtime-service.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
import {
|
||||||
|
AnkiJimakuIpcRuntimeOptions,
|
||||||
|
} from "./anki-jimaku-runtime-service";
|
||||||
|
|
||||||
|
export type AnkiJimakuIpcDepsRuntimeOptions = AnkiJimakuIpcRuntimeOptions;
|
||||||
|
|
||||||
|
export function createAnkiJimakuIpcDepsRuntimeService(
|
||||||
|
options: AnkiJimakuIpcDepsRuntimeOptions,
|
||||||
|
): AnkiJimakuIpcRuntimeOptions {
|
||||||
|
return {
|
||||||
|
patchAnkiConnectEnabled: options.patchAnkiConnectEnabled,
|
||||||
|
getResolvedConfig: options.getResolvedConfig,
|
||||||
|
getRuntimeOptionsManager: options.getRuntimeOptionsManager,
|
||||||
|
getSubtitleTimingTracker: options.getSubtitleTimingTracker,
|
||||||
|
getMpvClient: options.getMpvClient,
|
||||||
|
getAnkiIntegration: options.getAnkiIntegration,
|
||||||
|
setAnkiIntegration: options.setAnkiIntegration,
|
||||||
|
showDesktopNotification: options.showDesktopNotification,
|
||||||
|
createFieldGroupingCallback: options.createFieldGroupingCallback,
|
||||||
|
broadcastRuntimeOptionsChanged: options.broadcastRuntimeOptionsChanged,
|
||||||
|
getFieldGroupingResolver: options.getFieldGroupingResolver,
|
||||||
|
setFieldGroupingResolver: options.setFieldGroupingResolver,
|
||||||
|
parseMediaInfo: options.parseMediaInfo,
|
||||||
|
getCurrentMediaPath: options.getCurrentMediaPath,
|
||||||
|
jimakuFetchJson: options.jimakuFetchJson,
|
||||||
|
getJimakuMaxEntryResults: options.getJimakuMaxEntryResults,
|
||||||
|
getJimakuLanguagePreference: options.getJimakuLanguagePreference,
|
||||||
|
resolveJimakuApiKey: options.resolveJimakuApiKey,
|
||||||
|
isRemoteMediaPath: options.isRemoteMediaPath,
|
||||||
|
downloadToFile: options.downloadToFile,
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ interface SubtitleTimingTrackerLike {
|
|||||||
cleanup: () => void;
|
cleanup: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function registerAnkiJimakuIpcRuntimeService(options: {
|
export interface AnkiJimakuIpcRuntimeOptions {
|
||||||
patchAnkiConnectEnabled: (enabled: boolean) => void;
|
patchAnkiConnectEnabled: (enabled: boolean) => void;
|
||||||
getResolvedConfig: () => { ankiConnect?: AnkiConnectConfig };
|
getResolvedConfig: () => { ankiConnect?: AnkiConnectConfig };
|
||||||
getRuntimeOptionsManager: () => RuntimeOptionsManagerLike | null;
|
getRuntimeOptionsManager: () => RuntimeOptionsManagerLike | null;
|
||||||
@@ -55,7 +55,11 @@ export function registerAnkiJimakuIpcRuntimeService(options: {
|
|||||||
destPath: string,
|
destPath: string,
|
||||||
headers: Record<string, string>,
|
headers: Record<string, string>,
|
||||||
) => Promise<{ ok: true; path: string } | { ok: false; error: { error: string; code?: number; retryAfter?: number } }>;
|
) => Promise<{ ok: true; path: string } | { ok: false; error: { error: string; code?: number; retryAfter?: number } }>;
|
||||||
}): void {
|
}
|
||||||
|
|
||||||
|
export function registerAnkiJimakuIpcRuntimeService(
|
||||||
|
options: AnkiJimakuIpcRuntimeOptions,
|
||||||
|
): void {
|
||||||
registerAnkiJimakuIpcHandlers({
|
registerAnkiJimakuIpcHandlers({
|
||||||
setAnkiConnectEnabled: (enabled) => {
|
setAnkiConnectEnabled: (enabled) => {
|
||||||
options.patchAnkiConnectEnabled(enabled);
|
options.patchAnkiConnectEnabled(enabled);
|
||||||
|
|||||||
41
src/main.ts
41
src/main.ts
@@ -207,6 +207,7 @@ import { createMpvIpcClientDepsRuntimeService } from "./core/services/mpv-client
|
|||||||
import { createAppLifecycleDepsRuntimeService } from "./core/services/app-lifecycle-deps-runtime-service";
|
import { createAppLifecycleDepsRuntimeService } from "./core/services/app-lifecycle-deps-runtime-service";
|
||||||
import { createCliCommandDepsRuntimeService } from "./core/services/cli-command-deps-runtime-service";
|
import { createCliCommandDepsRuntimeService } from "./core/services/cli-command-deps-runtime-service";
|
||||||
import { createIpcDepsRuntimeService } from "./core/services/ipc-deps-runtime-service";
|
import { createIpcDepsRuntimeService } from "./core/services/ipc-deps-runtime-service";
|
||||||
|
import { createAnkiJimakuIpcDepsRuntimeService } from "./core/services/anki-jimaku-ipc-deps-runtime-service";
|
||||||
import { createRuntimeOptionsManagerRuntimeService } from "./core/services/runtime-options-manager-runtime-service";
|
import { createRuntimeOptionsManagerRuntimeService } from "./core/services/runtime-options-manager-runtime-service";
|
||||||
import { createAppLoggingRuntimeService } from "./core/services/app-logging-runtime-service";
|
import { createAppLoggingRuntimeService } from "./core/services/app-logging-runtime-service";
|
||||||
import {
|
import {
|
||||||
@@ -1323,12 +1324,34 @@ function sendToVisibleOverlay(channel: string, payload?: unknown, options?: { re
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
registerAnkiJimakuIpcRuntimeService({
|
registerAnkiJimakuIpcRuntimeService(
|
||||||
patchAnkiConnectEnabled: (enabled) => { configService.patchRawConfig({ ankiConnect: { enabled } }); },
|
createAnkiJimakuIpcDepsRuntimeService({
|
||||||
getResolvedConfig: () => getResolvedConfig(), getRuntimeOptionsManager: () => runtimeOptionsManager, getSubtitleTimingTracker: () => subtitleTimingTracker, getMpvClient: () => mpvClient, getAnkiIntegration: () => ankiIntegration, setAnkiIntegration: (integration) => { ankiIntegration = integration; },
|
patchAnkiConnectEnabled: (enabled) => {
|
||||||
showDesktopNotification, createFieldGroupingCallback: () => createFieldGroupingCallback(), broadcastRuntimeOptionsChanged: () => broadcastRuntimeOptionsChanged(),
|
configService.patchRawConfig({ ankiConnect: { enabled } });
|
||||||
getFieldGroupingResolver: () => fieldGroupingResolver, setFieldGroupingResolver: (resolver) => { fieldGroupingResolver = resolver; },
|
},
|
||||||
parseMediaInfo: (mediaPath) => parseMediaInfo(mediaPath), getCurrentMediaPath: () => currentMediaPath, jimakuFetchJson: (endpoint, query) => jimakuFetchJson(endpoint, query),
|
getResolvedConfig: () => getResolvedConfig(),
|
||||||
getJimakuMaxEntryResults: () => getJimakuMaxEntryResults(), getJimakuLanguagePreference: () => getJimakuLanguagePreference(), resolveJimakuApiKey: () => resolveJimakuApiKey(),
|
getRuntimeOptionsManager: () => runtimeOptionsManager,
|
||||||
isRemoteMediaPath: (mediaPath) => isRemoteMediaPath(mediaPath), downloadToFile: (url, destPath, headers) => downloadToFile(url, destPath, headers),
|
getSubtitleTimingTracker: () => subtitleTimingTracker,
|
||||||
});
|
getMpvClient: () => mpvClient,
|
||||||
|
getAnkiIntegration: () => ankiIntegration,
|
||||||
|
setAnkiIntegration: (integration) => {
|
||||||
|
ankiIntegration = integration;
|
||||||
|
},
|
||||||
|
showDesktopNotification,
|
||||||
|
createFieldGroupingCallback: () => createFieldGroupingCallback(),
|
||||||
|
broadcastRuntimeOptionsChanged: () => broadcastRuntimeOptionsChanged(),
|
||||||
|
getFieldGroupingResolver: () => fieldGroupingResolver,
|
||||||
|
setFieldGroupingResolver: (resolver) => {
|
||||||
|
fieldGroupingResolver = resolver;
|
||||||
|
},
|
||||||
|
parseMediaInfo: (mediaPath) => parseMediaInfo(mediaPath),
|
||||||
|
getCurrentMediaPath: () => currentMediaPath,
|
||||||
|
jimakuFetchJson: (endpoint, query) => jimakuFetchJson(endpoint, query),
|
||||||
|
getJimakuMaxEntryResults: () => getJimakuMaxEntryResults(),
|
||||||
|
getJimakuLanguagePreference: () => getJimakuLanguagePreference(),
|
||||||
|
resolveJimakuApiKey: () => resolveJimakuApiKey(),
|
||||||
|
isRemoteMediaPath: (mediaPath) => isRemoteMediaPath(mediaPath),
|
||||||
|
downloadToFile: (url, destPath, headers) =>
|
||||||
|
downloadToFile(url, destPath, headers),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user