refactor: inline runtime adapters in main wiring

This commit is contained in:
2026-02-10 03:09:06 -08:00
parent 579661fbef
commit 8343b42b8e
3 changed files with 121 additions and 90 deletions

View File

@@ -56,7 +56,11 @@ export {
updateOverlayBoundsService, updateOverlayBoundsService,
} from "./overlay-window-service"; } from "./overlay-window-service";
export { initializeOverlayRuntimeService } from "./overlay-runtime-init-service"; export { initializeOverlayRuntimeService } from "./overlay-runtime-init-service";
export { syncInvisibleOverlayMousePassthroughService } from "./overlay-visibility-runtime-service"; export {
setInvisibleOverlayVisibleService,
setVisibleOverlayVisibleService,
syncInvisibleOverlayMousePassthroughService,
} from "./overlay-visibility-runtime-service";
export { export {
setInvisibleOverlayVisibleRuntimeFacadeService, setInvisibleOverlayVisibleRuntimeFacadeService,
setVisibleOverlayVisibleRuntimeFacadeService, setVisibleOverlayVisibleRuntimeFacadeService,

View File

@@ -397,9 +397,9 @@ export class MpvIpcClient implements MpvClient {
this.send({ this.send({
command: ["set_property", "secondary-sid", match.id], command: ["set_property", "secondary-sid", match.id],
}); });
this.deps.showMpvOsd( // this.deps.showMpvOsd(
`Secondary subtitle: ${lang} (track ${match.id})`, // `Secondary subtitle: ${lang} (track ${match.id})`,
); // );
break; break;
} }
} }

View File

@@ -51,12 +51,15 @@ import type {
Keybinding, Keybinding,
WindowGeometry, WindowGeometry,
SecondarySubMode, SecondarySubMode,
SubsyncManualPayload,
SubsyncManualRunRequest, SubsyncManualRunRequest,
SubsyncResult, SubsyncResult,
KikuFieldGroupingChoice, KikuFieldGroupingChoice,
KikuMergePreviewRequest, KikuMergePreviewRequest,
KikuMergePreviewResponse, KikuMergePreviewResponse,
RuntimeOptionId,
RuntimeOptionState, RuntimeOptionState,
RuntimeOptionValue,
MpvSubtitleRenderMetrics, MpvSubtitleRenderMetrics,
} from "./types"; } from "./types";
import { SubtitleTimingTracker } from "./subtitle-timing-tracker"; import { SubtitleTimingTracker } from "./subtitle-timing-tracker";
@@ -98,22 +101,14 @@ import {
createCliCommandDepsRuntimeService, createCliCommandDepsRuntimeService,
createOverlayManagerService, createOverlayManagerService,
createFieldGroupingOverlayRuntimeService, createFieldGroupingOverlayRuntimeService,
createInitializeOverlayRuntimeDepsService,
createInvisibleOverlayVisibilityDepsRuntimeService,
createIpcDepsRuntimeService, createIpcDepsRuntimeService,
createMecabTokenizerAndCheckRuntimeService, createMecabTokenizerAndCheckRuntimeService,
createMpvCommandIpcDepsRuntimeService,
createNumericShortcutRuntimeService, createNumericShortcutRuntimeService,
createOverlayShortcutRuntimeHandlers, createOverlayShortcutRuntimeHandlers,
createOverlayWindowRuntimeDepsService,
createOverlayWindowService, createOverlayWindowService,
createRuntimeOptionsIpcDepsRuntimeService,
createRuntimeOptionsManagerRuntimeService, createRuntimeOptionsManagerRuntimeService,
createStartupLifecycleHooksRuntimeService,
createSubsyncRuntimeDepsService,
createSubtitleTimingTrackerRuntimeService, createSubtitleTimingTrackerRuntimeService,
createTokenizerDepsRuntimeService, createTokenizerDepsRuntimeService,
createVisibleOverlayVisibilityDepsRuntimeService,
cycleSecondarySubModeService, cycleSecondarySubModeService,
enforceOverlayLayerOrderService, enforceOverlayLayerOrderService,
ensureOverlayWindowLevelService, ensureOverlayWindowLevelService,
@@ -148,10 +143,10 @@ import {
runSubsyncManualFromIpcRuntimeService, runSubsyncManualFromIpcRuntimeService,
saveSubtitlePositionService, saveSubtitlePositionService,
sendMpvCommandRuntimeService, sendMpvCommandRuntimeService,
setInvisibleOverlayVisibleRuntimeFacadeService, setInvisibleOverlayVisibleService,
setMpvSubVisibilityRuntimeService, setMpvSubVisibilityRuntimeService,
setOverlayDebugVisualizationEnabledRuntimeService, setOverlayDebugVisualizationEnabledRuntimeService,
setVisibleOverlayVisibleRuntimeFacadeService, setVisibleOverlayVisibleService,
shouldAutoInitializeOverlayRuntimeFromConfigService, shouldAutoInitializeOverlayRuntimeFromConfigService,
shouldBindVisibleOverlayToMpvSubVisibilityService, shouldBindVisibleOverlayToMpvSubVisibilityService,
shortcutMatchesInputForLocalFallback, shortcutMatchesInputForLocalFallback,
@@ -160,8 +155,6 @@ import {
syncInvisibleOverlayMousePassthroughService, syncInvisibleOverlayMousePassthroughService,
syncOverlayShortcutsRuntimeService, syncOverlayShortcutsRuntimeService,
tokenizeSubtitleService, tokenizeSubtitleService,
toggleInvisibleOverlayRuntimeFacadeService,
toggleVisibleOverlayRuntimeFacadeService,
triggerFieldGroupingService, triggerFieldGroupingService,
triggerSubsyncFromConfigRuntimeService, triggerSubsyncFromConfigRuntimeService,
unregisterOverlayShortcutsRuntimeService, unregisterOverlayShortcutsRuntimeService,
@@ -171,6 +164,13 @@ import {
updateOverlayBoundsService, updateOverlayBoundsService,
updateVisibleOverlayVisibilityService, updateVisibleOverlayVisibilityService,
} from "./core/services"; } from "./core/services";
import { runAppReadyRuntimeService } from "./core/services/app-ready-runtime-service";
import { runAppShutdownRuntimeService } from "./core/services/app-shutdown-runtime-service";
import {
applyRuntimeOptionResultRuntimeService,
cycleRuntimeOptionFromIpcRuntimeService,
setRuntimeOptionFromIpcRuntimeService,
} from "./core/services/runtime-options-runtime-service";
import { import {
ConfigService, ConfigService,
DEFAULT_CONFIG, DEFAULT_CONFIG,
@@ -487,8 +487,8 @@ const startupState = runStartupBootstrapRuntimeService({
handleCliCommand: (nextArgs, source) => handleCliCommand(nextArgs, source), handleCliCommand: (nextArgs, source) => handleCliCommand(nextArgs, source),
printHelp: () => printHelp(DEFAULT_TEXTHOOKER_PORT), printHelp: () => printHelp(DEFAULT_TEXTHOOKER_PORT),
logNoRunningInstance: () => appLogger.logNoRunningInstance(), logNoRunningInstance: () => appLogger.logNoRunningInstance(),
...createStartupLifecycleHooksRuntimeService({ onReady: async () => {
appReadyDeps: { await runAppReadyRuntimeService({
loadSubtitlePosition: () => loadSubtitlePosition(), loadSubtitlePosition: () => loadSubtitlePosition(),
resolveKeybindings: () => { resolveKeybindings: () => {
keybindings = resolveKeybindings(getResolvedConfig(), DEFAULT_KEYBINDINGS); keybindings = resolveKeybindings(getResolvedConfig(), DEFAULT_KEYBINDINGS);
@@ -593,8 +593,10 @@ const startupState = runStartupBootstrapRuntimeService({
shouldAutoInitializeOverlayRuntimeFromConfig(), shouldAutoInitializeOverlayRuntimeFromConfig(),
initializeOverlayRuntime: () => initializeOverlayRuntime(), initializeOverlayRuntime: () => initializeOverlayRuntime(),
handleInitialArgs: () => handleInitialArgs(), handleInitialArgs: () => handleInitialArgs(),
}, });
appShutdownDeps: { },
onWillQuitCleanup: () => {
runAppShutdownRuntimeService({
unregisterAllGlobalShortcuts: () => { unregisterAllGlobalShortcuts: () => {
globalShortcut.unregisterAll(); globalShortcut.unregisterAll();
}, },
@@ -639,16 +641,16 @@ const startupState = runStartupBootstrapRuntimeService({
ankiIntegration.destroy(); ankiIntegration.destroy();
} }
}, },
}, });
shouldRestoreWindowsOnActivate: () => },
overlayRuntimeInitialized && BrowserWindow.getAllWindows().length === 0, shouldRestoreWindowsOnActivate: () =>
restoreWindowsOnActivate: () => { overlayRuntimeInitialized && BrowserWindow.getAllWindows().length === 0,
createMainWindow(); restoreWindowsOnActivate: () => {
createInvisibleWindow(); createMainWindow();
updateVisibleOverlayVisibility(); createInvisibleWindow();
updateInvisibleOverlayVisibility(); updateVisibleOverlayVisibility();
}, updateInvisibleOverlayVisibility();
}), },
})); }));
}, },
}); });
@@ -809,15 +811,17 @@ async function loadYomitanExtension(): Promise<Extension | null> {
function createOverlayWindow(kind: "visible" | "invisible"): BrowserWindow { function createOverlayWindow(kind: "visible" | "invisible"): BrowserWindow {
return createOverlayWindowService( return createOverlayWindowService(
kind, kind,
createOverlayWindowRuntimeDepsService({ {
isDev, isDev,
getOverlayDebugVisualizationEnabled: () => overlayDebugVisualizationEnabled, overlayDebugVisualizationEnabled,
ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window), ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window),
onRuntimeOptionsChanged: () => broadcastRuntimeOptionsChanged(), onRuntimeOptionsChanged: () => broadcastRuntimeOptionsChanged(),
setOverlayDebugVisualizationEnabled: (enabled) => setOverlayDebugVisualizationEnabled: (enabled) =>
setOverlayDebugVisualizationEnabled(enabled), setOverlayDebugVisualizationEnabled(enabled),
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(), isOverlayVisible: (windowKind) =>
getInvisibleOverlayVisible: () => overlayManager.getInvisibleOverlayVisible(), windowKind === "visible"
? overlayManager.getVisibleOverlayVisible()
: overlayManager.getInvisibleOverlayVisible(),
tryHandleOverlayShortcutLocalFallback: (input) => tryHandleOverlayShortcutLocalFallback: (input) =>
tryHandleOverlayShortcutLocalFallback(input), tryHandleOverlayShortcutLocalFallback(input),
onWindowClosed: (windowKind) => { onWindowClosed: (windowKind) => {
@@ -827,7 +831,7 @@ function createOverlayWindow(kind: "visible" | "invisible"): BrowserWindow {
overlayManager.setInvisibleWindow(null); overlayManager.setInvisibleWindow(null);
} }
}, },
}), },
); );
} }
@@ -847,7 +851,7 @@ function initializeOverlayRuntime(): void {
return; return;
} }
const result = initializeOverlayRuntimeService( const result = initializeOverlayRuntimeService(
createInitializeOverlayRuntimeDepsService({ {
backendOverride, backendOverride,
getInitialInvisibleOverlayVisibility: () => getInitialInvisibleOverlayVisibility: () =>
getInitialInvisibleOverlayVisibility(), getInitialInvisibleOverlayVisibility(),
@@ -888,7 +892,7 @@ function initializeOverlayRuntime(): void {
}, },
showDesktopNotification, showDesktopNotification,
createFieldGroupingCallback: () => createFieldGroupingCallback(), createFieldGroupingCallback: () => createFieldGroupingCallback(),
}), },
); );
overlayManager.setInvisibleOverlayVisible(result.invisibleOverlayVisible); overlayManager.setInvisibleOverlayVisible(result.invisibleOverlayVisible);
overlayRuntimeInitialized = true; overlayRuntimeInitialized = true;
@@ -1002,29 +1006,9 @@ const numericShortcutRuntime = createNumericShortcutRuntimeService({
}); });
const multiCopySession = numericShortcutRuntime.createSession(); const multiCopySession = numericShortcutRuntime.createSession();
const mineSentenceSession = numericShortcutRuntime.createSession(); const mineSentenceSession = numericShortcutRuntime.createSession();
const overlayVisibilityFacadeDeps = {
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(),
getInvisibleOverlayVisible: () => overlayManager.getInvisibleOverlayVisible(),
setVisibleOverlayVisibleState: (nextVisible: boolean) => {
overlayManager.setVisibleOverlayVisible(nextVisible);
},
setInvisibleOverlayVisibleState: (nextVisible: boolean) => {
overlayManager.setInvisibleOverlayVisible(nextVisible);
},
updateVisibleOverlayVisibility: () => updateVisibleOverlayVisibility(),
updateInvisibleOverlayVisibility: () => updateInvisibleOverlayVisibility(),
syncInvisibleOverlayMousePassthrough: () =>
syncInvisibleOverlayMousePassthrough(),
shouldBindVisibleOverlayToMpvSubVisibility: () =>
shouldBindVisibleOverlayToMpvSubVisibility(),
isMpvConnected: () => Boolean(mpvClient && mpvClient.connected),
setMpvSubVisibility: (mpvSubVisible: boolean) => {
setMpvSubVisibilityRuntimeService(mpvClient, mpvSubVisible);
},
};
function getSubsyncRuntimeDeps() { function getSubsyncRuntimeDeps() {
return createSubsyncRuntimeDepsService({ return {
getMpvClient: () => mpvClient, getMpvClient: () => mpvClient,
getResolvedSubsyncConfig: () => getSubsyncConfig(getResolvedConfig().subsync), getResolvedSubsyncConfig: () => getSubsyncConfig(getResolvedConfig().subsync),
isSubsyncInProgress: () => subsyncInProgress, isSubsyncInProgress: () => subsyncInProgress,
@@ -1032,9 +1016,12 @@ function getSubsyncRuntimeDeps() {
subsyncInProgress = inProgress; subsyncInProgress = inProgress;
}, },
showMpvOsd: (text: string) => showMpvOsd(text), showMpvOsd: (text: string) => showMpvOsd(text),
sendToVisibleOverlay: (channel, payload, options) => openManualPicker: (payload: SubsyncManualPayload) => {
sendToVisibleOverlay(channel, payload, options), sendToVisibleOverlay("subsync:open-manual", payload, {
}); restoreOnModalClose: "subsync",
});
},
};
} }
async function triggerSubsyncFromConfig(): Promise<void> { async function triggerSubsyncFromConfig(): Promise<void> {
@@ -1189,21 +1176,21 @@ function refreshOverlayShortcuts(): void {
function updateVisibleOverlayVisibility(): void { function updateVisibleOverlayVisibility(): void {
updateVisibleOverlayVisibilityService( updateVisibleOverlayVisibilityService(
createVisibleOverlayVisibilityDepsRuntimeService({ {
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(), visibleOverlayVisible: overlayManager.getVisibleOverlayVisible(),
getMainWindow: () => overlayManager.getMainWindow(), mainWindow: overlayManager.getMainWindow(),
getWindowTracker: () => windowTracker, windowTracker,
getTrackerNotReadyWarningShown: () => trackerNotReadyWarningShown, trackerNotReadyWarningShown,
setTrackerNotReadyWarningShown: (shown) => { setTrackerNotReadyWarningShown: (shown) => {
trackerNotReadyWarningShown = shown; trackerNotReadyWarningShown = shown;
}, },
shouldBindVisibleOverlayToMpvSubVisibility: () => shouldBindVisibleOverlayToMpvSubVisibility:
shouldBindVisibleOverlayToMpvSubVisibility(), shouldBindVisibleOverlayToMpvSubVisibility(),
getPreviousSecondarySubVisibility: () => previousSecondarySubVisibility, previousSecondarySubVisibility,
setPreviousSecondarySubVisibility: (value) => { setPreviousSecondarySubVisibility: (value) => {
previousSecondarySubVisibility = value; previousSecondarySubVisibility = value;
}, },
isMpvConnected: () => Boolean(mpvClient && mpvClient.connected), mpvConnected: Boolean(mpvClient && mpvClient.connected),
mpvSend: (payload) => { mpvSend: (payload) => {
if (!mpvClient) return; if (!mpvClient) return;
mpvClient.send(payload); mpvClient.send(payload);
@@ -1213,23 +1200,22 @@ function updateVisibleOverlayVisibility(): void {
ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window), ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window),
enforceOverlayLayerOrder: () => enforceOverlayLayerOrder(), enforceOverlayLayerOrder: () => enforceOverlayLayerOrder(),
syncOverlayShortcuts: () => syncOverlayShortcuts(), syncOverlayShortcuts: () => syncOverlayShortcuts(),
}), },
); );
} }
function updateInvisibleOverlayVisibility(): void { function updateInvisibleOverlayVisibility(): void {
updateInvisibleOverlayVisibilityService( updateInvisibleOverlayVisibilityService(
createInvisibleOverlayVisibilityDepsRuntimeService({ {
getInvisibleWindow: () => overlayManager.getInvisibleWindow(), invisibleWindow: overlayManager.getInvisibleWindow(),
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(), visibleOverlayVisible: overlayManager.getVisibleOverlayVisible(),
getInvisibleOverlayVisible: () => invisibleOverlayVisible: overlayManager.getInvisibleOverlayVisible(),
overlayManager.getInvisibleOverlayVisible(), windowTracker,
getWindowTracker: () => windowTracker,
updateOverlayBounds: (geometry) => updateOverlayBounds(geometry), updateOverlayBounds: (geometry) => updateOverlayBounds(geometry),
ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window), ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window),
enforceOverlayLayerOrder: () => enforceOverlayLayerOrder(), enforceOverlayLayerOrder: () => enforceOverlayLayerOrder(),
syncOverlayShortcuts: () => syncOverlayShortcuts(), syncOverlayShortcuts: () => syncOverlayShortcuts(),
}), },
); );
} }
@@ -1250,21 +1236,41 @@ function syncInvisibleOverlayMousePassthrough(): void {
} }
function setVisibleOverlayVisible(visible: boolean): void { function setVisibleOverlayVisible(visible: boolean): void {
setVisibleOverlayVisibleRuntimeFacadeService(visible, overlayVisibilityFacadeDeps); setVisibleOverlayVisibleService({
visible,
setVisibleOverlayVisibleState: (nextVisible) => {
overlayManager.setVisibleOverlayVisible(nextVisible);
},
updateVisibleOverlayVisibility: () => updateVisibleOverlayVisibility(),
updateInvisibleOverlayVisibility: () => updateInvisibleOverlayVisibility(),
syncInvisibleOverlayMousePassthrough: () =>
syncInvisibleOverlayMousePassthrough(),
shouldBindVisibleOverlayToMpvSubVisibility: () =>
shouldBindVisibleOverlayToMpvSubVisibility(),
isMpvConnected: () => Boolean(mpvClient && mpvClient.connected),
setMpvSubVisibility: (mpvSubVisible) => {
setMpvSubVisibilityRuntimeService(mpvClient, mpvSubVisible);
},
});
} }
function setInvisibleOverlayVisible(visible: boolean): void { function setInvisibleOverlayVisible(visible: boolean): void {
setInvisibleOverlayVisibleRuntimeFacadeService( setInvisibleOverlayVisibleService({
visible, visible,
overlayVisibilityFacadeDeps, setInvisibleOverlayVisibleState: (nextVisible) => {
); overlayManager.setInvisibleOverlayVisible(nextVisible);
},
updateInvisibleOverlayVisibility: () => updateInvisibleOverlayVisibility(),
syncInvisibleOverlayMousePassthrough: () =>
syncInvisibleOverlayMousePassthrough(),
});
} }
function toggleVisibleOverlay(): void { function toggleVisibleOverlay(): void {
toggleVisibleOverlayRuntimeFacadeService(overlayVisibilityFacadeDeps); setVisibleOverlayVisible(!overlayManager.getVisibleOverlayVisible());
} }
function toggleInvisibleOverlay(): void { function toggleInvisibleOverlay(): void {
toggleInvisibleOverlayRuntimeFacadeService(overlayVisibilityFacadeDeps); setInvisibleOverlayVisible(!overlayManager.getInvisibleOverlayVisible());
} }
function setOverlayVisible(visible: boolean): void { setVisibleOverlayVisible(visible); } function setOverlayVisible(visible: boolean): void { setVisibleOverlayVisible(visible); }
function toggleOverlay(): void { toggleVisibleOverlay(); } function toggleOverlay(): void { toggleVisibleOverlay(); }
@@ -1279,18 +1285,27 @@ function handleOverlayModalClosed(modal: OverlayHostedModal): void {
function handleMpvCommandFromIpc(command: (string | number)[]): void { function handleMpvCommandFromIpc(command: (string | number)[]): void {
handleMpvCommandFromIpcService( handleMpvCommandFromIpcService(
command, command,
createMpvCommandIpcDepsRuntimeService({ {
specialCommands: SPECIAL_COMMANDS, specialCommands: SPECIAL_COMMANDS,
triggerSubsyncFromConfig: () => triggerSubsyncFromConfig(), triggerSubsyncFromConfig: () => triggerSubsyncFromConfig(),
openRuntimeOptionsPalette: () => openRuntimeOptionsPalette(), openRuntimeOptionsPalette: () => openRuntimeOptionsPalette(),
getRuntimeOptionsManager: () => runtimeOptionsManager, runtimeOptionsCycle: (id, direction) => {
if (!runtimeOptionsManager) {
return { ok: false, error: "Runtime options manager unavailable" };
}
return applyRuntimeOptionResultRuntimeService(
runtimeOptionsManager.cycleOption(id, direction),
(text) => showMpvOsd(text),
);
},
showMpvOsd: (text) => showMpvOsd(text), showMpvOsd: (text) => showMpvOsd(text),
mpvReplaySubtitle: () => replayCurrentSubtitleRuntimeService(mpvClient), mpvReplaySubtitle: () => replayCurrentSubtitleRuntimeService(mpvClient),
mpvPlayNextSubtitle: () => playNextSubtitleRuntimeService(mpvClient), mpvPlayNextSubtitle: () => playNextSubtitleRuntimeService(mpvClient),
mpvSendCommand: (rawCommand) => mpvSendCommand: (rawCommand) =>
sendMpvCommandRuntimeService(mpvClient, rawCommand), sendMpvCommandRuntimeService(mpvClient, rawCommand),
isMpvConnected: () => Boolean(mpvClient && mpvClient.connected), isMpvConnected: () => Boolean(mpvClient && mpvClient.connected),
}), hasRuntimeOptionsManager: () => runtimeOptionsManager !== null,
},
); );
} }
@@ -1300,10 +1315,22 @@ async function runSubsyncManualFromIpc(
return runSubsyncManualFromIpcRuntimeService(request, getSubsyncRuntimeDeps()); return runSubsyncManualFromIpcRuntimeService(request, getSubsyncRuntimeDeps());
} }
const runtimeOptionsIpcDeps = createRuntimeOptionsIpcDepsRuntimeService({ const runtimeOptionsIpcDeps = {
getRuntimeOptionsManager: () => runtimeOptionsManager, setRuntimeOption: (id: string, value: unknown) =>
showMpvOsd: (text) => showMpvOsd(text), setRuntimeOptionFromIpcRuntimeService(
}); runtimeOptionsManager,
id as RuntimeOptionId,
value as RuntimeOptionValue,
(text) => showMpvOsd(text),
),
cycleRuntimeOption: (id: string, direction: 1 | -1) =>
cycleRuntimeOptionFromIpcRuntimeService(
runtimeOptionsManager,
id as RuntimeOptionId,
direction,
(text) => showMpvOsd(text),
),
};
registerIpcHandlersService( registerIpcHandlersService(
createIpcDepsRuntimeService({ createIpcDepsRuntimeService({