diff --git a/package.json b/package.json index 22caa16..e4f68cc 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "docs:build": "vitepress build docs", "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: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/field-grouping-overlay-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/field-grouping-overlay-runtime-service.test.js dist/core/services/subsync-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", "generate:config-example": "pnpm run build && node dist/generate-config-example.js", "start": "pnpm run build && electron . --start", diff --git a/src/core/services/subsync-deps-runtime-service.test.ts b/src/core/services/subsync-deps-runtime-service.test.ts new file mode 100644 index 0000000..d0c9200 --- /dev/null +++ b/src/core/services/subsync-deps-runtime-service.test.ts @@ -0,0 +1,37 @@ +import test from "node:test"; +import assert from "node:assert/strict"; +import { createSubsyncRuntimeDepsService } from "./subsync-deps-runtime-service"; + +test("createSubsyncRuntimeDepsService opens manual picker via visible overlay", () => { + let inProgress = false; + const calls: Array<{ channel: string; payload?: unknown; restore?: string }> = []; + + const deps = createSubsyncRuntimeDepsService({ + getMpvClient: () => null, + getResolvedSubsyncConfig: () => ({ + defaultMode: "auto", + ffsubsyncPath: "/usr/bin/ffsubsync", + alassPath: "/usr/bin/alass", + ffmpegPath: "/usr/bin/ffmpeg", + }), + isSubsyncInProgress: () => inProgress, + setSubsyncInProgress: (next) => { + inProgress = next; + }, + showMpvOsd: () => {}, + sendToVisibleOverlay: (channel, payload, options) => { + calls.push({ channel, payload, restore: options?.restoreOnModalClose }); + return true; + }, + }); + + deps.setSubsyncInProgress(true); + deps.openManualPicker({ + sourceTracks: [{ id: 1, label: "Japanese Track" }], + }); + + assert.equal(deps.isSubsyncInProgress(), true); + assert.equal(calls.length, 1); + assert.equal(calls[0]?.channel, "subsync:open-manual"); + assert.equal(calls[0]?.restore, "subsync"); +}); diff --git a/src/core/services/subsync-deps-runtime-service.ts b/src/core/services/subsync-deps-runtime-service.ts new file mode 100644 index 0000000..b9b171e --- /dev/null +++ b/src/core/services/subsync-deps-runtime-service.ts @@ -0,0 +1,44 @@ +import { + SubsyncManualPayload, +} from "../../types"; +import { + SubsyncRuntimeDeps, +} from "./subsync-runtime-service"; +import { SubsyncResolvedConfig } from "../../subsync/utils"; + +interface MpvClientLike { + connected: boolean; + currentAudioStreamIndex: number | null; + send: (payload: { command: (string | number)[] }) => void; + requestProperty: (name: string) => Promise; +} + +export interface SubsyncDepsRuntimeOptions { + getMpvClient: () => MpvClientLike | null; + getResolvedSubsyncConfig: () => SubsyncResolvedConfig; + isSubsyncInProgress: () => boolean; + setSubsyncInProgress: (inProgress: boolean) => void; + showMpvOsd: (text: string) => void; + sendToVisibleOverlay: ( + channel: string, + payload?: unknown, + options?: { restoreOnModalClose?: "runtime-options" | "subsync" }, + ) => boolean; +} + +export function createSubsyncRuntimeDepsService( + options: SubsyncDepsRuntimeOptions, +): SubsyncRuntimeDeps { + return { + getMpvClient: options.getMpvClient, + getResolvedSubsyncConfig: options.getResolvedSubsyncConfig, + isSubsyncInProgress: options.isSubsyncInProgress, + setSubsyncInProgress: options.setSubsyncInProgress, + showMpvOsd: options.showMpvOsd, + openManualPicker: (payload: SubsyncManualPayload) => { + options.sendToVisibleOverlay("subsync:open-manual", payload, { + restoreOnModalClose: "subsync", + }); + }, + }; +} diff --git a/src/main.ts b/src/main.ts index e472e3e..4c0fbd9 100644 --- a/src/main.ts +++ b/src/main.ts @@ -59,7 +59,6 @@ import { Keybinding, WindowGeometry, SecondarySubMode, - SubsyncManualPayload, SubsyncManualRunRequest, SubsyncResult, KikuFieldGroupingChoice, @@ -205,6 +204,7 @@ import { createCliCommandDepsRuntimeService } from "./core/services/cli-command- import { createIpcDepsRuntimeService } from "./core/services/ipc-deps-runtime-service"; 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 { createRuntimeOptionsManagerRuntimeService } from "./core/services/runtime-options-manager-runtime-service"; import { createAppLoggingRuntimeService } from "./core/services/app-logging-runtime-service"; import { @@ -978,7 +978,7 @@ const mineSentenceSession = createNumericShortcutSessionService({ }); function getSubsyncRuntimeDeps() { - return { + return createSubsyncRuntimeDepsService({ getMpvClient: () => mpvClient, getResolvedSubsyncConfig: () => getSubsyncConfig(getResolvedConfig().subsync), isSubsyncInProgress: () => subsyncInProgress, @@ -986,12 +986,9 @@ function getSubsyncRuntimeDeps() { subsyncInProgress = inProgress; }, showMpvOsd: (text: string) => showMpvOsd(text), - openManualPicker: (payload: SubsyncManualPayload) => { - sendToVisibleOverlay("subsync:open-manual", payload, { - restoreOnModalClose: "subsync", - }); - }, - }; + sendToVisibleOverlay: (channel, payload, options) => + sendToVisibleOverlay(channel, payload, options), + }); } async function triggerSubsyncFromConfig(): Promise {