mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
refactor: extract additional main runtime dependency builders
This commit is contained in:
@@ -6,7 +6,7 @@ Read first. Keep concise.
|
||||
| ------------ | -------------- | ---------------------------------------------------- | --------- | ------------------------------------- | ---------------------- |
|
||||
| `codex-main` | `planner-exec` | `Fix frequency/N+1 regression in plugin --start flow` | `in_progress` | `docs/subagents/agents/codex-main.md` | `2026-02-19T19:36:46Z` |
|
||||
| `codex-config-validation-20260219T172015Z-iiyf` | `codex-config-validation` | `Find root cause of config validation error for ~/.config/SubMiner/config.jsonc` | `completed` | `docs/subagents/agents/codex-config-validation-20260219T172015Z-iiyf.md` | `2026-02-19T17:26:17Z` |
|
||||
| `codex-task85-20260219T233711Z-46hc` | `codex-task85` | `Resume TASK-85 maintainability refactor from latest handoff point` | `in_progress` | `docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md` | `2026-02-20T07:35:01Z` |
|
||||
| `codex-task85-20260219T233711Z-46hc` | `codex-task85` | `Resume TASK-85 maintainability refactor from latest handoff point` | `in_progress` | `docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md` | `2026-02-20T08:00:02Z` |
|
||||
| `codex-anilist-deeplink-20260219T233926Z` | `anilist-deeplink` | `Fix external subminer:// AniList callback handling from browser` | `done` | `docs/subagents/agents/codex-anilist-deeplink-20260219T233926Z.md` | `2026-02-19T23:59:21Z` |
|
||||
| `codex-texthooker-highlights-20260220T002354Z-927c` | `codex-texthooker-highlights` | `Add optional texthooker highlight toggles for known/n+1/frequency/JLPT` | `completed` | `docs/subagents/agents/codex-texthooker-highlights-20260220T002354Z-927c.md` | `2026-02-20T00:30:49Z` |
|
||||
| `codex-texthooker-ui-playwright-20260220T003827Z-k3p9` | `codex-texthooker-ui-playwright` | `Run Playwright MCP smoke/regression checks for texthooker-ui changes` | `completed` | `docs/subagents/agents/codex-texthooker-ui-playwright-20260220T003827Z-k3p9.md` | `2026-02-20T00:42:09Z` |
|
||||
|
||||
@@ -9,6 +9,32 @@
|
||||
|
||||
## Current Work (newest first)
|
||||
|
||||
- [2026-02-20T08:00:02Z] progress: extracted Jellyfin command-dispatch deps assembly into `src/main/runtime/jellyfin-command-dispatch-main-deps.ts` (`createBuildRunJellyfinCommandMainDepsHandler`) and rewired `runJellyfinCommand` construction in `src/main.ts`.
|
||||
- [2026-02-20T08:00:02Z] progress: added parity tests in `src/main/runtime/jellyfin-command-dispatch-main-deps.test.ts`; `src/main.ts` now 2909 LOC.
|
||||
- [2026-02-20T08:00:02Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/jellyfin-command-dispatch-main-deps.test.js dist/main/runtime/jellyfin-command-dispatch.test.js dist/main/runtime/jellyfin-cli-main-deps.test.js` pass (8/8).
|
||||
- [2026-02-20T07:58:40Z] progress: extracted Jellyfin CLI handler deps assembly into `src/main/runtime/jellyfin-cli-main-deps.ts` (auth/list/play/remote-announce builders) and rewired those handler construction sites in `src/main.ts`.
|
||||
- [2026-02-20T07:58:40Z] progress: added parity tests in `src/main/runtime/jellyfin-cli-main-deps.test.ts`; `src/main.ts` now 2905 LOC.
|
||||
- [2026-02-20T07:58:40Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/jellyfin-cli-main-deps.test.js dist/main/runtime/jellyfin-cli-auth.test.js dist/main/runtime/jellyfin-cli-list.test.js dist/main/runtime/jellyfin-cli-play.test.js dist/main/runtime/jellyfin-cli-remote-announce.test.js` pass (16/16).
|
||||
- [2026-02-20T07:57:16Z] progress: extracted AniList setup protocol deps assembly into `src/main/runtime/anilist-setup-protocol-main-deps.ts` (notify, consume-token, protocol-url, protocol-client builders) and rewired those handler construction sites in `src/main.ts`.
|
||||
- [2026-02-20T07:57:16Z] progress: added parity tests in `src/main/runtime/anilist-setup-protocol-main-deps.test.ts`; `src/main.ts` now 2882 LOC.
|
||||
- [2026-02-20T07:57:16Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/anilist-setup-protocol-main-deps.test.js dist/main/runtime/anilist-setup-protocol.test.js dist/main/runtime/jellyfin-client-info-main-deps.test.js` pass (6/6).
|
||||
- [2026-02-20T07:52:56Z] progress: extracted Jellyfin client-info deps assembly into `src/main/runtime/jellyfin-client-info-main-deps.ts` (resolved-config + client-info builders) and rewired those handler construction sites in `src/main.ts`.
|
||||
- [2026-02-20T07:52:56Z] progress: added parity tests in `src/main/runtime/jellyfin-client-info-main-deps.test.ts`; `src/main.ts` now 2859 LOC.
|
||||
- [2026-02-20T07:52:56Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/jellyfin-client-info-main-deps.test.js dist/main/runtime/jellyfin-client-info.test.js dist/main/runtime/mpv-jellyfin-defaults-main-deps.test.js` pass (5/5).
|
||||
- [2026-02-20T07:51:58Z] progress: extracted MPV/Jellyfin defaults deps assembly into `src/main/runtime/mpv-jellyfin-defaults-main-deps.ts` (apply-defaults + default-socket-path builders) and rewired those constructor sites in `src/main.ts`.
|
||||
- [2026-02-20T07:51:58Z] progress: added parity tests in `src/main/runtime/mpv-jellyfin-defaults-main-deps.test.ts`; `src/main.ts` now 2848 LOC.
|
||||
- [2026-02-20T07:51:58Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/mpv-jellyfin-defaults-main-deps.test.js dist/main/runtime/mpv-jellyfin-defaults.test.js dist/main/runtime/jellyfin-remote-connection-main-deps.test.js` pass (5/5).
|
||||
- [2026-02-20T07:46:45Z] progress: extracted Jellyfin remote-connection deps assembly into `src/main/runtime/jellyfin-remote-connection-main-deps.ts` (wait, launch, ensure builders) and rewired those constructor sites in `src/main.ts`.
|
||||
- [2026-02-20T07:46:45Z] progress: added parity tests in `src/main/runtime/jellyfin-remote-connection-main-deps.test.ts`; `src/main.ts` now 2837 LOC.
|
||||
- [2026-02-20T07:46:45Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/jellyfin-remote-connection-main-deps.test.js dist/main/runtime/jellyfin-remote-connection.test.js dist/main/runtime/jellyfin-remote-main-deps.test.js` pass (8/8).
|
||||
- [2026-02-20T07:44:09Z] progress: extracted runtime-options/overlay-action deps assembly into `src/main/runtime/overlay-runtime-main-actions-main-deps.ts` (get-state, restore-secondary-sub, broadcast, send-active-overlay, debug-visualization, open-palette builders) and rewired handler construction in `src/main.ts`.
|
||||
- [2026-02-20T07:44:09Z] progress: added parity tests in `src/main/runtime/overlay-runtime-main-actions-main-deps.test.ts`; `src/main.ts` now 2821 LOC.
|
||||
- [2026-02-20T07:44:09Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/overlay-runtime-main-actions-main-deps.test.js dist/main/runtime/overlay-runtime-main-actions.test.js dist/main/runtime/overlay-bootstrap-main-deps.test.js` pass (10/10).
|
||||
- [2026-02-20T07:42:00Z] progress: extracted overlay bootstrap deps assembly into `src/main/runtime/overlay-bootstrap-main-deps.ts` (`createBuildOverlayContentMeasurementStoreMainDepsHandler`, `createBuildOverlayModalRuntimeMainDepsHandler`) and rewired overlay measurement/modal constructor wiring in `src/main.ts`.
|
||||
- [2026-02-20T07:42:00Z] progress: added parity tests in `src/main/runtime/overlay-bootstrap-main-deps.test.ts`; `src/main.ts` now 2794 LOC.
|
||||
- [2026-02-20T07:42:00Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/overlay-bootstrap-main-deps.test.js dist/core/services/overlay-content-measurement.test.js dist/main/runtime/runtime-bootstrap-main-deps.test.js` pass (8/8).
|
||||
- [2026-02-20T07:40:24Z] progress: after push of commit `561f7b3`, extracted bootstrap runtime deps assembly into `src/main/runtime/runtime-bootstrap-main-deps.ts` (immersion media, AniList state, config-derived, subsync builders) and rewired those constructor sites in `src/main.ts`.
|
||||
- [2026-02-20T07:40:24Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/runtime-bootstrap-main-deps.test.js dist/main/runtime/immersion-media.test.js dist/main/runtime/anilist-state.test.js` pass (10/10).
|
||||
- [2026-02-20T07:35:01Z] progress: extracted subtitle processing controller deps assembly into `src/main/runtime/subtitle-processing-main-deps.ts` (`createBuildSubtitleProcessingControllerMainDepsHandler`) and rewired `subtitleProcessingController` construction in `src/main.ts`.
|
||||
- [2026-02-20T07:35:01Z] progress: added parity tests in `src/main/runtime/subtitle-processing-main-deps.test.ts`; `src/main.ts` now 2775 LOC.
|
||||
- [2026-02-20T07:35:01Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + `node --test dist/main/runtime/subtitle-processing-main-deps.test.js dist/core/services/subtitle-processing-controller.test.js dist/main/runtime/jellyfin-remote-main-deps.test.js` pass (9/9).
|
||||
|
||||
202
src/main.ts
202
src/main.ts
@@ -94,6 +94,12 @@ import {
|
||||
createNotifyAnilistSetupHandler,
|
||||
createRegisterSubminerProtocolClientHandler,
|
||||
} from './main/runtime/anilist-setup-protocol';
|
||||
import {
|
||||
createBuildConsumeAnilistSetupTokenFromUrlMainDepsHandler,
|
||||
createBuildHandleAnilistSetupProtocolUrlMainDepsHandler,
|
||||
createBuildNotifyAnilistSetupMainDepsHandler,
|
||||
createBuildRegisterSubminerProtocolClientMainDepsHandler,
|
||||
} from './main/runtime/anilist-setup-protocol-main-deps';
|
||||
import { createRefreshAnilistClientSecretStateHandler } from './main/runtime/anilist-token-refresh';
|
||||
import {
|
||||
createHandleJellyfinRemoteGeneralCommand,
|
||||
@@ -114,11 +120,26 @@ import {
|
||||
createBuildReportJellyfinRemoteStoppedMainDepsHandler,
|
||||
} from './main/runtime/jellyfin-remote-main-deps';
|
||||
import { createBuildSubtitleProcessingControllerMainDepsHandler } from './main/runtime/subtitle-processing-main-deps';
|
||||
import {
|
||||
createBuildAnilistStateRuntimeMainDepsHandler,
|
||||
createBuildConfigDerivedRuntimeMainDepsHandler,
|
||||
createBuildImmersionMediaRuntimeMainDepsHandler,
|
||||
createBuildMainSubsyncRuntimeMainDepsHandler,
|
||||
} from './main/runtime/runtime-bootstrap-main-deps';
|
||||
import {
|
||||
createBuildOverlayContentMeasurementStoreMainDepsHandler,
|
||||
createBuildOverlayModalRuntimeMainDepsHandler,
|
||||
} from './main/runtime/overlay-bootstrap-main-deps';
|
||||
import {
|
||||
createEnsureMpvConnectedForJellyfinPlaybackHandler,
|
||||
createLaunchMpvIdleForJellyfinPlaybackHandler,
|
||||
createWaitForMpvConnectedHandler,
|
||||
} from './main/runtime/jellyfin-remote-connection';
|
||||
import {
|
||||
createBuildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler,
|
||||
createBuildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler,
|
||||
createBuildWaitForMpvConnectedMainDepsHandler,
|
||||
} from './main/runtime/jellyfin-remote-connection-main-deps';
|
||||
import {
|
||||
buildJellyfinSetupFormHtml,
|
||||
createOpenJellyfinSetupWindowHandler,
|
||||
@@ -156,14 +177,29 @@ import { createRunJellyfinCommandHandler } from './main/runtime/jellyfin-command
|
||||
import { createHandleJellyfinListCommands } from './main/runtime/jellyfin-cli-list';
|
||||
import { createHandleJellyfinPlayCommand } from './main/runtime/jellyfin-cli-play';
|
||||
import { createHandleJellyfinRemoteAnnounceCommand } from './main/runtime/jellyfin-cli-remote-announce';
|
||||
import {
|
||||
createBuildHandleJellyfinAuthCommandsMainDepsHandler,
|
||||
createBuildHandleJellyfinListCommandsMainDepsHandler,
|
||||
createBuildHandleJellyfinPlayCommandMainDepsHandler,
|
||||
createBuildHandleJellyfinRemoteAnnounceCommandMainDepsHandler,
|
||||
} from './main/runtime/jellyfin-cli-main-deps';
|
||||
import { createBuildRunJellyfinCommandMainDepsHandler } from './main/runtime/jellyfin-command-dispatch-main-deps';
|
||||
import {
|
||||
createGetJellyfinClientInfoHandler,
|
||||
createGetResolvedJellyfinConfigHandler,
|
||||
} from './main/runtime/jellyfin-client-info';
|
||||
import {
|
||||
createBuildGetJellyfinClientInfoMainDepsHandler,
|
||||
createBuildGetResolvedJellyfinConfigMainDepsHandler,
|
||||
} from './main/runtime/jellyfin-client-info-main-deps';
|
||||
import {
|
||||
createApplyJellyfinMpvDefaultsHandler,
|
||||
createGetDefaultSocketPathHandler,
|
||||
} from './main/runtime/mpv-jellyfin-defaults';
|
||||
import {
|
||||
createBuildApplyJellyfinMpvDefaultsMainDepsHandler,
|
||||
createBuildGetDefaultSocketPathMainDepsHandler,
|
||||
} from './main/runtime/mpv-jellyfin-defaults-main-deps';
|
||||
import { createBuildMediaRuntimeMainDepsHandler } from './main/runtime/media-runtime-main-deps';
|
||||
import {
|
||||
createBuildDictionaryRootsMainHandler,
|
||||
@@ -271,6 +307,14 @@ import {
|
||||
createSendToActiveOverlayWindowHandler,
|
||||
createSetOverlayDebugVisualizationEnabledHandler,
|
||||
} from './main/runtime/overlay-runtime-main-actions';
|
||||
import {
|
||||
createBuildBroadcastRuntimeOptionsChangedMainDepsHandler,
|
||||
createBuildGetRuntimeOptionsStateMainDepsHandler,
|
||||
createBuildOpenRuntimeOptionsPaletteMainDepsHandler,
|
||||
createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler,
|
||||
createBuildSendToActiveOverlayWindowMainDepsHandler,
|
||||
createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler,
|
||||
} from './main/runtime/overlay-runtime-main-actions-main-deps';
|
||||
import {
|
||||
createHandleMpvCommandFromIpcHandler,
|
||||
createRunSubsyncManualFromIpcHandler,
|
||||
@@ -486,10 +530,14 @@ let jellyfinMpvAutoLaunchInFlight: Promise<boolean> | null = null;
|
||||
let backgroundWarmupsStarted = false;
|
||||
let yomitanLoadInFlight: Promise<Extension | null> | null = null;
|
||||
|
||||
const applyJellyfinMpvDefaultsHandler = createApplyJellyfinMpvDefaultsHandler({
|
||||
const buildApplyJellyfinMpvDefaultsMainDepsHandler =
|
||||
createBuildApplyJellyfinMpvDefaultsMainDepsHandler({
|
||||
sendMpvCommandRuntime: (client, command) => sendMpvCommandRuntime(client as never, command),
|
||||
jellyfinLangPref: JELLYFIN_LANG_PREF,
|
||||
});
|
||||
const applyJellyfinMpvDefaultsHandler = createApplyJellyfinMpvDefaultsHandler(
|
||||
buildApplyJellyfinMpvDefaultsMainDepsHandler(),
|
||||
);
|
||||
|
||||
function applyJellyfinMpvDefaults(client: MpvIpcClient): void {
|
||||
applyJellyfinMpvDefaultsHandler(client);
|
||||
@@ -549,9 +597,12 @@ const appLogger = {
|
||||
},
|
||||
};
|
||||
|
||||
const getDefaultSocketPathHandler = createGetDefaultSocketPathHandler({
|
||||
const buildGetDefaultSocketPathMainDepsHandler = createBuildGetDefaultSocketPathMainDepsHandler({
|
||||
platform: process.platform,
|
||||
});
|
||||
const getDefaultSocketPathHandler = createGetDefaultSocketPathHandler(
|
||||
buildGetDefaultSocketPathMainDepsHandler(),
|
||||
);
|
||||
|
||||
function getDefaultSocketPath(): string {
|
||||
return getDefaultSocketPathHandler();
|
||||
@@ -570,19 +621,24 @@ process.on('SIGTERM', () => {
|
||||
});
|
||||
|
||||
const overlayManager = createOverlayManager();
|
||||
const overlayContentMeasurementStore = createOverlayContentMeasurementStore({
|
||||
const buildOverlayContentMeasurementStoreMainDepsHandler =
|
||||
createBuildOverlayContentMeasurementStoreMainDepsHandler({
|
||||
now: () => Date.now(),
|
||||
warn: (message: string) => logger.warn(message),
|
||||
});
|
||||
const overlayModalRuntime = createOverlayModalRuntimeService({
|
||||
const buildOverlayModalRuntimeMainDepsHandler = createBuildOverlayModalRuntimeMainDepsHandler({
|
||||
getMainWindow: () => overlayManager.getMainWindow(),
|
||||
getInvisibleWindow: () => overlayManager.getInvisibleWindow(),
|
||||
});
|
||||
const overlayContentMeasurementStore = createOverlayContentMeasurementStore(
|
||||
buildOverlayContentMeasurementStoreMainDepsHandler(),
|
||||
);
|
||||
const overlayModalRuntime = createOverlayModalRuntimeService(buildOverlayModalRuntimeMainDepsHandler());
|
||||
const appState = createAppState({
|
||||
mpvSocketPath: getDefaultSocketPath(),
|
||||
texthookerPort: DEFAULT_TEXTHOOKER_PORT,
|
||||
});
|
||||
const immersionMediaRuntime = createImmersionMediaRuntime({
|
||||
const buildImmersionMediaRuntimeMainDepsHandler = createBuildImmersionMediaRuntimeMainDepsHandler({
|
||||
getResolvedConfig: () => getResolvedConfig(),
|
||||
defaultImmersionDbPath: DEFAULT_IMMERSION_DB_PATH,
|
||||
getTracker: () => appState.immersionTracker,
|
||||
@@ -592,7 +648,7 @@ const immersionMediaRuntime = createImmersionMediaRuntime({
|
||||
logDebug: (message) => logger.debug(message),
|
||||
logInfo: (message) => logger.info(message),
|
||||
});
|
||||
const anilistStateRuntime = createAnilistStateRuntime({
|
||||
const buildAnilistStateRuntimeMainDepsHandler = createBuildAnilistStateRuntimeMainDepsHandler({
|
||||
getClientSecretState: () => appState.anilistClientSecretState,
|
||||
setClientSecretState: (next) => {
|
||||
appState.anilistClientSecretState = next;
|
||||
@@ -607,7 +663,7 @@ const anilistStateRuntime = createAnilistStateRuntime({
|
||||
anilistCachedAccessToken = null;
|
||||
},
|
||||
});
|
||||
const configDerivedRuntime = createConfigDerivedRuntime({
|
||||
const buildConfigDerivedRuntimeMainDepsHandler = createBuildConfigDerivedRuntimeMainDepsHandler({
|
||||
getResolvedConfig: () => getResolvedConfig(),
|
||||
getRuntimeOptionsManager: () => appState.runtimeOptionsManager,
|
||||
platform: process.platform,
|
||||
@@ -615,7 +671,7 @@ const configDerivedRuntime = createConfigDerivedRuntime({
|
||||
defaultJimakuMaxEntryResults: DEFAULT_CONFIG.jimaku.maxEntryResults,
|
||||
defaultJimakuApiBaseUrl: DEFAULT_CONFIG.jimaku.apiBaseUrl,
|
||||
});
|
||||
const subsyncRuntime = createMainSubsyncRuntime({
|
||||
const buildMainSubsyncRuntimeMainDepsHandler = createBuildMainSubsyncRuntimeMainDepsHandler({
|
||||
getMpvClient: () => appState.mpvClient,
|
||||
getResolvedConfig: () => getResolvedConfig(),
|
||||
getSubsyncInProgress: () => appState.subsyncInProgress,
|
||||
@@ -629,6 +685,10 @@ const subsyncRuntime = createMainSubsyncRuntime({
|
||||
});
|
||||
},
|
||||
});
|
||||
const immersionMediaRuntime = createImmersionMediaRuntime(buildImmersionMediaRuntimeMainDepsHandler());
|
||||
const anilistStateRuntime = createAnilistStateRuntime(buildAnilistStateRuntimeMainDepsHandler());
|
||||
const configDerivedRuntime = createConfigDerivedRuntime(buildConfigDerivedRuntimeMainDepsHandler());
|
||||
const subsyncRuntime = createMainSubsyncRuntime(buildMainSubsyncRuntimeMainDepsHandler());
|
||||
let appTray: Tray | null = null;
|
||||
const buildSubtitleProcessingControllerMainDepsHandler =
|
||||
createBuildSubtitleProcessingControllerMainDepsHandler({
|
||||
@@ -953,9 +1013,12 @@ const overlayVisibilityRuntime = createOverlayVisibilityRuntimeService(
|
||||
})(),
|
||||
);
|
||||
|
||||
const getRuntimeOptionsStateHandler = createGetRuntimeOptionsStateHandler({
|
||||
const buildGetRuntimeOptionsStateMainDepsHandler = createBuildGetRuntimeOptionsStateMainDepsHandler({
|
||||
getRuntimeOptionsManager: () => appState.runtimeOptionsManager,
|
||||
});
|
||||
const getRuntimeOptionsStateHandler = createGetRuntimeOptionsStateHandler(
|
||||
buildGetRuntimeOptionsStateMainDepsHandler(),
|
||||
);
|
||||
|
||||
function getRuntimeOptionsState(): RuntimeOptionState[] {
|
||||
return getRuntimeOptionsStateHandler();
|
||||
@@ -965,10 +1028,12 @@ function getOverlayWindows(): BrowserWindow[] {
|
||||
return overlayManager.getOverlayWindows();
|
||||
}
|
||||
|
||||
const restorePreviousSecondarySubVisibilityHandler = createRestorePreviousSecondarySubVisibilityHandler(
|
||||
{
|
||||
const buildRestorePreviousSecondarySubVisibilityMainDepsHandler =
|
||||
createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler({
|
||||
getMpvClient: () => appState.mpvClient,
|
||||
},
|
||||
});
|
||||
const restorePreviousSecondarySubVisibilityHandler = createRestorePreviousSecondarySubVisibilityHandler(
|
||||
buildRestorePreviousSecondarySubVisibilityMainDepsHandler(),
|
||||
);
|
||||
|
||||
function restorePreviousSecondarySubVisibility(): void {
|
||||
@@ -979,20 +1044,28 @@ function broadcastToOverlayWindows(channel: string, ...args: unknown[]): void {
|
||||
overlayManager.broadcastToOverlayWindows(channel, ...args);
|
||||
}
|
||||
|
||||
const broadcastRuntimeOptionsChangedHandler = createBroadcastRuntimeOptionsChangedHandler({
|
||||
const buildBroadcastRuntimeOptionsChangedMainDepsHandler =
|
||||
createBuildBroadcastRuntimeOptionsChangedMainDepsHandler({
|
||||
broadcastRuntimeOptionsChangedRuntime,
|
||||
getRuntimeOptionsState: () => getRuntimeOptionsState(),
|
||||
broadcastToOverlayWindows: (channel, ...args) => broadcastToOverlayWindows(channel, ...args),
|
||||
});
|
||||
const broadcastRuntimeOptionsChangedHandler = createBroadcastRuntimeOptionsChangedHandler(
|
||||
buildBroadcastRuntimeOptionsChangedMainDepsHandler(),
|
||||
);
|
||||
|
||||
function broadcastRuntimeOptionsChanged(): void {
|
||||
broadcastRuntimeOptionsChangedHandler();
|
||||
}
|
||||
|
||||
const sendToActiveOverlayWindowHandler = createSendToActiveOverlayWindowHandler({
|
||||
const buildSendToActiveOverlayWindowMainDepsHandler =
|
||||
createBuildSendToActiveOverlayWindowMainDepsHandler({
|
||||
sendToActiveOverlayWindowRuntime: (channel, payload, runtimeOptions) =>
|
||||
overlayModalRuntime.sendToActiveOverlayWindow(channel, payload, runtimeOptions),
|
||||
});
|
||||
const sendToActiveOverlayWindowHandler = createSendToActiveOverlayWindowHandler(
|
||||
buildSendToActiveOverlayWindowMainDepsHandler(),
|
||||
);
|
||||
|
||||
function sendToActiveOverlayWindow(
|
||||
channel: string,
|
||||
@@ -1002,24 +1075,30 @@ function sendToActiveOverlayWindow(
|
||||
return sendToActiveOverlayWindowHandler(channel, payload, runtimeOptions);
|
||||
}
|
||||
|
||||
const setOverlayDebugVisualizationEnabledHandler = createSetOverlayDebugVisualizationEnabledHandler(
|
||||
{
|
||||
const buildSetOverlayDebugVisualizationEnabledMainDepsHandler =
|
||||
createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler({
|
||||
setOverlayDebugVisualizationEnabledRuntime,
|
||||
getCurrentEnabled: () => appState.overlayDebugVisualizationEnabled,
|
||||
setCurrentEnabled: (next) => {
|
||||
appState.overlayDebugVisualizationEnabled = next;
|
||||
},
|
||||
broadcastToOverlayWindows: (channel, ...args) => broadcastToOverlayWindows(channel, ...args),
|
||||
},
|
||||
});
|
||||
const setOverlayDebugVisualizationEnabledHandler = createSetOverlayDebugVisualizationEnabledHandler(
|
||||
buildSetOverlayDebugVisualizationEnabledMainDepsHandler(),
|
||||
);
|
||||
|
||||
function setOverlayDebugVisualizationEnabled(enabled: boolean): void {
|
||||
setOverlayDebugVisualizationEnabledHandler(enabled);
|
||||
}
|
||||
|
||||
const openRuntimeOptionsPaletteHandler = createOpenRuntimeOptionsPaletteHandler({
|
||||
const buildOpenRuntimeOptionsPaletteMainDepsHandler =
|
||||
createBuildOpenRuntimeOptionsPaletteMainDepsHandler({
|
||||
openRuntimeOptionsPaletteRuntime: () => overlayModalRuntime.openRuntimeOptionsPalette(),
|
||||
});
|
||||
const openRuntimeOptionsPaletteHandler = createOpenRuntimeOptionsPaletteHandler(
|
||||
buildOpenRuntimeOptionsPaletteMainDepsHandler(),
|
||||
);
|
||||
|
||||
function openRuntimeOptionsPalette(): void {
|
||||
openRuntimeOptionsPaletteHandler();
|
||||
@@ -1029,30 +1108,41 @@ function getResolvedConfig() {
|
||||
return configService.getConfig();
|
||||
}
|
||||
|
||||
const getResolvedJellyfinConfigHandler = createGetResolvedJellyfinConfigHandler({
|
||||
const buildGetResolvedJellyfinConfigMainDepsHandler =
|
||||
createBuildGetResolvedJellyfinConfigMainDepsHandler({
|
||||
getResolvedConfig: () => getResolvedConfig(),
|
||||
});
|
||||
const getResolvedJellyfinConfigHandler = createGetResolvedJellyfinConfigHandler(
|
||||
buildGetResolvedJellyfinConfigMainDepsHandler(),
|
||||
);
|
||||
|
||||
function getResolvedJellyfinConfig() {
|
||||
return getResolvedJellyfinConfigHandler();
|
||||
}
|
||||
|
||||
const getJellyfinClientInfoHandler = createGetJellyfinClientInfoHandler({
|
||||
const buildGetJellyfinClientInfoMainDepsHandler = createBuildGetJellyfinClientInfoMainDepsHandler({
|
||||
getResolvedJellyfinConfig: () => getResolvedJellyfinConfig(),
|
||||
getDefaultJellyfinConfig: () => DEFAULT_CONFIG.jellyfin,
|
||||
});
|
||||
const getJellyfinClientInfoHandler = createGetJellyfinClientInfoHandler(
|
||||
buildGetJellyfinClientInfoMainDepsHandler(),
|
||||
);
|
||||
|
||||
function getJellyfinClientInfo(config = getResolvedJellyfinConfig()) {
|
||||
return getJellyfinClientInfoHandler(config);
|
||||
}
|
||||
|
||||
const waitForMpvConnected = createWaitForMpvConnectedHandler({
|
||||
const buildWaitForMpvConnectedMainDepsHandler = createBuildWaitForMpvConnectedMainDepsHandler({
|
||||
getMpvClient: () => appState.mpvClient,
|
||||
now: () => Date.now(),
|
||||
sleep: (delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)),
|
||||
});
|
||||
const waitForMpvConnected = createWaitForMpvConnectedHandler(
|
||||
buildWaitForMpvConnectedMainDepsHandler(),
|
||||
);
|
||||
|
||||
const launchMpvIdleForJellyfinPlayback = createLaunchMpvIdleForJellyfinPlaybackHandler({
|
||||
const buildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler =
|
||||
createBuildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler({
|
||||
getSocketPath: () => appState.mpvSocketPath,
|
||||
platform: process.platform,
|
||||
execPath: process.execPath,
|
||||
@@ -1069,8 +1159,12 @@ const launchMpvIdleForJellyfinPlayback = createLaunchMpvIdleForJellyfinPlaybackH
|
||||
logWarn: (message, error) => logger.warn(message, error),
|
||||
logInfo: (message) => logger.info(message),
|
||||
});
|
||||
const launchMpvIdleForJellyfinPlayback = createLaunchMpvIdleForJellyfinPlaybackHandler(
|
||||
buildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler(),
|
||||
);
|
||||
|
||||
const ensureMpvConnectedForJellyfinPlayback = createEnsureMpvConnectedForJellyfinPlaybackHandler({
|
||||
const buildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler =
|
||||
createBuildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler({
|
||||
getMpvClient: () => appState.mpvClient,
|
||||
setMpvClient: (client) => {
|
||||
appState.mpvClient = client as MpvIpcClient | null;
|
||||
@@ -1085,6 +1179,9 @@ const ensureMpvConnectedForJellyfinPlayback = createEnsureMpvConnectedForJellyfi
|
||||
connectTimeoutMs: JELLYFIN_MPV_CONNECT_TIMEOUT_MS,
|
||||
autoLaunchTimeoutMs: JELLYFIN_MPV_AUTO_LAUNCH_TIMEOUT_MS,
|
||||
});
|
||||
const ensureMpvConnectedForJellyfinPlayback = createEnsureMpvConnectedForJellyfinPlaybackHandler(
|
||||
buildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler(),
|
||||
);
|
||||
|
||||
const preloadJellyfinExternalSubtitles = createPreloadJellyfinExternalSubtitlesHandler({
|
||||
listJellyfinSubtitleTracks: (session, clientInfo, itemId) =>
|
||||
@@ -1143,7 +1240,8 @@ const playJellyfinItemInMpv = createPlayJellyfinItemInMpvHandler({
|
||||
},
|
||||
});
|
||||
|
||||
const handleJellyfinAuthCommands = createHandleJellyfinAuthCommands({
|
||||
const buildHandleJellyfinAuthCommandsMainDepsHandler =
|
||||
createBuildHandleJellyfinAuthCommandsMainDepsHandler({
|
||||
patchRawConfig: (patch) => {
|
||||
configService.patchRawConfig(patch);
|
||||
},
|
||||
@@ -1151,8 +1249,12 @@ const handleJellyfinAuthCommands = createHandleJellyfinAuthCommands({
|
||||
authenticateWithPasswordRuntime(serverUrl, username, password, clientInfo),
|
||||
logInfo: (message) => logger.info(message),
|
||||
});
|
||||
const handleJellyfinAuthCommands = createHandleJellyfinAuthCommands(
|
||||
buildHandleJellyfinAuthCommandsMainDepsHandler(),
|
||||
);
|
||||
|
||||
const handleJellyfinListCommands = createHandleJellyfinListCommands({
|
||||
const buildHandleJellyfinListCommandsMainDepsHandler =
|
||||
createBuildHandleJellyfinListCommandsMainDepsHandler({
|
||||
listJellyfinLibraries: (session, clientInfo) => listJellyfinLibrariesRuntime(session, clientInfo),
|
||||
listJellyfinItems: (session, clientInfo, params) =>
|
||||
listJellyfinItemsRuntime(session, clientInfo, params),
|
||||
@@ -1160,19 +1262,31 @@ const handleJellyfinListCommands = createHandleJellyfinListCommands({
|
||||
listJellyfinSubtitleTracksRuntime(session, clientInfo, itemId),
|
||||
logInfo: (message) => logger.info(message),
|
||||
});
|
||||
const handleJellyfinListCommands = createHandleJellyfinListCommands(
|
||||
buildHandleJellyfinListCommandsMainDepsHandler(),
|
||||
);
|
||||
|
||||
const handleJellyfinPlayCommand = createHandleJellyfinPlayCommand({
|
||||
const buildHandleJellyfinPlayCommandMainDepsHandler = createBuildHandleJellyfinPlayCommandMainDepsHandler(
|
||||
{
|
||||
playJellyfinItemInMpv: (params) =>
|
||||
playJellyfinItemInMpv(params as Parameters<typeof playJellyfinItemInMpv>[0]),
|
||||
logWarn: (message) => logger.warn(message),
|
||||
});
|
||||
},
|
||||
);
|
||||
const handleJellyfinPlayCommand = createHandleJellyfinPlayCommand(
|
||||
buildHandleJellyfinPlayCommandMainDepsHandler(),
|
||||
);
|
||||
|
||||
const handleJellyfinRemoteAnnounceCommand = createHandleJellyfinRemoteAnnounceCommand({
|
||||
const buildHandleJellyfinRemoteAnnounceCommandMainDepsHandler =
|
||||
createBuildHandleJellyfinRemoteAnnounceCommandMainDepsHandler({
|
||||
startJellyfinRemoteSession: () => startJellyfinRemoteSession(),
|
||||
getRemoteSession: () => appState.jellyfinRemoteSession,
|
||||
logInfo: (message) => logger.info(message),
|
||||
logWarn: (message) => logger.warn(message),
|
||||
});
|
||||
const handleJellyfinRemoteAnnounceCommand = createHandleJellyfinRemoteAnnounceCommand(
|
||||
buildHandleJellyfinRemoteAnnounceCommandMainDepsHandler(),
|
||||
);
|
||||
|
||||
const startJellyfinRemoteSession = createStartJellyfinRemoteSessionHandler({
|
||||
getJellyfinConfig: () => getResolvedJellyfinConfig(),
|
||||
@@ -1201,7 +1315,7 @@ const stopJellyfinRemoteSession = createStopJellyfinRemoteSessionHandler({
|
||||
},
|
||||
});
|
||||
|
||||
const runJellyfinCommand = createRunJellyfinCommandHandler({
|
||||
const buildRunJellyfinCommandMainDepsHandler = createBuildRunJellyfinCommandMainDepsHandler({
|
||||
getJellyfinConfig: () => getResolvedJellyfinConfig(),
|
||||
defaultServerUrl: DEFAULT_CONFIG.jellyfin.serverUrl,
|
||||
getJellyfinClientInfo: (jellyfinConfig) => getJellyfinClientInfo(jellyfinConfig),
|
||||
@@ -1210,15 +1324,22 @@ const runJellyfinCommand = createRunJellyfinCommandHandler({
|
||||
handleListCommands: (params) => handleJellyfinListCommands(params),
|
||||
handlePlayCommand: (params) => handleJellyfinPlayCommand(params),
|
||||
});
|
||||
const runJellyfinCommand = createRunJellyfinCommandHandler(
|
||||
buildRunJellyfinCommandMainDepsHandler(),
|
||||
);
|
||||
|
||||
const notifyAnilistSetup = createNotifyAnilistSetupHandler({
|
||||
const buildNotifyAnilistSetupMainDepsHandler = createBuildNotifyAnilistSetupMainDepsHandler({
|
||||
hasMpvClient: () => Boolean(appState.mpvClient),
|
||||
showMpvOsd: (message) => showMpvOsd(message),
|
||||
showDesktopNotification: (title, options) => showDesktopNotification(title, options),
|
||||
logInfo: (message) => logger.info(message),
|
||||
});
|
||||
const notifyAnilistSetup = createNotifyAnilistSetupHandler(
|
||||
buildNotifyAnilistSetupMainDepsHandler(),
|
||||
);
|
||||
|
||||
const consumeAnilistSetupTokenFromUrl = createConsumeAnilistSetupTokenFromUrlHandler({
|
||||
const buildConsumeAnilistSetupTokenFromUrlMainDepsHandler =
|
||||
createBuildConsumeAnilistSetupTokenFromUrlMainDepsHandler({
|
||||
consumeAnilistSetupCallbackUrl,
|
||||
saveToken: (token) => anilistTokenStore.saveToken(token),
|
||||
setCachedToken: (token) => {
|
||||
@@ -1245,21 +1366,34 @@ const consumeAnilistSetupTokenFromUrl = createConsumeAnilistSetupTokenFromUrlHan
|
||||
}
|
||||
},
|
||||
});
|
||||
const consumeAnilistSetupTokenFromUrl = createConsumeAnilistSetupTokenFromUrlHandler(
|
||||
buildConsumeAnilistSetupTokenFromUrlMainDepsHandler(),
|
||||
);
|
||||
|
||||
const handleAnilistSetupProtocolUrl = createHandleAnilistSetupProtocolUrlHandler({
|
||||
const buildHandleAnilistSetupProtocolUrlMainDepsHandler =
|
||||
createBuildHandleAnilistSetupProtocolUrlMainDepsHandler({
|
||||
consumeAnilistSetupTokenFromUrl: (rawUrl) => consumeAnilistSetupTokenFromUrl(rawUrl),
|
||||
logWarn: (message, details) => logger.warn(message, details),
|
||||
});
|
||||
const handleAnilistSetupProtocolUrl = createHandleAnilistSetupProtocolUrlHandler(
|
||||
buildHandleAnilistSetupProtocolUrlMainDepsHandler(),
|
||||
);
|
||||
|
||||
const registerSubminerProtocolClient = createRegisterSubminerProtocolClientHandler({
|
||||
const buildRegisterSubminerProtocolClientMainDepsHandler =
|
||||
createBuildRegisterSubminerProtocolClientMainDepsHandler({
|
||||
isDefaultApp: () => Boolean(process.defaultApp),
|
||||
getArgv: () => process.argv,
|
||||
execPath: process.execPath,
|
||||
resolvePath: (value) => path.resolve(value),
|
||||
setAsDefaultProtocolClient: (scheme, appPath, args) =>
|
||||
appPath ? app.setAsDefaultProtocolClient(scheme, appPath, args) : app.setAsDefaultProtocolClient(scheme),
|
||||
appPath
|
||||
? app.setAsDefaultProtocolClient(scheme, appPath, args)
|
||||
: app.setAsDefaultProtocolClient(scheme),
|
||||
logWarn: (message, details) => logger.warn(message, details),
|
||||
});
|
||||
const registerSubminerProtocolClient = createRegisterSubminerProtocolClientHandler(
|
||||
buildRegisterSubminerProtocolClientMainDepsHandler(),
|
||||
);
|
||||
|
||||
function openAnilistSetupWindow(): void {
|
||||
createOpenAnilistSetupWindowHandler({
|
||||
|
||||
87
src/main/runtime/anilist-setup-protocol-main-deps.test.ts
Normal file
87
src/main/runtime/anilist-setup-protocol-main-deps.test.ts
Normal file
@@ -0,0 +1,87 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createBuildConsumeAnilistSetupTokenFromUrlMainDepsHandler,
|
||||
createBuildHandleAnilistSetupProtocolUrlMainDepsHandler,
|
||||
createBuildNotifyAnilistSetupMainDepsHandler,
|
||||
createBuildRegisterSubminerProtocolClientMainDepsHandler,
|
||||
} from './anilist-setup-protocol-main-deps';
|
||||
|
||||
test('notify anilist setup main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildNotifyAnilistSetupMainDepsHandler({
|
||||
hasMpvClient: () => true,
|
||||
showMpvOsd: (message) => calls.push(`osd:${message}`),
|
||||
showDesktopNotification: (title) => calls.push(`notify:${title}`),
|
||||
logInfo: (message) => calls.push(`log:${message}`),
|
||||
})();
|
||||
|
||||
assert.equal(deps.hasMpvClient(), true);
|
||||
deps.showMpvOsd('ok');
|
||||
deps.showDesktopNotification('SubMiner', { body: 'x' });
|
||||
deps.logInfo('done');
|
||||
assert.deepEqual(calls, ['osd:ok', 'notify:SubMiner', 'log:done']);
|
||||
});
|
||||
|
||||
test('consume anilist setup token main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildConsumeAnilistSetupTokenFromUrlMainDepsHandler({
|
||||
consumeAnilistSetupCallbackUrl: () => true,
|
||||
saveToken: () => calls.push('save'),
|
||||
setCachedToken: () => calls.push('cache'),
|
||||
setResolvedState: () => calls.push('resolved'),
|
||||
setSetupPageOpened: () => calls.push('opened'),
|
||||
onSuccess: () => calls.push('success'),
|
||||
closeWindow: () => calls.push('close'),
|
||||
})();
|
||||
|
||||
assert.equal(
|
||||
deps.consumeAnilistSetupCallbackUrl({
|
||||
rawUrl: 'subminer://anilist-setup',
|
||||
saveToken: () => {},
|
||||
setCachedToken: () => {},
|
||||
setResolvedState: () => {},
|
||||
setSetupPageOpened: () => {},
|
||||
onSuccess: () => {},
|
||||
closeWindow: () => {},
|
||||
}),
|
||||
true,
|
||||
);
|
||||
deps.saveToken('token');
|
||||
deps.setCachedToken('token');
|
||||
deps.setResolvedState(Date.now());
|
||||
deps.setSetupPageOpened(true);
|
||||
deps.onSuccess();
|
||||
deps.closeWindow();
|
||||
assert.deepEqual(calls, ['save', 'cache', 'resolved', 'opened', 'success', 'close']);
|
||||
});
|
||||
|
||||
test('handle anilist setup protocol url main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildHandleAnilistSetupProtocolUrlMainDepsHandler({
|
||||
consumeAnilistSetupTokenFromUrl: () => true,
|
||||
logWarn: (message) => calls.push(`warn:${message}`),
|
||||
})();
|
||||
|
||||
assert.equal(deps.consumeAnilistSetupTokenFromUrl('subminer://anilist-setup'), true);
|
||||
deps.logWarn('missing', null);
|
||||
assert.deepEqual(calls, ['warn:missing']);
|
||||
});
|
||||
|
||||
test('register subminer protocol client main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildRegisterSubminerProtocolClientMainDepsHandler({
|
||||
isDefaultApp: () => true,
|
||||
getArgv: () => ['electron', 'entry.js'],
|
||||
execPath: '/tmp/electron',
|
||||
resolvePath: (value) => `/abs/${value}`,
|
||||
setAsDefaultProtocolClient: () => true,
|
||||
logWarn: (message) => calls.push(`warn:${message}`),
|
||||
})();
|
||||
|
||||
assert.equal(deps.isDefaultApp(), true);
|
||||
assert.deepEqual(deps.getArgv(), ['electron', 'entry.js']);
|
||||
assert.equal(deps.execPath, '/tmp/electron');
|
||||
assert.equal(deps.resolvePath('entry.js'), '/abs/entry.js');
|
||||
assert.equal(deps.setAsDefaultProtocolClient('subminer'), true);
|
||||
});
|
||||
64
src/main/runtime/anilist-setup-protocol-main-deps.ts
Normal file
64
src/main/runtime/anilist-setup-protocol-main-deps.ts
Normal file
@@ -0,0 +1,64 @@
|
||||
import type {
|
||||
createConsumeAnilistSetupTokenFromUrlHandler,
|
||||
createHandleAnilistSetupProtocolUrlHandler,
|
||||
createNotifyAnilistSetupHandler,
|
||||
createRegisterSubminerProtocolClientHandler,
|
||||
} from './anilist-setup-protocol';
|
||||
|
||||
type NotifyAnilistSetupMainDeps = Parameters<typeof createNotifyAnilistSetupHandler>[0];
|
||||
type ConsumeAnilistSetupTokenMainDeps = Parameters<
|
||||
typeof createConsumeAnilistSetupTokenFromUrlHandler
|
||||
>[0];
|
||||
type HandleAnilistSetupProtocolUrlMainDeps = Parameters<
|
||||
typeof createHandleAnilistSetupProtocolUrlHandler
|
||||
>[0];
|
||||
type RegisterSubminerProtocolClientMainDeps = Parameters<
|
||||
typeof createRegisterSubminerProtocolClientHandler
|
||||
>[0];
|
||||
|
||||
export function createBuildNotifyAnilistSetupMainDepsHandler(deps: NotifyAnilistSetupMainDeps) {
|
||||
return (): NotifyAnilistSetupMainDeps => ({
|
||||
hasMpvClient: () => deps.hasMpvClient(),
|
||||
showMpvOsd: (message: string) => deps.showMpvOsd(message),
|
||||
showDesktopNotification: (title: string, options: { body: string }) =>
|
||||
deps.showDesktopNotification(title, options),
|
||||
logInfo: (message: string) => deps.logInfo(message),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildConsumeAnilistSetupTokenFromUrlMainDepsHandler(
|
||||
deps: ConsumeAnilistSetupTokenMainDeps,
|
||||
) {
|
||||
return (): ConsumeAnilistSetupTokenMainDeps => ({
|
||||
consumeAnilistSetupCallbackUrl: (input) => deps.consumeAnilistSetupCallbackUrl(input),
|
||||
saveToken: (token: string) => deps.saveToken(token),
|
||||
setCachedToken: (token: string) => deps.setCachedToken(token),
|
||||
setResolvedState: (resolvedAt: number) => deps.setResolvedState(resolvedAt),
|
||||
setSetupPageOpened: (opened: boolean) => deps.setSetupPageOpened(opened),
|
||||
onSuccess: () => deps.onSuccess(),
|
||||
closeWindow: () => deps.closeWindow(),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildHandleAnilistSetupProtocolUrlMainDepsHandler(
|
||||
deps: HandleAnilistSetupProtocolUrlMainDeps,
|
||||
) {
|
||||
return (): HandleAnilistSetupProtocolUrlMainDeps => ({
|
||||
consumeAnilistSetupTokenFromUrl: (rawUrl: string) => deps.consumeAnilistSetupTokenFromUrl(rawUrl),
|
||||
logWarn: (message: string, details: unknown) => deps.logWarn(message, details),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildRegisterSubminerProtocolClientMainDepsHandler(
|
||||
deps: RegisterSubminerProtocolClientMainDeps,
|
||||
) {
|
||||
return (): RegisterSubminerProtocolClientMainDeps => ({
|
||||
isDefaultApp: () => deps.isDefaultApp(),
|
||||
getArgv: () => deps.getArgv(),
|
||||
execPath: deps.execPath,
|
||||
resolvePath: (value: string) => deps.resolvePath(value),
|
||||
setAsDefaultProtocolClient: (scheme: string, path?: string, args?: string[]) =>
|
||||
deps.setAsDefaultProtocolClient(scheme, path, args),
|
||||
logWarn: (message: string, details?: unknown) => deps.logWarn(message, details),
|
||||
});
|
||||
}
|
||||
84
src/main/runtime/jellyfin-cli-main-deps.test.ts
Normal file
84
src/main/runtime/jellyfin-cli-main-deps.test.ts
Normal file
@@ -0,0 +1,84 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createBuildHandleJellyfinAuthCommandsMainDepsHandler,
|
||||
createBuildHandleJellyfinListCommandsMainDepsHandler,
|
||||
createBuildHandleJellyfinPlayCommandMainDepsHandler,
|
||||
createBuildHandleJellyfinRemoteAnnounceCommandMainDepsHandler,
|
||||
} from './jellyfin-cli-main-deps';
|
||||
|
||||
test('jellyfin auth commands main deps builder maps callbacks', async () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildHandleJellyfinAuthCommandsMainDepsHandler({
|
||||
patchRawConfig: () => calls.push('patch'),
|
||||
authenticateWithPassword: async () => ({}) as never,
|
||||
logInfo: (message) => calls.push(`info:${message}`),
|
||||
})();
|
||||
|
||||
deps.patchRawConfig({ jellyfin: {} });
|
||||
await deps.authenticateWithPassword('', '', '', {
|
||||
deviceId: '',
|
||||
clientName: '',
|
||||
clientVersion: '',
|
||||
});
|
||||
deps.logInfo('ok');
|
||||
assert.deepEqual(calls, ['patch', 'info:ok']);
|
||||
});
|
||||
|
||||
test('jellyfin list commands main deps builder maps callbacks', async () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildHandleJellyfinListCommandsMainDepsHandler({
|
||||
listJellyfinLibraries: async () => {
|
||||
calls.push('libraries');
|
||||
return [];
|
||||
},
|
||||
listJellyfinItems: async () => {
|
||||
calls.push('items');
|
||||
return [];
|
||||
},
|
||||
listJellyfinSubtitleTracks: async () => {
|
||||
calls.push('subtitles');
|
||||
return [];
|
||||
},
|
||||
logInfo: (message) => calls.push(`info:${message}`),
|
||||
})();
|
||||
|
||||
await deps.listJellyfinLibraries({} as never, {} as never);
|
||||
await deps.listJellyfinItems({} as never, {} as never, { libraryId: '', limit: 1 });
|
||||
await deps.listJellyfinSubtitleTracks({} as never, {} as never, 'id');
|
||||
deps.logInfo('done');
|
||||
assert.deepEqual(calls, ['libraries', 'items', 'subtitles', 'info:done']);
|
||||
});
|
||||
|
||||
test('jellyfin play command main deps builder maps callbacks', async () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildHandleJellyfinPlayCommandMainDepsHandler({
|
||||
playJellyfinItemInMpv: async () => {
|
||||
calls.push('play');
|
||||
},
|
||||
logWarn: (message) => calls.push(`warn:${message}`),
|
||||
})();
|
||||
|
||||
await deps.playJellyfinItemInMpv({} as never);
|
||||
deps.logWarn('missing');
|
||||
assert.deepEqual(calls, ['play', 'warn:missing']);
|
||||
});
|
||||
|
||||
test('jellyfin remote announce main deps builder maps callbacks', async () => {
|
||||
const calls: string[] = [];
|
||||
const session = { advertiseNow: async () => true };
|
||||
const deps = createBuildHandleJellyfinRemoteAnnounceCommandMainDepsHandler({
|
||||
startJellyfinRemoteSession: async () => {
|
||||
calls.push('start');
|
||||
},
|
||||
getRemoteSession: () => session,
|
||||
logInfo: (message) => calls.push(`info:${message}`),
|
||||
logWarn: (message) => calls.push(`warn:${message}`),
|
||||
})();
|
||||
|
||||
await deps.startJellyfinRemoteSession();
|
||||
assert.equal(deps.getRemoteSession(), session);
|
||||
deps.logInfo('visible');
|
||||
deps.logWarn('not-visible');
|
||||
assert.deepEqual(calls, ['start', 'info:visible', 'warn:not-visible']);
|
||||
});
|
||||
63
src/main/runtime/jellyfin-cli-main-deps.ts
Normal file
63
src/main/runtime/jellyfin-cli-main-deps.ts
Normal file
@@ -0,0 +1,63 @@
|
||||
import type {
|
||||
createHandleJellyfinAuthCommands,
|
||||
} from './jellyfin-cli-auth';
|
||||
import type {
|
||||
createHandleJellyfinListCommands,
|
||||
} from './jellyfin-cli-list';
|
||||
import type {
|
||||
createHandleJellyfinPlayCommand,
|
||||
} from './jellyfin-cli-play';
|
||||
import type {
|
||||
createHandleJellyfinRemoteAnnounceCommand,
|
||||
} from './jellyfin-cli-remote-announce';
|
||||
|
||||
type HandleJellyfinAuthCommandsMainDeps = Parameters<typeof createHandleJellyfinAuthCommands>[0];
|
||||
type HandleJellyfinListCommandsMainDeps = Parameters<typeof createHandleJellyfinListCommands>[0];
|
||||
type HandleJellyfinPlayCommandMainDeps = Parameters<typeof createHandleJellyfinPlayCommand>[0];
|
||||
type HandleJellyfinRemoteAnnounceCommandMainDeps = Parameters<
|
||||
typeof createHandleJellyfinRemoteAnnounceCommand
|
||||
>[0];
|
||||
|
||||
export function createBuildHandleJellyfinAuthCommandsMainDepsHandler(
|
||||
deps: HandleJellyfinAuthCommandsMainDeps,
|
||||
) {
|
||||
return (): HandleJellyfinAuthCommandsMainDeps => ({
|
||||
patchRawConfig: (patch) => deps.patchRawConfig(patch),
|
||||
authenticateWithPassword: (serverUrl, username, password, clientInfo) =>
|
||||
deps.authenticateWithPassword(serverUrl, username, password, clientInfo),
|
||||
logInfo: (message: string) => deps.logInfo(message),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildHandleJellyfinListCommandsMainDepsHandler(
|
||||
deps: HandleJellyfinListCommandsMainDeps,
|
||||
) {
|
||||
return (): HandleJellyfinListCommandsMainDeps => ({
|
||||
listJellyfinLibraries: (session, clientInfo) => deps.listJellyfinLibraries(session, clientInfo),
|
||||
listJellyfinItems: (session, clientInfo, params) =>
|
||||
deps.listJellyfinItems(session, clientInfo, params),
|
||||
listJellyfinSubtitleTracks: (session, clientInfo, itemId) =>
|
||||
deps.listJellyfinSubtitleTracks(session, clientInfo, itemId),
|
||||
logInfo: (message: string) => deps.logInfo(message),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildHandleJellyfinPlayCommandMainDepsHandler(
|
||||
deps: HandleJellyfinPlayCommandMainDeps,
|
||||
) {
|
||||
return (): HandleJellyfinPlayCommandMainDeps => ({
|
||||
playJellyfinItemInMpv: (params) => deps.playJellyfinItemInMpv(params),
|
||||
logWarn: (message: string) => deps.logWarn(message),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildHandleJellyfinRemoteAnnounceCommandMainDepsHandler(
|
||||
deps: HandleJellyfinRemoteAnnounceCommandMainDeps,
|
||||
) {
|
||||
return (): HandleJellyfinRemoteAnnounceCommandMainDeps => ({
|
||||
startJellyfinRemoteSession: () => deps.startJellyfinRemoteSession(),
|
||||
getRemoteSession: () => deps.getRemoteSession(),
|
||||
logInfo: (message: string) => deps.logInfo(message),
|
||||
logWarn: (message: string) => deps.logWarn(message),
|
||||
});
|
||||
}
|
||||
26
src/main/runtime/jellyfin-client-info-main-deps.test.ts
Normal file
26
src/main/runtime/jellyfin-client-info-main-deps.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createBuildGetJellyfinClientInfoMainDepsHandler,
|
||||
createBuildGetResolvedJellyfinConfigMainDepsHandler,
|
||||
} from './jellyfin-client-info-main-deps';
|
||||
|
||||
test('get resolved jellyfin config main deps builder maps callbacks', () => {
|
||||
const resolved = { jellyfin: { url: 'https://example.com' } };
|
||||
const deps = createBuildGetResolvedJellyfinConfigMainDepsHandler({
|
||||
getResolvedConfig: () => resolved as never,
|
||||
})();
|
||||
assert.equal(deps.getResolvedConfig(), resolved);
|
||||
});
|
||||
|
||||
test('get jellyfin client info main deps builder maps callbacks', () => {
|
||||
const configured = { clientName: 'Configured' };
|
||||
const defaults = { clientName: 'Default' };
|
||||
const deps = createBuildGetJellyfinClientInfoMainDepsHandler({
|
||||
getResolvedJellyfinConfig: () => configured as never,
|
||||
getDefaultJellyfinConfig: () => defaults as never,
|
||||
})();
|
||||
|
||||
assert.equal(deps.getResolvedJellyfinConfig(), configured);
|
||||
assert.equal(deps.getDefaultJellyfinConfig(), defaults);
|
||||
});
|
||||
24
src/main/runtime/jellyfin-client-info-main-deps.ts
Normal file
24
src/main/runtime/jellyfin-client-info-main-deps.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type {
|
||||
createGetJellyfinClientInfoHandler,
|
||||
createGetResolvedJellyfinConfigHandler,
|
||||
} from './jellyfin-client-info';
|
||||
|
||||
type GetResolvedJellyfinConfigMainDeps = Parameters<typeof createGetResolvedJellyfinConfigHandler>[0];
|
||||
type GetJellyfinClientInfoMainDeps = Parameters<typeof createGetJellyfinClientInfoHandler>[0];
|
||||
|
||||
export function createBuildGetResolvedJellyfinConfigMainDepsHandler(
|
||||
deps: GetResolvedJellyfinConfigMainDeps,
|
||||
) {
|
||||
return (): GetResolvedJellyfinConfigMainDeps => ({
|
||||
getResolvedConfig: () => deps.getResolvedConfig(),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildGetJellyfinClientInfoMainDepsHandler(
|
||||
deps: GetJellyfinClientInfoMainDeps,
|
||||
) {
|
||||
return (): GetJellyfinClientInfoMainDeps => ({
|
||||
getResolvedJellyfinConfig: () => deps.getResolvedJellyfinConfig(),
|
||||
getDefaultJellyfinConfig: () => deps.getDefaultJellyfinConfig(),
|
||||
});
|
||||
}
|
||||
72
src/main/runtime/jellyfin-command-dispatch-main-deps.test.ts
Normal file
72
src/main/runtime/jellyfin-command-dispatch-main-deps.test.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import type { CliArgs } from '../../cli/args';
|
||||
import { createBuildRunJellyfinCommandMainDepsHandler } from './jellyfin-command-dispatch-main-deps';
|
||||
|
||||
test('run jellyfin command main deps builder maps callbacks', async () => {
|
||||
const calls: string[] = [];
|
||||
const args = { raw: [] } as unknown as CliArgs;
|
||||
const config = {
|
||||
serverUrl: 'http://localhost:8096',
|
||||
accessToken: 'token',
|
||||
userId: 'uid',
|
||||
username: 'alice',
|
||||
};
|
||||
const clientInfo = { clientName: 'SubMiner' };
|
||||
|
||||
const deps = createBuildRunJellyfinCommandMainDepsHandler({
|
||||
getJellyfinConfig: () => config,
|
||||
defaultServerUrl: 'http://127.0.0.1:8096',
|
||||
getJellyfinClientInfo: () => clientInfo,
|
||||
handleAuthCommands: async () => {
|
||||
calls.push('auth');
|
||||
return false;
|
||||
},
|
||||
handleRemoteAnnounceCommand: async () => {
|
||||
calls.push('remote');
|
||||
return false;
|
||||
},
|
||||
handleListCommands: async () => {
|
||||
calls.push('list');
|
||||
return false;
|
||||
},
|
||||
handlePlayCommand: async () => {
|
||||
calls.push('play');
|
||||
return true;
|
||||
},
|
||||
})();
|
||||
|
||||
assert.equal(deps.getJellyfinConfig(), config);
|
||||
assert.equal(deps.defaultServerUrl, 'http://127.0.0.1:8096');
|
||||
assert.equal(deps.getJellyfinClientInfo(config), clientInfo);
|
||||
await deps.handleAuthCommands({
|
||||
args,
|
||||
jellyfinConfig: config,
|
||||
serverUrl: config.serverUrl,
|
||||
clientInfo,
|
||||
});
|
||||
await deps.handleRemoteAnnounceCommand(args);
|
||||
await deps.handleListCommands({
|
||||
args,
|
||||
session: {
|
||||
serverUrl: config.serverUrl,
|
||||
accessToken: config.accessToken,
|
||||
userId: config.userId,
|
||||
username: config.username,
|
||||
},
|
||||
clientInfo,
|
||||
jellyfinConfig: config,
|
||||
});
|
||||
await deps.handlePlayCommand({
|
||||
args,
|
||||
session: {
|
||||
serverUrl: config.serverUrl,
|
||||
accessToken: config.accessToken,
|
||||
userId: config.userId,
|
||||
username: config.username,
|
||||
},
|
||||
clientInfo,
|
||||
jellyfinConfig: config,
|
||||
});
|
||||
assert.deepEqual(calls, ['auth', 'remote', 'list', 'play']);
|
||||
});
|
||||
55
src/main/runtime/jellyfin-command-dispatch-main-deps.ts
Normal file
55
src/main/runtime/jellyfin-command-dispatch-main-deps.ts
Normal file
@@ -0,0 +1,55 @@
|
||||
import type { CliArgs } from '../../cli/args';
|
||||
|
||||
type JellyfinConfigBase = {
|
||||
serverUrl?: string;
|
||||
accessToken?: string;
|
||||
userId?: string;
|
||||
username?: string;
|
||||
};
|
||||
|
||||
type JellyfinSession = {
|
||||
serverUrl: string;
|
||||
accessToken: string;
|
||||
userId: string;
|
||||
username: string;
|
||||
};
|
||||
|
||||
export type RunJellyfinCommandMainDeps<TClientInfo, TConfig extends JellyfinConfigBase> = {
|
||||
getJellyfinConfig: () => TConfig;
|
||||
defaultServerUrl: string;
|
||||
getJellyfinClientInfo: (config: TConfig) => TClientInfo;
|
||||
handleAuthCommands: (params: {
|
||||
args: CliArgs;
|
||||
jellyfinConfig: TConfig;
|
||||
serverUrl: string;
|
||||
clientInfo: TClientInfo;
|
||||
}) => Promise<boolean>;
|
||||
handleRemoteAnnounceCommand: (args: CliArgs) => Promise<boolean>;
|
||||
handleListCommands: (params: {
|
||||
args: CliArgs;
|
||||
session: JellyfinSession;
|
||||
clientInfo: TClientInfo;
|
||||
jellyfinConfig: TConfig;
|
||||
}) => Promise<boolean>;
|
||||
handlePlayCommand: (params: {
|
||||
args: CliArgs;
|
||||
session: JellyfinSession;
|
||||
clientInfo: TClientInfo;
|
||||
jellyfinConfig: TConfig;
|
||||
}) => Promise<boolean>;
|
||||
};
|
||||
|
||||
export function createBuildRunJellyfinCommandMainDepsHandler<
|
||||
TClientInfo,
|
||||
TConfig extends JellyfinConfigBase,
|
||||
>(deps: RunJellyfinCommandMainDeps<TClientInfo, TConfig>) {
|
||||
return (): RunJellyfinCommandMainDeps<TClientInfo, TConfig> => ({
|
||||
getJellyfinConfig: () => deps.getJellyfinConfig(),
|
||||
defaultServerUrl: deps.defaultServerUrl,
|
||||
getJellyfinClientInfo: (config: TConfig) => deps.getJellyfinClientInfo(config),
|
||||
handleAuthCommands: (params) => deps.handleAuthCommands(params),
|
||||
handleRemoteAnnounceCommand: (args: CliArgs) => deps.handleRemoteAnnounceCommand(args),
|
||||
handleListCommands: (params) => deps.handleListCommands(params),
|
||||
handlePlayCommand: (params) => deps.handlePlayCommand(params),
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createBuildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler,
|
||||
createBuildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler,
|
||||
createBuildWaitForMpvConnectedMainDepsHandler,
|
||||
} from './jellyfin-remote-connection-main-deps';
|
||||
|
||||
test('wait for mpv connected main deps builder maps callbacks', async () => {
|
||||
const calls: string[] = [];
|
||||
const client = { connected: false, connect: () => calls.push('connect') };
|
||||
const deps = createBuildWaitForMpvConnectedMainDepsHandler({
|
||||
getMpvClient: () => client,
|
||||
now: () => 123,
|
||||
sleep: async () => {
|
||||
calls.push('sleep');
|
||||
},
|
||||
})();
|
||||
|
||||
assert.equal(deps.getMpvClient(), client);
|
||||
assert.equal(deps.now(), 123);
|
||||
await deps.sleep(10);
|
||||
assert.deepEqual(calls, ['sleep']);
|
||||
});
|
||||
|
||||
test('launch mpv for jellyfin main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const proc = {
|
||||
on: () => {},
|
||||
unref: () => {
|
||||
calls.push('unref');
|
||||
},
|
||||
};
|
||||
const deps = createBuildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler({
|
||||
getSocketPath: () => '/tmp/mpv.sock',
|
||||
platform: 'darwin',
|
||||
execPath: '/tmp/subminer',
|
||||
defaultMpvLogPath: '/tmp/mpv.log',
|
||||
defaultMpvArgs: ['--no-config'],
|
||||
removeSocketPath: (socketPath) => calls.push(`rm:${socketPath}`),
|
||||
spawnMpv: (args) => {
|
||||
calls.push(`spawn:${args.join(' ')}`);
|
||||
return proc;
|
||||
},
|
||||
logWarn: (message) => calls.push(`warn:${message}`),
|
||||
logInfo: (message) => calls.push(`info:${message}`),
|
||||
})();
|
||||
|
||||
assert.equal(deps.getSocketPath(), '/tmp/mpv.sock');
|
||||
assert.equal(deps.platform, 'darwin');
|
||||
assert.equal(deps.execPath, '/tmp/subminer');
|
||||
assert.equal(deps.defaultMpvLogPath, '/tmp/mpv.log');
|
||||
assert.deepEqual(deps.defaultMpvArgs, ['--no-config']);
|
||||
deps.removeSocketPath('/tmp/mpv.sock');
|
||||
deps.spawnMpv(['--idle=yes']);
|
||||
deps.logInfo('launched');
|
||||
deps.logWarn('bad', null);
|
||||
assert.deepEqual(calls, ['rm:/tmp/mpv.sock', 'spawn:--idle=yes', 'info:launched', 'warn:bad']);
|
||||
});
|
||||
|
||||
test('ensure mpv connected for jellyfin main deps builder maps callbacks', async () => {
|
||||
const calls: string[] = [];
|
||||
const client = { connected: true, connect: () => {} };
|
||||
const waitPromise = Promise.resolve(true);
|
||||
const inFlight = Promise.resolve(false);
|
||||
const deps = createBuildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler({
|
||||
getMpvClient: () => client,
|
||||
setMpvClient: () => calls.push('set-client'),
|
||||
createMpvClient: () => client,
|
||||
waitForMpvConnected: () => waitPromise,
|
||||
launchMpvIdleForJellyfinPlayback: () => calls.push('launch'),
|
||||
getAutoLaunchInFlight: () => inFlight,
|
||||
setAutoLaunchInFlight: () => calls.push('set-in-flight'),
|
||||
connectTimeoutMs: 7000,
|
||||
autoLaunchTimeoutMs: 15000,
|
||||
})();
|
||||
|
||||
assert.equal(deps.getMpvClient(), client);
|
||||
deps.setMpvClient(client);
|
||||
assert.equal(deps.createMpvClient(), client);
|
||||
assert.equal(await deps.waitForMpvConnected(1), true);
|
||||
deps.launchMpvIdleForJellyfinPlayback();
|
||||
assert.equal(deps.getAutoLaunchInFlight(), inFlight);
|
||||
deps.setAutoLaunchInFlight(null);
|
||||
assert.equal(deps.connectTimeoutMs, 7000);
|
||||
assert.equal(deps.autoLaunchTimeoutMs, 15000);
|
||||
assert.deepEqual(calls, ['set-client', 'launch', 'set-in-flight']);
|
||||
});
|
||||
45
src/main/runtime/jellyfin-remote-connection-main-deps.ts
Normal file
45
src/main/runtime/jellyfin-remote-connection-main-deps.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import type {
|
||||
EnsureMpvConnectedDeps,
|
||||
LaunchMpvForJellyfinDeps,
|
||||
WaitForMpvConnectedDeps,
|
||||
} from './jellyfin-remote-connection';
|
||||
|
||||
export function createBuildWaitForMpvConnectedMainDepsHandler(deps: WaitForMpvConnectedDeps) {
|
||||
return (): WaitForMpvConnectedDeps => ({
|
||||
getMpvClient: () => deps.getMpvClient(),
|
||||
now: () => deps.now(),
|
||||
sleep: (delayMs: number) => deps.sleep(delayMs),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler(
|
||||
deps: LaunchMpvForJellyfinDeps,
|
||||
) {
|
||||
return (): LaunchMpvForJellyfinDeps => ({
|
||||
getSocketPath: () => deps.getSocketPath(),
|
||||
platform: deps.platform,
|
||||
execPath: deps.execPath,
|
||||
defaultMpvLogPath: deps.defaultMpvLogPath,
|
||||
defaultMpvArgs: deps.defaultMpvArgs,
|
||||
removeSocketPath: (socketPath: string) => deps.removeSocketPath(socketPath),
|
||||
spawnMpv: (args: string[]) => deps.spawnMpv(args),
|
||||
logWarn: (message: string, error: unknown) => deps.logWarn(message, error),
|
||||
logInfo: (message: string) => deps.logInfo(message),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler(
|
||||
deps: EnsureMpvConnectedDeps,
|
||||
) {
|
||||
return (): EnsureMpvConnectedDeps => ({
|
||||
getMpvClient: () => deps.getMpvClient(),
|
||||
setMpvClient: (client) => deps.setMpvClient(client),
|
||||
createMpvClient: () => deps.createMpvClient(),
|
||||
waitForMpvConnected: (timeoutMs: number) => deps.waitForMpvConnected(timeoutMs),
|
||||
launchMpvIdleForJellyfinPlayback: () => deps.launchMpvIdleForJellyfinPlayback(),
|
||||
getAutoLaunchInFlight: () => deps.getAutoLaunchInFlight(),
|
||||
setAutoLaunchInFlight: (promise) => deps.setAutoLaunchInFlight(promise),
|
||||
connectTimeoutMs: deps.connectTimeoutMs,
|
||||
autoLaunchTimeoutMs: deps.autoLaunchTimeoutMs,
|
||||
});
|
||||
}
|
||||
25
src/main/runtime/mpv-jellyfin-defaults-main-deps.test.ts
Normal file
25
src/main/runtime/mpv-jellyfin-defaults-main-deps.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createBuildApplyJellyfinMpvDefaultsMainDepsHandler,
|
||||
createBuildGetDefaultSocketPathMainDepsHandler,
|
||||
} from './mpv-jellyfin-defaults-main-deps';
|
||||
|
||||
test('apply jellyfin mpv defaults main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildApplyJellyfinMpvDefaultsMainDepsHandler({
|
||||
sendMpvCommandRuntime: (_client, command) => calls.push(command.join(':')),
|
||||
jellyfinLangPref: 'ja,jp',
|
||||
})();
|
||||
|
||||
deps.sendMpvCommandRuntime({}, ['set_property', 'aid', 'auto']);
|
||||
assert.equal(deps.jellyfinLangPref, 'ja,jp');
|
||||
assert.deepEqual(calls, ['set_property:aid:auto']);
|
||||
});
|
||||
|
||||
test('get default socket path main deps builder maps platform', () => {
|
||||
const deps = createBuildGetDefaultSocketPathMainDepsHandler({
|
||||
platform: 'darwin',
|
||||
})();
|
||||
assert.equal(deps.platform, 'darwin');
|
||||
});
|
||||
24
src/main/runtime/mpv-jellyfin-defaults-main-deps.ts
Normal file
24
src/main/runtime/mpv-jellyfin-defaults-main-deps.ts
Normal file
@@ -0,0 +1,24 @@
|
||||
import type {
|
||||
createApplyJellyfinMpvDefaultsHandler,
|
||||
createGetDefaultSocketPathHandler,
|
||||
} from './mpv-jellyfin-defaults';
|
||||
|
||||
type ApplyJellyfinMpvDefaultsMainDeps = Parameters<typeof createApplyJellyfinMpvDefaultsHandler>[0];
|
||||
type GetDefaultSocketPathMainDeps = Parameters<typeof createGetDefaultSocketPathHandler>[0];
|
||||
|
||||
export function createBuildApplyJellyfinMpvDefaultsMainDepsHandler(
|
||||
deps: ApplyJellyfinMpvDefaultsMainDeps,
|
||||
) {
|
||||
return (): ApplyJellyfinMpvDefaultsMainDeps => ({
|
||||
sendMpvCommandRuntime: (client, command) => deps.sendMpvCommandRuntime(client, command),
|
||||
jellyfinLangPref: deps.jellyfinLangPref,
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildGetDefaultSocketPathMainDepsHandler(
|
||||
deps: GetDefaultSocketPathMainDeps,
|
||||
) {
|
||||
return (): GetDefaultSocketPathMainDeps => ({
|
||||
platform: deps.platform,
|
||||
});
|
||||
}
|
||||
30
src/main/runtime/overlay-bootstrap-main-deps.test.ts
Normal file
30
src/main/runtime/overlay-bootstrap-main-deps.test.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createBuildOverlayContentMeasurementStoreMainDepsHandler,
|
||||
createBuildOverlayModalRuntimeMainDepsHandler,
|
||||
} from './overlay-bootstrap-main-deps';
|
||||
|
||||
test('overlay content measurement store main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildOverlayContentMeasurementStoreMainDepsHandler({
|
||||
now: () => 42,
|
||||
warn: (message) => calls.push(`warn:${message}`),
|
||||
})();
|
||||
|
||||
assert.equal(deps.now(), 42);
|
||||
deps.warn('bad payload');
|
||||
assert.deepEqual(calls, ['warn:bad payload']);
|
||||
});
|
||||
|
||||
test('overlay modal runtime main deps builder maps window resolvers', () => {
|
||||
const mainWindow = { id: 'main' };
|
||||
const invisibleWindow = { id: 'invisible' };
|
||||
const deps = createBuildOverlayModalRuntimeMainDepsHandler({
|
||||
getMainWindow: () => mainWindow as never,
|
||||
getInvisibleWindow: () => invisibleWindow as never,
|
||||
})();
|
||||
|
||||
assert.equal(deps.getMainWindow(), mainWindow);
|
||||
assert.equal(deps.getInvisibleWindow(), invisibleWindow);
|
||||
});
|
||||
22
src/main/runtime/overlay-bootstrap-main-deps.ts
Normal file
22
src/main/runtime/overlay-bootstrap-main-deps.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import type { OverlayWindowResolver } from '../overlay-runtime';
|
||||
|
||||
type OverlayContentMeasurementStoreMainDeps = {
|
||||
now: () => number;
|
||||
warn: (message: string) => void;
|
||||
};
|
||||
|
||||
export function createBuildOverlayContentMeasurementStoreMainDepsHandler(
|
||||
deps: OverlayContentMeasurementStoreMainDeps,
|
||||
) {
|
||||
return (): OverlayContentMeasurementStoreMainDeps => ({
|
||||
now: () => deps.now(),
|
||||
warn: (message: string) => deps.warn(message),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildOverlayModalRuntimeMainDepsHandler(deps: OverlayWindowResolver) {
|
||||
return (): OverlayWindowResolver => ({
|
||||
getMainWindow: () => deps.getMainWindow(),
|
||||
getInvisibleWindow: () => deps.getInvisibleWindow(),
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createBuildBroadcastRuntimeOptionsChangedMainDepsHandler,
|
||||
createBuildGetRuntimeOptionsStateMainDepsHandler,
|
||||
createBuildOpenRuntimeOptionsPaletteMainDepsHandler,
|
||||
createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler,
|
||||
createBuildSendToActiveOverlayWindowMainDepsHandler,
|
||||
createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler,
|
||||
} from './overlay-runtime-main-actions-main-deps';
|
||||
|
||||
test('get runtime options state main deps builder maps callbacks', () => {
|
||||
const manager = { listOptions: () => [] };
|
||||
const deps = createBuildGetRuntimeOptionsStateMainDepsHandler({
|
||||
getRuntimeOptionsManager: () => manager,
|
||||
})();
|
||||
assert.equal(deps.getRuntimeOptionsManager(), manager);
|
||||
});
|
||||
|
||||
test('restore secondary sub visibility main deps builder maps callbacks', () => {
|
||||
const deps = createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler({
|
||||
getMpvClient: () => ({ connected: true, restorePreviousSecondarySubVisibility: () => {} }),
|
||||
})();
|
||||
assert.equal(deps.getMpvClient()?.connected, true);
|
||||
});
|
||||
|
||||
test('broadcast runtime options changed main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildBroadcastRuntimeOptionsChangedMainDepsHandler({
|
||||
broadcastRuntimeOptionsChangedRuntime: () => calls.push('broadcast-runtime'),
|
||||
getRuntimeOptionsState: () => [],
|
||||
broadcastToOverlayWindows: (channel) => calls.push(channel),
|
||||
})();
|
||||
|
||||
deps.broadcastRuntimeOptionsChangedRuntime(() => [], () => {});
|
||||
deps.broadcastToOverlayWindows('runtime-options:changed');
|
||||
assert.deepEqual(deps.getRuntimeOptionsState(), []);
|
||||
assert.deepEqual(calls, ['broadcast-runtime', 'runtime-options:changed']);
|
||||
});
|
||||
|
||||
test('send to active overlay window main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildSendToActiveOverlayWindowMainDepsHandler({
|
||||
sendToActiveOverlayWindowRuntime: () => {
|
||||
calls.push('send');
|
||||
return true;
|
||||
},
|
||||
})();
|
||||
|
||||
assert.equal(deps.sendToActiveOverlayWindowRuntime('x'), true);
|
||||
assert.deepEqual(calls, ['send']);
|
||||
});
|
||||
|
||||
test('set overlay debug visualization main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler({
|
||||
setOverlayDebugVisualizationEnabledRuntime: () => calls.push('set-runtime'),
|
||||
getCurrentEnabled: () => false,
|
||||
setCurrentEnabled: () => calls.push('set-current'),
|
||||
broadcastToOverlayWindows: () => calls.push('broadcast'),
|
||||
})();
|
||||
|
||||
deps.setOverlayDebugVisualizationEnabledRuntime(false, true, () => {}, () => {});
|
||||
assert.equal(deps.getCurrentEnabled(), false);
|
||||
deps.setCurrentEnabled(true);
|
||||
deps.broadcastToOverlayWindows('overlay:debug');
|
||||
assert.deepEqual(calls, ['set-runtime', 'set-current', 'broadcast']);
|
||||
});
|
||||
|
||||
test('open runtime options palette main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildOpenRuntimeOptionsPaletteMainDepsHandler({
|
||||
openRuntimeOptionsPaletteRuntime: () => calls.push('open'),
|
||||
})();
|
||||
|
||||
deps.openRuntimeOptionsPaletteRuntime();
|
||||
assert.deepEqual(calls, ['open']);
|
||||
});
|
||||
89
src/main/runtime/overlay-runtime-main-actions-main-deps.ts
Normal file
89
src/main/runtime/overlay-runtime-main-actions-main-deps.ts
Normal file
@@ -0,0 +1,89 @@
|
||||
import {
|
||||
createBroadcastRuntimeOptionsChangedHandler,
|
||||
createGetRuntimeOptionsStateHandler,
|
||||
createOpenRuntimeOptionsPaletteHandler,
|
||||
createRestorePreviousSecondarySubVisibilityHandler,
|
||||
createSendToActiveOverlayWindowHandler,
|
||||
createSetOverlayDebugVisualizationEnabledHandler,
|
||||
} from './overlay-runtime-main-actions';
|
||||
|
||||
type GetRuntimeOptionsStateMainDeps = Parameters<typeof createGetRuntimeOptionsStateHandler>[0];
|
||||
type RestorePreviousSecondarySubVisibilityMainDeps = Parameters<
|
||||
typeof createRestorePreviousSecondarySubVisibilityHandler
|
||||
>[0];
|
||||
type BroadcastRuntimeOptionsChangedMainDeps = Parameters<
|
||||
typeof createBroadcastRuntimeOptionsChangedHandler
|
||||
>[0];
|
||||
type SendToActiveOverlayWindowMainDeps = Parameters<typeof createSendToActiveOverlayWindowHandler>[0];
|
||||
type SetOverlayDebugVisualizationEnabledMainDeps = Parameters<
|
||||
typeof createSetOverlayDebugVisualizationEnabledHandler
|
||||
>[0];
|
||||
type OpenRuntimeOptionsPaletteMainDeps = Parameters<typeof createOpenRuntimeOptionsPaletteHandler>[0];
|
||||
|
||||
export function createBuildGetRuntimeOptionsStateMainDepsHandler(
|
||||
deps: GetRuntimeOptionsStateMainDeps,
|
||||
) {
|
||||
return (): GetRuntimeOptionsStateMainDeps => ({
|
||||
getRuntimeOptionsManager: () => deps.getRuntimeOptionsManager(),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler(
|
||||
deps: RestorePreviousSecondarySubVisibilityMainDeps,
|
||||
) {
|
||||
return (): RestorePreviousSecondarySubVisibilityMainDeps => ({
|
||||
getMpvClient: () => deps.getMpvClient(),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildBroadcastRuntimeOptionsChangedMainDepsHandler(
|
||||
deps: BroadcastRuntimeOptionsChangedMainDeps,
|
||||
) {
|
||||
return (): BroadcastRuntimeOptionsChangedMainDeps => ({
|
||||
broadcastRuntimeOptionsChangedRuntime: (getRuntimeOptionsState, broadcastToOverlayWindows) =>
|
||||
deps.broadcastRuntimeOptionsChangedRuntime(getRuntimeOptionsState, broadcastToOverlayWindows),
|
||||
getRuntimeOptionsState: () => deps.getRuntimeOptionsState(),
|
||||
broadcastToOverlayWindows: (channel: string, ...args: unknown[]) =>
|
||||
deps.broadcastToOverlayWindows(channel, ...args),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildSendToActiveOverlayWindowMainDepsHandler(
|
||||
deps: SendToActiveOverlayWindowMainDeps,
|
||||
) {
|
||||
return (): SendToActiveOverlayWindowMainDeps => ({
|
||||
sendToActiveOverlayWindowRuntime: (channel, payload, runtimeOptions) =>
|
||||
deps.sendToActiveOverlayWindowRuntime(channel, payload, runtimeOptions),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler(
|
||||
deps: SetOverlayDebugVisualizationEnabledMainDeps,
|
||||
) {
|
||||
return (): SetOverlayDebugVisualizationEnabledMainDeps => ({
|
||||
setOverlayDebugVisualizationEnabledRuntime: (
|
||||
currentEnabled,
|
||||
nextEnabled,
|
||||
setCurrentEnabled,
|
||||
broadcastToOverlayWindows,
|
||||
) =>
|
||||
deps.setOverlayDebugVisualizationEnabledRuntime(
|
||||
currentEnabled,
|
||||
nextEnabled,
|
||||
setCurrentEnabled,
|
||||
broadcastToOverlayWindows,
|
||||
),
|
||||
getCurrentEnabled: () => deps.getCurrentEnabled(),
|
||||
setCurrentEnabled: (enabled: boolean) => deps.setCurrentEnabled(enabled),
|
||||
broadcastToOverlayWindows: (channel: string, ...args: unknown[]) =>
|
||||
deps.broadcastToOverlayWindows(channel, ...args),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildOpenRuntimeOptionsPaletteMainDepsHandler(
|
||||
deps: OpenRuntimeOptionsPaletteMainDeps,
|
||||
) {
|
||||
return (): OpenRuntimeOptionsPaletteMainDeps => ({
|
||||
openRuntimeOptionsPaletteRuntime: () => deps.openRuntimeOptionsPaletteRuntime(),
|
||||
});
|
||||
}
|
||||
99
src/main/runtime/runtime-bootstrap-main-deps.test.ts
Normal file
99
src/main/runtime/runtime-bootstrap-main-deps.test.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import assert from 'node:assert/strict';
|
||||
import test from 'node:test';
|
||||
import {
|
||||
createBuildAnilistStateRuntimeMainDepsHandler,
|
||||
createBuildConfigDerivedRuntimeMainDepsHandler,
|
||||
createBuildImmersionMediaRuntimeMainDepsHandler,
|
||||
createBuildMainSubsyncRuntimeMainDepsHandler,
|
||||
} from './runtime-bootstrap-main-deps';
|
||||
|
||||
test('immersion media runtime main deps builder maps callbacks', async () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildImmersionMediaRuntimeMainDepsHandler({
|
||||
getResolvedConfig: () => ({ immersionTracking: { dbPath: '/tmp/db.sqlite' } }),
|
||||
defaultImmersionDbPath: '/tmp/default.sqlite',
|
||||
getTracker: () => ({ handleMediaChange: () => calls.push('track') }),
|
||||
getMpvClient: () => ({ connected: true }),
|
||||
getCurrentMediaPath: () => '/tmp/media.mkv',
|
||||
getCurrentMediaTitle: () => 'Title',
|
||||
sleep: async () => {
|
||||
calls.push('sleep');
|
||||
},
|
||||
seedWaitMs: 25,
|
||||
seedAttempts: 3,
|
||||
logDebug: (message) => calls.push(`debug:${message}`),
|
||||
logInfo: (message) => calls.push(`info:${message}`),
|
||||
})();
|
||||
|
||||
assert.equal(deps.defaultImmersionDbPath, '/tmp/default.sqlite');
|
||||
assert.deepEqual(deps.getResolvedConfig(), { immersionTracking: { dbPath: '/tmp/db.sqlite' } });
|
||||
assert.deepEqual(deps.getMpvClient(), { connected: true });
|
||||
assert.equal(deps.getCurrentMediaPath(), '/tmp/media.mkv');
|
||||
assert.equal(deps.getCurrentMediaTitle(), 'Title');
|
||||
assert.equal(deps.seedWaitMs, 25);
|
||||
assert.equal(deps.seedAttempts, 3);
|
||||
await deps.sleep?.(1);
|
||||
deps.logDebug('a');
|
||||
deps.logInfo('b');
|
||||
assert.deepEqual(calls, ['sleep', 'debug:a', 'info:b']);
|
||||
});
|
||||
|
||||
test('anilist state runtime main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildAnilistStateRuntimeMainDepsHandler({
|
||||
getClientSecretState: () => ({ status: 'resolved' } as never),
|
||||
setClientSecretState: () => calls.push('set-client'),
|
||||
getRetryQueueState: () => ({ pending: 1 } as never),
|
||||
setRetryQueueState: () => calls.push('set-queue'),
|
||||
getUpdateQueueSnapshot: () => ({ pending: 2 } as never),
|
||||
clearStoredToken: () => calls.push('clear-stored'),
|
||||
clearCachedAccessToken: () => calls.push('clear-cached'),
|
||||
})();
|
||||
|
||||
assert.deepEqual(deps.getClientSecretState(), { status: 'resolved' });
|
||||
assert.deepEqual(deps.getRetryQueueState(), { pending: 1 });
|
||||
assert.deepEqual(deps.getUpdateQueueSnapshot(), { pending: 2 });
|
||||
deps.setClientSecretState({} as never);
|
||||
deps.setRetryQueueState({} as never);
|
||||
deps.clearStoredToken();
|
||||
deps.clearCachedAccessToken();
|
||||
assert.deepEqual(calls, ['set-client', 'set-queue', 'clear-stored', 'clear-cached']);
|
||||
});
|
||||
|
||||
test('config derived runtime main deps builder maps callbacks', () => {
|
||||
const deps = createBuildConfigDerivedRuntimeMainDepsHandler({
|
||||
getResolvedConfig: () => ({ jimaku: {} } as never),
|
||||
getRuntimeOptionsManager: () => null,
|
||||
platform: 'darwin',
|
||||
defaultJimakuLanguagePreference: 'ja',
|
||||
defaultJimakuMaxEntryResults: 20,
|
||||
defaultJimakuApiBaseUrl: 'https://api.example.com',
|
||||
})();
|
||||
|
||||
assert.deepEqual(deps.getResolvedConfig(), { jimaku: {} });
|
||||
assert.equal(deps.getRuntimeOptionsManager(), null);
|
||||
assert.equal(deps.platform, 'darwin');
|
||||
assert.equal(deps.defaultJimakuLanguagePreference, 'ja');
|
||||
assert.equal(deps.defaultJimakuMaxEntryResults, 20);
|
||||
assert.equal(deps.defaultJimakuApiBaseUrl, 'https://api.example.com');
|
||||
});
|
||||
|
||||
test('main subsync runtime main deps builder maps callbacks', () => {
|
||||
const calls: string[] = [];
|
||||
const deps = createBuildMainSubsyncRuntimeMainDepsHandler({
|
||||
getMpvClient: () => ({ connected: true }) as never,
|
||||
getResolvedConfig: () => ({ subsync: {} } as never),
|
||||
getSubsyncInProgress: () => true,
|
||||
setSubsyncInProgress: () => calls.push('set-progress'),
|
||||
showMpvOsd: (text) => calls.push(`osd:${text}`),
|
||||
openManualPicker: () => calls.push('open-picker'),
|
||||
})();
|
||||
|
||||
assert.deepEqual(deps.getMpvClient(), { connected: true });
|
||||
assert.deepEqual(deps.getResolvedConfig(), { subsync: {} });
|
||||
assert.equal(deps.getSubsyncInProgress(), true);
|
||||
deps.setSubsyncInProgress(false);
|
||||
deps.showMpvOsd('ready');
|
||||
deps.openManualPicker({} as never);
|
||||
assert.deepEqual(calls, ['set-progress', 'osd:ready', 'open-picker']);
|
||||
});
|
||||
54
src/main/runtime/runtime-bootstrap-main-deps.ts
Normal file
54
src/main/runtime/runtime-bootstrap-main-deps.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import type { AnilistStateRuntimeDeps } from './anilist-state';
|
||||
import type { ConfigDerivedRuntimeDeps } from './config-derived';
|
||||
import type { ImmersionMediaRuntimeDeps } from './immersion-media';
|
||||
import type { MainSubsyncRuntimeDeps } from './subsync-runtime';
|
||||
|
||||
export function createBuildImmersionMediaRuntimeMainDepsHandler(deps: ImmersionMediaRuntimeDeps) {
|
||||
return (): ImmersionMediaRuntimeDeps => ({
|
||||
getResolvedConfig: () => deps.getResolvedConfig(),
|
||||
defaultImmersionDbPath: deps.defaultImmersionDbPath,
|
||||
getTracker: () => deps.getTracker(),
|
||||
getMpvClient: () => deps.getMpvClient(),
|
||||
getCurrentMediaPath: () => deps.getCurrentMediaPath(),
|
||||
getCurrentMediaTitle: () => deps.getCurrentMediaTitle(),
|
||||
sleep: deps.sleep,
|
||||
seedWaitMs: deps.seedWaitMs,
|
||||
seedAttempts: deps.seedAttempts,
|
||||
logDebug: (message: string) => deps.logDebug(message),
|
||||
logInfo: (message: string) => deps.logInfo(message),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildAnilistStateRuntimeMainDepsHandler(deps: AnilistStateRuntimeDeps) {
|
||||
return (): AnilistStateRuntimeDeps => ({
|
||||
getClientSecretState: () => deps.getClientSecretState(),
|
||||
setClientSecretState: (next) => deps.setClientSecretState(next),
|
||||
getRetryQueueState: () => deps.getRetryQueueState(),
|
||||
setRetryQueueState: (next) => deps.setRetryQueueState(next),
|
||||
getUpdateQueueSnapshot: () => deps.getUpdateQueueSnapshot(),
|
||||
clearStoredToken: () => deps.clearStoredToken(),
|
||||
clearCachedAccessToken: () => deps.clearCachedAccessToken(),
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildConfigDerivedRuntimeMainDepsHandler(deps: ConfigDerivedRuntimeDeps) {
|
||||
return (): ConfigDerivedRuntimeDeps => ({
|
||||
getResolvedConfig: () => deps.getResolvedConfig(),
|
||||
getRuntimeOptionsManager: () => deps.getRuntimeOptionsManager(),
|
||||
platform: deps.platform,
|
||||
defaultJimakuLanguagePreference: deps.defaultJimakuLanguagePreference,
|
||||
defaultJimakuMaxEntryResults: deps.defaultJimakuMaxEntryResults,
|
||||
defaultJimakuApiBaseUrl: deps.defaultJimakuApiBaseUrl,
|
||||
});
|
||||
}
|
||||
|
||||
export function createBuildMainSubsyncRuntimeMainDepsHandler(deps: MainSubsyncRuntimeDeps) {
|
||||
return (): MainSubsyncRuntimeDeps => ({
|
||||
getMpvClient: () => deps.getMpvClient(),
|
||||
getResolvedConfig: () => deps.getResolvedConfig(),
|
||||
getSubsyncInProgress: () => deps.getSubsyncInProgress(),
|
||||
setSubsyncInProgress: (inProgress: boolean) => deps.setSubsyncInProgress(inProgress),
|
||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
||||
openManualPicker: (payload) => deps.openManualPicker(payload),
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user