mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-11-11 04:46:07 -08:00
refactor(main): drop pass-through main-deps builders (#306)
* refactor(main): drop mining/anki main-deps builders * refactor(anilist): drop main-deps builders * refactor(jellyfin): drop main-deps builders * refactor(overlay): drop overlay and shortcut main-deps builders * refactor(main): drop ipc, tray, and osd main-deps builders * refactor(startup): drop startup main-deps builders * test(scripts): ignore stray local requests in AUR download test Also apply prettier to launcher/mpv.test.ts so format:check:src passes. * fix(shortcuts): forward overlay numeric selection hooks through the composer composeShortcutRuntimes only passed the digit callbacks, so the visible-overlay selection added in #78 never ran from the multi-copy/mine-sentence shortcuts. * fix(stats): skip mpv auto-connect when stats starts the immersion tracker The immersion-startup main-deps builder never forwarded shouldAutoConnectMpv, so background stats and stats CLI startup always connected to mpv. Drop the builder and pass the deps straight to the handler. * build(deps): bump follow-redirects override to 1.16.2 Resolves GHSA-mrwp-f3q8-3g9p (high), which fails the quality-gate bun audit --audit-level high step. * test(subtitles): cover the null-tokenization settle path in prefetch test The mock ignored the value the test resolved, so the null case never ran. * test(e2e): surface mpv crashes and install current mpv on macOS CI The harness IPC client never handled socket close, so a crashed mpv left commands pending until the 120s test timeout with an empty mpv.log. Reject pending commands on close, write mpv's own log via --log-file, and refresh Homebrew on macOS CI so the installed mpv build no longer depends on the runner image. * test(e2e): render mpv through cocoa-cb OpenGL on macOS mpv 0.41.0_12 with libplacebo 7.387.0 segfaults in gpu-next's MoltenVK path on GitHub's paravirtual macOS GPU on the first frame, so the E2E session never started. * test(e2e): name mpv-stdio.log in the mpv close diagnostic
This commit is contained in:
1 parent
0129e03c0f
commit
2a0e931325
84 files changed
+719
-2754
No files matched your search
@@ -56,7 +56,12 @@ jobs:
|
|||||||
|
|
||||||
- name: Install mpv and ffmpeg (macOS)
|
- name: Install mpv and ffmpeg (macOS)
|
||||||
if: runner.os == 'macOS'
|
if: runner.os == 'macOS'
|
||||||
run: brew install mpv ffmpeg
|
run: |
|
||||||
|
# Runner images bake in different Homebrew metadata, so without an update the
|
||||||
|
# installed mpv build depends on which image the job lands on.
|
||||||
|
brew update
|
||||||
|
brew install mpv ffmpeg
|
||||||
|
mpv --version
|
||||||
|
|
||||||
- name: Install mpv and ffmpeg (Windows)
|
- name: Install mpv and ffmpeg (Windows)
|
||||||
if: runner.os == 'Windows'
|
if: runner.os == 'Windows'
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
"brace-expansion": "5.0.11",
|
"brace-expansion": "5.0.11",
|
||||||
"electron-builder-squirrel-windows": "26.16.1",
|
"electron-builder-squirrel-windows": "26.16.1",
|
||||||
"fast-uri": "3.1.7",
|
"fast-uri": "3.1.7",
|
||||||
"follow-redirects": "1.16.1",
|
"follow-redirects": "1.16.2",
|
||||||
"form-data": "4.0.6",
|
"form-data": "4.0.6",
|
||||||
"ip-address": "10.2.0",
|
"ip-address": "10.2.0",
|
||||||
"js-yaml": "4.3.2",
|
"js-yaml": "4.3.2",
|
||||||
@@ -351,7 +351,7 @@
|
|||||||
|
|
||||||
"filelist": ["filelist@1.0.6", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA=="],
|
"filelist": ["filelist@1.0.6", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA=="],
|
||||||
|
|
||||||
"follow-redirects": ["follow-redirects@1.16.1", "", { "peerDependencies": { "debug": "*" }, "optionalPeers": ["debug"] }, "sha512-FNvFGzoMLWmE6Yj9spb/zjd7yiNCHiAW9/Tg9CXrQ8wuu32HtlJOwWO11OJafl5FfY3DxTdQ0vj42zU1kvv5jg=="],
|
"follow-redirects": ["follow-redirects@1.16.2", "", {}, "sha512-/kVP2U8z596Ia0gwFrwyIeo74ta5aVmSeU1FfAUMAmcEP5EP7zydmag3SLiN64NaRKef3lxsq7i/g7ltJQDGow=="],
|
||||||
|
|
||||||
"form-data": ["form-data@4.0.6", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.4", "mime-types": "^2.1.35" } }, "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ=="],
|
"form-data": ["form-data@4.0.6", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "es-set-tostringtag": "^2.1.0", "hasown": "^2.0.4", "mime-types": "^2.1.35" } }, "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ=="],
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ Renderer, launcher, plugin, and stats each keep their own local layering and sho
|
|||||||
## Rules
|
## Rules
|
||||||
|
|
||||||
- Keep `src/main.ts` thin; wire, do not implement.
|
- Keep `src/main.ts` thin; wire, do not implement.
|
||||||
|
- Pass deps straight to a handler factory (`createXHandler({...})`). Do not add
|
||||||
|
`*-main-deps.ts` builders that only re-wrap deps; existing ones are being removed.
|
||||||
- Prefer injecting dependencies from `src/main/` instead of reaching outward from core services.
|
- Prefer injecting dependencies from `src/main/` instead of reaching outward from core services.
|
||||||
- Keep side effects explicit and close to composition boundaries.
|
- Keep side effects explicit and close to composition boundaries.
|
||||||
- Put reusable business logic in focused services, not in top-level lifecycle files.
|
- Put reusable business logic in focused services, not in top-level lifecycle files.
|
||||||
|
|||||||
@@ -125,7 +125,8 @@ whenever the behavior does not depend on a specific compositor.
|
|||||||
- Scenarios live in `e2e/*.e2e.test.ts` and share one session per file through
|
- Scenarios live in `e2e/*.e2e.test.ts` and share one session per file through
|
||||||
`startE2eSession()`. Pass `config` to override settings for a scenario file.
|
`startE2eSession()`. Pass `config` to override settings for a scenario file.
|
||||||
- On a failed startup the temp dir is kept and its path is in the error. Set
|
- On a failed startup the temp dir is kept and its path is in the error. Set
|
||||||
`SUBMINER_E2E_KEEP=1` to keep it after any run (`app-stdio.log`, `app.log`, `mpv.log`).
|
`SUBMINER_E2E_KEEP=1` to keep it after any run (`app-stdio.log`, `app.log`, `mpv.log`,
|
||||||
|
`mpv-stdio.log`).
|
||||||
|
|
||||||
For exploratory checks, keep one session up and poke at it:
|
For exploratory checks, keep one session up and poke at it:
|
||||||
|
|
||||||
|
|||||||
+39
-4
@@ -15,25 +15,38 @@ export type MpvClient = {
|
|||||||
|
|
||||||
type MpvReply = { request_id?: number; error?: string; data?: unknown };
|
type MpvReply = { request_id?: number; error?: string; data?: unknown };
|
||||||
|
|
||||||
|
function videoOutputArgs(display: E2eDisplay): string[] {
|
||||||
|
// Xvfb has no GPU; the software X11 output always works there.
|
||||||
|
if (display.kind === 'xvfb') return ['--vo=x11'];
|
||||||
|
// gpu-next's Vulkan path (libplacebo over MoltenVK) segfaults on the first frame
|
||||||
|
// on GitHub's paravirtual macOS GPU with libplacebo 7.387. `--vo=libmpv` is mpv's
|
||||||
|
// cocoa-cb OpenGL output, which avoids it and still opens the window the overlay tracks.
|
||||||
|
if (process.platform === 'darwin') return ['--vo=libmpv'];
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
export async function startMpv(options: {
|
export async function startMpv(options: {
|
||||||
socketPath: string;
|
socketPath: string;
|
||||||
mediaPath: string;
|
mediaPath: string;
|
||||||
subtitlePath: string;
|
subtitlePath: string;
|
||||||
|
/** mpv's own verbose log (`--log-file`); `--no-terminal` silences its console output. */
|
||||||
logPath: string;
|
logPath: string;
|
||||||
|
/** Process stdout/stderr, which still catches crash output from mpv's libraries. */
|
||||||
|
stdioLogPath: string;
|
||||||
display: E2eDisplay;
|
display: E2eDisplay;
|
||||||
}): Promise<ChildProcess> {
|
}): Promise<ChildProcess> {
|
||||||
const log = fs.openSync(options.logPath, 'w');
|
const log = fs.openSync(options.stdioLogPath, 'w');
|
||||||
const child = spawn(
|
const child = spawn(
|
||||||
'mpv',
|
'mpv',
|
||||||
[
|
[
|
||||||
'--no-config',
|
'--no-config',
|
||||||
'--no-terminal',
|
'--no-terminal',
|
||||||
|
`--log-file=${options.logPath}`,
|
||||||
'--pause',
|
'--pause',
|
||||||
'--keep-open=yes',
|
'--keep-open=yes',
|
||||||
'--ao=null',
|
'--ao=null',
|
||||||
`--geometry=${E2E_SCREEN.width}x${E2E_SCREEN.height}+0+0`,
|
`--geometry=${E2E_SCREEN.width}x${E2E_SCREEN.height}+0+0`,
|
||||||
// Xvfb has no GPU; the software X11 output always works there.
|
...videoOutputArgs(options.display),
|
||||||
...(options.display.kind === 'xvfb' ? ['--vo=x11'] : []),
|
|
||||||
`--input-ipc-server=${options.socketPath}`,
|
`--input-ipc-server=${options.socketPath}`,
|
||||||
`--sub-file=${options.subtitlePath}`,
|
`--sub-file=${options.subtitlePath}`,
|
||||||
options.mediaPath,
|
options.mediaPath,
|
||||||
@@ -58,13 +71,31 @@ function tryConnect(socketPath: string): Promise<net.Socket | null> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function connectMpv(socketPath: string): Promise<MpvClient> {
|
/**
|
||||||
|
* Connects to mpv's JSON IPC socket. Once the socket closes (mpv exited or
|
||||||
|
* crashed), pending and later commands reject instead of hanging until the test
|
||||||
|
* timeout; `describeClose` adds context such as mpv's exit status.
|
||||||
|
*/
|
||||||
|
export async function connectMpv(
|
||||||
|
socketPath: string,
|
||||||
|
describeClose: () => string = () => 'mpv IPC connection closed',
|
||||||
|
): Promise<MpvClient> {
|
||||||
const socket = await waitUntil(() => tryConnect(socketPath), {
|
const socket = await waitUntil(() => tryConnect(socketPath), {
|
||||||
description: `mpv IPC socket ${socketPath}`,
|
description: `mpv IPC socket ${socketPath}`,
|
||||||
});
|
});
|
||||||
const pending = new Map<number, (reply: MpvReply) => void>();
|
const pending = new Map<number, (reply: MpvReply) => void>();
|
||||||
let nextRequestId = 1;
|
let nextRequestId = 1;
|
||||||
let buffer = '';
|
let buffer = '';
|
||||||
|
let closedError: Error | null = null;
|
||||||
|
|
||||||
|
const failPending = () => {
|
||||||
|
closedError ??= new Error(describeClose());
|
||||||
|
for (const settle of pending.values()) settle({ error: closedError.message });
|
||||||
|
pending.clear();
|
||||||
|
};
|
||||||
|
socket.on('close', failPending);
|
||||||
|
// 'close' always follows 'error'; listening here keeps the error from being thrown.
|
||||||
|
socket.on('error', () => {});
|
||||||
|
|
||||||
socket.setEncoding('utf8');
|
socket.setEncoding('utf8');
|
||||||
socket.on('data', (chunk: string) => {
|
socket.on('data', (chunk: string) => {
|
||||||
@@ -83,6 +114,10 @@ export async function connectMpv(socketPath: string): Promise<MpvClient> {
|
|||||||
return {
|
return {
|
||||||
command: (...args) =>
|
command: (...args) =>
|
||||||
new Promise((resolve, reject) => {
|
new Promise((resolve, reject) => {
|
||||||
|
if (closedError) {
|
||||||
|
reject(new Error(`mpv ${JSON.stringify(args)} failed: ${closedError.message}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
const requestId = nextRequestId++;
|
const requestId = nextRequestId++;
|
||||||
pending.set(requestId, (reply) => {
|
pending.set(requestId, (reply) => {
|
||||||
if (reply.error === 'success') resolve(reply.data);
|
if (reply.error === 'success') resolve(reply.data);
|
||||||
|
|||||||
+12
-2
@@ -265,15 +265,25 @@ export async function startE2eSession(options: E2eSessionOptions = {}): Promise<
|
|||||||
settings.close();
|
settings.close();
|
||||||
await stopProcess(seeder.child);
|
await stopProcess(seeder.child);
|
||||||
|
|
||||||
|
const mpvLogPath = path.join(root, 'mpv.log');
|
||||||
|
const mpvStdioLogPath = path.join(root, 'mpv-stdio.log');
|
||||||
const mpvProcess = await startMpv({
|
const mpvProcess = await startMpv({
|
||||||
socketPath: mpvSocketPath,
|
socketPath: mpvSocketPath,
|
||||||
mediaPath,
|
mediaPath,
|
||||||
subtitlePath,
|
subtitlePath,
|
||||||
logPath: path.join(root, 'mpv.log'),
|
logPath: mpvLogPath,
|
||||||
|
stdioLogPath: mpvStdioLogPath,
|
||||||
display,
|
display,
|
||||||
});
|
});
|
||||||
teardown.push(() => stopProcess(mpvProcess));
|
teardown.push(() => stopProcess(mpvProcess));
|
||||||
const mpv = await connectMpv(mpvSocketPath);
|
const mpv = await connectMpv(mpvSocketPath, () => {
|
||||||
|
const { exitCode, signalCode } = mpvProcess;
|
||||||
|
const status =
|
||||||
|
exitCode === null && signalCode === null
|
||||||
|
? 'mpv IPC connection closed'
|
||||||
|
: `mpv exited (code ${String(exitCode)}, signal ${String(signalCode)})`;
|
||||||
|
return `${status}; see ${mpvLogPath} and ${mpvStdioLogPath}`;
|
||||||
|
});
|
||||||
teardown.push(mpv.close);
|
teardown.push(mpv.close);
|
||||||
|
|
||||||
const app = await launchApp(['--start']);
|
const app = await launchApp(['--start']);
|
||||||
|
|||||||
+22
-25
@@ -172,33 +172,30 @@ test('runAppCommandCaptureOutput strips ELECTRON_RUN_AS_NODE from app child env'
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test(
|
test('runAppCommandCaptureOutput transports Linux AppImage args through environment', async () => {
|
||||||
'runAppCommandCaptureOutput transports Linux AppImage args through environment',
|
// Bun's node:test shim ignores the `skip` option, so gate the platform here.
|
||||||
async () => {
|
if (process.platform !== 'linux') return;
|
||||||
// Bun's node:test shim ignores the `skip` option, so gate the platform here.
|
await withTempCase(({ dir }) => {
|
||||||
if (process.platform !== 'linux') return;
|
const appPath = writeFakeApp(
|
||||||
await withTempCase(({ dir }) => {
|
dir,
|
||||||
const appPath = writeFakeApp(
|
[
|
||||||
dir,
|
'printf "args:%s\\n" "$*"',
|
||||||
[
|
'printf "argc:%s\\n" "$SUBMINER_APP_ARGC"',
|
||||||
'printf "args:%s\\n" "$*"',
|
'printf "arg0:%s\\n" "$SUBMINER_APP_ARG_0"',
|
||||||
'printf "argc:%s\\n" "$SUBMINER_APP_ARGC"',
|
'printf "arg1:%s\\n" "$SUBMINER_APP_ARG_1"',
|
||||||
'printf "arg0:%s\\n" "$SUBMINER_APP_ARG_0"',
|
],
|
||||||
'printf "arg1:%s\\n" "$SUBMINER_APP_ARG_1"',
|
'SubMiner.AppImage',
|
||||||
],
|
);
|
||||||
'SubMiner.AppImage',
|
|
||||||
);
|
|
||||||
|
|
||||||
const result = runAppCommandCaptureOutput(appPath, ['--app-ping', '--socket']);
|
const result = runAppCommandCaptureOutput(appPath, ['--app-ping', '--socket']);
|
||||||
|
|
||||||
assert.equal(result.status, 0);
|
assert.equal(result.status, 0);
|
||||||
assert.match(result.stdout, /^args:\n/m);
|
assert.match(result.stdout, /^args:\n/m);
|
||||||
assert.match(result.stdout, /^argc:2\n/m);
|
assert.match(result.stdout, /^argc:2\n/m);
|
||||||
assert.match(result.stdout, /^arg0:--app-ping\n/m);
|
assert.match(result.stdout, /^arg0:--app-ping\n/m);
|
||||||
assert.match(result.stdout, /^arg1:--socket\n/m);
|
assert.match(result.stdout, /^arg1:--socket\n/m);
|
||||||
});
|
});
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
test('runAppCommandCaptureOutput runs Linux AppImage sync in Node-only mode', async () => {
|
test('runAppCommandCaptureOutput runs Linux AppImage sync in Node-only mode', async () => {
|
||||||
await withTempCase(({ dir }) => {
|
await withTempCase(({ dir }) => {
|
||||||
|
|||||||
+1
-1
@@ -93,7 +93,7 @@
|
|||||||
"brace-expansion": "5.0.11",
|
"brace-expansion": "5.0.11",
|
||||||
"electron-builder-squirrel-windows": "26.16.1",
|
"electron-builder-squirrel-windows": "26.16.1",
|
||||||
"fast-uri": "3.1.7",
|
"fast-uri": "3.1.7",
|
||||||
"follow-redirects": "1.16.1",
|
"follow-redirects": "1.16.2",
|
||||||
"form-data": "4.0.6",
|
"form-data": "4.0.6",
|
||||||
"ip-address": "10.2.0",
|
"ip-address": "10.2.0",
|
||||||
"js-yaml": "4.3.2",
|
"js-yaml": "4.3.2",
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ test.each([false, true])(
|
|||||||
port: 0,
|
port: 0,
|
||||||
fetch(request) {
|
fetch(request) {
|
||||||
const pathname = new URL(request.url).pathname;
|
const pathname = new URL(request.url).pathname;
|
||||||
|
// Ignore stray local probes of the ephemeral port; only count the script's downloads.
|
||||||
|
if (!pathname.startsWith('/ksyasuda/SubMiner/releases/download/')) {
|
||||||
|
return new Response('not found', { status: 404 });
|
||||||
|
}
|
||||||
requests.push(pathname);
|
requests.push(pathname);
|
||||||
if (unavailable || requests.length === 1) return new Response('try again', { status: 503 });
|
if (unavailable || requests.length === 1) return new Response('try again', { status: 503 });
|
||||||
const name = pathname.split('/').at(-1);
|
const name = pathname.split('/').at(-1);
|
||||||
|
|||||||
+234
-370
@@ -155,7 +155,6 @@ import {
|
|||||||
buildAnilistSetupUrl,
|
buildAnilistSetupUrl,
|
||||||
consumeAnilistSetupCallbackUrl,
|
consumeAnilistSetupCallbackUrl,
|
||||||
createAnilistStateRuntime,
|
createAnilistStateRuntime,
|
||||||
createBuildOpenAnilistSetupWindowMainDepsHandler,
|
|
||||||
createMaybeFocusExistingAnilistSetupWindowHandler,
|
createMaybeFocusExistingAnilistSetupWindowHandler,
|
||||||
createOpenAnilistSetupWindowHandler,
|
createOpenAnilistSetupWindowHandler,
|
||||||
findAnilistSetupDeepLinkArgvUrl,
|
findAnilistSetupDeepLinkArgvUrl,
|
||||||
@@ -168,8 +167,6 @@ import { DEFAULT_MIN_WATCH_RATIO } from './shared/watch-threshold';
|
|||||||
import { shouldShowTexthookerTrayEntry } from './main/runtime/tray-main-actions';
|
import { shouldShowTexthookerTrayEntry } from './main/runtime/tray-main-actions';
|
||||||
import {
|
import {
|
||||||
createApplyJellyfinMpvDefaultsHandler,
|
createApplyJellyfinMpvDefaultsHandler,
|
||||||
createBuildApplyJellyfinMpvDefaultsMainDepsHandler,
|
|
||||||
createBuildGetDefaultSocketPathMainDepsHandler,
|
|
||||||
createGetDefaultSocketPathHandler,
|
createGetDefaultSocketPathHandler,
|
||||||
buildJellyfinSetupFormHtml,
|
buildJellyfinSetupFormHtml,
|
||||||
parseJellyfinSetupSubmissionUrl,
|
parseJellyfinSetupSubmissionUrl,
|
||||||
@@ -184,22 +181,7 @@ import {
|
|||||||
createBuildConfigHotReloadRuntimeMainDepsHandler,
|
createBuildConfigHotReloadRuntimeMainDepsHandler,
|
||||||
createBuildWatchConfigPathMainDepsHandler,
|
createBuildWatchConfigPathMainDepsHandler,
|
||||||
createWatchConfigPathHandler,
|
createWatchConfigPathHandler,
|
||||||
createBuildOverlayContentMeasurementStoreMainDepsHandler,
|
|
||||||
createBuildOverlayModalRuntimeMainDepsHandler,
|
|
||||||
createBuildAppendClipboardVideoToQueueMainDepsHandler,
|
|
||||||
createBuildHandleOverlayModalClosedMainDepsHandler,
|
|
||||||
createBuildLoadSubtitlePositionMainDepsHandler,
|
|
||||||
createBuildSaveSubtitlePositionMainDepsHandler,
|
|
||||||
createBuildFieldGroupingOverlayMainDepsHandler,
|
|
||||||
createBuildGetFieldGroupingResolverMainDepsHandler,
|
|
||||||
createBuildSetFieldGroupingResolverMainDepsHandler,
|
|
||||||
createBuildOverlayVisibilityRuntimeMainDepsHandler,
|
createBuildOverlayVisibilityRuntimeMainDepsHandler,
|
||||||
createBuildBroadcastRuntimeOptionsChangedMainDepsHandler,
|
|
||||||
createBuildGetRuntimeOptionsStateMainDepsHandler,
|
|
||||||
createBuildOpenRuntimeOptionsPaletteMainDepsHandler,
|
|
||||||
createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler,
|
|
||||||
createBuildSendToActiveOverlayWindowMainDepsHandler,
|
|
||||||
createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler,
|
|
||||||
createTrayRuntimeHandlers,
|
createTrayRuntimeHandlers,
|
||||||
createOverlayVisibilityRuntime,
|
createOverlayVisibilityRuntime,
|
||||||
createGetRuntimeOptionsStateHandler,
|
createGetRuntimeOptionsStateHandler,
|
||||||
@@ -219,12 +201,6 @@ import {
|
|||||||
resolveSubtitleStyleForRenderer,
|
resolveSubtitleStyleForRenderer,
|
||||||
} from './main/runtime/domains/overlay';
|
} from './main/runtime/domains/overlay';
|
||||||
import {
|
import {
|
||||||
createBuildAnilistStateRuntimeMainDepsHandler,
|
|
||||||
createBuildConfigDerivedRuntimeMainDepsHandler,
|
|
||||||
createBuildImmersionMediaRuntimeMainDepsHandler,
|
|
||||||
createBuildMainSubsyncRuntimeMainDepsHandler,
|
|
||||||
createBuildSubtitleProcessingControllerMainDepsHandler,
|
|
||||||
createBuildMediaRuntimeMainDepsHandler,
|
|
||||||
createBuildDictionaryRootsMainHandler,
|
createBuildDictionaryRootsMainHandler,
|
||||||
createBuildFrequencyDictionaryRootsMainHandler,
|
createBuildFrequencyDictionaryRootsMainHandler,
|
||||||
createBuildFrequencyDictionaryRuntimeMainDepsHandler,
|
createBuildFrequencyDictionaryRuntimeMainDepsHandler,
|
||||||
@@ -244,14 +220,6 @@ import {
|
|||||||
resolvePrimarySubtitle,
|
resolvePrimarySubtitle,
|
||||||
} from './main/runtime/primary-subtitle-text';
|
} from './main/runtime/primary-subtitle-text';
|
||||||
import {
|
import {
|
||||||
createBuildCopyCurrentSubtitleMainDepsHandler,
|
|
||||||
createBuildHandleMineSentenceDigitMainDepsHandler,
|
|
||||||
createBuildHandleMultiCopyDigitMainDepsHandler,
|
|
||||||
createBuildMarkLastCardAsAudioCardMainDepsHandler,
|
|
||||||
createBuildMineSentenceCardMainDepsHandler,
|
|
||||||
createBuildRefreshKnownWordCacheMainDepsHandler,
|
|
||||||
createBuildTriggerFieldGroupingMainDepsHandler,
|
|
||||||
createBuildUpdateLastCardFromClipboardMainDepsHandler,
|
|
||||||
createMarkLastCardAsAudioCardHandler,
|
createMarkLastCardAsAudioCardHandler,
|
||||||
createMineSentenceCardHandler,
|
createMineSentenceCardHandler,
|
||||||
createRefreshKnownWordCacheHandler,
|
createRefreshKnownWordCacheHandler,
|
||||||
@@ -291,7 +259,6 @@ import {
|
|||||||
createOverlayContentMeasurementStore,
|
createOverlayContentMeasurementStore,
|
||||||
createOverlayManager,
|
createOverlayManager,
|
||||||
createOverlayWindow as createOverlayWindowCore,
|
createOverlayWindow as createOverlayWindowCore,
|
||||||
createSubtitleProcessingController,
|
|
||||||
createTokenizerDepsRuntime,
|
createTokenizerDepsRuntime,
|
||||||
cycleSecondarySubMode as cycleSecondarySubModeCore,
|
cycleSecondarySubMode as cycleSecondarySubModeCore,
|
||||||
deleteYomitanDictionaryByTitle,
|
deleteYomitanDictionaryByTitle,
|
||||||
@@ -428,8 +395,10 @@ import {
|
|||||||
shouldQuitOnWindowAllClosedForTrayState,
|
shouldQuitOnWindowAllClosedForTrayState,
|
||||||
} from './main/runtime/startup-tray-policy';
|
} from './main/runtime/startup-tray-policy';
|
||||||
import { createLogExportTrayRuntime } from './main/runtime/log-export-tray';
|
import { createLogExportTrayRuntime } from './main/runtime/log-export-tray';
|
||||||
import { createImmersionTrackerStartupHandler } from './main/runtime/immersion-startup';
|
import {
|
||||||
import { createBuildImmersionTrackerStartupMainDepsHandler } from './main/runtime/immersion-startup-main-deps';
|
createImmersionTrackerStartupHandler,
|
||||||
|
type ImmersionTrackerStartupDeps,
|
||||||
|
} from './main/runtime/immersion-startup';
|
||||||
import {
|
import {
|
||||||
createRunStatsCliCommandHandler,
|
createRunStatsCliCommandHandler,
|
||||||
writeStatsCliCommandResponse,
|
writeStatsCliCommandResponse,
|
||||||
@@ -529,6 +498,7 @@ import {
|
|||||||
getJlptDictionarySearchPaths,
|
getJlptDictionarySearchPaths,
|
||||||
} from './main/jlpt-runtime';
|
} from './main/jlpt-runtime';
|
||||||
import { createMediaRuntimeService } from './main/media-runtime';
|
import { createMediaRuntimeService } from './main/media-runtime';
|
||||||
|
import { createPrefetchAwareSubtitleProcessingController } from './main/runtime/subtitle-processing-runtime';
|
||||||
import { createOverlayVisibilityRuntimeService } from './main/overlay-visibility-runtime';
|
import { createOverlayVisibilityRuntimeService } from './main/overlay-visibility-runtime';
|
||||||
import { createDiscordPresenceRuntime } from './main/runtime/discord-presence-runtime';
|
import { createDiscordPresenceRuntime } from './main/runtime/discord-presence-runtime';
|
||||||
import { createCharacterDictionaryRuntimeService } from './main/character-dictionary-runtime';
|
import { createCharacterDictionaryRuntimeService } from './main/character-dictionary-runtime';
|
||||||
@@ -707,15 +677,10 @@ let backgroundWarmupsStarted = false;
|
|||||||
let yomitanLoadInFlight: Promise<Extension | null> | null = null;
|
let yomitanLoadInFlight: Promise<Extension | null> | null = null;
|
||||||
let notifyAnilistTokenStoreWarning: (message: string) => void = () => {};
|
let notifyAnilistTokenStoreWarning: (message: string) => void = () => {};
|
||||||
|
|
||||||
const buildApplyJellyfinMpvDefaultsMainDepsHandler =
|
const applyJellyfinMpvDefaultsHandler = createApplyJellyfinMpvDefaultsHandler({
|
||||||
createBuildApplyJellyfinMpvDefaultsMainDepsHandler({
|
sendMpvCommandRuntime: (client, command) => sendMpvCommandRuntime(client, command),
|
||||||
sendMpvCommandRuntime: (client, command) => sendMpvCommandRuntime(client, command),
|
jellyfinLangPref: JELLYFIN_LANG_PREF,
|
||||||
jellyfinLangPref: JELLYFIN_LANG_PREF,
|
});
|
||||||
});
|
|
||||||
const applyJellyfinMpvDefaultsMainDeps = buildApplyJellyfinMpvDefaultsMainDepsHandler();
|
|
||||||
const applyJellyfinMpvDefaultsHandler = createApplyJellyfinMpvDefaultsHandler(
|
|
||||||
applyJellyfinMpvDefaultsMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const isDev = process.argv.includes('--dev') || process.argv.includes('--debug');
|
const isDev = process.argv.includes('--dev') || process.argv.includes('--debug');
|
||||||
const texthookerService = new Texthooker(() => {
|
const texthookerService = new Texthooker(() => {
|
||||||
@@ -758,11 +723,9 @@ const texthookerService = new Texthooker(() => {
|
|||||||
});
|
});
|
||||||
let syncOverlayShortcutsForModal: (isActive: boolean) => void = () => {};
|
let syncOverlayShortcutsForModal: (isActive: boolean) => void = () => {};
|
||||||
let syncOverlayVisibilityForModal: () => void = () => {};
|
let syncOverlayVisibilityForModal: () => void = () => {};
|
||||||
const buildGetDefaultSocketPathMainDepsHandler = createBuildGetDefaultSocketPathMainDepsHandler({
|
const getDefaultSocketPathHandler = createGetDefaultSocketPathHandler({
|
||||||
platform: process.platform,
|
platform: process.platform,
|
||||||
});
|
});
|
||||||
const getDefaultSocketPathMainDeps = buildGetDefaultSocketPathMainDepsHandler();
|
|
||||||
const getDefaultSocketPathHandler = createGetDefaultSocketPathHandler(getDefaultSocketPathMainDeps);
|
|
||||||
|
|
||||||
type BootServices = MainBootServicesResult<
|
type BootServices = MainBootServicesResult<
|
||||||
ConfigService,
|
ConfigService,
|
||||||
@@ -852,45 +815,46 @@ const bootServices = createMainBootServices({
|
|||||||
}),
|
}),
|
||||||
createOverlayModalInputState,
|
createOverlayModalInputState,
|
||||||
createOverlayContentMeasurementStore: ({ logger }) => {
|
createOverlayContentMeasurementStore: ({ logger }) => {
|
||||||
const buildHandler = createBuildOverlayContentMeasurementStoreMainDepsHandler({
|
return createOverlayContentMeasurementStore({
|
||||||
now: () => Date.now(),
|
now: () => Date.now(),
|
||||||
warn: (message: string) => logger.warn(message),
|
warn: (message: string) => logger.warn(message),
|
||||||
});
|
});
|
||||||
return createOverlayContentMeasurementStore(buildHandler());
|
|
||||||
},
|
},
|
||||||
getSyncOverlayShortcutsForModal: () => syncOverlayShortcutsForModal,
|
getSyncOverlayShortcutsForModal: () => syncOverlayShortcutsForModal,
|
||||||
getSyncOverlayVisibilityForModal: () => syncOverlayVisibilityForModal,
|
getSyncOverlayVisibilityForModal: () => syncOverlayVisibilityForModal,
|
||||||
createOverlayModalRuntime: ({ overlayManager, overlayModalInputState }) => {
|
createOverlayModalRuntime: ({ overlayManager, overlayModalInputState }) => {
|
||||||
const buildHandler = createBuildOverlayModalRuntimeMainDepsHandler({
|
return createOverlayModalRuntimeService(
|
||||||
getMainWindow: () => overlayManager.getMainWindow(),
|
{
|
||||||
getModalWindow: () => overlayManager.getModalWindow(),
|
getMainWindow: () => overlayManager.getMainWindow(),
|
||||||
createModalWindow: () => createModalWindow(),
|
getModalWindow: () => overlayManager.getModalWindow(),
|
||||||
getModalGeometry: () => overlayGeometryRuntime.getCurrentOverlayGeometry(),
|
createModalWindow: () => createModalWindow(),
|
||||||
setModalWindowBounds: (geometry) => overlayManager.setModalWindowBounds(geometry),
|
getModalGeometry: () => overlayGeometryRuntime.getCurrentOverlayGeometry(),
|
||||||
});
|
setModalWindowBounds: (geometry) => overlayManager.setModalWindowBounds(geometry),
|
||||||
return createOverlayModalRuntimeService(buildHandler(), {
|
|
||||||
onModalStateChange: (isActive: boolean) =>
|
|
||||||
overlayModalInputState.handleModalInputStateChange(isActive),
|
|
||||||
// On macOS, after the last modal closes the post-close visibility sync hides the overlay
|
|
||||||
// when neither it nor mpv is focused, and keyboard focus is left in limbo (mpv keys like
|
|
||||||
// shift-to-unpause stop working). Programmatically focusing mpv from our background helper
|
|
||||||
// is refused by macOS (most visibly in native fullscreen), so instead resign SubMiner's
|
|
||||||
// active status — exactly what a manual click does — handing focus back to the previously
|
|
||||||
// active app (mpv). The overlay is already hidden at this point, so app.hide() hides nothing
|
|
||||||
// visible; once mpv is focused the tracker re-shows the overlay above it.
|
|
||||||
onFinalModalClosed: () => {
|
|
||||||
void restoreMacOSMpvFocusAfterModalClose({
|
|
||||||
platform: process.platform,
|
|
||||||
focusMpv: async () => {
|
|
||||||
app.hide();
|
|
||||||
},
|
|
||||||
getWindowTracker: () => appState.windowTracker,
|
|
||||||
updateVisibleOverlayVisibility: () =>
|
|
||||||
overlayVisibilityRuntime.updateVisibleOverlayVisibility(),
|
|
||||||
warn: (message, details) => logger.warn(message, details),
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
onModalStateChange: (isActive: boolean) =>
|
||||||
|
overlayModalInputState.handleModalInputStateChange(isActive),
|
||||||
|
// On macOS, after the last modal closes the post-close visibility sync hides the overlay
|
||||||
|
// when neither it nor mpv is focused, and keyboard focus is left in limbo (mpv keys like
|
||||||
|
// shift-to-unpause stop working). Programmatically focusing mpv from our background helper
|
||||||
|
// is refused by macOS (most visibly in native fullscreen), so instead resign SubMiner's
|
||||||
|
// active status — exactly what a manual click does — handing focus back to the previously
|
||||||
|
// active app (mpv). The overlay is already hidden at this point, so app.hide() hides nothing
|
||||||
|
// visible; once mpv is focused the tracker re-shows the overlay above it.
|
||||||
|
onFinalModalClosed: () => {
|
||||||
|
void restoreMacOSMpvFocusAfterModalClose({
|
||||||
|
platform: process.platform,
|
||||||
|
focusMpv: async () => {
|
||||||
|
app.hide();
|
||||||
|
},
|
||||||
|
getWindowTracker: () => appState.windowTracker,
|
||||||
|
updateVisibleOverlayVisibility: () =>
|
||||||
|
overlayVisibilityRuntime.updateVisibleOverlayVisibility(),
|
||||||
|
warn: (message, details) => logger.warn(message, details),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
createAppState,
|
createAppState,
|
||||||
}) as BootServices;
|
}) as BootServices;
|
||||||
@@ -1717,7 +1681,7 @@ function syncOverlayMpvSubtitleSuppression(): void {
|
|||||||
restoreOverlayMpvSubtitles();
|
restoreOverlayMpvSubtitles();
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildImmersionMediaRuntimeMainDepsHandler = createBuildImmersionMediaRuntimeMainDepsHandler({
|
const immersionMediaRuntime = createImmersionMediaRuntime({
|
||||||
getResolvedConfig: () => configService.getConfig(),
|
getResolvedConfig: () => configService.getConfig(),
|
||||||
defaultImmersionDbPath: DEFAULT_IMMERSION_DB_PATH,
|
defaultImmersionDbPath: DEFAULT_IMMERSION_DB_PATH,
|
||||||
getTracker: () => appState.immersionTracker,
|
getTracker: () => appState.immersionTracker,
|
||||||
@@ -1727,7 +1691,23 @@ const buildImmersionMediaRuntimeMainDepsHandler = createBuildImmersionMediaRunti
|
|||||||
logDebug: (message) => logger.debug(message),
|
logDebug: (message) => logger.debug(message),
|
||||||
logInfo: (message) => logger.info(message),
|
logInfo: (message) => logger.info(message),
|
||||||
});
|
});
|
||||||
const buildAnilistStateRuntimeMainDepsHandler = createBuildAnilistStateRuntimeMainDepsHandler({
|
const anilistRateLimiter = createAnilistRateLimiter();
|
||||||
|
const statsCoverArtFetcher = createCoverArtFetcher(
|
||||||
|
anilistRateLimiter,
|
||||||
|
createLogger('main:stats-cover-art'),
|
||||||
|
{
|
||||||
|
liveAction: createLiveActionMetadataResolver(
|
||||||
|
createTmdbClient({
|
||||||
|
resolveApiKey: createTmdbApiKeyResolver(
|
||||||
|
() => configService.getConfig().tmdb,
|
||||||
|
() => bundledTmdbApiKey,
|
||||||
|
),
|
||||||
|
}),
|
||||||
|
createLogger('main:tmdb'),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
const anilistStateRuntime = createAnilistStateRuntime({
|
||||||
getClientSecretState: () => appState.anilistClientSecretState,
|
getClientSecretState: () => appState.anilistClientSecretState,
|
||||||
setClientSecretState: (next) => {
|
setClientSecretState: (next) => {
|
||||||
appState.anilistClientSecretState = transitionAnilistClientSecretState(
|
appState.anilistClientSecretState = transitionAnilistClientSecretState(
|
||||||
@@ -1748,14 +1728,14 @@ const buildAnilistStateRuntimeMainDepsHandler = createBuildAnilistStateRuntimeMa
|
|||||||
anilistCachedAccessToken = null;
|
anilistCachedAccessToken = null;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const buildConfigDerivedRuntimeMainDepsHandler = createBuildConfigDerivedRuntimeMainDepsHandler({
|
const configDerivedRuntime = createConfigDerivedRuntime({
|
||||||
getResolvedConfig: () => configService.getConfig(),
|
getResolvedConfig: () => configService.getConfig(),
|
||||||
getRuntimeOptionsManager: () => appState.runtimeOptionsManager,
|
getRuntimeOptionsManager: () => appState.runtimeOptionsManager,
|
||||||
defaultJimakuLanguagePreference: DEFAULT_CONFIG.jimaku.languagePreference,
|
defaultJimakuLanguagePreference: DEFAULT_CONFIG.jimaku.languagePreference,
|
||||||
defaultJimakuMaxEntryResults: DEFAULT_CONFIG.jimaku.maxEntryResults,
|
defaultJimakuMaxEntryResults: DEFAULT_CONFIG.jimaku.maxEntryResults,
|
||||||
defaultJimakuApiBaseUrl: DEFAULT_CONFIG.jimaku.apiBaseUrl,
|
defaultJimakuApiBaseUrl: DEFAULT_CONFIG.jimaku.apiBaseUrl,
|
||||||
});
|
});
|
||||||
const buildMainSubsyncRuntimeMainDepsHandler = createBuildMainSubsyncRuntimeMainDepsHandler({
|
const subsyncRuntime = createMainSubsyncRuntime({
|
||||||
getMpvClient: () => appState.mpvClient,
|
getMpvClient: () => appState.mpvClient,
|
||||||
getResolvedConfig: () => configService.getConfig(),
|
getResolvedConfig: () => configService.getConfig(),
|
||||||
getSubsyncInProgress: () => appState.subsyncInProgress,
|
getSubsyncInProgress: () => appState.subsyncInProgress,
|
||||||
@@ -1771,28 +1751,6 @@ const buildMainSubsyncRuntimeMainDepsHandler = createBuildMainSubsyncRuntimeMain
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const immersionMediaRuntime = createImmersionMediaRuntime(
|
|
||||||
buildImmersionMediaRuntimeMainDepsHandler(),
|
|
||||||
);
|
|
||||||
const anilistRateLimiter = createAnilistRateLimiter();
|
|
||||||
const statsCoverArtFetcher = createCoverArtFetcher(
|
|
||||||
anilistRateLimiter,
|
|
||||||
createLogger('main:stats-cover-art'),
|
|
||||||
{
|
|
||||||
liveAction: createLiveActionMetadataResolver(
|
|
||||||
createTmdbClient({
|
|
||||||
resolveApiKey: createTmdbApiKeyResolver(
|
|
||||||
() => configService.getConfig().tmdb,
|
|
||||||
() => bundledTmdbApiKey,
|
|
||||||
),
|
|
||||||
}),
|
|
||||||
createLogger('main:tmdb'),
|
|
||||||
),
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const anilistStateRuntime = createAnilistStateRuntime(buildAnilistStateRuntimeMainDepsHandler());
|
|
||||||
const configDerivedRuntime = createConfigDerivedRuntime(buildConfigDerivedRuntimeMainDepsHandler());
|
|
||||||
const subsyncRuntime = createMainSubsyncRuntime(buildMainSubsyncRuntimeMainDepsHandler());
|
|
||||||
const currentMediaTokenizationGate = createCurrentMediaTokenizationGate();
|
const currentMediaTokenizationGate = createCurrentMediaTokenizationGate();
|
||||||
const startupOsdSequencer = createStartupOsdSequencer({
|
const startupOsdSequencer = createStartupOsdSequencer({
|
||||||
getNotificationType: () => overlayNotificationsRuntime.getConfiguredStatusNotificationType(),
|
getNotificationType: () => overlayNotificationsRuntime.getConfiguredStatusNotificationType(),
|
||||||
@@ -2061,30 +2019,18 @@ function signalCurrentSubtitleAutoplayReady(): void {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const buildSubtitleProcessingControllerMainDepsHandler =
|
const subtitleProcessingController = createPrefetchAwareSubtitleProcessingController({
|
||||||
createBuildSubtitleProcessingControllerMainDepsHandler({
|
tokenizeSubtitle: async (text: string) =>
|
||||||
tokenizeSubtitle: async (text: string) =>
|
tokenizeSubtitleDeferred ? await tokenizeSubtitleDeferred(text) : { text, tokens: null },
|
||||||
tokenizeSubtitleDeferred ? await tokenizeSubtitleDeferred(text) : { text, tokens: null },
|
emitSubtitlePayload: (payload, options) => emitSubtitlePayload(payload, options),
|
||||||
// Controller emits never release the prefetch pause: the first emit for an
|
resumePrefetch: () => {
|
||||||
// uncached line is the provisional plain payload, sent before tokenization
|
subtitlePrefetchService?.resume();
|
||||||
// starts, so resuming on it would put prefetch back in contention with the
|
},
|
||||||
// on-screen line for the single parser window.
|
logDebug: (message) => {
|
||||||
emitSubtitle: (payload) => emitSubtitlePayload(payload, { resumePrefetch: false }),
|
logger.debug(`[subtitle-processing] ${message}`);
|
||||||
// The pause is released once the controller has no work left, which covers
|
},
|
||||||
// the runs that end without an emit (suppressed duplicate, failed
|
now: () => Date.now(),
|
||||||
// tokenization) as well as the ones that deliver a payload.
|
});
|
||||||
onProcessingSettled: () => {
|
|
||||||
subtitlePrefetchService?.resume();
|
|
||||||
},
|
|
||||||
logDebug: (message) => {
|
|
||||||
logger.debug(`[subtitle-processing] ${message}`);
|
|
||||||
},
|
|
||||||
now: () => Date.now(),
|
|
||||||
});
|
|
||||||
const subtitleProcessingControllerMainDeps = buildSubtitleProcessingControllerMainDepsHandler();
|
|
||||||
const subtitleProcessingController = createSubtitleProcessingController(
|
|
||||||
subtitleProcessingControllerMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
let subtitlePrefetchService: SubtitlePrefetchService | null = null;
|
let subtitlePrefetchService: SubtitlePrefetchService | null = null;
|
||||||
let lastObservedTimePos = 0;
|
let lastObservedTimePos = 0;
|
||||||
@@ -2645,79 +2591,68 @@ const frequencyDictionaryRuntime = createFrequencyDictionaryRuntimeService(
|
|||||||
})(),
|
})(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildGetFieldGroupingResolverMainDepsHandler =
|
const getFieldGroupingResolverHandler = createGetFieldGroupingResolverHandler({
|
||||||
createBuildGetFieldGroupingResolverMainDepsHandler({
|
getResolver: () => appState.fieldGroupingResolver,
|
||||||
getResolver: () => appState.fieldGroupingResolver,
|
});
|
||||||
});
|
|
||||||
const getFieldGroupingResolverMainDeps = buildGetFieldGroupingResolverMainDepsHandler();
|
|
||||||
const getFieldGroupingResolverHandler = createGetFieldGroupingResolverHandler(
|
|
||||||
getFieldGroupingResolverMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildSetFieldGroupingResolverMainDepsHandler =
|
const setFieldGroupingResolverHandler = createSetFieldGroupingResolverHandler({
|
||||||
createBuildSetFieldGroupingResolverMainDepsHandler({
|
setResolver: (resolver) => {
|
||||||
setResolver: (resolver) => {
|
appState.fieldGroupingResolver = resolver;
|
||||||
appState.fieldGroupingResolver = resolver;
|
},
|
||||||
},
|
nextSequence: () => {
|
||||||
nextSequence: () => {
|
appState.fieldGroupingResolverSequence += 1;
|
||||||
appState.fieldGroupingResolverSequence += 1;
|
return appState.fieldGroupingResolverSequence;
|
||||||
return appState.fieldGroupingResolverSequence;
|
},
|
||||||
},
|
getSequence: () => appState.fieldGroupingResolverSequence,
|
||||||
getSequence: () => appState.fieldGroupingResolverSequence,
|
});
|
||||||
});
|
|
||||||
const setFieldGroupingResolverMainDeps = buildSetFieldGroupingResolverMainDepsHandler();
|
|
||||||
const setFieldGroupingResolverHandler = createSetFieldGroupingResolverHandler(
|
|
||||||
setFieldGroupingResolverMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const fieldGroupingOverlayRuntime = createFieldGroupingOverlayRuntime<OverlayHostedModal>(
|
const fieldGroupingOverlayRuntime = createFieldGroupingOverlayRuntime<OverlayHostedModal>({
|
||||||
createBuildFieldGroupingOverlayMainDepsHandler<OverlayHostedModal>({
|
getMainWindow: () => overlayManager.getMainWindow(),
|
||||||
getMainWindow: () => overlayManager.getMainWindow(),
|
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(),
|
||||||
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(),
|
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
||||||
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
getResolver: () => getFieldGroupingResolverHandler(),
|
||||||
getResolver: () => getFieldGroupingResolverHandler(),
|
setResolver: (resolver) => setFieldGroupingResolverHandler(resolver),
|
||||||
setResolver: (resolver) => setFieldGroupingResolverHandler(resolver),
|
getRestoreVisibleOverlayOnModalClose: () =>
|
||||||
getRestoreVisibleOverlayOnModalClose: () =>
|
overlayModalRuntime.getRestoreVisibleOverlayOnModalClose(),
|
||||||
overlayModalRuntime.getRestoreVisibleOverlayOnModalClose(),
|
// These are optional on the runtime options, so a missing forward compiles silently, but
|
||||||
waitForModalOpen: (modal, timeoutMs) => overlayModalRuntime.waitForModalOpen(modal, timeoutMs),
|
// dropping them leaves the field grouping modal with no modal-open ack/retry, no teardown on
|
||||||
handleOverlayModalClosed: (modal) => overlayModalRuntime.handleOverlayModalClosed(modal),
|
// failure, and no warn logging.
|
||||||
logWarn: (message) => logger.warn(message),
|
waitForModalOpen: (modal, timeoutMs) => overlayModalRuntime.waitForModalOpen(modal, timeoutMs),
|
||||||
ensureOverlayStartupPrereqs: () => ensureOverlayStartupPrereqs(),
|
handleOverlayModalClosed: (modal) => overlayModalRuntime.handleOverlayModalClosed(modal),
|
||||||
ensureOverlayWindowsReadyForVisibilityActions: () =>
|
logWarn: (message) => logger.warn(message),
|
||||||
ensureOverlayWindowsReadyForVisibilityActions(),
|
ensureOverlayStartupPrereqs: () => ensureOverlayStartupPrereqs(),
|
||||||
sendToActiveOverlayWindow: (channel, payload, runtimeOptions) =>
|
ensureOverlayWindowsReadyForVisibilityActions: () =>
|
||||||
overlayModalRuntime.sendToActiveOverlayWindow(channel, payload, runtimeOptions),
|
ensureOverlayWindowsReadyForVisibilityActions(),
|
||||||
})(),
|
sendToVisibleOverlay: (channel, payload, runtimeOptions) =>
|
||||||
);
|
overlayModalRuntime.sendToActiveOverlayWindow(channel, payload, runtimeOptions),
|
||||||
|
});
|
||||||
const createFieldGroupingCallback = fieldGroupingOverlayRuntime.createFieldGroupingCallback;
|
const createFieldGroupingCallback = fieldGroupingOverlayRuntime.createFieldGroupingCallback;
|
||||||
|
|
||||||
const SUBTITLE_POSITIONS_DIR = path.join(CONFIG_DIR, 'subtitle-positions');
|
const SUBTITLE_POSITIONS_DIR = path.join(CONFIG_DIR, 'subtitle-positions');
|
||||||
|
|
||||||
const mediaRuntime = createMediaRuntimeService(
|
const mediaRuntime = createMediaRuntimeService({
|
||||||
createBuildMediaRuntimeMainDepsHandler({
|
isRemoteMediaPath: (mediaPath) => isRemoteMediaPath(mediaPath),
|
||||||
isRemoteMediaPath: (mediaPath) => isRemoteMediaPath(mediaPath),
|
loadSubtitlePosition: () => loadSubtitlePosition(),
|
||||||
loadSubtitlePosition: () => loadSubtitlePosition(),
|
getCurrentMediaPath: () => appState.currentMediaPath,
|
||||||
getCurrentMediaPath: () => appState.currentMediaPath,
|
getPendingSubtitlePosition: () => appState.pendingSubtitlePosition,
|
||||||
getPendingSubtitlePosition: () => appState.pendingSubtitlePosition,
|
getSubtitlePositionsDir: () => SUBTITLE_POSITIONS_DIR,
|
||||||
getSubtitlePositionsDir: () => SUBTITLE_POSITIONS_DIR,
|
setCurrentMediaPath: (nextPath: string | null) => {
|
||||||
setCurrentMediaPath: (nextPath: string | null) => {
|
appState.currentMediaPath = nextPath;
|
||||||
appState.currentMediaPath = nextPath;
|
},
|
||||||
},
|
clearPendingSubtitlePosition: () => {
|
||||||
clearPendingSubtitlePosition: () => {
|
appState.pendingSubtitlePosition = null;
|
||||||
appState.pendingSubtitlePosition = null;
|
},
|
||||||
},
|
setSubtitlePosition: (position: SubtitlePosition | null) => {
|
||||||
setSubtitlePosition: (position: SubtitlePosition | null) => {
|
appState.subtitlePosition = position;
|
||||||
appState.subtitlePosition = position;
|
},
|
||||||
},
|
broadcastSubtitlePosition: (position) => {
|
||||||
broadcastToOverlayWindows: (channel, payload) => {
|
overlayManager.broadcastToOverlayWindows('subtitle-position:set', position);
|
||||||
overlayManager.broadcastToOverlayWindows(channel, payload);
|
},
|
||||||
},
|
getCurrentMediaTitle: () => appState.currentMediaTitle,
|
||||||
getCurrentMediaTitle: () => appState.currentMediaTitle,
|
setCurrentMediaTitle: (title) => {
|
||||||
setCurrentMediaTitle: (title) => {
|
appState.currentMediaTitle = title;
|
||||||
appState.currentMediaTitle = title;
|
},
|
||||||
},
|
});
|
||||||
})(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const characterDictionaryRuntime = createCharacterDictionaryRuntimeService({
|
const characterDictionaryRuntime = createCharacterDictionaryRuntimeService({
|
||||||
userDataPath: USER_DATA_PATH,
|
userDataPath: USER_DATA_PATH,
|
||||||
@@ -2993,20 +2928,10 @@ const visibleOverlayInteractionRuntime = createVisibleOverlayInteractionRuntime(
|
|||||||
getOverlayForegroundSeparateWindows: () => getOverlayForegroundSeparateWindows(),
|
getOverlayForegroundSeparateWindows: () => getOverlayForegroundSeparateWindows(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const buildGetRuntimeOptionsStateMainDepsHandler = createBuildGetRuntimeOptionsStateMainDepsHandler(
|
const getRuntimeOptionsStateHandler = createGetRuntimeOptionsStateHandler({
|
||||||
{
|
getRuntimeOptionsManager: () => appState.runtimeOptionsManager,
|
||||||
getRuntimeOptionsManager: () => appState.runtimeOptionsManager,
|
});
|
||||||
},
|
|
||||||
);
|
|
||||||
const getRuntimeOptionsStateMainDeps = buildGetRuntimeOptionsStateMainDepsHandler();
|
|
||||||
const getRuntimeOptionsStateHandler = createGetRuntimeOptionsStateHandler(
|
|
||||||
getRuntimeOptionsStateMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildRestorePreviousSecondarySubVisibilityMainDepsHandler =
|
|
||||||
createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler({
|
|
||||||
getMpvClient: () => appState.mpvClient,
|
|
||||||
});
|
|
||||||
syncOverlayVisibilityForModal = () => {
|
syncOverlayVisibilityForModal = () => {
|
||||||
overlayVisibilityRuntime.updateVisibleOverlayVisibility();
|
overlayVisibilityRuntime.updateVisibleOverlayVisibility();
|
||||||
};
|
};
|
||||||
@@ -3031,42 +2956,31 @@ const {
|
|||||||
maybeStartOverlayLoadingOsd,
|
maybeStartOverlayLoadingOsd,
|
||||||
} = overlayNotificationsRuntime;
|
} = overlayNotificationsRuntime;
|
||||||
|
|
||||||
const buildBroadcastRuntimeOptionsChangedMainDepsHandler =
|
const overlayVisibilityComposer = composeOverlayVisibilityRuntime({
|
||||||
createBuildBroadcastRuntimeOptionsChangedMainDepsHandler({
|
overlayVisibilityRuntime,
|
||||||
|
restorePreviousSecondarySubVisibilityMainDeps: {
|
||||||
|
getMpvClient: () => appState.mpvClient,
|
||||||
|
},
|
||||||
|
broadcastRuntimeOptionsChangedMainDeps: {
|
||||||
broadcastRuntimeOptionsChangedRuntime,
|
broadcastRuntimeOptionsChangedRuntime,
|
||||||
getRuntimeOptionsState: () => getRuntimeOptionsStateHandler(),
|
getRuntimeOptionsState: () => getRuntimeOptionsStateHandler(),
|
||||||
broadcastToOverlayWindows: (channel, ...args) =>
|
broadcastToOverlayWindows: (channel, ...args) =>
|
||||||
overlayManager.broadcastToOverlayWindows(channel, ...args),
|
overlayManager.broadcastToOverlayWindows(channel, ...args),
|
||||||
});
|
},
|
||||||
|
sendToActiveOverlayWindowMainDeps: {
|
||||||
const buildSendToActiveOverlayWindowMainDepsHandler =
|
|
||||||
createBuildSendToActiveOverlayWindowMainDepsHandler({
|
|
||||||
sendToActiveOverlayWindowRuntime: (channel, payload, runtimeOptions) =>
|
sendToActiveOverlayWindowRuntime: (channel, payload, runtimeOptions) =>
|
||||||
overlayModalRuntime.sendToActiveOverlayWindow(channel, payload, runtimeOptions),
|
overlayModalRuntime.sendToActiveOverlayWindow(channel, payload, runtimeOptions),
|
||||||
});
|
},
|
||||||
|
setOverlayDebugVisualizationEnabledMainDeps: {
|
||||||
const buildSetOverlayDebugVisualizationEnabledMainDepsHandler =
|
|
||||||
createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler({
|
|
||||||
setOverlayDebugVisualizationEnabledRuntime,
|
setOverlayDebugVisualizationEnabledRuntime,
|
||||||
getCurrentEnabled: () => appState.overlayDebugVisualizationEnabled,
|
getCurrentEnabled: () => appState.overlayDebugVisualizationEnabled,
|
||||||
setCurrentEnabled: (next) => {
|
setCurrentEnabled: (next) => {
|
||||||
appState.overlayDebugVisualizationEnabled = next;
|
appState.overlayDebugVisualizationEnabled = next;
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
openRuntimeOptionsPaletteMainDeps: {
|
||||||
const buildOpenRuntimeOptionsPaletteMainDepsHandler =
|
|
||||||
createBuildOpenRuntimeOptionsPaletteMainDepsHandler({
|
|
||||||
openRuntimeOptionsPaletteRuntime: () => overlayModalRuntime.openRuntimeOptionsPalette(),
|
openRuntimeOptionsPaletteRuntime: () => overlayModalRuntime.openRuntimeOptionsPalette(),
|
||||||
});
|
},
|
||||||
const overlayVisibilityComposer = composeOverlayVisibilityRuntime({
|
|
||||||
overlayVisibilityRuntime,
|
|
||||||
restorePreviousSecondarySubVisibilityMainDeps:
|
|
||||||
buildRestorePreviousSecondarySubVisibilityMainDepsHandler(),
|
|
||||||
broadcastRuntimeOptionsChangedMainDeps: buildBroadcastRuntimeOptionsChangedMainDepsHandler(),
|
|
||||||
sendToActiveOverlayWindowMainDeps: buildSendToActiveOverlayWindowMainDepsHandler(),
|
|
||||||
setOverlayDebugVisualizationEnabledMainDeps:
|
|
||||||
buildSetOverlayDebugVisualizationEnabledMainDepsHandler(),
|
|
||||||
openRuntimeOptionsPaletteMainDeps: buildOpenRuntimeOptionsPaletteMainDepsHandler(),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
function createOverlayHostedModalOpenDeps(): {
|
function createOverlayHostedModalOpenDeps(): {
|
||||||
@@ -3881,56 +3795,50 @@ const {
|
|||||||
const maybeFocusExistingAnilistSetupWindow = createMaybeFocusExistingAnilistSetupWindowHandler({
|
const maybeFocusExistingAnilistSetupWindow = createMaybeFocusExistingAnilistSetupWindowHandler({
|
||||||
getSetupWindow: () => appState.anilistSetupWindow,
|
getSetupWindow: () => appState.anilistSetupWindow,
|
||||||
});
|
});
|
||||||
const buildOpenAnilistSetupWindowMainDepsHandler = createBuildOpenAnilistSetupWindowMainDepsHandler(
|
const openAnilistSetupWindowHandler = createOpenAnilistSetupWindowHandler({
|
||||||
{
|
maybeFocusExistingSetupWindow: maybeFocusExistingAnilistSetupWindow,
|
||||||
maybeFocusExistingSetupWindow: maybeFocusExistingAnilistSetupWindow,
|
createSetupWindow: createCreateAnilistSetupWindowHandler({
|
||||||
createSetupWindow: createCreateAnilistSetupWindowHandler({
|
createBrowserWindow: (options) => new BrowserWindow(options),
|
||||||
createBrowserWindow: (options) => new BrowserWindow(options),
|
}),
|
||||||
|
buildAuthorizeUrl: () =>
|
||||||
|
buildAnilistSetupUrl({
|
||||||
|
authorizeUrl: ANILIST_SETUP_CLIENT_ID_URL,
|
||||||
|
clientId: ANILIST_DEFAULT_CLIENT_ID,
|
||||||
|
responseType: ANILIST_SETUP_RESPONSE_TYPE,
|
||||||
}),
|
}),
|
||||||
buildAuthorizeUrl: () =>
|
consumeCallbackUrl: (rawUrl) => consumeAnilistSetupTokenFromUrl(rawUrl),
|
||||||
buildAnilistSetupUrl({
|
openSetupInBrowser: (authorizeUrl) =>
|
||||||
authorizeUrl: ANILIST_SETUP_CLIENT_ID_URL,
|
openAnilistSetupInBrowser({
|
||||||
clientId: ANILIST_DEFAULT_CLIENT_ID,
|
authorizeUrl,
|
||||||
responseType: ANILIST_SETUP_RESPONSE_TYPE,
|
openExternal: (url) => shell.openExternal(url),
|
||||||
}),
|
logError: (message, error) => logger.error(message, error),
|
||||||
consumeCallbackUrl: (rawUrl) => consumeAnilistSetupTokenFromUrl(rawUrl),
|
}),
|
||||||
openSetupInBrowser: (authorizeUrl) =>
|
loadManualTokenEntry: (setupWindow, authorizeUrl) =>
|
||||||
openAnilistSetupInBrowser({
|
loadAnilistManualTokenEntry({
|
||||||
authorizeUrl,
|
setupWindow: setupWindow as BrowserWindow,
|
||||||
openExternal: (url) => shell.openExternal(url),
|
authorizeUrl,
|
||||||
logError: (message, error) => logger.error(message, error),
|
developerSettingsUrl: ANILIST_DEVELOPER_SETTINGS_URL,
|
||||||
}),
|
logWarn: (message, data) => logger.warn(message, data),
|
||||||
loadManualTokenEntry: (setupWindow, authorizeUrl) =>
|
}),
|
||||||
loadAnilistManualTokenEntry({
|
redirectUri: ANILIST_REDIRECT_URI,
|
||||||
setupWindow: setupWindow as BrowserWindow,
|
developerSettingsUrl: ANILIST_DEVELOPER_SETTINGS_URL,
|
||||||
authorizeUrl,
|
isAllowedExternalUrl: (url) => isAllowedAnilistExternalUrl(url),
|
||||||
developerSettingsUrl: ANILIST_DEVELOPER_SETTINGS_URL,
|
isAllowedNavigationUrl: (url) => isAllowedAnilistSetupNavigationUrl(url),
|
||||||
logWarn: (message, data) => logger.warn(message, data),
|
logWarn: (message, details) => logger.warn(message, details),
|
||||||
}),
|
logError: (message, details) => logger.error(message, details),
|
||||||
redirectUri: ANILIST_REDIRECT_URI,
|
clearSetupWindow: () => {
|
||||||
developerSettingsUrl: ANILIST_DEVELOPER_SETTINGS_URL,
|
appState.anilistSetupWindow = null;
|
||||||
isAllowedExternalUrl: (url) => isAllowedAnilistExternalUrl(url),
|
|
||||||
isAllowedNavigationUrl: (url) => isAllowedAnilistSetupNavigationUrl(url),
|
|
||||||
logWarn: (message, details) => logger.warn(message, details),
|
|
||||||
logError: (message, details) => logger.error(message, details),
|
|
||||||
clearSetupWindow: () => {
|
|
||||||
appState.anilistSetupWindow = null;
|
|
||||||
},
|
|
||||||
setSetupPageOpened: (opened) => {
|
|
||||||
appState.anilistSetupPageOpened = opened;
|
|
||||||
},
|
|
||||||
setSetupWindow: (setupWindow) => {
|
|
||||||
appState.anilistSetupWindow = setupWindow as BrowserWindow;
|
|
||||||
},
|
|
||||||
openExternal: (url) => {
|
|
||||||
void shell.openExternal(url);
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
);
|
setSetupPageOpened: (opened) => {
|
||||||
|
appState.anilistSetupPageOpened = opened;
|
||||||
const openAnilistSetupWindowHandler = createOpenAnilistSetupWindowHandler(
|
},
|
||||||
buildOpenAnilistSetupWindowMainDepsHandler(),
|
setSetupWindow: (setupWindow) => {
|
||||||
);
|
appState.anilistSetupWindow = setupWindow as BrowserWindow;
|
||||||
|
},
|
||||||
|
openExternal: (url) => {
|
||||||
|
void shell.openExternal(url);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
refreshAnilistClientSecretState,
|
refreshAnilistClientSecretState,
|
||||||
@@ -4191,7 +4099,7 @@ const rememberAnilistAttemptedUpdate = (key: string): void => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const buildLoadSubtitlePositionMainDepsHandler = createBuildLoadSubtitlePositionMainDepsHandler({
|
const loadSubtitlePosition = createLoadSubtitlePositionHandler({
|
||||||
loadSubtitlePositionCore: () =>
|
loadSubtitlePositionCore: () =>
|
||||||
loadSubtitlePositionCore({
|
loadSubtitlePositionCore({
|
||||||
currentMediaPath: appState.currentMediaPath,
|
currentMediaPath: appState.currentMediaPath,
|
||||||
@@ -4202,10 +4110,8 @@ const buildLoadSubtitlePositionMainDepsHandler = createBuildLoadSubtitlePosition
|
|||||||
appState.subtitlePosition = position;
|
appState.subtitlePosition = position;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const loadSubtitlePositionMainDeps = buildLoadSubtitlePositionMainDepsHandler();
|
|
||||||
const loadSubtitlePosition = createLoadSubtitlePositionHandler(loadSubtitlePositionMainDeps);
|
|
||||||
|
|
||||||
const buildSaveSubtitlePositionMainDepsHandler = createBuildSaveSubtitlePositionMainDepsHandler({
|
const saveSubtitlePosition = createSaveSubtitlePositionHandler({
|
||||||
saveSubtitlePositionCore: (position) => {
|
saveSubtitlePositionCore: (position) => {
|
||||||
saveSubtitlePositionCore({
|
saveSubtitlePositionCore({
|
||||||
position,
|
position,
|
||||||
@@ -4223,8 +4129,6 @@ const buildSaveSubtitlePositionMainDepsHandler = createBuildSaveSubtitlePosition
|
|||||||
appState.subtitlePosition = position;
|
appState.subtitlePosition = position;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
const saveSubtitlePositionMainDeps = buildSaveSubtitlePositionMainDepsHandler();
|
|
||||||
const saveSubtitlePosition = createSaveSubtitlePositionHandler(saveSubtitlePositionMainDeps);
|
|
||||||
|
|
||||||
registerSubminerProtocolClient();
|
registerSubminerProtocolClient();
|
||||||
let flushPendingMpvLogWrites = (): void => {};
|
let flushPendingMpvLogWrites = (): void => {};
|
||||||
@@ -4377,9 +4281,7 @@ const resolveLegacyVocabularyPos = async (row: {
|
|||||||
return null;
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const immersionTrackerStartupMainDeps: Parameters<
|
const immersionTrackerStartupMainDeps: ImmersionTrackerStartupDeps = {
|
||||||
typeof createBuildImmersionTrackerStartupMainDepsHandler
|
|
||||||
>[0] = {
|
|
||||||
getResolvedConfig: () => configService.getConfig(),
|
getResolvedConfig: () => configService.getConfig(),
|
||||||
getConfiguredDbPath: () => immersionMediaRuntime.getConfiguredDbPath(),
|
getConfiguredDbPath: () => immersionMediaRuntime.getConfiguredDbPath(),
|
||||||
createTrackerService: (params) =>
|
createTrackerService: (params) =>
|
||||||
@@ -4437,7 +4339,7 @@ const immersionTrackerStartupMainDeps: Parameters<
|
|||||||
logWarn: (message, details) => logger.warn(message, details),
|
logWarn: (message, details) => logger.warn(message, details),
|
||||||
};
|
};
|
||||||
const createImmersionTrackerStartup = createImmersionTrackerStartupHandler(
|
const createImmersionTrackerStartup = createImmersionTrackerStartupHandler(
|
||||||
createBuildImmersionTrackerStartupMainDepsHandler(immersionTrackerStartupMainDeps)(),
|
immersionTrackerStartupMainDeps,
|
||||||
);
|
);
|
||||||
const recordSubtitleMiningContext = (context: SubtitleMiningContext | null): void => {
|
const recordSubtitleMiningContext = (context: SubtitleMiningContext | null): void => {
|
||||||
pendingSubtitleMiningContext = context;
|
pendingSubtitleMiningContext = context;
|
||||||
@@ -5538,8 +5440,8 @@ const {
|
|||||||
buildRegisterGlobalShortcutsMainDeps: (getConfiguredShortcutsHandler) => ({
|
buildRegisterGlobalShortcutsMainDeps: (getConfiguredShortcutsHandler) => ({
|
||||||
getConfiguredShortcuts: () => getConfiguredShortcutsHandler(),
|
getConfiguredShortcuts: () => getConfiguredShortcutsHandler(),
|
||||||
registerGlobalShortcutsCore,
|
registerGlobalShortcutsCore,
|
||||||
toggleVisibleOverlay: () => toggleVisibleOverlay(),
|
onToggleVisibleOverlay: () => toggleVisibleOverlay(),
|
||||||
openYomitanSettings: () => openDictionarySettings(),
|
onOpenYomitanSettings: () => openDictionarySettings(),
|
||||||
isDev,
|
isDev,
|
||||||
getMainWindow: () => overlayManager.getMainWindow(),
|
getMainWindow: () => overlayManager.getMainWindow(),
|
||||||
}),
|
}),
|
||||||
@@ -5668,8 +5570,8 @@ const cycleSecondarySubMode = createCycleSecondarySubModeRuntimeHandler({
|
|||||||
setLastSecondarySubToggleAtMs: (timestampMs: number) => {
|
setLastSecondarySubToggleAtMs: (timestampMs: number) => {
|
||||||
appState.lastSecondarySubToggleAtMs = timestampMs;
|
appState.lastSecondarySubToggleAtMs = timestampMs;
|
||||||
},
|
},
|
||||||
broadcastToOverlayWindows: (channel, mode) => {
|
broadcastSecondarySubMode: (mode) => {
|
||||||
overlayManager.broadcastToOverlayWindows(channel, mode);
|
overlayManager.broadcastToOverlayWindows('secondary-subtitle:mode', mode);
|
||||||
},
|
},
|
||||||
showMpvOsd: (text: string) => showConfiguredPlaybackFeedback(text),
|
showMpvOsd: (text: string) => showConfiguredPlaybackFeedback(text),
|
||||||
},
|
},
|
||||||
@@ -5680,90 +5582,62 @@ function setSecondarySubMode(mode: SecondarySubMode): void {
|
|||||||
appState.secondarySubMode = mode;
|
appState.secondarySubMode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const buildUpdateLastCardFromClipboardMainDepsHandler =
|
const updateLastCardFromClipboardHandler = createUpdateLastCardFromClipboardHandler({
|
||||||
createBuildUpdateLastCardFromClipboardMainDepsHandler({
|
getAnkiIntegration: () => appState.ankiIntegration,
|
||||||
getAnkiIntegration: () => appState.ankiIntegration,
|
readClipboardText: () => clipboard.readText(),
|
||||||
readClipboardText: () => clipboard.readText(),
|
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
||||||
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
updateLastCardFromClipboardCore,
|
||||||
updateLastCardFromClipboardCore,
|
});
|
||||||
});
|
|
||||||
const updateLastCardFromClipboardMainDeps = buildUpdateLastCardFromClipboardMainDepsHandler();
|
|
||||||
const updateLastCardFromClipboardHandler = createUpdateLastCardFromClipboardHandler(
|
|
||||||
updateLastCardFromClipboardMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildRefreshKnownWordCacheMainDepsHandler = createBuildRefreshKnownWordCacheMainDepsHandler({
|
const refreshKnownWordCacheHandler = createRefreshKnownWordCacheHandler({
|
||||||
getAnkiIntegration: () => appState.ankiIntegration,
|
getAnkiIntegration: () => appState.ankiIntegration,
|
||||||
missingIntegrationMessage: 'AnkiConnect integration not enabled',
|
missingIntegrationMessage: 'AnkiConnect integration not enabled',
|
||||||
});
|
});
|
||||||
const refreshKnownWordCacheMainDeps = buildRefreshKnownWordCacheMainDepsHandler();
|
|
||||||
const refreshKnownWordCacheHandler = createRefreshKnownWordCacheHandler(
|
|
||||||
refreshKnownWordCacheMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildTriggerFieldGroupingMainDepsHandler = createBuildTriggerFieldGroupingMainDepsHandler({
|
const triggerFieldGroupingHandler = createTriggerFieldGroupingHandler({
|
||||||
getAnkiIntegration: () => appState.ankiIntegration,
|
getAnkiIntegration: () => appState.ankiIntegration,
|
||||||
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
||||||
triggerFieldGroupingCore,
|
triggerFieldGroupingCore,
|
||||||
});
|
});
|
||||||
const triggerFieldGroupingMainDeps = buildTriggerFieldGroupingMainDepsHandler();
|
|
||||||
const triggerFieldGroupingHandler = createTriggerFieldGroupingHandler(triggerFieldGroupingMainDeps);
|
|
||||||
|
|
||||||
const buildMarkLastCardAsAudioCardMainDepsHandler =
|
const markLastCardAsAudioCardHandler = createMarkLastCardAsAudioCardHandler({
|
||||||
createBuildMarkLastCardAsAudioCardMainDepsHandler({
|
getAnkiIntegration: () => appState.ankiIntegration,
|
||||||
getAnkiIntegration: () => appState.ankiIntegration,
|
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
||||||
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
markLastCardAsAudioCardCore,
|
||||||
markLastCardAsAudioCardCore,
|
});
|
||||||
});
|
|
||||||
const markLastCardAsAudioCardMainDeps = buildMarkLastCardAsAudioCardMainDepsHandler();
|
|
||||||
const markLastCardAsAudioCardHandler = createMarkLastCardAsAudioCardHandler(
|
|
||||||
markLastCardAsAudioCardMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildMineSentenceCardMainDepsHandler = createBuildMineSentenceCardMainDepsHandler({
|
const mineSentenceCardHandler = createMineSentenceCardHandler({
|
||||||
getAnkiIntegration: () => appState.ankiIntegration,
|
getAnkiIntegration: () => appState.ankiIntegration,
|
||||||
getMpvClient: () => appState.mpvClient,
|
getMpvClient: () => appState.mpvClient,
|
||||||
getPrimarySubtitle: () => captureCurrentPrimarySubtitleMiningContext(),
|
getPrimarySubtitle: () => captureCurrentPrimarySubtitleMiningContext(),
|
||||||
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
||||||
mineSentenceCardCore,
|
mineSentenceCardCore,
|
||||||
});
|
});
|
||||||
const mineSentenceCardHandler = createMineSentenceCardHandler(
|
|
||||||
buildMineSentenceCardMainDepsHandler(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildHandleMultiCopyDigitMainDepsHandler = createBuildHandleMultiCopyDigitMainDepsHandler({
|
const handleMultiCopyDigitHandler = createHandleMultiCopyDigitHandler({
|
||||||
getSubtitleTimingTracker: () => appState.subtitleTimingTracker,
|
getSubtitleTimingTracker: () => appState.subtitleTimingTracker,
|
||||||
writeClipboardText: (text) => clipboard.writeText(text),
|
writeClipboardText: (text) => clipboard.writeText(text),
|
||||||
showMpvOsd: (text) => showConfiguredPlaybackFeedback(text),
|
showMpvOsd: (text) => showConfiguredPlaybackFeedback(text),
|
||||||
handleMultiCopyDigitCore,
|
handleMultiCopyDigitCore,
|
||||||
});
|
});
|
||||||
const handleMultiCopyDigitMainDeps = buildHandleMultiCopyDigitMainDepsHandler();
|
|
||||||
const handleMultiCopyDigitHandler = createHandleMultiCopyDigitHandler(handleMultiCopyDigitMainDeps);
|
|
||||||
|
|
||||||
const buildCopyCurrentSubtitleMainDepsHandler = createBuildCopyCurrentSubtitleMainDepsHandler({
|
const copyCurrentSubtitleHandler = createCopyCurrentSubtitleHandler({
|
||||||
getSubtitleTimingTracker: () => appState.subtitleTimingTracker,
|
getSubtitleTimingTracker: () => appState.subtitleTimingTracker,
|
||||||
writeClipboardText: (text) => clipboard.writeText(text),
|
writeClipboardText: (text) => clipboard.writeText(text),
|
||||||
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
||||||
copyCurrentSubtitleCore,
|
copyCurrentSubtitleCore,
|
||||||
});
|
});
|
||||||
const copyCurrentSubtitleMainDeps = buildCopyCurrentSubtitleMainDepsHandler();
|
|
||||||
const copyCurrentSubtitleHandler = createCopyCurrentSubtitleHandler(copyCurrentSubtitleMainDeps);
|
|
||||||
|
|
||||||
const buildHandleMineSentenceDigitMainDepsHandler =
|
const handleMineSentenceDigitHandler = createHandleMineSentenceDigitHandler({
|
||||||
createBuildHandleMineSentenceDigitMainDepsHandler({
|
getSubtitleTimingTracker: () => appState.subtitleTimingTracker,
|
||||||
getSubtitleTimingTracker: () => appState.subtitleTimingTracker,
|
getAnkiIntegration: () => appState.ankiIntegration,
|
||||||
getAnkiIntegration: () => appState.ankiIntegration,
|
getCurrentSecondarySubText: () => appState.mpvClient?.currentSecondarySubText || undefined,
|
||||||
getCurrentSecondarySubText: () => appState.mpvClient?.currentSecondarySubText || undefined,
|
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
||||||
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
logError: (message, err) => {
|
||||||
logError: (message, err) => {
|
logger.error(message, err);
|
||||||
logger.error(message, err);
|
},
|
||||||
},
|
handleMineSentenceDigitCore,
|
||||||
handleMineSentenceDigitCore,
|
});
|
||||||
});
|
|
||||||
const handleMineSentenceDigitMainDeps = buildHandleMineSentenceDigitMainDepsHandler();
|
|
||||||
const handleMineSentenceDigitHandler = createHandleMineSentenceDigitHandler(
|
|
||||||
handleMineSentenceDigitMainDeps,
|
|
||||||
);
|
|
||||||
const {
|
const {
|
||||||
setVisibleOverlayVisible: setVisibleOverlayVisibleHandler,
|
setVisibleOverlayVisible: setVisibleOverlayVisibleHandler,
|
||||||
toggleVisibleOverlay: toggleVisibleOverlayHandler,
|
toggleVisibleOverlay: toggleVisibleOverlayHandler,
|
||||||
@@ -5779,29 +5653,19 @@ const {
|
|||||||
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(),
|
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const buildHandleOverlayModalClosedMainDepsHandler =
|
const handleOverlayModalClosedHandler = createHandleOverlayModalClosedHandler({
|
||||||
createBuildHandleOverlayModalClosedMainDepsHandler({
|
handleOverlayModalClosedRuntime: (modal) => overlayModalRuntime.handleOverlayModalClosed(modal),
|
||||||
handleOverlayModalClosedRuntime: (modal) => overlayModalRuntime.handleOverlayModalClosed(modal),
|
});
|
||||||
});
|
|
||||||
const handleOverlayModalClosedMainDeps = buildHandleOverlayModalClosedMainDepsHandler();
|
|
||||||
const handleOverlayModalClosedHandler = createHandleOverlayModalClosedHandler(
|
|
||||||
handleOverlayModalClosedMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildAppendClipboardVideoToQueueMainDepsHandler =
|
const appendClipboardVideoToQueueHandler = createAppendClipboardVideoToQueueHandler({
|
||||||
createBuildAppendClipboardVideoToQueueMainDepsHandler({
|
appendClipboardVideoToQueueRuntime,
|
||||||
appendClipboardVideoToQueueRuntime,
|
getMpvClient: () => appState.mpvClient,
|
||||||
getMpvClient: () => appState.mpvClient,
|
readClipboardText: () => clipboard.readText(),
|
||||||
readClipboardText: () => clipboard.readText(),
|
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
||||||
showMpvOsd: (text) => overlayNotificationsRuntime.showConfiguredStatusNotification(text),
|
sendMpvCommand: (command) => {
|
||||||
sendMpvCommand: (command) => {
|
sendMpvCommandRuntime(appState.mpvClient, command);
|
||||||
sendMpvCommandRuntime(appState.mpvClient, command);
|
},
|
||||||
},
|
});
|
||||||
});
|
|
||||||
const appendClipboardVideoToQueueMainDeps = buildAppendClipboardVideoToQueueMainDepsHandler();
|
|
||||||
const appendClipboardVideoToQueueHandler = createAppendClipboardVideoToQueueHandler(
|
|
||||||
appendClipboardVideoToQueueMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
async function dispatchSessionAction(request: SessionActionDispatchRequest): Promise<void> {
|
async function dispatchSessionAction(request: SessionActionDispatchRequest): Promise<void> {
|
||||||
await dispatchSessionActionCore(request, {
|
await dispatchSessionActionCore(request, {
|
||||||
|
|||||||
@@ -425,25 +425,6 @@ test('subtitle annotation updates invalidate prefetched tokenizations before ref
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('subtitle processing controller resumes prefetch on settle, not on its emits', () => {
|
|
||||||
const source = readMainSource();
|
|
||||||
const depsBlock = source.match(
|
|
||||||
/createBuildSubtitleProcessingControllerMainDepsHandler\(\{(?<body>[\s\S]*?)\n \}\);/,
|
|
||||||
)?.groups?.body;
|
|
||||||
|
|
||||||
assert.ok(depsBlock);
|
|
||||||
// A controller emit can be the provisional plain payload sent before the
|
|
||||||
// scan runs, so it must not release the prefetch pause.
|
|
||||||
assert.match(
|
|
||||||
depsBlock,
|
|
||||||
/emitSubtitle: \(payload\) => emitSubtitlePayload\(payload, \{ resumePrefetch: false \}\),/,
|
|
||||||
);
|
|
||||||
assert.match(
|
|
||||||
depsBlock,
|
|
||||||
/onProcessingSettled: \(\) => \{\s+subtitlePrefetchService\?\.resume\(\);/,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('annotation upgrades skip the duplicate basic websocket event', () => {
|
test('annotation upgrades skip the duplicate basic websocket event', () => {
|
||||||
const source = readMainSource();
|
const source = readMainSource();
|
||||||
const emitBlock = source.match(
|
const emitBlock = source.match(
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
import type {
|
|
||||||
createEnsureAnilistMediaGuessHandler,
|
|
||||||
createMaybeProbeAnilistDurationHandler,
|
|
||||||
} from './anilist-media-guess';
|
|
||||||
|
|
||||||
type MaybeProbeAnilistDurationMainDeps = Parameters<
|
|
||||||
typeof createMaybeProbeAnilistDurationHandler
|
|
||||||
>[0];
|
|
||||||
type EnsureAnilistMediaGuessMainDeps = Parameters<typeof createEnsureAnilistMediaGuessHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildMaybeProbeAnilistDurationMainDepsHandler(
|
|
||||||
deps: MaybeProbeAnilistDurationMainDeps,
|
|
||||||
) {
|
|
||||||
return (): MaybeProbeAnilistDurationMainDeps => ({
|
|
||||||
getState: () => deps.getState(),
|
|
||||||
setState: (state) => deps.setState(state),
|
|
||||||
durationRetryIntervalMs: deps.durationRetryIntervalMs,
|
|
||||||
now: () => deps.now(),
|
|
||||||
requestMpvDuration: () => deps.requestMpvDuration(),
|
|
||||||
logWarn: (message: string, error: unknown) => deps.logWarn(message, error),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildEnsureAnilistMediaGuessMainDepsHandler(
|
|
||||||
deps: EnsureAnilistMediaGuessMainDeps,
|
|
||||||
) {
|
|
||||||
return (): EnsureAnilistMediaGuessMainDeps => ({
|
|
||||||
getState: () => deps.getState(),
|
|
||||||
setState: (state) => deps.setState(state),
|
|
||||||
resolveMediaPathForJimaku: (currentMediaPath) =>
|
|
||||||
deps.resolveMediaPathForJimaku(currentMediaPath),
|
|
||||||
getCurrentMediaPath: () => deps.getCurrentMediaPath(),
|
|
||||||
getCurrentMediaTitle: () => deps.getCurrentMediaTitle(),
|
|
||||||
guessAnilistMediaInfo: (mediaPath, mediaTitle) =>
|
|
||||||
deps.guessAnilistMediaInfo(mediaPath, mediaTitle),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,90 +0,0 @@
|
|||||||
import type {
|
|
||||||
createGetAnilistMediaGuessRuntimeStateHandler,
|
|
||||||
createGetCurrentAnilistMediaKeyHandler,
|
|
||||||
createRecordAnilistMediaDurationHandler,
|
|
||||||
createResetAnilistMediaGuessStateHandler,
|
|
||||||
createResetAnilistMediaTrackingHandler,
|
|
||||||
createSetAnilistMediaGuessRuntimeStateHandler,
|
|
||||||
} from './anilist-media-state';
|
|
||||||
|
|
||||||
type GetCurrentAnilistMediaKeyMainDeps = Parameters<
|
|
||||||
typeof createGetCurrentAnilistMediaKeyHandler
|
|
||||||
>[0];
|
|
||||||
type ResetAnilistMediaTrackingMainDeps = Parameters<
|
|
||||||
typeof createResetAnilistMediaTrackingHandler
|
|
||||||
>[0];
|
|
||||||
type GetAnilistMediaGuessRuntimeStateMainDeps = Parameters<
|
|
||||||
typeof createGetAnilistMediaGuessRuntimeStateHandler
|
|
||||||
>[0];
|
|
||||||
type SetAnilistMediaGuessRuntimeStateMainDeps = Parameters<
|
|
||||||
typeof createSetAnilistMediaGuessRuntimeStateHandler
|
|
||||||
>[0];
|
|
||||||
type RecordAnilistMediaDurationMainDeps = Parameters<
|
|
||||||
typeof createRecordAnilistMediaDurationHandler
|
|
||||||
>[0];
|
|
||||||
type ResetAnilistMediaGuessStateMainDeps = Parameters<
|
|
||||||
typeof createResetAnilistMediaGuessStateHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildGetCurrentAnilistMediaKeyMainDepsHandler(
|
|
||||||
deps: GetCurrentAnilistMediaKeyMainDeps,
|
|
||||||
) {
|
|
||||||
return (): GetCurrentAnilistMediaKeyMainDeps => ({
|
|
||||||
getCurrentMediaPath: () => deps.getCurrentMediaPath(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildResetAnilistMediaTrackingMainDepsHandler(
|
|
||||||
deps: ResetAnilistMediaTrackingMainDeps,
|
|
||||||
) {
|
|
||||||
return (): ResetAnilistMediaTrackingMainDeps => ({
|
|
||||||
setMediaKey: (value) => deps.setMediaKey(value),
|
|
||||||
setMediaDurationSec: (value) => deps.setMediaDurationSec(value),
|
|
||||||
setMediaGuess: (value) => deps.setMediaGuess(value),
|
|
||||||
setMediaGuessPromise: (value) => deps.setMediaGuessPromise(value),
|
|
||||||
setLastDurationProbeAtMs: (value: number) => deps.setLastDurationProbeAtMs(value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildGetAnilistMediaGuessRuntimeStateMainDepsHandler(
|
|
||||||
deps: GetAnilistMediaGuessRuntimeStateMainDeps,
|
|
||||||
) {
|
|
||||||
return (): GetAnilistMediaGuessRuntimeStateMainDeps => ({
|
|
||||||
getMediaKey: () => deps.getMediaKey(),
|
|
||||||
getMediaDurationSec: () => deps.getMediaDurationSec(),
|
|
||||||
getMediaGuess: () => deps.getMediaGuess(),
|
|
||||||
getMediaGuessPromise: () => deps.getMediaGuessPromise(),
|
|
||||||
getLastDurationProbeAtMs: () => deps.getLastDurationProbeAtMs(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildSetAnilistMediaGuessRuntimeStateMainDepsHandler(
|
|
||||||
deps: SetAnilistMediaGuessRuntimeStateMainDeps,
|
|
||||||
) {
|
|
||||||
return (): SetAnilistMediaGuessRuntimeStateMainDeps => ({
|
|
||||||
setMediaKey: (value) => deps.setMediaKey(value),
|
|
||||||
setMediaDurationSec: (value) => deps.setMediaDurationSec(value),
|
|
||||||
setMediaGuess: (value) => deps.setMediaGuess(value),
|
|
||||||
setMediaGuessPromise: (value) => deps.setMediaGuessPromise(value),
|
|
||||||
setLastDurationProbeAtMs: (value: number) => deps.setLastDurationProbeAtMs(value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildRecordAnilistMediaDurationMainDepsHandler(
|
|
||||||
deps: RecordAnilistMediaDurationMainDeps,
|
|
||||||
) {
|
|
||||||
return (): RecordAnilistMediaDurationMainDeps => ({
|
|
||||||
getCurrentMediaKey: () => deps.getCurrentMediaKey(),
|
|
||||||
getState: () => deps.getState(),
|
|
||||||
setState: (state) => deps.setState(state),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildResetAnilistMediaGuessStateMainDepsHandler(
|
|
||||||
deps: ResetAnilistMediaGuessStateMainDeps,
|
|
||||||
) {
|
|
||||||
return (): ResetAnilistMediaGuessStateMainDeps => ({
|
|
||||||
setMediaGuess: (value) => deps.setMediaGuess(value),
|
|
||||||
setMediaGuessPromise: (value) => deps.setMediaGuessPromise(value),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
import type {
|
|
||||||
createMaybeRunAnilistPostWatchUpdateHandler,
|
|
||||||
createProcessNextAnilistRetryUpdateHandler,
|
|
||||||
} from './anilist-post-watch';
|
|
||||||
|
|
||||||
type ProcessNextAnilistRetryUpdateMainDeps = Parameters<
|
|
||||||
typeof createProcessNextAnilistRetryUpdateHandler
|
|
||||||
>[0];
|
|
||||||
type MaybeRunAnilistPostWatchUpdateMainDeps = Parameters<
|
|
||||||
typeof createMaybeRunAnilistPostWatchUpdateHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildProcessNextAnilistRetryUpdateMainDepsHandler(
|
|
||||||
deps: ProcessNextAnilistRetryUpdateMainDeps,
|
|
||||||
) {
|
|
||||||
return (): ProcessNextAnilistRetryUpdateMainDeps => ({
|
|
||||||
nextReady: () => deps.nextReady(),
|
|
||||||
refreshRetryQueueState: () => deps.refreshRetryQueueState(),
|
|
||||||
setLastAttemptAt: (value: number) => deps.setLastAttemptAt(value),
|
|
||||||
setLastError: (value: string | null) => deps.setLastError(value),
|
|
||||||
refreshAnilistClientSecretState: () => deps.refreshAnilistClientSecretState(),
|
|
||||||
updateAnilistPostWatchProgress: (
|
|
||||||
accessToken: string,
|
|
||||||
title: string,
|
|
||||||
episode: number,
|
|
||||||
season?: number | null,
|
|
||||||
mediaId?: number | null,
|
|
||||||
) => deps.updateAnilistPostWatchProgress(accessToken, title, episode, season, mediaId),
|
|
||||||
markSuccess: (key: string) => deps.markSuccess(key),
|
|
||||||
rememberAttemptedUpdateKey: (key: string) => deps.rememberAttemptedUpdateKey(key),
|
|
||||||
markFailure: (key: string, message: string) => deps.markFailure(key, message),
|
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
|
||||||
now: () => deps.now(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildMaybeRunAnilistPostWatchUpdateMainDepsHandler(
|
|
||||||
deps: MaybeRunAnilistPostWatchUpdateMainDeps,
|
|
||||||
) {
|
|
||||||
return (): MaybeRunAnilistPostWatchUpdateMainDeps => ({
|
|
||||||
getInFlight: () => deps.getInFlight(),
|
|
||||||
setInFlight: (value: boolean) => deps.setInFlight(value),
|
|
||||||
getResolvedConfig: () => deps.getResolvedConfig(),
|
|
||||||
isAnilistTrackingEnabled: (config) => deps.isAnilistTrackingEnabled(config),
|
|
||||||
getCurrentMediaKey: () => deps.getCurrentMediaKey(),
|
|
||||||
hasMpvClient: () => deps.hasMpvClient(),
|
|
||||||
getTrackedMediaKey: () => deps.getTrackedMediaKey(),
|
|
||||||
resetTrackedMedia: (mediaKey) => deps.resetTrackedMedia(mediaKey),
|
|
||||||
getWatchedSeconds: () => deps.getWatchedSeconds(),
|
|
||||||
maybeProbeAnilistDuration: (mediaKey: string, options) =>
|
|
||||||
deps.maybeProbeAnilistDuration(mediaKey, options),
|
|
||||||
ensureAnilistMediaGuess: (mediaKey: string) => deps.ensureAnilistMediaGuess(mediaKey),
|
|
||||||
hasAttemptedUpdateKey: (key: string) => deps.hasAttemptedUpdateKey(key),
|
|
||||||
processNextAnilistRetryUpdate: () => deps.processNextAnilistRetryUpdate(),
|
|
||||||
refreshAnilistClientSecretState: () => deps.refreshAnilistClientSecretState(),
|
|
||||||
enqueueRetry: (
|
|
||||||
key: string,
|
|
||||||
title: string,
|
|
||||||
episode: number,
|
|
||||||
season?: number | null,
|
|
||||||
mediaId?: number | null,
|
|
||||||
) => deps.enqueueRetry(key, title, episode, season, mediaId),
|
|
||||||
getCurrentMediaTitle: deps.getCurrentMediaTitle
|
|
||||||
? () => deps.getCurrentMediaTitle!()
|
|
||||||
: undefined,
|
|
||||||
resolvePinnedAnilistMediaId: deps.resolvePinnedAnilistMediaId
|
|
||||||
? (input) => deps.resolvePinnedAnilistMediaId!(input)
|
|
||||||
: undefined,
|
|
||||||
markRetryFailure: (key: string, message: string) => deps.markRetryFailure(key, message),
|
|
||||||
markRetrySuccess: (key: string) => deps.markRetrySuccess(key),
|
|
||||||
refreshRetryQueueState: () => deps.refreshRetryQueueState(),
|
|
||||||
updateAnilistPostWatchProgress: (
|
|
||||||
accessToken: string,
|
|
||||||
title: string,
|
|
||||||
episode: number,
|
|
||||||
season?: number | null,
|
|
||||||
mediaId?: number | null,
|
|
||||||
) => deps.updateAnilistPostWatchProgress(accessToken, title, episode, season, mediaId),
|
|
||||||
rememberAttemptedUpdateKey: (key: string) => deps.rememberAttemptedUpdateKey(key),
|
|
||||||
showMpvOsd: (message: string) => deps.showMpvOsd(message),
|
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
|
||||||
logWarn: (message: string) => deps.logWarn(message),
|
|
||||||
minWatchSeconds: deps.minWatchSeconds,
|
|
||||||
minWatchRatio: deps.minWatchRatio,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
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 => ({
|
|
||||||
getNotificationType: deps.getNotificationType ? () => deps.getNotificationType?.() : undefined,
|
|
||||||
hasMpvClient: () => deps.hasMpvClient(),
|
|
||||||
showMpvOsd: (message: string) => deps.showMpvOsd(message),
|
|
||||||
showOverlayNotification: deps.showOverlayNotification
|
|
||||||
? (payload) => deps.showOverlayNotification?.(payload)
|
|
||||||
: undefined,
|
|
||||||
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),
|
|
||||||
logDebug: (message: string, details?: unknown) => deps.logDebug(message, details),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
import type { createOpenAnilistSetupWindowHandler } from './anilist-setup-window';
|
|
||||||
|
|
||||||
type OpenAnilistSetupWindowMainDeps = Parameters<typeof createOpenAnilistSetupWindowHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildOpenAnilistSetupWindowMainDepsHandler(
|
|
||||||
deps: OpenAnilistSetupWindowMainDeps,
|
|
||||||
) {
|
|
||||||
return (): OpenAnilistSetupWindowMainDeps => ({
|
|
||||||
maybeFocusExistingSetupWindow: () => deps.maybeFocusExistingSetupWindow(),
|
|
||||||
createSetupWindow: () => deps.createSetupWindow(),
|
|
||||||
buildAuthorizeUrl: () => deps.buildAuthorizeUrl(),
|
|
||||||
consumeCallbackUrl: (rawUrl: string) => deps.consumeCallbackUrl(rawUrl),
|
|
||||||
openSetupInBrowser: (authorizeUrl: string) => deps.openSetupInBrowser(authorizeUrl),
|
|
||||||
loadManualTokenEntry: (setupWindow, authorizeUrl: string) =>
|
|
||||||
deps.loadManualTokenEntry(setupWindow, authorizeUrl),
|
|
||||||
redirectUri: deps.redirectUri,
|
|
||||||
developerSettingsUrl: deps.developerSettingsUrl,
|
|
||||||
isAllowedExternalUrl: (url: string) => deps.isAllowedExternalUrl(url),
|
|
||||||
isAllowedNavigationUrl: (url: string) => deps.isAllowedNavigationUrl(url),
|
|
||||||
logWarn: (message: string, details?: unknown) => deps.logWarn(message, details),
|
|
||||||
logError: (message: string, details: unknown) => deps.logError(message, details),
|
|
||||||
clearSetupWindow: () => deps.clearSetupWindow(),
|
|
||||||
setSetupPageOpened: (opened: boolean) => deps.setSetupPageOpened(opened),
|
|
||||||
setSetupWindow: (setupWindow) => deps.setSetupWindow(setupWindow),
|
|
||||||
openExternal: (url: string) => deps.openExternal(url),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import type { createRefreshAnilistClientSecretStateHandler } from './anilist-token-refresh';
|
|
||||||
|
|
||||||
type RefreshAnilistClientSecretStateMainDeps = Parameters<
|
|
||||||
typeof createRefreshAnilistClientSecretStateHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildRefreshAnilistClientSecretStateMainDepsHandler(
|
|
||||||
deps: RefreshAnilistClientSecretStateMainDeps,
|
|
||||||
) {
|
|
||||||
return (): RefreshAnilistClientSecretStateMainDeps => ({
|
|
||||||
getResolvedConfig: () => deps.getResolvedConfig(),
|
|
||||||
isAnilistTrackingEnabled: (config) => deps.isAnilistTrackingEnabled(config),
|
|
||||||
getCachedAccessToken: () => deps.getCachedAccessToken(),
|
|
||||||
setCachedAccessToken: (token) => deps.setCachedAccessToken(token),
|
|
||||||
saveStoredToken: (token: string) => deps.saveStoredToken(token),
|
|
||||||
loadStoredToken: () => deps.loadStoredToken(),
|
|
||||||
setClientSecretState: (state) => deps.setClientSecretState(state),
|
|
||||||
getAnilistSetupPageOpened: () => deps.getAnilistSetupPageOpened(),
|
|
||||||
setAnilistSetupPageOpened: (opened: boolean) => deps.setAnilistSetupPageOpened(opened),
|
|
||||||
openAnilistSetupWindow: () => deps.openAnilistSetupWindow(),
|
|
||||||
now: () => deps.now(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
import type { createRefreshKnownWordCacheHandler, PrimarySubtitle } from './anki-actions';
|
|
||||||
|
|
||||||
type RefreshKnownWordCacheMainDeps = Parameters<typeof createRefreshKnownWordCacheHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildUpdateLastCardFromClipboardMainDepsHandler<TAnki>(deps: {
|
|
||||||
getAnkiIntegration: () => TAnki;
|
|
||||||
readClipboardText: () => string;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
updateLastCardFromClipboardCore: (options: {
|
|
||||||
ankiIntegration: TAnki;
|
|
||||||
readClipboardText: () => string;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => Promise<void>;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getAnkiIntegration: () => deps.getAnkiIntegration(),
|
|
||||||
readClipboardText: () => deps.readClipboardText(),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
updateLastCardFromClipboardCore: (options: {
|
|
||||||
ankiIntegration: TAnki;
|
|
||||||
readClipboardText: () => string;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => deps.updateLastCardFromClipboardCore(options),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildRefreshKnownWordCacheMainDepsHandler(
|
|
||||||
deps: RefreshKnownWordCacheMainDeps,
|
|
||||||
) {
|
|
||||||
return (): RefreshKnownWordCacheMainDeps => ({
|
|
||||||
getAnkiIntegration: () => deps.getAnkiIntegration(),
|
|
||||||
missingIntegrationMessage: deps.missingIntegrationMessage,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildTriggerFieldGroupingMainDepsHandler<TAnki>(deps: {
|
|
||||||
getAnkiIntegration: () => TAnki;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
triggerFieldGroupingCore: (options: {
|
|
||||||
ankiIntegration: TAnki;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => Promise<void>;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getAnkiIntegration: () => deps.getAnkiIntegration(),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
triggerFieldGroupingCore: (options: {
|
|
||||||
ankiIntegration: TAnki;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => deps.triggerFieldGroupingCore(options),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildMarkLastCardAsAudioCardMainDepsHandler<TAnki>(deps: {
|
|
||||||
getAnkiIntegration: () => TAnki;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
markLastCardAsAudioCardCore: (options: {
|
|
||||||
ankiIntegration: TAnki;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => Promise<void>;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getAnkiIntegration: () => deps.getAnkiIntegration(),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
markLastCardAsAudioCardCore: (options: {
|
|
||||||
ankiIntegration: TAnki;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => deps.markLastCardAsAudioCardCore(options),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildMineSentenceCardMainDepsHandler<TAnki, TMpv>(deps: {
|
|
||||||
getAnkiIntegration: () => TAnki;
|
|
||||||
getMpvClient: () => TMpv;
|
|
||||||
getPrimarySubtitle?: () => PrimarySubtitle | null;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
mineSentenceCardCore: (options: {
|
|
||||||
ankiIntegration: TAnki;
|
|
||||||
mpvClient: TMpv;
|
|
||||||
primarySubtitle?: PrimarySubtitle;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => Promise<boolean>;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getAnkiIntegration: () => deps.getAnkiIntegration(),
|
|
||||||
getMpvClient: () => deps.getMpvClient(),
|
|
||||||
...(deps.getPrimarySubtitle
|
|
||||||
? { getPrimarySubtitle: () => deps.getPrimarySubtitle?.() ?? null }
|
|
||||||
: {}),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
mineSentenceCardCore: (options: {
|
|
||||||
ankiIntegration: TAnki;
|
|
||||||
mpvClient: TMpv;
|
|
||||||
primarySubtitle?: PrimarySubtitle;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => deps.mineSentenceCardCore(options),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
import type { AppReadyRuntimeDepsFactoryInput } from '../app-lifecycle';
|
|
||||||
|
|
||||||
export function createBuildAppReadyRuntimeMainDepsHandler(deps: AppReadyRuntimeDepsFactoryInput) {
|
|
||||||
return (): AppReadyRuntimeDepsFactoryInput => ({
|
|
||||||
ensureDefaultConfigBootstrap: deps.ensureDefaultConfigBootstrap,
|
|
||||||
loadSubtitlePosition: deps.loadSubtitlePosition,
|
|
||||||
resolveKeybindings: deps.resolveKeybindings,
|
|
||||||
createMpvClient: deps.createMpvClient,
|
|
||||||
reloadConfig: deps.reloadConfig,
|
|
||||||
getResolvedConfig: deps.getResolvedConfig,
|
|
||||||
getConfigWarnings: deps.getConfigWarnings,
|
|
||||||
logConfigWarning: deps.logConfigWarning,
|
|
||||||
initRuntimeOptionsManager: deps.initRuntimeOptionsManager,
|
|
||||||
setSecondarySubMode: deps.setSecondarySubMode,
|
|
||||||
defaultSecondarySubMode: deps.defaultSecondarySubMode,
|
|
||||||
defaultWebsocketPort: deps.defaultWebsocketPort,
|
|
||||||
defaultAnnotationWebsocketPort: deps.defaultAnnotationWebsocketPort,
|
|
||||||
defaultTexthookerPort: deps.defaultTexthookerPort,
|
|
||||||
hasMpvWebsocketPlugin: deps.hasMpvWebsocketPlugin,
|
|
||||||
startSubtitleWebsocket: deps.startSubtitleWebsocket,
|
|
||||||
startAnnotationWebsocket: deps.startAnnotationWebsocket,
|
|
||||||
startTexthooker: deps.startTexthooker,
|
|
||||||
log: deps.log,
|
|
||||||
setLogLevel: deps.setLogLevel,
|
|
||||||
setLogRotation: deps.setLogRotation,
|
|
||||||
setLogFileToggles: deps.setLogFileToggles,
|
|
||||||
createMecabTokenizerAndCheck: deps.createMecabTokenizerAndCheck,
|
|
||||||
createSubtitleTimingTracker: deps.createSubtitleTimingTracker,
|
|
||||||
createImmersionTracker: deps.createImmersionTracker,
|
|
||||||
startJellyfinRemoteSession: deps.startJellyfinRemoteSession,
|
|
||||||
loadYomitanExtension: deps.loadYomitanExtension,
|
|
||||||
ensureYomitanExtensionLoaded: deps.ensureYomitanExtensionLoaded,
|
|
||||||
handleFirstRunSetup: deps.handleFirstRunSetup,
|
|
||||||
prewarmSubtitleDictionaries: deps.prewarmSubtitleDictionaries,
|
|
||||||
startBackgroundWarmups: deps.startBackgroundWarmups,
|
|
||||||
texthookerOnlyMode: deps.texthookerOnlyMode,
|
|
||||||
shouldAutoInitializeOverlayRuntimeFromConfig: deps.shouldAutoInitializeOverlayRuntimeFromConfig,
|
|
||||||
setVisibleOverlayVisible: deps.setVisibleOverlayVisible,
|
|
||||||
initializeOverlayRuntime: deps.initializeOverlayRuntime,
|
|
||||||
runHeadlessInitialCommand: deps.runHeadlessInitialCommand,
|
|
||||||
handleInitialArgs: deps.handleInitialArgs,
|
|
||||||
onCriticalConfigErrors: deps.onCriticalConfigErrors,
|
|
||||||
logDebug: deps.logDebug,
|
|
||||||
now: deps.now,
|
|
||||||
shouldRunHeadlessInitialCommand: deps.shouldRunHeadlessInitialCommand,
|
|
||||||
shouldUseMinimalStartup: deps.shouldUseMinimalStartup,
|
|
||||||
shouldSkipHeavyStartup: deps.shouldSkipHeavyStartup,
|
|
||||||
shouldHandleInitialArgsBeforeDeferredOverlayWarmup:
|
|
||||||
deps.shouldHandleInitialArgsBeforeDeferredOverlayWarmup,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
import type { CliArgs } from '../../cli/args';
|
|
||||||
|
|
||||||
export function createBuildHandleTexthookerOnlyModeTransitionMainDepsHandler(deps: {
|
|
||||||
isTexthookerOnlyMode: () => boolean;
|
|
||||||
setTexthookerOnlyMode: (enabled: boolean) => void;
|
|
||||||
commandNeedsOverlayStartupPrereqs: (args: CliArgs) => boolean;
|
|
||||||
ensureOverlayStartupPrereqs: () => void;
|
|
||||||
startBackgroundWarmups: () => void;
|
|
||||||
logInfo: (message: string) => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
isTexthookerOnlyMode: () => deps.isTexthookerOnlyMode(),
|
|
||||||
setTexthookerOnlyMode: (enabled: boolean) => deps.setTexthookerOnlyMode(enabled),
|
|
||||||
commandNeedsOverlayStartupPrereqs: (args: CliArgs) =>
|
|
||||||
deps.commandNeedsOverlayStartupPrereqs(args),
|
|
||||||
ensureOverlayStartupPrereqs: () => deps.ensureOverlayStartupPrereqs(),
|
|
||||||
startBackgroundWarmups: () => deps.startBackgroundWarmups(),
|
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
import type { CliArgs, CliCommandSource } from '../../cli/args';
|
import type { CliArgs, CliCommandSource } from '../../cli/args';
|
||||||
import { createHandleTexthookerOnlyModeTransitionHandler } from './cli-command-prechecks';
|
import { createHandleTexthookerOnlyModeTransitionHandler } from './cli-command-prechecks';
|
||||||
import { createBuildHandleTexthookerOnlyModeTransitionMainDepsHandler } from './cli-command-prechecks-main-deps';
|
|
||||||
|
|
||||||
type HandleTexthookerOnlyModeTransitionMainDeps = Parameters<
|
type HandleTexthookerOnlyModeTransitionMainDeps = Parameters<
|
||||||
typeof createBuildHandleTexthookerOnlyModeTransitionMainDepsHandler
|
typeof createHandleTexthookerOnlyModeTransitionHandler
|
||||||
>[0];
|
>[0];
|
||||||
|
|
||||||
export function createCliCommandRuntimeHandler<TCliContext>(deps: {
|
export function createCliCommandRuntimeHandler<TCliContext>(deps: {
|
||||||
@@ -17,9 +16,7 @@ export function createCliCommandRuntimeHandler<TCliContext>(deps: {
|
|||||||
) => void;
|
) => void;
|
||||||
}) {
|
}) {
|
||||||
const handleTexthookerOnlyModeTransitionHandler = createHandleTexthookerOnlyModeTransitionHandler(
|
const handleTexthookerOnlyModeTransitionHandler = createHandleTexthookerOnlyModeTransitionHandler(
|
||||||
createBuildHandleTexthookerOnlyModeTransitionMainDepsHandler(
|
deps.handleTexthookerOnlyModeTransitionMainDeps,
|
||||||
deps.handleTexthookerOnlyModeTransitionMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (args: CliArgs, source: CliCommandSource = 'initial'): void => {
|
return (args: CliArgs, source: CliCommandSource = 'initial'): void => {
|
||||||
|
|||||||
@@ -1,8 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
createBuildConsumeAnilistSetupTokenFromUrlMainDepsHandler,
|
|
||||||
createBuildHandleAnilistSetupProtocolUrlMainDepsHandler,
|
|
||||||
createBuildNotifyAnilistSetupMainDepsHandler,
|
|
||||||
createBuildRegisterSubminerProtocolClientMainDepsHandler,
|
|
||||||
createConsumeAnilistSetupTokenFromUrlHandler,
|
createConsumeAnilistSetupTokenFromUrlHandler,
|
||||||
createHandleAnilistSetupProtocolUrlHandler,
|
createHandleAnilistSetupProtocolUrlHandler,
|
||||||
createNotifyAnilistSetupHandler,
|
createNotifyAnilistSetupHandler,
|
||||||
@@ -16,12 +12,10 @@ type HandleProtocolHandler = ReturnType<typeof createHandleAnilistSetupProtocolU
|
|||||||
type RegisterClientHandler = ReturnType<typeof createRegisterSubminerProtocolClientHandler>;
|
type RegisterClientHandler = ReturnType<typeof createRegisterSubminerProtocolClientHandler>;
|
||||||
|
|
||||||
export type AnilistSetupComposerOptions = ComposerInputs<{
|
export type AnilistSetupComposerOptions = ComposerInputs<{
|
||||||
notifyDeps: Parameters<typeof createBuildNotifyAnilistSetupMainDepsHandler>[0];
|
notifyDeps: Parameters<typeof createNotifyAnilistSetupHandler>[0];
|
||||||
consumeTokenDeps: Parameters<typeof createBuildConsumeAnilistSetupTokenFromUrlMainDepsHandler>[0];
|
consumeTokenDeps: Parameters<typeof createConsumeAnilistSetupTokenFromUrlHandler>[0];
|
||||||
handleProtocolDeps: Parameters<typeof createBuildHandleAnilistSetupProtocolUrlMainDepsHandler>[0];
|
handleProtocolDeps: Parameters<typeof createHandleAnilistSetupProtocolUrlHandler>[0];
|
||||||
registerProtocolClientDeps: Parameters<
|
registerProtocolClientDeps: Parameters<typeof createRegisterSubminerProtocolClientHandler>[0];
|
||||||
typeof createBuildRegisterSubminerProtocolClientMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type AnilistSetupComposerResult = ComposerOutputs<{
|
export type AnilistSetupComposerResult = ComposerOutputs<{
|
||||||
@@ -34,17 +28,15 @@ export type AnilistSetupComposerResult = ComposerOutputs<{
|
|||||||
export function composeAnilistSetupHandlers(
|
export function composeAnilistSetupHandlers(
|
||||||
options: AnilistSetupComposerOptions,
|
options: AnilistSetupComposerOptions,
|
||||||
): AnilistSetupComposerResult {
|
): AnilistSetupComposerResult {
|
||||||
const notifyAnilistSetup = createNotifyAnilistSetupHandler(
|
const notifyAnilistSetup = createNotifyAnilistSetupHandler(options.notifyDeps);
|
||||||
createBuildNotifyAnilistSetupMainDepsHandler(options.notifyDeps)(),
|
|
||||||
);
|
|
||||||
const consumeAnilistSetupTokenFromUrl = createConsumeAnilistSetupTokenFromUrlHandler(
|
const consumeAnilistSetupTokenFromUrl = createConsumeAnilistSetupTokenFromUrlHandler(
|
||||||
createBuildConsumeAnilistSetupTokenFromUrlMainDepsHandler(options.consumeTokenDeps)(),
|
options.consumeTokenDeps,
|
||||||
);
|
);
|
||||||
const handleAnilistSetupProtocolUrl = createHandleAnilistSetupProtocolUrlHandler(
|
const handleAnilistSetupProtocolUrl = createHandleAnilistSetupProtocolUrlHandler(
|
||||||
createBuildHandleAnilistSetupProtocolUrlMainDepsHandler(options.handleProtocolDeps)(),
|
options.handleProtocolDeps,
|
||||||
);
|
);
|
||||||
const registerSubminerProtocolClient = createRegisterSubminerProtocolClientHandler(
|
const registerSubminerProtocolClient = createRegisterSubminerProtocolClientHandler(
|
||||||
createBuildRegisterSubminerProtocolClientMainDepsHandler(options.registerProtocolClientDeps)(),
|
options.registerProtocolClientDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,15 +1,4 @@
|
|||||||
import {
|
import {
|
||||||
createBuildEnsureAnilistMediaGuessMainDepsHandler,
|
|
||||||
createBuildGetAnilistMediaGuessRuntimeStateMainDepsHandler,
|
|
||||||
createBuildGetCurrentAnilistMediaKeyMainDepsHandler,
|
|
||||||
createBuildMaybeProbeAnilistDurationMainDepsHandler,
|
|
||||||
createBuildMaybeRunAnilistPostWatchUpdateMainDepsHandler,
|
|
||||||
createBuildProcessNextAnilistRetryUpdateMainDepsHandler,
|
|
||||||
createBuildRecordAnilistMediaDurationMainDepsHandler,
|
|
||||||
createBuildRefreshAnilistClientSecretStateMainDepsHandler,
|
|
||||||
createBuildResetAnilistMediaGuessStateMainDepsHandler,
|
|
||||||
createBuildResetAnilistMediaTrackingMainDepsHandler,
|
|
||||||
createBuildSetAnilistMediaGuessRuntimeStateMainDepsHandler,
|
|
||||||
createEnsureAnilistMediaGuessHandler,
|
createEnsureAnilistMediaGuessHandler,
|
||||||
createGetAnilistMediaGuessRuntimeStateHandler,
|
createGetAnilistMediaGuessRuntimeStateHandler,
|
||||||
createGetCurrentAnilistMediaKeyHandler,
|
createGetCurrentAnilistMediaKeyHandler,
|
||||||
@@ -25,36 +14,22 @@ import {
|
|||||||
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
||||||
|
|
||||||
export type AnilistTrackingComposerOptions = ComposerInputs<{
|
export type AnilistTrackingComposerOptions = ComposerInputs<{
|
||||||
refreshClientSecretMainDeps: Parameters<
|
refreshClientSecretMainDeps: Parameters<typeof createRefreshAnilistClientSecretStateHandler>[0];
|
||||||
typeof createBuildRefreshAnilistClientSecretStateMainDepsHandler
|
getCurrentMediaKeyMainDeps: Parameters<typeof createGetCurrentAnilistMediaKeyHandler>[0];
|
||||||
>[0];
|
resetMediaTrackingMainDeps: Parameters<typeof createResetAnilistMediaTrackingHandler>[0];
|
||||||
getCurrentMediaKeyMainDeps: Parameters<
|
|
||||||
typeof createBuildGetCurrentAnilistMediaKeyMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
resetMediaTrackingMainDeps: Parameters<
|
|
||||||
typeof createBuildResetAnilistMediaTrackingMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
getMediaGuessRuntimeStateMainDeps: Parameters<
|
getMediaGuessRuntimeStateMainDeps: Parameters<
|
||||||
typeof createBuildGetAnilistMediaGuessRuntimeStateMainDepsHandler
|
typeof createGetAnilistMediaGuessRuntimeStateHandler
|
||||||
>[0];
|
>[0];
|
||||||
setMediaGuessRuntimeStateMainDeps: Parameters<
|
setMediaGuessRuntimeStateMainDeps: Parameters<
|
||||||
typeof createBuildSetAnilistMediaGuessRuntimeStateMainDepsHandler
|
typeof createSetAnilistMediaGuessRuntimeStateHandler
|
||||||
>[0];
|
|
||||||
recordMediaDurationMainDeps: Parameters<
|
|
||||||
typeof createBuildRecordAnilistMediaDurationMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
resetMediaGuessStateMainDeps: Parameters<
|
|
||||||
typeof createBuildResetAnilistMediaGuessStateMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
maybeProbeDurationMainDeps: Parameters<
|
|
||||||
typeof createBuildMaybeProbeAnilistDurationMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
ensureMediaGuessMainDeps: Parameters<typeof createBuildEnsureAnilistMediaGuessMainDepsHandler>[0];
|
|
||||||
processNextRetryUpdateMainDeps: Parameters<
|
|
||||||
typeof createBuildProcessNextAnilistRetryUpdateMainDepsHandler
|
|
||||||
>[0];
|
>[0];
|
||||||
|
recordMediaDurationMainDeps: Parameters<typeof createRecordAnilistMediaDurationHandler>[0];
|
||||||
|
resetMediaGuessStateMainDeps: Parameters<typeof createResetAnilistMediaGuessStateHandler>[0];
|
||||||
|
maybeProbeDurationMainDeps: Parameters<typeof createMaybeProbeAnilistDurationHandler>[0];
|
||||||
|
ensureMediaGuessMainDeps: Parameters<typeof createEnsureAnilistMediaGuessHandler>[0];
|
||||||
|
processNextRetryUpdateMainDeps: Parameters<typeof createProcessNextAnilistRetryUpdateHandler>[0];
|
||||||
maybeRunPostWatchUpdateMainDeps: Parameters<
|
maybeRunPostWatchUpdateMainDeps: Parameters<
|
||||||
typeof createBuildMaybeRunAnilistPostWatchUpdateMainDepsHandler
|
typeof createMaybeRunAnilistPostWatchUpdateHandler
|
||||||
>[0];
|
>[0];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
@@ -80,47 +55,37 @@ export function composeAnilistTrackingHandlers(
|
|||||||
options: AnilistTrackingComposerOptions,
|
options: AnilistTrackingComposerOptions,
|
||||||
): AnilistTrackingComposerResult {
|
): AnilistTrackingComposerResult {
|
||||||
const refreshAnilistClientSecretState = createRefreshAnilistClientSecretStateHandler(
|
const refreshAnilistClientSecretState = createRefreshAnilistClientSecretStateHandler(
|
||||||
createBuildRefreshAnilistClientSecretStateMainDepsHandler(
|
options.refreshClientSecretMainDeps,
|
||||||
options.refreshClientSecretMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
const getCurrentAnilistMediaKey = createGetCurrentAnilistMediaKeyHandler(
|
const getCurrentAnilistMediaKey = createGetCurrentAnilistMediaKeyHandler(
|
||||||
createBuildGetCurrentAnilistMediaKeyMainDepsHandler(options.getCurrentMediaKeyMainDeps)(),
|
options.getCurrentMediaKeyMainDeps,
|
||||||
);
|
);
|
||||||
const resetAnilistMediaTracking = createResetAnilistMediaTrackingHandler(
|
const resetAnilistMediaTracking = createResetAnilistMediaTrackingHandler(
|
||||||
createBuildResetAnilistMediaTrackingMainDepsHandler(options.resetMediaTrackingMainDeps)(),
|
options.resetMediaTrackingMainDeps,
|
||||||
);
|
);
|
||||||
const getAnilistMediaGuessRuntimeState = createGetAnilistMediaGuessRuntimeStateHandler(
|
const getAnilistMediaGuessRuntimeState = createGetAnilistMediaGuessRuntimeStateHandler(
|
||||||
createBuildGetAnilistMediaGuessRuntimeStateMainDepsHandler(
|
options.getMediaGuessRuntimeStateMainDeps,
|
||||||
options.getMediaGuessRuntimeStateMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
const setAnilistMediaGuessRuntimeState = createSetAnilistMediaGuessRuntimeStateHandler(
|
const setAnilistMediaGuessRuntimeState = createSetAnilistMediaGuessRuntimeStateHandler(
|
||||||
createBuildSetAnilistMediaGuessRuntimeStateMainDepsHandler(
|
options.setMediaGuessRuntimeStateMainDeps,
|
||||||
options.setMediaGuessRuntimeStateMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
const recordAnilistMediaDuration = createRecordAnilistMediaDurationHandler(
|
const recordAnilistMediaDuration = createRecordAnilistMediaDurationHandler(
|
||||||
createBuildRecordAnilistMediaDurationMainDepsHandler(options.recordMediaDurationMainDeps)(),
|
options.recordMediaDurationMainDeps,
|
||||||
);
|
);
|
||||||
const resetAnilistMediaGuessState = createResetAnilistMediaGuessStateHandler(
|
const resetAnilistMediaGuessState = createResetAnilistMediaGuessStateHandler(
|
||||||
createBuildResetAnilistMediaGuessStateMainDepsHandler(options.resetMediaGuessStateMainDeps)(),
|
options.resetMediaGuessStateMainDeps,
|
||||||
);
|
);
|
||||||
const maybeProbeAnilistDuration = createMaybeProbeAnilistDurationHandler(
|
const maybeProbeAnilistDuration = createMaybeProbeAnilistDurationHandler(
|
||||||
createBuildMaybeProbeAnilistDurationMainDepsHandler(options.maybeProbeDurationMainDeps)(),
|
options.maybeProbeDurationMainDeps,
|
||||||
);
|
);
|
||||||
const ensureAnilistMediaGuess = createEnsureAnilistMediaGuessHandler(
|
const ensureAnilistMediaGuess = createEnsureAnilistMediaGuessHandler(
|
||||||
createBuildEnsureAnilistMediaGuessMainDepsHandler(options.ensureMediaGuessMainDeps)(),
|
options.ensureMediaGuessMainDeps,
|
||||||
);
|
);
|
||||||
const processNextAnilistRetryUpdate = createProcessNextAnilistRetryUpdateHandler(
|
const processNextAnilistRetryUpdate = createProcessNextAnilistRetryUpdateHandler(
|
||||||
createBuildProcessNextAnilistRetryUpdateMainDepsHandler(
|
options.processNextRetryUpdateMainDeps,
|
||||||
options.processNextRetryUpdateMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
const maybeRunAnilistPostWatchUpdate = createMaybeRunAnilistPostWatchUpdateHandler(
|
const maybeRunAnilistPostWatchUpdate = createMaybeRunAnilistPostWatchUpdateHandler(
|
||||||
createBuildMaybeRunAnilistPostWatchUpdateMainDepsHandler(
|
options.maybeRunPostWatchUpdateMainDeps,
|
||||||
options.maybeRunPostWatchUpdateMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,27 +1,22 @@
|
|||||||
import { createAppReadyRuntimeRunner } from '../../app-lifecycle';
|
|
||||||
import { createBuildAppReadyRuntimeMainDepsHandler } from '../app-ready-main-deps';
|
|
||||||
import {
|
import {
|
||||||
createBuildCriticalConfigErrorMainDepsHandler,
|
createAppReadyRuntimeRunner,
|
||||||
createBuildReloadConfigMainDepsHandler,
|
type AppReadyRuntimeDepsFactoryInput,
|
||||||
} from '../startup-config-main-deps';
|
} from '../../app-lifecycle';
|
||||||
import { createCriticalConfigErrorHandler, createReloadConfigHandler } from '../startup-config';
|
import { createCriticalConfigErrorHandler, createReloadConfigHandler } from '../startup-config';
|
||||||
import { createBuildImmersionTrackerStartupMainDepsHandler } from '../immersion-startup-main-deps';
|
|
||||||
import { createImmersionTrackerStartupHandler } from '../immersion-startup';
|
import { createImmersionTrackerStartupHandler } from '../immersion-startup';
|
||||||
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
||||||
|
|
||||||
type ReloadConfigMainDeps = Parameters<typeof createBuildReloadConfigMainDepsHandler>[0];
|
type ReloadConfigMainDeps = Parameters<typeof createReloadConfigHandler>[0];
|
||||||
type CriticalConfigErrorMainDeps = Parameters<
|
type CriticalConfigErrorMainDeps = Parameters<typeof createCriticalConfigErrorHandler>[0];
|
||||||
typeof createBuildCriticalConfigErrorMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type AppReadyRuntimeMainDeps = Parameters<typeof createBuildAppReadyRuntimeMainDepsHandler>[0];
|
|
||||||
|
|
||||||
export type AppReadyComposerOptions = ComposerInputs<{
|
export type AppReadyComposerOptions = ComposerInputs<{
|
||||||
reloadConfigMainDeps: ReloadConfigMainDeps;
|
reloadConfigMainDeps: ReloadConfigMainDeps;
|
||||||
criticalConfigErrorMainDeps: CriticalConfigErrorMainDeps;
|
criticalConfigErrorMainDeps: CriticalConfigErrorMainDeps;
|
||||||
appReadyRuntimeMainDeps: Omit<AppReadyRuntimeMainDeps, 'reloadConfig' | 'onCriticalConfigErrors'>;
|
appReadyRuntimeMainDeps: Omit<
|
||||||
immersionTrackerStartupMainDeps: Parameters<
|
AppReadyRuntimeDepsFactoryInput,
|
||||||
typeof createBuildImmersionTrackerStartupMainDepsHandler
|
'reloadConfig' | 'onCriticalConfigErrors'
|
||||||
>[0];
|
>;
|
||||||
|
immersionTrackerStartupMainDeps: Parameters<typeof createImmersionTrackerStartupHandler>[0];
|
||||||
}>;
|
}>;
|
||||||
|
|
||||||
export type AppReadyComposerResult = ComposerOutputs<{
|
export type AppReadyComposerResult = ComposerOutputs<{
|
||||||
@@ -31,27 +26,17 @@ export type AppReadyComposerResult = ComposerOutputs<{
|
|||||||
}>;
|
}>;
|
||||||
|
|
||||||
export function composeAppReadyRuntime(options: AppReadyComposerOptions): AppReadyComposerResult {
|
export function composeAppReadyRuntime(options: AppReadyComposerOptions): AppReadyComposerResult {
|
||||||
const reloadConfig = createReloadConfigHandler(
|
const reloadConfig = createReloadConfigHandler(options.reloadConfigMainDeps);
|
||||||
createBuildReloadConfigMainDepsHandler(options.reloadConfigMainDeps)(),
|
const criticalConfigError = createCriticalConfigErrorHandler(options.criticalConfigErrorMainDeps);
|
||||||
);
|
|
||||||
const criticalConfigError = createCriticalConfigErrorHandler(
|
|
||||||
createBuildCriticalConfigErrorMainDepsHandler(options.criticalConfigErrorMainDeps)(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const appReadyRuntimeRunner = createAppReadyRuntimeRunner(
|
const appReadyRuntimeRunner = createAppReadyRuntimeRunner({
|
||||||
createBuildAppReadyRuntimeMainDepsHandler({
|
...options.appReadyRuntimeMainDeps,
|
||||||
...options.appReadyRuntimeMainDeps,
|
reloadConfig,
|
||||||
reloadConfig,
|
createImmersionTracker:
|
||||||
createImmersionTracker:
|
options.appReadyRuntimeMainDeps.createImmersionTracker ??
|
||||||
options.appReadyRuntimeMainDeps.createImmersionTracker ??
|
createImmersionTrackerStartupHandler(options.immersionTrackerStartupMainDeps),
|
||||||
createImmersionTrackerStartupHandler(
|
onCriticalConfigErrors: criticalConfigError,
|
||||||
createBuildImmersionTrackerStartupMainDepsHandler(
|
});
|
||||||
options.immersionTrackerStartupMainDeps,
|
|
||||||
)(),
|
|
||||||
),
|
|
||||||
onCriticalConfigErrors: criticalConfigError,
|
|
||||||
})(),
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
reloadConfig,
|
reloadConfig,
|
||||||
|
|||||||
@@ -1,9 +1,7 @@
|
|||||||
import type { RegisterIpcRuntimeServicesParams } from '../../ipc-runtime';
|
import type { RegisterIpcRuntimeServicesParams } from '../../ipc-runtime';
|
||||||
|
import type { MpvCommandFromIpcRuntimeDeps } from '../../ipc-mpv-command';
|
||||||
import type { SubsyncManualRunRequest, SubsyncResult } from '../../../types';
|
import type { SubsyncManualRunRequest, SubsyncResult } from '../../../types';
|
||||||
import {
|
import { createIpcRuntimeHandlers } from '../domains/ipc';
|
||||||
createBuildMpvCommandFromIpcRuntimeMainDepsHandler,
|
|
||||||
createIpcRuntimeHandlers,
|
|
||||||
} from '../domains/ipc';
|
|
||||||
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
||||||
|
|
||||||
type MpvCommand = (string | number)[];
|
type MpvCommand = (string | number)[];
|
||||||
@@ -17,7 +15,7 @@ type IpcRuntimeDeps = Parameters<
|
|||||||
>[0];
|
>[0];
|
||||||
|
|
||||||
export type IpcRuntimeComposerOptions = ComposerInputs<{
|
export type IpcRuntimeComposerOptions = ComposerInputs<{
|
||||||
mpvCommandMainDeps: Parameters<typeof createBuildMpvCommandFromIpcRuntimeMainDepsHandler>[0];
|
mpvCommandMainDeps: MpvCommandFromIpcRuntimeDeps;
|
||||||
handleMpvCommandFromIpcRuntime: IpcRuntimeDeps['handleMpvCommandFromIpcDeps']['handleMpvCommandFromIpcRuntime'];
|
handleMpvCommandFromIpcRuntime: IpcRuntimeDeps['handleMpvCommandFromIpcDeps']['handleMpvCommandFromIpcRuntime'];
|
||||||
runSubsyncManualFromIpc: RunSubsyncManual;
|
runSubsyncManualFromIpc: RunSubsyncManual;
|
||||||
registration: {
|
registration: {
|
||||||
@@ -37,16 +35,13 @@ export type IpcRuntimeComposerResult = ComposerOutputs<{
|
|||||||
export function composeIpcRuntimeHandlers(
|
export function composeIpcRuntimeHandlers(
|
||||||
options: IpcRuntimeComposerOptions,
|
options: IpcRuntimeComposerOptions,
|
||||||
): IpcRuntimeComposerResult {
|
): IpcRuntimeComposerResult {
|
||||||
const mpvCommandFromIpcRuntimeMainDeps = createBuildMpvCommandFromIpcRuntimeMainDepsHandler(
|
|
||||||
options.mpvCommandMainDeps,
|
|
||||||
)();
|
|
||||||
const { handleMpvCommandFromIpc, runSubsyncManualFromIpc } = createIpcRuntimeHandlers<
|
const { handleMpvCommandFromIpc, runSubsyncManualFromIpc } = createIpcRuntimeHandlers<
|
||||||
SubsyncManualRunRequest,
|
SubsyncManualRunRequest,
|
||||||
SubsyncResult
|
SubsyncResult
|
||||||
>({
|
>({
|
||||||
handleMpvCommandFromIpcDeps: {
|
handleMpvCommandFromIpcDeps: {
|
||||||
handleMpvCommandFromIpcRuntime: options.handleMpvCommandFromIpcRuntime,
|
handleMpvCommandFromIpcRuntime: options.handleMpvCommandFromIpcRuntime,
|
||||||
buildMpvCommandDeps: () => mpvCommandFromIpcRuntimeMainDeps,
|
buildMpvCommandDeps: () => options.mpvCommandMainDeps,
|
||||||
},
|
},
|
||||||
runSubsyncManualFromIpcDeps: {
|
runSubsyncManualFromIpcDeps: {
|
||||||
runManualFromIpc: (request) => options.runSubsyncManualFromIpc(request),
|
runManualFromIpc: (request) => options.runSubsyncManualFromIpc(request),
|
||||||
|
|||||||
@@ -1,21 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
buildJellyfinSetupFormHtml,
|
buildJellyfinSetupFormHtml,
|
||||||
createEnsureMpvConnectedForJellyfinPlaybackHandler,
|
createEnsureMpvConnectedForJellyfinPlaybackHandler,
|
||||||
createBuildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler,
|
|
||||||
createBuildGetJellyfinClientInfoMainDepsHandler,
|
createBuildGetJellyfinClientInfoMainDepsHandler,
|
||||||
createBuildGetResolvedJellyfinConfigMainDepsHandler,
|
createBuildGetResolvedJellyfinConfigMainDepsHandler,
|
||||||
createBuildHandleJellyfinAuthCommandsMainDepsHandler,
|
|
||||||
createBuildHandleJellyfinListCommandsMainDepsHandler,
|
|
||||||
createBuildHandleJellyfinPlayCommandMainDepsHandler,
|
|
||||||
createBuildHandleJellyfinRemoteAnnounceCommandMainDepsHandler,
|
|
||||||
createBuildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler,
|
|
||||||
createBuildOpenJellyfinSetupWindowMainDepsHandler,
|
createBuildOpenJellyfinSetupWindowMainDepsHandler,
|
||||||
createBuildPlayJellyfinItemInMpvMainDepsHandler,
|
|
||||||
createBuildPreloadJellyfinExternalSubtitlesMainDepsHandler,
|
|
||||||
createBuildRunJellyfinCommandMainDepsHandler,
|
|
||||||
createBuildStartJellyfinRemoteSessionMainDepsHandler,
|
|
||||||
createBuildStopJellyfinRemoteSessionMainDepsHandler,
|
|
||||||
createBuildWaitForMpvConnectedMainDepsHandler,
|
|
||||||
createGetJellyfinClientInfoHandler,
|
createGetJellyfinClientInfoHandler,
|
||||||
createGetResolvedJellyfinConfigHandler,
|
createGetResolvedJellyfinConfigHandler,
|
||||||
createHandleJellyfinAuthCommands,
|
createHandleJellyfinAuthCommands,
|
||||||
@@ -40,23 +28,13 @@ import {
|
|||||||
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
||||||
|
|
||||||
type EnsureMpvConnectedMainDeps = Parameters<
|
type EnsureMpvConnectedMainDeps = Parameters<
|
||||||
typeof createBuildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler
|
typeof createEnsureMpvConnectedForJellyfinPlaybackHandler
|
||||||
>[0];
|
|
||||||
type PlayJellyfinItemMainDeps = Parameters<
|
|
||||||
typeof createBuildPlayJellyfinItemInMpvMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type HandlePlayCommandMainDeps = Parameters<
|
|
||||||
typeof createBuildHandleJellyfinPlayCommandMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type HandleRemoteAnnounceMainDeps = Parameters<
|
|
||||||
typeof createBuildHandleJellyfinRemoteAnnounceCommandMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type StartRemoteSessionMainDeps = Parameters<
|
|
||||||
typeof createBuildStartJellyfinRemoteSessionMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type RunJellyfinCommandMainDeps = Parameters<
|
|
||||||
typeof createBuildRunJellyfinCommandMainDepsHandler
|
|
||||||
>[0];
|
>[0];
|
||||||
|
type PlayJellyfinItemMainDeps = Parameters<typeof createPlayJellyfinItemInMpvHandler>[0];
|
||||||
|
type HandlePlayCommandMainDeps = Parameters<typeof createHandleJellyfinPlayCommand>[0];
|
||||||
|
type HandleRemoteAnnounceMainDeps = Parameters<typeof createHandleJellyfinRemoteAnnounceCommand>[0];
|
||||||
|
type StartRemoteSessionMainDeps = Parameters<typeof createStartJellyfinRemoteSessionHandler>[0];
|
||||||
|
type RunJellyfinCommandMainDeps = Parameters<typeof createRunJellyfinCommandHandler>[0];
|
||||||
type OpenJellyfinSetupWindowMainDeps = Parameters<
|
type OpenJellyfinSetupWindowMainDeps = Parameters<
|
||||||
typeof createBuildOpenJellyfinSetupWindowMainDepsHandler
|
typeof createBuildOpenJellyfinSetupWindowMainDepsHandler
|
||||||
>[0];
|
>[0];
|
||||||
@@ -68,16 +46,16 @@ export type JellyfinRuntimeComposerOptions = ComposerInputs<{
|
|||||||
getJellyfinClientInfoMainDeps: Parameters<
|
getJellyfinClientInfoMainDeps: Parameters<
|
||||||
typeof createBuildGetJellyfinClientInfoMainDepsHandler
|
typeof createBuildGetJellyfinClientInfoMainDepsHandler
|
||||||
>[0];
|
>[0];
|
||||||
waitForMpvConnectedMainDeps: Parameters<typeof createBuildWaitForMpvConnectedMainDepsHandler>[0];
|
waitForMpvConnectedMainDeps: Parameters<typeof createWaitForMpvConnectedHandler>[0];
|
||||||
launchMpvIdleForJellyfinPlaybackMainDeps: Parameters<
|
launchMpvIdleForJellyfinPlaybackMainDeps: Parameters<
|
||||||
typeof createBuildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler
|
typeof createLaunchMpvIdleForJellyfinPlaybackHandler
|
||||||
>[0];
|
>[0];
|
||||||
ensureMpvConnectedForJellyfinPlaybackMainDeps: Omit<
|
ensureMpvConnectedForJellyfinPlaybackMainDeps: Omit<
|
||||||
EnsureMpvConnectedMainDeps,
|
EnsureMpvConnectedMainDeps,
|
||||||
'waitForMpvConnected' | 'launchMpvIdleForJellyfinPlayback'
|
'waitForMpvConnected' | 'launchMpvIdleForJellyfinPlayback'
|
||||||
>;
|
>;
|
||||||
preloadJellyfinExternalSubtitlesMainDeps: Parameters<
|
preloadJellyfinExternalSubtitlesMainDeps: Parameters<
|
||||||
typeof createBuildPreloadJellyfinExternalSubtitlesMainDepsHandler
|
typeof createPreloadJellyfinExternalSubtitlesHandler
|
||||||
>[0];
|
>[0];
|
||||||
playJellyfinItemInMpvMainDeps: Omit<
|
playJellyfinItemInMpvMainDeps: Omit<
|
||||||
PlayJellyfinItemMainDeps,
|
PlayJellyfinItemMainDeps,
|
||||||
@@ -87,12 +65,8 @@ export type JellyfinRuntimeComposerOptions = ComposerInputs<{
|
|||||||
JellyfinRemoteComposerOptions,
|
JellyfinRemoteComposerOptions,
|
||||||
'getClientInfo' | 'getJellyfinConfig' | 'playJellyfinItem'
|
'getClientInfo' | 'getJellyfinConfig' | 'playJellyfinItem'
|
||||||
>;
|
>;
|
||||||
handleJellyfinAuthCommandsMainDeps: Parameters<
|
handleJellyfinAuthCommandsMainDeps: Parameters<typeof createHandleJellyfinAuthCommands>[0];
|
||||||
typeof createBuildHandleJellyfinAuthCommandsMainDepsHandler
|
handleJellyfinListCommandsMainDeps: Parameters<typeof createHandleJellyfinListCommands>[0];
|
||||||
>[0];
|
|
||||||
handleJellyfinListCommandsMainDeps: Parameters<
|
|
||||||
typeof createBuildHandleJellyfinListCommandsMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
handleJellyfinPlayCommandMainDeps: Omit<HandlePlayCommandMainDeps, 'playJellyfinItemInMpv'>;
|
handleJellyfinPlayCommandMainDeps: Omit<HandlePlayCommandMainDeps, 'playJellyfinItemInMpv'>;
|
||||||
handleJellyfinRemoteAnnounceCommandMainDeps: Omit<
|
handleJellyfinRemoteAnnounceCommandMainDeps: Omit<
|
||||||
HandleRemoteAnnounceMainDeps,
|
HandleRemoteAnnounceMainDeps,
|
||||||
@@ -106,9 +80,7 @@ export type JellyfinRuntimeComposerOptions = ComposerInputs<{
|
|||||||
| 'handlePlaystate'
|
| 'handlePlaystate'
|
||||||
| 'handleGeneralCommand'
|
| 'handleGeneralCommand'
|
||||||
>;
|
>;
|
||||||
stopJellyfinRemoteSessionMainDeps: Parameters<
|
stopJellyfinRemoteSessionMainDeps: Parameters<typeof createStopJellyfinRemoteSessionHandler>[0];
|
||||||
typeof createBuildStopJellyfinRemoteSessionMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
runJellyfinCommandMainDeps: Omit<
|
runJellyfinCommandMainDeps: Omit<
|
||||||
RunJellyfinCommandMainDeps,
|
RunJellyfinCommandMainDeps,
|
||||||
| 'getJellyfinConfig'
|
| 'getJellyfinConfig'
|
||||||
@@ -177,36 +149,26 @@ export function composeJellyfinRuntimeHandlers(
|
|||||||
createBuildGetJellyfinClientInfoMainDepsHandler(options.getJellyfinClientInfoMainDeps)(),
|
createBuildGetJellyfinClientInfoMainDepsHandler(options.getJellyfinClientInfoMainDeps)(),
|
||||||
);
|
);
|
||||||
|
|
||||||
const waitForMpvConnected = createWaitForMpvConnectedHandler(
|
const waitForMpvConnected = createWaitForMpvConnectedHandler(options.waitForMpvConnectedMainDeps);
|
||||||
createBuildWaitForMpvConnectedMainDepsHandler(options.waitForMpvConnectedMainDeps)(),
|
|
||||||
);
|
|
||||||
const launchMpvIdleForJellyfinPlayback = createLaunchMpvIdleForJellyfinPlaybackHandler(
|
const launchMpvIdleForJellyfinPlayback = createLaunchMpvIdleForJellyfinPlaybackHandler(
|
||||||
createBuildLaunchMpvIdleForJellyfinPlaybackMainDepsHandler(
|
options.launchMpvIdleForJellyfinPlaybackMainDeps,
|
||||||
options.launchMpvIdleForJellyfinPlaybackMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
|
||||||
const ensureMpvConnectedForJellyfinPlayback = createEnsureMpvConnectedForJellyfinPlaybackHandler(
|
|
||||||
createBuildEnsureMpvConnectedForJellyfinPlaybackMainDepsHandler({
|
|
||||||
...options.ensureMpvConnectedForJellyfinPlaybackMainDeps,
|
|
||||||
waitForMpvConnected: (timeoutMs) => waitForMpvConnected(timeoutMs),
|
|
||||||
launchMpvIdleForJellyfinPlayback: () => launchMpvIdleForJellyfinPlayback(),
|
|
||||||
})(),
|
|
||||||
);
|
);
|
||||||
|
const ensureMpvConnectedForJellyfinPlayback = createEnsureMpvConnectedForJellyfinPlaybackHandler({
|
||||||
|
...options.ensureMpvConnectedForJellyfinPlaybackMainDeps,
|
||||||
|
waitForMpvConnected: (timeoutMs) => waitForMpvConnected(timeoutMs),
|
||||||
|
launchMpvIdleForJellyfinPlayback: () => launchMpvIdleForJellyfinPlayback(),
|
||||||
|
});
|
||||||
|
|
||||||
const preloadJellyfinExternalSubtitles = createPreloadJellyfinExternalSubtitlesHandler(
|
const preloadJellyfinExternalSubtitles = createPreloadJellyfinExternalSubtitlesHandler(
|
||||||
createBuildPreloadJellyfinExternalSubtitlesMainDepsHandler(
|
options.preloadJellyfinExternalSubtitlesMainDeps,
|
||||||
options.preloadJellyfinExternalSubtitlesMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
|
||||||
const playJellyfinItemInMpv = createPlayJellyfinItemInMpvHandler(
|
|
||||||
createBuildPlayJellyfinItemInMpvMainDepsHandler({
|
|
||||||
...options.playJellyfinItemInMpvMainDeps,
|
|
||||||
ensureMpvConnectedForPlayback: () => ensureMpvConnectedForJellyfinPlayback(),
|
|
||||||
preloadExternalSubtitles: (params) => {
|
|
||||||
void preloadJellyfinExternalSubtitles(params);
|
|
||||||
},
|
|
||||||
})(),
|
|
||||||
);
|
);
|
||||||
|
const playJellyfinItemInMpv = createPlayJellyfinItemInMpvHandler({
|
||||||
|
...options.playJellyfinItemInMpvMainDeps,
|
||||||
|
ensureMpvConnectedForPlayback: () => ensureMpvConnectedForJellyfinPlayback(),
|
||||||
|
preloadExternalSubtitles: (params) => {
|
||||||
|
void preloadJellyfinExternalSubtitles(params);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const {
|
const {
|
||||||
reportJellyfinRemoteProgress,
|
reportJellyfinRemoteProgress,
|
||||||
@@ -223,59 +185,45 @@ export function composeJellyfinRuntimeHandlers(
|
|||||||
});
|
});
|
||||||
|
|
||||||
const handleJellyfinAuthCommands = createHandleJellyfinAuthCommands(
|
const handleJellyfinAuthCommands = createHandleJellyfinAuthCommands(
|
||||||
createBuildHandleJellyfinAuthCommandsMainDepsHandler(
|
options.handleJellyfinAuthCommandsMainDeps,
|
||||||
options.handleJellyfinAuthCommandsMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
const handleJellyfinListCommands = createHandleJellyfinListCommands(
|
const handleJellyfinListCommands = createHandleJellyfinListCommands(
|
||||||
createBuildHandleJellyfinListCommandsMainDepsHandler(
|
options.handleJellyfinListCommandsMainDeps,
|
||||||
options.handleJellyfinListCommandsMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
|
||||||
const handleJellyfinPlayCommand = createHandleJellyfinPlayCommand(
|
|
||||||
createBuildHandleJellyfinPlayCommandMainDepsHandler({
|
|
||||||
...options.handleJellyfinPlayCommandMainDeps,
|
|
||||||
playJellyfinItemInMpv: (params) =>
|
|
||||||
playJellyfinItemInMpv(params as Parameters<typeof playJellyfinItemInMpv>[0]),
|
|
||||||
})(),
|
|
||||||
);
|
);
|
||||||
|
const handleJellyfinPlayCommand = createHandleJellyfinPlayCommand({
|
||||||
|
...options.handleJellyfinPlayCommandMainDeps,
|
||||||
|
playJellyfinItemInMpv: (params) =>
|
||||||
|
playJellyfinItemInMpv(params as Parameters<typeof playJellyfinItemInMpv>[0]),
|
||||||
|
});
|
||||||
|
|
||||||
let startJellyfinRemoteSession!: ReturnType<typeof createStartJellyfinRemoteSessionHandler>;
|
let startJellyfinRemoteSession!: ReturnType<typeof createStartJellyfinRemoteSessionHandler>;
|
||||||
const handleJellyfinRemoteAnnounceCommand = createHandleJellyfinRemoteAnnounceCommand(
|
const handleJellyfinRemoteAnnounceCommand = createHandleJellyfinRemoteAnnounceCommand({
|
||||||
createBuildHandleJellyfinRemoteAnnounceCommandMainDepsHandler({
|
...options.handleJellyfinRemoteAnnounceCommandMainDeps,
|
||||||
...options.handleJellyfinRemoteAnnounceCommandMainDeps,
|
startJellyfinRemoteSession: (startOptions) => startJellyfinRemoteSession(startOptions),
|
||||||
startJellyfinRemoteSession: (startOptions) => startJellyfinRemoteSession(startOptions),
|
});
|
||||||
})(),
|
|
||||||
);
|
|
||||||
|
|
||||||
startJellyfinRemoteSession = createStartJellyfinRemoteSessionHandler(
|
startJellyfinRemoteSession = createStartJellyfinRemoteSessionHandler({
|
||||||
createBuildStartJellyfinRemoteSessionMainDepsHandler({
|
...options.startJellyfinRemoteSessionMainDeps,
|
||||||
...options.startJellyfinRemoteSessionMainDeps,
|
getJellyfinConfig: () => getResolvedJellyfinConfig(),
|
||||||
getJellyfinConfig: () => getResolvedJellyfinConfig(),
|
getClientInfo: () => getJellyfinClientInfo(),
|
||||||
getClientInfo: () => getJellyfinClientInfo(),
|
handlePlay: (payload) => handleJellyfinRemotePlay(payload),
|
||||||
handlePlay: (payload) => handleJellyfinRemotePlay(payload),
|
handlePlaystate: (payload) => handleJellyfinRemotePlaystate(payload),
|
||||||
handlePlaystate: (payload) => handleJellyfinRemotePlaystate(payload),
|
handleGeneralCommand: (payload) => handleJellyfinRemoteGeneralCommand(payload),
|
||||||
handleGeneralCommand: (payload) => handleJellyfinRemoteGeneralCommand(payload),
|
});
|
||||||
})(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const stopJellyfinRemoteSession = createStopJellyfinRemoteSessionHandler(
|
const stopJellyfinRemoteSession = createStopJellyfinRemoteSessionHandler(
|
||||||
createBuildStopJellyfinRemoteSessionMainDepsHandler(
|
options.stopJellyfinRemoteSessionMainDeps,
|
||||||
options.stopJellyfinRemoteSessionMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const runJellyfinCommand = createRunJellyfinCommandHandler(
|
const runJellyfinCommand = createRunJellyfinCommandHandler({
|
||||||
createBuildRunJellyfinCommandMainDepsHandler({
|
...options.runJellyfinCommandMainDeps,
|
||||||
...options.runJellyfinCommandMainDeps,
|
getJellyfinConfig: () => getResolvedJellyfinConfig(),
|
||||||
getJellyfinConfig: () => getResolvedJellyfinConfig(),
|
getJellyfinClientInfo: (jellyfinConfig) => getJellyfinClientInfo(jellyfinConfig),
|
||||||
getJellyfinClientInfo: (jellyfinConfig) => getJellyfinClientInfo(jellyfinConfig),
|
handleAuthCommands: (params) => handleJellyfinAuthCommands(params),
|
||||||
handleAuthCommands: (params) => handleJellyfinAuthCommands(params),
|
handleRemoteAnnounceCommand: (args) => handleJellyfinRemoteAnnounceCommand(args),
|
||||||
handleRemoteAnnounceCommand: (args) => handleJellyfinRemoteAnnounceCommand(args),
|
handleListCommands: (params) => handleJellyfinListCommands(params),
|
||||||
handleListCommands: (params) => handleJellyfinListCommands(params),
|
handlePlayCommand: (params) => handleJellyfinPlayCommand(params),
|
||||||
handlePlayCommand: (params) => handleJellyfinPlayCommand(params),
|
});
|
||||||
})(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const maybeFocusExistingJellyfinSetupWindow = createMaybeFocusExistingJellyfinSetupWindowHandler(
|
const maybeFocusExistingJellyfinSetupWindow = createMaybeFocusExistingJellyfinSetupWindowHandler(
|
||||||
options.maybeFocusExistingJellyfinSetupWindowMainDeps,
|
options.maybeFocusExistingJellyfinSetupWindowMainDeps,
|
||||||
|
|||||||
@@ -4,17 +4,12 @@ import { createBuildMpvClientRuntimeServiceFactoryDepsHandler } from '../mpv-cli
|
|||||||
import { createMpvClientRuntimeServiceFactory } from '../mpv-client-runtime-service';
|
import { createMpvClientRuntimeServiceFactory } from '../mpv-client-runtime-service';
|
||||||
import type { MpvClientRuntimeServiceOptions } from '../mpv-client-runtime-service';
|
import type { MpvClientRuntimeServiceOptions } from '../mpv-client-runtime-service';
|
||||||
import type { Config } from '../../../types';
|
import type { Config } from '../../../types';
|
||||||
import { createBuildUpdateMpvSubtitleRenderMetricsMainDepsHandler } from '../mpv-subtitle-render-metrics-main-deps';
|
|
||||||
import { createUpdateMpvSubtitleRenderMetricsHandler } from '../mpv-subtitle-render-metrics';
|
import { createUpdateMpvSubtitleRenderMetricsHandler } from '../mpv-subtitle-render-metrics';
|
||||||
import {
|
import {
|
||||||
createBuildTokenizerDepsMainHandler,
|
createBuildTokenizerDepsMainHandler,
|
||||||
createCreateMecabTokenizerAndCheckMainHandler,
|
createCreateMecabTokenizerAndCheckMainHandler,
|
||||||
createPrewarmSubtitleDictionariesMainHandler,
|
createPrewarmSubtitleDictionariesMainHandler,
|
||||||
} from '../subtitle-tokenization-main-deps';
|
} from '../subtitle-tokenization-main-deps';
|
||||||
import {
|
|
||||||
createBuildLaunchBackgroundWarmupTaskMainDepsHandler,
|
|
||||||
createBuildStartBackgroundWarmupsMainDepsHandler,
|
|
||||||
} from '../startup-warmups-main-deps';
|
|
||||||
import {
|
import {
|
||||||
createLaunchBackgroundWarmupTaskHandler as createLaunchBackgroundWarmupTaskFromStartup,
|
createLaunchBackgroundWarmupTaskHandler as createLaunchBackgroundWarmupTaskFromStartup,
|
||||||
createStartBackgroundWarmupsHandler as createStartBackgroundWarmupsFromStartup,
|
createStartBackgroundWarmupsHandler as createStartBackgroundWarmupsFromStartup,
|
||||||
@@ -38,7 +33,7 @@ type MpvClientRuntimeServiceFactoryMainDeps<TMpvClient extends RuntimeMpvClient>
|
|||||||
'bindEventHandlers'
|
'bindEventHandlers'
|
||||||
>;
|
>;
|
||||||
type UpdateMpvSubtitleRenderMetricsMainDeps = Parameters<
|
type UpdateMpvSubtitleRenderMetricsMainDeps = Parameters<
|
||||||
typeof createBuildUpdateMpvSubtitleRenderMetricsMainDepsHandler
|
typeof createUpdateMpvSubtitleRenderMetricsHandler
|
||||||
>[0];
|
>[0];
|
||||||
type BuildTokenizerDepsMainDeps = Parameters<typeof createBuildTokenizerDepsMainHandler>[0];
|
type BuildTokenizerDepsMainDeps = Parameters<typeof createBuildTokenizerDepsMainHandler>[0];
|
||||||
type TokenizerMainDeps = BuiltMainDeps<typeof createBuildTokenizerDepsMainHandler>;
|
type TokenizerMainDeps = BuiltMainDeps<typeof createBuildTokenizerDepsMainHandler>;
|
||||||
@@ -49,10 +44,10 @@ type PrewarmSubtitleDictionariesMainDeps = Parameters<
|
|||||||
typeof createPrewarmSubtitleDictionariesMainHandler
|
typeof createPrewarmSubtitleDictionariesMainHandler
|
||||||
>[0];
|
>[0];
|
||||||
type LaunchBackgroundWarmupTaskMainDeps = Parameters<
|
type LaunchBackgroundWarmupTaskMainDeps = Parameters<
|
||||||
typeof createBuildLaunchBackgroundWarmupTaskMainDepsHandler
|
typeof createLaunchBackgroundWarmupTaskFromStartup
|
||||||
>[0];
|
>[0];
|
||||||
type StartBackgroundWarmupsMainDeps = Omit<
|
type StartBackgroundWarmupsMainDeps = Omit<
|
||||||
Parameters<typeof createBuildStartBackgroundWarmupsMainDepsHandler>[0],
|
Parameters<typeof createStartBackgroundWarmupsFromStartup>[0],
|
||||||
'launchTask' | 'createMecabTokenizerAndCheck' | 'prewarmSubtitleDictionaries'
|
'launchTask' | 'createMecabTokenizerAndCheck' | 'prewarmSubtitleDictionaries'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@@ -120,9 +115,7 @@ export function composeMpvRuntimeHandlers<
|
|||||||
createMpvClientRuntimeServiceFactory(buildMpvClientRuntimeServiceFactoryMainDepsHandler())();
|
createMpvClientRuntimeServiceFactory(buildMpvClientRuntimeServiceFactoryMainDepsHandler())();
|
||||||
|
|
||||||
const updateMpvSubtitleRenderMetrics = createUpdateMpvSubtitleRenderMetricsHandler(
|
const updateMpvSubtitleRenderMetrics = createUpdateMpvSubtitleRenderMetricsHandler(
|
||||||
createBuildUpdateMpvSubtitleRenderMetricsMainDepsHandler(
|
options.updateMpvSubtitleRenderMetricsMainDeps,
|
||||||
options.updateMpvSubtitleRenderMetricsMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildTokenizerDepsHandler = createBuildTokenizerDepsMainHandler(
|
const buildTokenizerDepsHandler = createBuildTokenizerDepsMainHandler(
|
||||||
@@ -257,48 +250,44 @@ export function composeMpvRuntimeHandlers<
|
|||||||
};
|
};
|
||||||
|
|
||||||
const launchBackgroundWarmupTask = createLaunchBackgroundWarmupTaskFromStartup(
|
const launchBackgroundWarmupTask = createLaunchBackgroundWarmupTaskFromStartup(
|
||||||
createBuildLaunchBackgroundWarmupTaskMainDepsHandler(
|
options.warmups.launchBackgroundWarmupTaskMainDeps,
|
||||||
options.warmups.launchBackgroundWarmupTaskMainDeps,
|
|
||||||
)(),
|
|
||||||
);
|
|
||||||
const startBackgroundWarmups = createStartBackgroundWarmupsFromStartup(
|
|
||||||
createBuildStartBackgroundWarmupsMainDepsHandler({
|
|
||||||
...options.warmups.startBackgroundWarmupsMainDeps,
|
|
||||||
launchTask: (label, task) => launchBackgroundWarmupTask(label, task),
|
|
||||||
createMecabTokenizerAndCheck: () => createMecabTokenizerAndCheck(),
|
|
||||||
prewarmSubtitleDictionaries: () => prewarmSubtitleDictionaries(),
|
|
||||||
onYomitanExtensionWarmupScheduled: (promise) => {
|
|
||||||
if (tokenizationPrerequisiteWarmupCompleted) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const finalizedPromise = promise
|
|
||||||
.then(() => {
|
|
||||||
markTokenizationPrerequisiteWarmupCompleted();
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
if (tokenizationPrerequisiteWarmupInFlight === finalizedPromise) {
|
|
||||||
tokenizationPrerequisiteWarmupInFlight = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
tokenizationPrerequisiteWarmupInFlight = finalizedPromise;
|
|
||||||
},
|
|
||||||
onTokenizationWarmupScheduled: (promise) => {
|
|
||||||
if (tokenizationWarmupCompleted || !backgroundWarmupCoversOnDemandTokenization()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const finalizedPromise = promise
|
|
||||||
.then(() => {
|
|
||||||
markTokenizationWarmupCompleted();
|
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
if (tokenizationWarmupInFlight === finalizedPromise) {
|
|
||||||
tokenizationWarmupInFlight = null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
tokenizationWarmupInFlight = finalizedPromise;
|
|
||||||
},
|
|
||||||
})(),
|
|
||||||
);
|
);
|
||||||
|
const startBackgroundWarmups = createStartBackgroundWarmupsFromStartup({
|
||||||
|
...options.warmups.startBackgroundWarmupsMainDeps,
|
||||||
|
launchTask: (label, task) => launchBackgroundWarmupTask(label, task),
|
||||||
|
createMecabTokenizerAndCheck: () => createMecabTokenizerAndCheck(),
|
||||||
|
prewarmSubtitleDictionaries: () => prewarmSubtitleDictionaries(),
|
||||||
|
onYomitanExtensionWarmupScheduled: (promise) => {
|
||||||
|
if (tokenizationPrerequisiteWarmupCompleted) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const finalizedPromise = promise
|
||||||
|
.then(() => {
|
||||||
|
markTokenizationPrerequisiteWarmupCompleted();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
if (tokenizationPrerequisiteWarmupInFlight === finalizedPromise) {
|
||||||
|
tokenizationPrerequisiteWarmupInFlight = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tokenizationPrerequisiteWarmupInFlight = finalizedPromise;
|
||||||
|
},
|
||||||
|
onTokenizationWarmupScheduled: (promise) => {
|
||||||
|
if (tokenizationWarmupCompleted || !backgroundWarmupCoversOnDemandTokenization()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const finalizedPromise = promise
|
||||||
|
.then(() => {
|
||||||
|
markTokenizationWarmupCompleted();
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
if (tokenizationWarmupInFlight === finalizedPromise) {
|
||||||
|
tokenizationWarmupInFlight = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tokenizationWarmupInFlight = finalizedPromise;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
bindMpvClientEventHandlers: (client) => bindMpvClientEventHandlers(client),
|
bindMpvClientEventHandlers: (client) => bindMpvClientEventHandlers(client),
|
||||||
|
|||||||
@@ -5,29 +5,22 @@ import {
|
|||||||
createSendToActiveOverlayWindowHandler,
|
createSendToActiveOverlayWindowHandler,
|
||||||
createSetOverlayDebugVisualizationEnabledHandler,
|
createSetOverlayDebugVisualizationEnabledHandler,
|
||||||
} from '../overlay-runtime-main-actions';
|
} from '../overlay-runtime-main-actions';
|
||||||
import {
|
|
||||||
createBuildBroadcastRuntimeOptionsChangedMainDepsHandler,
|
|
||||||
createBuildOpenRuntimeOptionsPaletteMainDepsHandler,
|
|
||||||
createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler,
|
|
||||||
createBuildSendToActiveOverlayWindowMainDepsHandler,
|
|
||||||
createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler,
|
|
||||||
} from '../overlay-runtime-main-actions-main-deps';
|
|
||||||
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
||||||
|
|
||||||
type RestorePreviousSecondarySubVisibilityMainDeps = Parameters<
|
type RestorePreviousSecondarySubVisibilityMainDeps = Parameters<
|
||||||
typeof createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler
|
typeof createRestorePreviousSecondarySubVisibilityHandler
|
||||||
>[0];
|
>[0];
|
||||||
type BroadcastRuntimeOptionsChangedMainDeps = Parameters<
|
type BroadcastRuntimeOptionsChangedMainDeps = Parameters<
|
||||||
typeof createBuildBroadcastRuntimeOptionsChangedMainDepsHandler
|
typeof createBroadcastRuntimeOptionsChangedHandler
|
||||||
>[0];
|
>[0];
|
||||||
type SendToActiveOverlayWindowMainDeps = Parameters<
|
type SendToActiveOverlayWindowMainDeps = Parameters<
|
||||||
typeof createBuildSendToActiveOverlayWindowMainDepsHandler
|
typeof createSendToActiveOverlayWindowHandler
|
||||||
>[0];
|
>[0];
|
||||||
type SetOverlayDebugVisualizationEnabledMainDeps = Parameters<
|
type SetOverlayDebugVisualizationEnabledMainDeps = Parameters<
|
||||||
typeof createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler
|
typeof createSetOverlayDebugVisualizationEnabledHandler
|
||||||
>[0];
|
>[0];
|
||||||
type OpenRuntimeOptionsPaletteMainDeps = Parameters<
|
type OpenRuntimeOptionsPaletteMainDeps = Parameters<
|
||||||
typeof createBuildOpenRuntimeOptionsPaletteMainDepsHandler
|
typeof createOpenRuntimeOptionsPaletteHandler
|
||||||
>[0];
|
>[0];
|
||||||
|
|
||||||
export type OverlayVisibilityRuntimeComposerOptions = ComposerInputs<{
|
export type OverlayVisibilityRuntimeComposerOptions = ComposerInputs<{
|
||||||
@@ -61,29 +54,19 @@ export function composeOverlayVisibilityRuntime(
|
|||||||
updateVisibleOverlayVisibility: () =>
|
updateVisibleOverlayVisibility: () =>
|
||||||
options.overlayVisibilityRuntime.updateVisibleOverlayVisibility(),
|
options.overlayVisibilityRuntime.updateVisibleOverlayVisibility(),
|
||||||
restorePreviousSecondarySubVisibility: createRestorePreviousSecondarySubVisibilityHandler(
|
restorePreviousSecondarySubVisibility: createRestorePreviousSecondarySubVisibilityHandler(
|
||||||
createBuildRestorePreviousSecondarySubVisibilityMainDepsHandler(
|
options.restorePreviousSecondarySubVisibilityMainDeps,
|
||||||
options.restorePreviousSecondarySubVisibilityMainDeps,
|
|
||||||
)(),
|
|
||||||
),
|
),
|
||||||
broadcastRuntimeOptionsChanged: createBroadcastRuntimeOptionsChangedHandler(
|
broadcastRuntimeOptionsChanged: createBroadcastRuntimeOptionsChangedHandler(
|
||||||
createBuildBroadcastRuntimeOptionsChangedMainDepsHandler(
|
options.broadcastRuntimeOptionsChangedMainDeps,
|
||||||
options.broadcastRuntimeOptionsChangedMainDeps,
|
|
||||||
)(),
|
|
||||||
),
|
),
|
||||||
sendToActiveOverlayWindow: createSendToActiveOverlayWindowHandler(
|
sendToActiveOverlayWindow: createSendToActiveOverlayWindowHandler(
|
||||||
createBuildSendToActiveOverlayWindowMainDepsHandler(
|
options.sendToActiveOverlayWindowMainDeps,
|
||||||
options.sendToActiveOverlayWindowMainDeps,
|
|
||||||
)(),
|
|
||||||
),
|
),
|
||||||
setOverlayDebugVisualizationEnabled: createSetOverlayDebugVisualizationEnabledHandler(
|
setOverlayDebugVisualizationEnabled: createSetOverlayDebugVisualizationEnabledHandler(
|
||||||
createBuildSetOverlayDebugVisualizationEnabledMainDepsHandler(
|
options.setOverlayDebugVisualizationEnabledMainDeps,
|
||||||
options.setOverlayDebugVisualizationEnabledMainDeps,
|
|
||||||
)(),
|
|
||||||
),
|
),
|
||||||
openRuntimeOptionsPalette: createOpenRuntimeOptionsPaletteHandler(
|
openRuntimeOptionsPalette: createOpenRuntimeOptionsPaletteHandler(
|
||||||
createBuildOpenRuntimeOptionsPaletteMainDepsHandler(
|
options.openRuntimeOptionsPaletteMainDeps,
|
||||||
options.openRuntimeOptionsPaletteMainDeps,
|
|
||||||
)(),
|
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,69 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import test from 'node:test';
|
||||||
|
import {
|
||||||
|
composeShortcutRuntimes,
|
||||||
|
type ShortcutsRuntimeComposerOptions,
|
||||||
|
} from './shortcuts-runtime-composer';
|
||||||
|
|
||||||
|
type GlobalShortcutsOptions = ShortcutsRuntimeComposerOptions['globalShortcuts'];
|
||||||
|
|
||||||
|
function createComposerOptions(tryBeginOverlaySelection: (timeoutMs: number) => boolean) {
|
||||||
|
const registeredAccelerators: string[] = [];
|
||||||
|
const options: ShortcutsRuntimeComposerOptions = {
|
||||||
|
// Global and overlay shortcut handlers are only constructed here, never invoked.
|
||||||
|
globalShortcuts: {
|
||||||
|
getConfiguredShortcutsMainDeps:
|
||||||
|
{} as GlobalShortcutsOptions['getConfiguredShortcutsMainDeps'],
|
||||||
|
buildRegisterGlobalShortcutsMainDeps: () =>
|
||||||
|
({}) as ReturnType<GlobalShortcutsOptions['buildRegisterGlobalShortcutsMainDeps']>,
|
||||||
|
buildRefreshGlobalAndOverlayShortcutsMainDeps: () =>
|
||||||
|
({}) as ReturnType<GlobalShortcutsOptions['buildRefreshGlobalAndOverlayShortcutsMainDeps']>,
|
||||||
|
},
|
||||||
|
overlayShortcutsRuntimeMainDeps:
|
||||||
|
{} as ShortcutsRuntimeComposerOptions['overlayShortcutsRuntimeMainDeps'],
|
||||||
|
numericShortcutRuntimeMainDeps: {
|
||||||
|
globalShortcut: {
|
||||||
|
register: (accelerator) => {
|
||||||
|
registeredAccelerators.push(accelerator);
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
unregister: () => {},
|
||||||
|
},
|
||||||
|
showMpvOsd: () => {},
|
||||||
|
setTimer: () => setTimeout(() => {}, 0),
|
||||||
|
clearTimer: (timer) => clearTimeout(timer),
|
||||||
|
},
|
||||||
|
numericSessions: {
|
||||||
|
onMultiCopyDigit: () => {},
|
||||||
|
onMineSentenceDigit: () => {},
|
||||||
|
tryBeginMultiCopyOverlaySelection: tryBeginOverlaySelection,
|
||||||
|
tryBeginMineSentenceOverlaySelection: tryBeginOverlaySelection,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return { options, registeredAccelerators };
|
||||||
|
}
|
||||||
|
|
||||||
|
test('numeric sessions delegate to the visible overlay when it accepts the selection', () => {
|
||||||
|
const timeouts: number[] = [];
|
||||||
|
const { options, registeredAccelerators } = createComposerOptions((timeoutMs) => {
|
||||||
|
timeouts.push(timeoutMs);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
const runtimes = composeShortcutRuntimes(options);
|
||||||
|
|
||||||
|
runtimes.startPendingMultiCopy(3000);
|
||||||
|
runtimes.startPendingMineSentenceMultiple(4000);
|
||||||
|
|
||||||
|
assert.deepEqual(timeouts, [3000, 4000]);
|
||||||
|
assert.deepEqual(registeredAccelerators, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('numeric sessions fall back to global digit shortcuts when the overlay declines', () => {
|
||||||
|
const { options, registeredAccelerators } = createComposerOptions(() => false);
|
||||||
|
const runtimes = composeShortcutRuntimes(options);
|
||||||
|
|
||||||
|
runtimes.startPendingMultiCopy(3000);
|
||||||
|
|
||||||
|
assert.ok(registeredAccelerators.length > 0);
|
||||||
|
runtimes.cancelPendingMultiCopy();
|
||||||
|
});
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import { createNumericShortcutRuntime } from '../../../core/services/numeric-shortcut';
|
import { createNumericShortcutRuntime } from '../../../core/services/numeric-shortcut';
|
||||||
import {
|
import {
|
||||||
createBuildNumericShortcutRuntimeMainDepsHandler,
|
|
||||||
createGlobalShortcutsRuntimeHandlers,
|
createGlobalShortcutsRuntimeHandlers,
|
||||||
createNumericShortcutSessionRuntimeHandlers,
|
createNumericShortcutSessionRuntimeHandlers,
|
||||||
createOverlayShortcutsRuntimeHandlers,
|
createOverlayShortcutsRuntimeHandlers,
|
||||||
@@ -8,9 +7,7 @@ import {
|
|||||||
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
import type { ComposerInputs, ComposerOutputs } from './contracts';
|
||||||
|
|
||||||
type GlobalShortcutsOptions = Parameters<typeof createGlobalShortcutsRuntimeHandlers>[0];
|
type GlobalShortcutsOptions = Parameters<typeof createGlobalShortcutsRuntimeHandlers>[0];
|
||||||
type NumericShortcutRuntimeMainDeps = Parameters<
|
type NumericShortcutRuntimeMainDeps = Parameters<typeof createNumericShortcutRuntime>[0];
|
||||||
typeof createBuildNumericShortcutRuntimeMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type NumericSessionOptions = Omit<
|
type NumericSessionOptions = Omit<
|
||||||
Parameters<typeof createNumericShortcutSessionRuntimeHandlers>[0],
|
Parameters<typeof createNumericShortcutSessionRuntimeHandlers>[0],
|
||||||
'multiCopySession' | 'mineSentenceSession'
|
'multiCopySession' | 'mineSentenceSession'
|
||||||
@@ -37,15 +34,13 @@ export function composeShortcutRuntimes(
|
|||||||
): ShortcutsRuntimeComposerResult {
|
): ShortcutsRuntimeComposerResult {
|
||||||
const globalShortcuts = createGlobalShortcutsRuntimeHandlers(options.globalShortcuts);
|
const globalShortcuts = createGlobalShortcutsRuntimeHandlers(options.globalShortcuts);
|
||||||
|
|
||||||
const numericShortcutRuntimeMainDeps = createBuildNumericShortcutRuntimeMainDepsHandler(
|
const numericShortcutRuntime = createNumericShortcutRuntime(
|
||||||
options.numericShortcutRuntimeMainDeps,
|
options.numericShortcutRuntimeMainDeps,
|
||||||
)();
|
);
|
||||||
const numericShortcutRuntime = createNumericShortcutRuntime(numericShortcutRuntimeMainDeps);
|
|
||||||
const numericSessions = createNumericShortcutSessionRuntimeHandlers({
|
const numericSessions = createNumericShortcutSessionRuntimeHandlers({
|
||||||
|
...options.numericSessions,
|
||||||
multiCopySession: numericShortcutRuntime.createSession(),
|
multiCopySession: numericShortcutRuntime.createSession(),
|
||||||
mineSentenceSession: numericShortcutRuntime.createSession(),
|
mineSentenceSession: numericShortcutRuntime.createSession(),
|
||||||
onMultiCopyDigit: options.numericSessions.onMultiCopyDigit,
|
|
||||||
onMineSentenceDigit: options.numericSessions.onMineSentenceDigit,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const overlayShortcuts = createOverlayShortcutsRuntimeHandlers({
|
const overlayShortcuts = createOverlayShortcutsRuntimeHandlers({
|
||||||
|
|||||||
@@ -1,15 +1,9 @@
|
|||||||
export * from '../anilist-media-guess';
|
export * from '../anilist-media-guess';
|
||||||
export * from '../anilist-media-guess-main-deps';
|
|
||||||
export * from '../anilist-media-state';
|
export * from '../anilist-media-state';
|
||||||
export * from '../anilist-media-state-main-deps';
|
|
||||||
export * from '../anilist-post-watch';
|
export * from '../anilist-post-watch';
|
||||||
export * from '../anilist-post-watch-main-deps';
|
|
||||||
export * from '../anilist-setup';
|
export * from '../anilist-setup';
|
||||||
export * from '../anilist-setup-protocol';
|
export * from '../anilist-setup-protocol';
|
||||||
export * from '../anilist-setup-protocol-main-deps';
|
|
||||||
export * from '../anilist-setup-window';
|
export * from '../anilist-setup-window';
|
||||||
export * from '../anilist-setup-window-main-deps';
|
|
||||||
export * from '../anilist-state';
|
export * from '../anilist-state';
|
||||||
export * from '../anilist-token-refresh';
|
export * from '../anilist-token-refresh';
|
||||||
export * from '../anilist-token-refresh-main-deps';
|
|
||||||
export * from '../protocol-url-handlers';
|
export * from '../protocol-url-handlers';
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
export * from '../cli-command-context-factory';
|
export * from '../cli-command-context-factory';
|
||||||
export * from '../cli-command-runtime-handler';
|
export * from '../cli-command-runtime-handler';
|
||||||
export * from '../initial-args-runtime-handler';
|
export * from '../initial-args-runtime-handler';
|
||||||
export * from '../ipc-mpv-command-main-deps';
|
|
||||||
export * from '../ipc-runtime-handlers';
|
export * from '../ipc-runtime-handlers';
|
||||||
@@ -1,25 +1,18 @@
|
|||||||
export * from '../jellyfin-cli-auth';
|
export * from '../jellyfin-cli-auth';
|
||||||
export * from '../jellyfin-cli-list';
|
export * from '../jellyfin-cli-list';
|
||||||
export * from '../jellyfin-cli-main-deps';
|
|
||||||
export * from '../jellyfin-cli-play';
|
export * from '../jellyfin-cli-play';
|
||||||
export * from '../jellyfin-cli-remote-announce';
|
export * from '../jellyfin-cli-remote-announce';
|
||||||
export * from '../jellyfin-client-info';
|
export * from '../jellyfin-client-info';
|
||||||
export * from '../jellyfin-client-info-main-deps';
|
export * from '../jellyfin-client-info-main-deps';
|
||||||
export * from '../jellyfin-command-dispatch';
|
export * from '../jellyfin-command-dispatch';
|
||||||
export * from '../jellyfin-command-dispatch-main-deps';
|
|
||||||
export * from '../jellyfin-device-identity';
|
export * from '../jellyfin-device-identity';
|
||||||
export * from '../jellyfin-playback-launch';
|
export * from '../jellyfin-playback-launch';
|
||||||
export * from '../jellyfin-playback-launch-main-deps';
|
|
||||||
export * from '../jellyfin-remote-commands';
|
export * from '../jellyfin-remote-commands';
|
||||||
export * from '../jellyfin-remote-connection';
|
export * from '../jellyfin-remote-connection';
|
||||||
export * from '../jellyfin-remote-connection-main-deps';
|
|
||||||
export * from '../jellyfin-remote-main-deps';
|
export * from '../jellyfin-remote-main-deps';
|
||||||
export * from '../jellyfin-remote-playback';
|
export * from '../jellyfin-remote-playback';
|
||||||
export * from '../jellyfin-remote-session-lifecycle';
|
export * from '../jellyfin-remote-session-lifecycle';
|
||||||
export * from '../jellyfin-remote-session-main-deps';
|
|
||||||
export * from '../jellyfin-setup-window';
|
export * from '../jellyfin-setup-window';
|
||||||
export * from '../jellyfin-setup-window-main-deps';
|
export * from '../jellyfin-setup-window-main-deps';
|
||||||
export * from '../jellyfin-subtitle-preload';
|
export * from '../jellyfin-subtitle-preload';
|
||||||
export * from '../jellyfin-subtitle-preload-main-deps';
|
|
||||||
export * from '../mpv-jellyfin-defaults';
|
export * from '../mpv-jellyfin-defaults';
|
||||||
export * from '../mpv-jellyfin-defaults-main-deps';
|
|
||||||
@@ -1,4 +1,2 @@
|
|||||||
export * from '../anki-actions';
|
export * from '../anki-actions';
|
||||||
export * from '../anki-actions-main-deps';
|
|
||||||
export * from '../mining-actions';
|
export * from '../mining-actions';
|
||||||
export * from '../mining-actions-main-deps';
|
|
||||||
@@ -4,6 +4,5 @@ export * from '../mpv-main-event-bindings';
|
|||||||
export * from '../mpv-main-event-main-deps';
|
export * from '../mpv-main-event-main-deps';
|
||||||
export * from '../mpv-osd-runtime-handlers';
|
export * from '../mpv-osd-runtime-handlers';
|
||||||
export * from '../mpv-subtitle-render-metrics';
|
export * from '../mpv-subtitle-render-metrics';
|
||||||
export * from '../mpv-subtitle-render-metrics-main-deps';
|
|
||||||
export * from '../secondary-sub-mode-runtime-handler';
|
export * from '../secondary-sub-mode-runtime-handler';
|
||||||
export * from '../subtitle-tokenization-main-deps';
|
export * from '../subtitle-tokenization-main-deps';
|
||||||
@@ -1,21 +1,15 @@
|
|||||||
export * from '../config-hot-reload-handlers';
|
export * from '../config-hot-reload-handlers';
|
||||||
export * from '../config-hot-reload-main-deps';
|
export * from '../config-hot-reload-main-deps';
|
||||||
export * from '../field-grouping-overlay-main-deps';
|
|
||||||
export * from '../field-grouping-resolver';
|
export * from '../field-grouping-resolver';
|
||||||
export * from '../field-grouping-resolver-main-deps';
|
|
||||||
export * from '../overlay-bootstrap-main-deps';
|
|
||||||
export * from '../overlay-main-actions';
|
export * from '../overlay-main-actions';
|
||||||
export * from '../overlay-main-actions-main-deps';
|
|
||||||
export * from '../overlay-runtime-bootstrap-handlers';
|
export * from '../overlay-runtime-bootstrap-handlers';
|
||||||
export * from '../overlay-runtime-main-actions';
|
export * from '../overlay-runtime-main-actions';
|
||||||
export * from '../overlay-runtime-main-actions-main-deps';
|
|
||||||
export * from '../overlay-visibility-runtime';
|
export * from '../overlay-visibility-runtime';
|
||||||
export * from '../overlay-visibility-runtime-main-deps';
|
export * from '../overlay-visibility-runtime-main-deps';
|
||||||
export * from '../overlay-window-layout';
|
export * from '../overlay-window-layout';
|
||||||
export * from '../overlay-window-layout-main-deps';
|
export * from '../overlay-window-layout-main-deps';
|
||||||
export * from '../overlay-window-runtime-handlers';
|
export * from '../overlay-window-runtime-handlers';
|
||||||
export * from '../subtitle-position';
|
export * from '../subtitle-position';
|
||||||
export * from '../subtitle-position-main-deps';
|
|
||||||
export * from '../tray-runtime';
|
export * from '../tray-runtime';
|
||||||
export * from '../tray-runtime-handlers';
|
export * from '../tray-runtime-handlers';
|
||||||
export * from '../yomitan-extension-runtime';
|
export * from '../yomitan-extension-runtime';
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
export * from '../global-shortcuts-runtime-handlers';
|
export * from '../global-shortcuts-runtime-handlers';
|
||||||
export * from '../numeric-shortcut-runtime-main-deps';
|
|
||||||
export * from '../numeric-shortcut-session-runtime-handlers';
|
export * from '../numeric-shortcut-session-runtime-handlers';
|
||||||
export * from '../overlay-shortcuts-runtime-handlers';
|
export * from '../overlay-shortcuts-runtime-handlers';
|
||||||
export * from '../overlay-shortcuts-runtime-main-deps';
|
export * from '../overlay-shortcuts-runtime-main-deps';
|
||||||
@@ -1,19 +1,12 @@
|
|||||||
export * from '../app-lifecycle-actions';
|
export * from '../app-lifecycle-actions';
|
||||||
export * from '../app-lifecycle-main-activate';
|
export * from '../app-lifecycle-main-activate';
|
||||||
export * from '../app-lifecycle-main-cleanup';
|
export * from '../app-lifecycle-main-cleanup';
|
||||||
export * from '../app-ready-main-deps';
|
|
||||||
export * from '../clipboard-queue';
|
export * from '../clipboard-queue';
|
||||||
export * from '../config-derived';
|
export * from '../config-derived';
|
||||||
export * from '../dictionary-runtime-main-deps';
|
export * from '../dictionary-runtime-main-deps';
|
||||||
export * from '../immersion-media';
|
export * from '../immersion-media';
|
||||||
export * from '../immersion-startup';
|
export * from '../immersion-startup';
|
||||||
export * from '../immersion-startup-main-deps';
|
|
||||||
export * from '../media-runtime-main-deps';
|
|
||||||
export * from '../runtime-bootstrap-main-deps';
|
|
||||||
export * from '../startup-config';
|
export * from '../startup-config';
|
||||||
export * from '../startup-config-main-deps';
|
|
||||||
export * from '../startup-runtime-handlers';
|
export * from '../startup-runtime-handlers';
|
||||||
export * from '../startup-warmups';
|
export * from '../startup-warmups';
|
||||||
export * from '../startup-warmups-main-deps';
|
|
||||||
export * from '../subtitle-processing-main-deps';
|
|
||||||
export * from '../subsync-runtime';
|
export * from '../subsync-runtime';
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import type { FieldGroupingOverlayRuntimeOptions } from '../../core/services/field-grouping-overlay';
|
|
||||||
|
|
||||||
type FieldGroupingOverlayMainDeps<TModal extends string> = Omit<
|
|
||||||
FieldGroupingOverlayRuntimeOptions<TModal>,
|
|
||||||
'sendToVisibleOverlay'
|
|
||||||
> & {
|
|
||||||
sendToActiveOverlayWindow: (
|
|
||||||
channel: string,
|
|
||||||
payload?: unknown,
|
|
||||||
runtimeOptions?: { restoreOnModalClose?: TModal; preferModalWindow?: boolean },
|
|
||||||
) => boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
type BuiltFieldGroupingOverlayMainDeps<TModal extends string> =
|
|
||||||
FieldGroupingOverlayRuntimeOptions<TModal> & {
|
|
||||||
sendToVisibleOverlay: NonNullable<
|
|
||||||
FieldGroupingOverlayRuntimeOptions<TModal>['sendToVisibleOverlay']
|
|
||||||
>;
|
|
||||||
};
|
|
||||||
|
|
||||||
export function createBuildFieldGroupingOverlayMainDepsHandler<TModal extends string>(
|
|
||||||
deps: FieldGroupingOverlayMainDeps<TModal>,
|
|
||||||
) {
|
|
||||||
return (): BuiltFieldGroupingOverlayMainDeps<TModal> => ({
|
|
||||||
getMainWindow: () => deps.getMainWindow(),
|
|
||||||
getVisibleOverlayVisible: () => deps.getVisibleOverlayVisible(),
|
|
||||||
setVisibleOverlayVisible: (visible: boolean) => deps.setVisibleOverlayVisible(visible),
|
|
||||||
getResolver: () => deps.getResolver(),
|
|
||||||
setResolver: (resolver) => deps.setResolver(resolver),
|
|
||||||
getRestoreVisibleOverlayOnModalClose: () => deps.getRestoreVisibleOverlayOnModalClose(),
|
|
||||||
// These are optional on the runtime options, so a missing forward compiles silently — but
|
|
||||||
// dropping them left the field grouping modal with no modal-open ack/retry, no teardown on
|
|
||||||
// failure, and no warn logging, which is why the earlier recovery fixes never took effect.
|
|
||||||
waitForModalOpen: deps.waitForModalOpen,
|
|
||||||
handleOverlayModalClosed: deps.handleOverlayModalClosed,
|
|
||||||
logWarn: deps.logWarn,
|
|
||||||
ensureOverlayStartupPrereqs: deps.ensureOverlayStartupPrereqs,
|
|
||||||
ensureOverlayWindowsReadyForVisibilityActions:
|
|
||||||
deps.ensureOverlayWindowsReadyForVisibilityActions,
|
|
||||||
sendToVisibleOverlay: (
|
|
||||||
channel: string,
|
|
||||||
payload?: unknown,
|
|
||||||
runtimeOptions?: { restoreOnModalClose?: TModal; preferModalWindow?: boolean },
|
|
||||||
) => deps.sendToActiveOverlayWindow(channel, payload, runtimeOptions),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import type {
|
|
||||||
createGetFieldGroupingResolverHandler,
|
|
||||||
createSetFieldGroupingResolverHandler,
|
|
||||||
} from './field-grouping-resolver';
|
|
||||||
|
|
||||||
type GetFieldGroupingResolverMainDeps = Parameters<typeof createGetFieldGroupingResolverHandler>[0];
|
|
||||||
type SetFieldGroupingResolverMainDeps = Parameters<typeof createSetFieldGroupingResolverHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildGetFieldGroupingResolverMainDepsHandler(
|
|
||||||
deps: GetFieldGroupingResolverMainDeps,
|
|
||||||
) {
|
|
||||||
return (): GetFieldGroupingResolverMainDeps => ({
|
|
||||||
getResolver: () => deps.getResolver(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildSetFieldGroupingResolverMainDepsHandler(
|
|
||||||
deps: SetFieldGroupingResolverMainDeps,
|
|
||||||
) {
|
|
||||||
return (): SetFieldGroupingResolverMainDeps => ({
|
|
||||||
setResolver: (resolver) => deps.setResolver(resolver),
|
|
||||||
nextSequence: () => deps.nextSequence(),
|
|
||||||
getSequence: () => deps.getSequence(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
import type { Config } from '../../types';
|
|
||||||
import type { ConfiguredShortcuts } from '../../core/utils/shortcut-config';
|
|
||||||
import type { RegisterGlobalShortcutsServiceOptions } from '../../core/services/shortcut';
|
|
||||||
|
|
||||||
export function createBuildGetConfiguredShortcutsMainDepsHandler(deps: {
|
|
||||||
getResolvedConfig: () => Config;
|
|
||||||
defaultConfig: Config;
|
|
||||||
resolveConfiguredShortcuts: (config: Config, defaultConfig: Config) => ConfiguredShortcuts;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getResolvedConfig: () => deps.getResolvedConfig(),
|
|
||||||
defaultConfig: deps.defaultConfig,
|
|
||||||
resolveConfiguredShortcuts: (config: Config, defaultConfig: Config) =>
|
|
||||||
deps.resolveConfiguredShortcuts(config, defaultConfig),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildRegisterGlobalShortcutsMainDepsHandler(deps: {
|
|
||||||
getConfiguredShortcuts: () => RegisterGlobalShortcutsServiceOptions['shortcuts'];
|
|
||||||
registerGlobalShortcutsCore: (options: RegisterGlobalShortcutsServiceOptions) => void;
|
|
||||||
toggleVisibleOverlay: () => void;
|
|
||||||
openYomitanSettings: () => void;
|
|
||||||
isDev: boolean;
|
|
||||||
getMainWindow: RegisterGlobalShortcutsServiceOptions['getMainWindow'];
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getConfiguredShortcuts: () => deps.getConfiguredShortcuts(),
|
|
||||||
registerGlobalShortcutsCore: (options: RegisterGlobalShortcutsServiceOptions) =>
|
|
||||||
deps.registerGlobalShortcutsCore(options),
|
|
||||||
onToggleVisibleOverlay: () => deps.toggleVisibleOverlay(),
|
|
||||||
onOpenYomitanSettings: () => deps.openYomitanSettings(),
|
|
||||||
isDev: deps.isDev,
|
|
||||||
getMainWindow: deps.getMainWindow,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildRefreshGlobalAndOverlayShortcutsMainDepsHandler(deps: {
|
|
||||||
unregisterAllGlobalShortcuts: () => void;
|
|
||||||
registerGlobalShortcuts: () => void;
|
|
||||||
syncOverlayShortcuts: () => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
unregisterAllGlobalShortcuts: () => deps.unregisterAllGlobalShortcuts(),
|
|
||||||
registerGlobalShortcuts: () => deps.registerGlobalShortcuts(),
|
|
||||||
syncOverlayShortcuts: () => deps.syncOverlayShortcuts(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -4,20 +4,11 @@ import {
|
|||||||
createRefreshGlobalAndOverlayShortcutsHandler,
|
createRefreshGlobalAndOverlayShortcutsHandler,
|
||||||
createRegisterGlobalShortcutsHandler,
|
createRegisterGlobalShortcutsHandler,
|
||||||
} from './global-shortcuts';
|
} from './global-shortcuts';
|
||||||
import {
|
|
||||||
createBuildGetConfiguredShortcutsMainDepsHandler,
|
|
||||||
createBuildRefreshGlobalAndOverlayShortcutsMainDepsHandler,
|
|
||||||
createBuildRegisterGlobalShortcutsMainDepsHandler,
|
|
||||||
} from './global-shortcuts-main-deps';
|
|
||||||
|
|
||||||
type GetConfiguredShortcutsMainDeps = Parameters<
|
type GetConfiguredShortcutsMainDeps = Parameters<typeof createGetConfiguredShortcutsHandler>[0];
|
||||||
typeof createBuildGetConfiguredShortcutsMainDepsHandler
|
type RegisterGlobalShortcutsMainDeps = Parameters<typeof createRegisterGlobalShortcutsHandler>[0];
|
||||||
>[0];
|
|
||||||
type RegisterGlobalShortcutsMainDeps = Parameters<
|
|
||||||
typeof createBuildRegisterGlobalShortcutsMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type RefreshGlobalAndOverlayShortcutsMainDeps = Parameters<
|
type RefreshGlobalAndOverlayShortcutsMainDeps = Parameters<
|
||||||
typeof createBuildRefreshGlobalAndOverlayShortcutsMainDepsHandler
|
typeof createRefreshGlobalAndOverlayShortcutsHandler
|
||||||
>[0];
|
>[0];
|
||||||
|
|
||||||
export function createGlobalShortcutsRuntimeHandlers(deps: {
|
export function createGlobalShortcutsRuntimeHandlers(deps: {
|
||||||
@@ -29,28 +20,18 @@ export function createGlobalShortcutsRuntimeHandlers(deps: {
|
|||||||
registerGlobalShortcuts: () => void,
|
registerGlobalShortcuts: () => void,
|
||||||
) => RefreshGlobalAndOverlayShortcutsMainDeps;
|
) => RefreshGlobalAndOverlayShortcutsMainDeps;
|
||||||
}) {
|
}) {
|
||||||
const getConfiguredShortcutsMainDeps = createBuildGetConfiguredShortcutsMainDepsHandler(
|
|
||||||
deps.getConfiguredShortcutsMainDeps,
|
|
||||||
)();
|
|
||||||
const getConfiguredShortcutsHandler = createGetConfiguredShortcutsHandler(
|
const getConfiguredShortcutsHandler = createGetConfiguredShortcutsHandler(
|
||||||
getConfiguredShortcutsMainDeps,
|
deps.getConfiguredShortcutsMainDeps,
|
||||||
);
|
);
|
||||||
const getConfiguredShortcuts = () => getConfiguredShortcutsHandler();
|
const getConfiguredShortcuts = () => getConfiguredShortcutsHandler();
|
||||||
|
|
||||||
const registerGlobalShortcutsMainDeps = createBuildRegisterGlobalShortcutsMainDepsHandler(
|
|
||||||
deps.buildRegisterGlobalShortcutsMainDeps(getConfiguredShortcuts),
|
|
||||||
)();
|
|
||||||
const registerGlobalShortcutsHandler = createRegisterGlobalShortcutsHandler(
|
const registerGlobalShortcutsHandler = createRegisterGlobalShortcutsHandler(
|
||||||
registerGlobalShortcutsMainDeps,
|
deps.buildRegisterGlobalShortcutsMainDeps(getConfiguredShortcuts),
|
||||||
);
|
);
|
||||||
const registerGlobalShortcuts = () => registerGlobalShortcutsHandler();
|
const registerGlobalShortcuts = () => registerGlobalShortcutsHandler();
|
||||||
|
|
||||||
const refreshGlobalAndOverlayShortcutsMainDeps =
|
|
||||||
createBuildRefreshGlobalAndOverlayShortcutsMainDepsHandler(
|
|
||||||
deps.buildRefreshGlobalAndOverlayShortcutsMainDeps(registerGlobalShortcuts),
|
|
||||||
)();
|
|
||||||
const refreshGlobalAndOverlayShortcutsHandler = createRefreshGlobalAndOverlayShortcutsHandler(
|
const refreshGlobalAndOverlayShortcutsHandler = createRefreshGlobalAndOverlayShortcutsHandler(
|
||||||
refreshGlobalAndOverlayShortcutsMainDeps,
|
deps.buildRefreshGlobalAndOverlayShortcutsMainDeps(registerGlobalShortcuts),
|
||||||
);
|
);
|
||||||
const refreshGlobalAndOverlayShortcuts = () => refreshGlobalAndOverlayShortcutsHandler();
|
const refreshGlobalAndOverlayShortcuts = () => refreshGlobalAndOverlayShortcutsHandler();
|
||||||
|
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
import type {
|
|
||||||
ImmersionTrackerStartupDeps,
|
|
||||||
createImmersionTrackerStartupHandler,
|
|
||||||
} from './immersion-startup';
|
|
||||||
|
|
||||||
type ImmersionTrackerStartupMainDeps = Parameters<typeof createImmersionTrackerStartupHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildImmersionTrackerStartupMainDepsHandler(
|
|
||||||
deps: ImmersionTrackerStartupMainDeps,
|
|
||||||
) {
|
|
||||||
return (): ImmersionTrackerStartupDeps => ({
|
|
||||||
getResolvedConfig: () => deps.getResolvedConfig(),
|
|
||||||
getConfiguredDbPath: () => deps.getConfiguredDbPath(),
|
|
||||||
createTrackerService: (params) => deps.createTrackerService(params),
|
|
||||||
setTracker: (tracker) => deps.setTracker(tracker),
|
|
||||||
getMpvClient: () => deps.getMpvClient(),
|
|
||||||
seedTrackerFromCurrentMedia: () => deps.seedTrackerFromCurrentMedia(),
|
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
|
||||||
logDebug: (message: string) => deps.logDebug(message),
|
|
||||||
logWarn: (message: string, details: unknown) => deps.logWarn(message, details),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
import type { CliArgs } from '../../cli/args';
|
|
||||||
|
|
||||||
export function createBuildHandleInitialArgsMainDepsHandler(deps: {
|
|
||||||
getInitialArgs: () => CliArgs | null;
|
|
||||||
isBackgroundMode: () => boolean;
|
|
||||||
shouldEnsureTrayOnStartup: () => boolean;
|
|
||||||
shouldRunHeadlessInitialCommand: (args: CliArgs) => boolean;
|
|
||||||
ensureTray: () => void;
|
|
||||||
isTexthookerOnlyMode: () => boolean;
|
|
||||||
hasImmersionTracker: () => boolean;
|
|
||||||
getMpvClient: () => { connected: boolean; connect: () => void } | null;
|
|
||||||
commandNeedsOverlayStartupPrereqs: (args: CliArgs) => boolean;
|
|
||||||
commandNeedsOverlayRuntime: (args: CliArgs) => boolean;
|
|
||||||
ensureOverlayStartupPrereqs: () => void;
|
|
||||||
isOverlayRuntimeInitialized: () => boolean;
|
|
||||||
initializeOverlayRuntime: () => void;
|
|
||||||
logInfo: (message: string) => void;
|
|
||||||
handleCliCommand: (args: CliArgs, source: 'initial') => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getInitialArgs: () => deps.getInitialArgs(),
|
|
||||||
isBackgroundMode: () => deps.isBackgroundMode(),
|
|
||||||
shouldEnsureTrayOnStartup: () => deps.shouldEnsureTrayOnStartup(),
|
|
||||||
shouldRunHeadlessInitialCommand: (args: CliArgs) => deps.shouldRunHeadlessInitialCommand(args),
|
|
||||||
ensureTray: () => deps.ensureTray(),
|
|
||||||
isTexthookerOnlyMode: () => deps.isTexthookerOnlyMode(),
|
|
||||||
hasImmersionTracker: () => deps.hasImmersionTracker(),
|
|
||||||
getMpvClient: () => deps.getMpvClient(),
|
|
||||||
commandNeedsOverlayStartupPrereqs: (args: CliArgs) =>
|
|
||||||
deps.commandNeedsOverlayStartupPrereqs(args),
|
|
||||||
commandNeedsOverlayRuntime: (args: CliArgs) => deps.commandNeedsOverlayRuntime(args),
|
|
||||||
ensureOverlayStartupPrereqs: () => deps.ensureOverlayStartupPrereqs(),
|
|
||||||
isOverlayRuntimeInitialized: () => deps.isOverlayRuntimeInitialized(),
|
|
||||||
initializeOverlayRuntime: () => deps.initializeOverlayRuntime(),
|
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
|
||||||
handleCliCommand: (args: CliArgs, source: 'initial') => deps.handleCliCommand(args, source),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
import { createHandleInitialArgsHandler } from './initial-args-handler';
|
import { createHandleInitialArgsHandler } from './initial-args-handler';
|
||||||
import { createBuildHandleInitialArgsMainDepsHandler } from './initial-args-main-deps';
|
|
||||||
|
|
||||||
type InitialArgsMainDeps = Parameters<typeof createBuildHandleInitialArgsMainDepsHandler>[0];
|
type InitialArgsMainDeps = Parameters<typeof createHandleInitialArgsHandler>[0];
|
||||||
|
|
||||||
export function createInitialArgsRuntimeHandler(deps: InitialArgsMainDeps) {
|
export function createInitialArgsRuntimeHandler(deps: InitialArgsMainDeps) {
|
||||||
const buildHandleInitialArgsMainDepsHandler = createBuildHandleInitialArgsMainDepsHandler(deps);
|
return createHandleInitialArgsHandler(deps);
|
||||||
const handleInitialArgsMainDeps = buildHandleInitialArgsMainDepsHandler();
|
|
||||||
return createHandleInitialArgsHandler(handleInitialArgsMainDeps);
|
|
||||||
}
|
}
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import type { createHandleMpvCommandFromIpcHandler } from './ipc-bridge-actions';
|
|
||||||
|
|
||||||
type HandleMpvCommandFromIpcMainDeps = Parameters<typeof createHandleMpvCommandFromIpcHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildHandleMpvCommandFromIpcMainDepsHandler(
|
|
||||||
deps: HandleMpvCommandFromIpcMainDeps,
|
|
||||||
) {
|
|
||||||
return (): HandleMpvCommandFromIpcMainDeps => ({
|
|
||||||
handleMpvCommandFromIpcRuntime: (command, options) =>
|
|
||||||
deps.handleMpvCommandFromIpcRuntime(command, options),
|
|
||||||
buildMpvCommandDeps: () => deps.buildMpvCommandDeps(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildRunSubsyncManualFromIpcMainDepsHandler<TRequest, TResult>(deps: {
|
|
||||||
runManualFromIpc: (request: TRequest) => Promise<TResult>;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
runManualFromIpc: (request: TRequest) => deps.runManualFromIpc(request),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import type { MpvCommandFromIpcRuntimeDeps } from '../ipc-mpv-command';
|
|
||||||
|
|
||||||
export function createBuildMpvCommandFromIpcRuntimeMainDepsHandler(
|
|
||||||
deps: MpvCommandFromIpcRuntimeDeps,
|
|
||||||
) {
|
|
||||||
return (): MpvCommandFromIpcRuntimeDeps => {
|
|
||||||
const showPlaybackFeedback = deps.showPlaybackFeedback;
|
|
||||||
const showRawMpvOsd = deps.showRawMpvOsd;
|
|
||||||
return {
|
|
||||||
triggerSubsyncFromConfig: () => deps.triggerSubsyncFromConfig(),
|
|
||||||
openRuntimeOptionsPalette: () => deps.openRuntimeOptionsPalette(),
|
|
||||||
openJimaku: () => deps.openJimaku(),
|
|
||||||
openTsukihime: () => deps.openTsukihime(),
|
|
||||||
openYoutubeTrackPicker: () => deps.openYoutubeTrackPicker(),
|
|
||||||
openPlaylistBrowser: () => deps.openPlaylistBrowser(),
|
|
||||||
cycleRuntimeOption: (id, direction) => deps.cycleRuntimeOption(id, direction),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
...(showRawMpvOsd ? { showRawMpvOsd: (text: string) => showRawMpvOsd(text) } : {}),
|
|
||||||
...(showPlaybackFeedback
|
|
||||||
? { showPlaybackFeedback: (text: string) => showPlaybackFeedback(text) }
|
|
||||||
: {}),
|
|
||||||
replayCurrentSubtitle: () => deps.replayCurrentSubtitle(),
|
|
||||||
playNextSubtitle: () => deps.playNextSubtitle(),
|
|
||||||
sendMpvCommand: (command: (string | number)[]) => deps.sendMpvCommand(command),
|
|
||||||
getMpvClient: () => deps.getMpvClient(),
|
|
||||||
isMpvConnected: () => deps.isMpvConnected(),
|
|
||||||
hasRuntimeOptionsManager: () => deps.hasRuntimeOptionsManager(),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -2,35 +2,18 @@ import {
|
|||||||
createHandleMpvCommandFromIpcHandler,
|
createHandleMpvCommandFromIpcHandler,
|
||||||
createRunSubsyncManualFromIpcHandler,
|
createRunSubsyncManualFromIpcHandler,
|
||||||
} from './ipc-bridge-actions';
|
} from './ipc-bridge-actions';
|
||||||
import {
|
|
||||||
createBuildHandleMpvCommandFromIpcMainDepsHandler,
|
|
||||||
createBuildRunSubsyncManualFromIpcMainDepsHandler,
|
|
||||||
} from './ipc-bridge-actions-main-deps';
|
|
||||||
|
|
||||||
type HandleMpvCommandFromIpcMainDeps = Parameters<
|
|
||||||
typeof createBuildHandleMpvCommandFromIpcMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type RunSubsyncManualFromIpcMainDeps<TRequest, TResult> = Parameters<
|
|
||||||
typeof createBuildRunSubsyncManualFromIpcMainDepsHandler<TRequest, TResult>
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createIpcRuntimeHandlers<TRequest, TResult>(deps: {
|
export function createIpcRuntimeHandlers<TRequest, TResult>(deps: {
|
||||||
handleMpvCommandFromIpcDeps: HandleMpvCommandFromIpcMainDeps;
|
handleMpvCommandFromIpcDeps: Parameters<typeof createHandleMpvCommandFromIpcHandler>[0];
|
||||||
runSubsyncManualFromIpcDeps: RunSubsyncManualFromIpcMainDeps<TRequest, TResult>;
|
runSubsyncManualFromIpcDeps: Parameters<
|
||||||
|
typeof createRunSubsyncManualFromIpcHandler<TRequest, TResult>
|
||||||
|
>[0];
|
||||||
}) {
|
}) {
|
||||||
const handleMpvCommandFromIpcMainDeps = createBuildHandleMpvCommandFromIpcMainDepsHandler(
|
|
||||||
deps.handleMpvCommandFromIpcDeps,
|
|
||||||
)();
|
|
||||||
const handleMpvCommandFromIpc = createHandleMpvCommandFromIpcHandler(
|
const handleMpvCommandFromIpc = createHandleMpvCommandFromIpcHandler(
|
||||||
handleMpvCommandFromIpcMainDeps,
|
deps.handleMpvCommandFromIpcDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const runSubsyncManualFromIpcMainDeps = createBuildRunSubsyncManualFromIpcMainDepsHandler<
|
|
||||||
TRequest,
|
|
||||||
TResult
|
|
||||||
>(deps.runSubsyncManualFromIpcDeps)();
|
|
||||||
const runSubsyncManualFromIpc = createRunSubsyncManualFromIpcHandler<TRequest, TResult>(
|
const runSubsyncManualFromIpc = createRunSubsyncManualFromIpcHandler<TRequest, TResult>(
|
||||||
runSubsyncManualFromIpcMainDeps,
|
deps.runSubsyncManualFromIpcDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,59 +0,0 @@
|
|||||||
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),
|
|
||||||
saveStoredSession: (session) => deps.saveStoredSession(session),
|
|
||||||
clearStoredSession: () => deps.clearStoredSession(),
|
|
||||||
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),
|
|
||||||
writeJellyfinResponse: (responsePath, response) =>
|
|
||||||
deps.writeJellyfinResponse(responsePath, response),
|
|
||||||
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: (options) => deps.startJellyfinRemoteSession(options),
|
|
||||||
getRemoteSession: () => deps.getRemoteSession(),
|
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
|
||||||
logWarn: (message: string) => deps.logWarn(message),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
import type { CliArgs } from '../../cli/args';
|
|
||||||
import type { JellyfinCliResponse } from '../../shared/jellyfin-cli-response';
|
|
||||||
|
|
||||||
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>;
|
|
||||||
writeJellyfinResponse: (responsePath: string, response: JellyfinCliResponse) => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
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),
|
|
||||||
writeJellyfinResponse: (responsePath, response) =>
|
|
||||||
deps.writeJellyfinResponse(responsePath, response),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import type { createPlayJellyfinItemInMpvHandler } from './jellyfin-playback-launch';
|
|
||||||
|
|
||||||
type PlayJellyfinItemInMpvMainDeps = Parameters<typeof createPlayJellyfinItemInMpvHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildPlayJellyfinItemInMpvMainDepsHandler(
|
|
||||||
deps: PlayJellyfinItemInMpvMainDeps,
|
|
||||||
) {
|
|
||||||
return (): PlayJellyfinItemInMpvMainDeps => ({
|
|
||||||
ensureMpvConnectedForPlayback: () => deps.ensureMpvConnectedForPlayback(),
|
|
||||||
getMpvClient: () => deps.getMpvClient(),
|
|
||||||
resolvePlaybackPlan: (params) => deps.resolvePlaybackPlan(params),
|
|
||||||
applyJellyfinMpvDefaults: (mpvClient) => deps.applyJellyfinMpvDefaults(mpvClient),
|
|
||||||
showVisibleOverlay: () => deps.showVisibleOverlay(),
|
|
||||||
sendMpvCommand: (command: Array<string | number>) => deps.sendMpvCommand(command),
|
|
||||||
armQuitOnDisconnect: () => deps.armQuitOnDisconnect(),
|
|
||||||
schedule: (callback: () => void, delayMs: number) => deps.schedule(callback, delayMs),
|
|
||||||
convertTicksToSeconds: (ticks: number) => deps.convertTicksToSeconds(ticks),
|
|
||||||
preloadExternalSubtitles: (params) => deps.preloadExternalSubtitles(params),
|
|
||||||
setActivePlayback: (state) => deps.setActivePlayback(state),
|
|
||||||
setLastProgressAtMs: (value: number) => deps.setLastProgressAtMs(value),
|
|
||||||
createPlaybackReporter: (params) => deps.createPlaybackReporter(params),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
recordJellyfinPlaybackMetadata: deps.recordJellyfinPlaybackMetadata
|
|
||||||
? (metadata) => deps.recordJellyfinPlaybackMetadata!(metadata)
|
|
||||||
: undefined,
|
|
||||||
updateCurrentMediaTitle: deps.updateCurrentMediaTitle
|
|
||||||
? (title) => deps.updateCurrentMediaTitle!(title)
|
|
||||||
: undefined,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
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 => ({
|
|
||||||
getMpvExecutablePath: () => deps.getMpvExecutablePath(),
|
|
||||||
getSocketPath: () => deps.getSocketPath(),
|
|
||||||
getLaunchMode: () => deps.getLaunchMode(),
|
|
||||||
platform: deps.platform,
|
|
||||||
execPath: deps.execPath,
|
|
||||||
getRuntimePluginEntrypoint: deps.getRuntimePluginEntrypoint,
|
|
||||||
getInstalledPluginDetection: deps.getInstalledPluginDetection,
|
|
||||||
getPluginRuntimeConfig: deps.getPluginRuntimeConfig,
|
|
||||||
getDefaultMpvLogPath: () => deps.getDefaultMpvLogPath(),
|
|
||||||
defaultMpvArgs: deps.defaultMpvArgs,
|
|
||||||
removeSocketPath: (socketPath: string) => deps.removeSocketPath(socketPath),
|
|
||||||
spawnMpv: (executablePath, args) => deps.spawnMpv(executablePath, 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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
import type {
|
|
||||||
createStartJellyfinRemoteSessionHandler,
|
|
||||||
createStopJellyfinRemoteSessionHandler,
|
|
||||||
} from './jellyfin-remote-session-lifecycle';
|
|
||||||
|
|
||||||
type StartJellyfinRemoteSessionMainDeps = Parameters<
|
|
||||||
typeof createStartJellyfinRemoteSessionHandler
|
|
||||||
>[0];
|
|
||||||
type StopJellyfinRemoteSessionMainDeps = Parameters<
|
|
||||||
typeof createStopJellyfinRemoteSessionHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildStartJellyfinRemoteSessionMainDepsHandler(
|
|
||||||
deps: StartJellyfinRemoteSessionMainDeps,
|
|
||||||
) {
|
|
||||||
return (): StartJellyfinRemoteSessionMainDeps => ({
|
|
||||||
getJellyfinConfig: () => deps.getJellyfinConfig(),
|
|
||||||
getCurrentSession: () => deps.getCurrentSession(),
|
|
||||||
setCurrentSession: (session) => deps.setCurrentSession(session),
|
|
||||||
createRemoteSessionService: (options) => deps.createRemoteSessionService(options),
|
|
||||||
getClientInfo: () => deps.getClientInfo(),
|
|
||||||
getHostName: () => deps.getHostName(),
|
|
||||||
defaultDeviceId: deps.defaultDeviceId,
|
|
||||||
defaultClientName: deps.defaultClientName,
|
|
||||||
defaultClientVersion: deps.defaultClientVersion,
|
|
||||||
handlePlay: (payload) => deps.handlePlay(payload),
|
|
||||||
handlePlaystate: (payload) => deps.handlePlaystate(payload),
|
|
||||||
handleGeneralCommand: (payload) => deps.handleGeneralCommand(payload),
|
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
|
||||||
logWarn: (message: string, details?: unknown) => deps.logWarn(message, details),
|
|
||||||
onSessionStateChanged: deps.onSessionStateChanged,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildStopJellyfinRemoteSessionMainDepsHandler(
|
|
||||||
deps: StopJellyfinRemoteSessionMainDeps,
|
|
||||||
) {
|
|
||||||
return (): StopJellyfinRemoteSessionMainDeps => ({
|
|
||||||
getCurrentSession: () => deps.getCurrentSession(),
|
|
||||||
setCurrentSession: (session) => deps.setCurrentSession(session),
|
|
||||||
clearActivePlayback: () => deps.clearActivePlayback(),
|
|
||||||
onSessionStateChanged: deps.onSessionStateChanged,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
import type { createPreloadJellyfinExternalSubtitlesHandler } from './jellyfin-subtitle-preload';
|
|
||||||
|
|
||||||
type PreloadJellyfinExternalSubtitlesMainDeps = Parameters<
|
|
||||||
typeof createPreloadJellyfinExternalSubtitlesHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildPreloadJellyfinExternalSubtitlesMainDepsHandler(
|
|
||||||
deps: PreloadJellyfinExternalSubtitlesMainDeps,
|
|
||||||
) {
|
|
||||||
return (): PreloadJellyfinExternalSubtitlesMainDeps => ({
|
|
||||||
listJellyfinSubtitleTracks: (session, clientInfo, itemId) =>
|
|
||||||
deps.listJellyfinSubtitleTracks(session, clientInfo, itemId),
|
|
||||||
getMpvClient: () => deps.getMpvClient(),
|
|
||||||
sendMpvCommand: (command) => deps.sendMpvCommand(command),
|
|
||||||
wait: (ms: number) => deps.wait(ms),
|
|
||||||
cacheSubtitleTrack: (track) => deps.cacheSubtitleTrack(track),
|
|
||||||
cleanupCachedSubtitles: (dirs) => deps.cleanupCachedSubtitles(dirs),
|
|
||||||
initSubtitlePrefetch: deps.initSubtitlePrefetch
|
|
||||||
? (sourcePath) => deps.initSubtitlePrefetch!(sourcePath)
|
|
||||||
: undefined,
|
|
||||||
logDebug: (message: string, error: unknown) => deps.logDebug(message, error),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
import type { SubtitlePosition } from '../../types';
|
|
||||||
|
|
||||||
export function createBuildMediaRuntimeMainDepsHandler(deps: {
|
|
||||||
isRemoteMediaPath: (mediaPath: string) => boolean;
|
|
||||||
loadSubtitlePosition: () => SubtitlePosition | null;
|
|
||||||
getCurrentMediaPath: () => string | null;
|
|
||||||
getPendingSubtitlePosition: () => SubtitlePosition | null;
|
|
||||||
getSubtitlePositionsDir: () => string;
|
|
||||||
setCurrentMediaPath: (mediaPath: string | null) => void;
|
|
||||||
clearPendingSubtitlePosition: () => void;
|
|
||||||
setSubtitlePosition: (position: SubtitlePosition | null) => void;
|
|
||||||
broadcastToOverlayWindows: (channel: string, payload: unknown) => void;
|
|
||||||
getCurrentMediaTitle: () => string | null;
|
|
||||||
setCurrentMediaTitle: (title: string | null) => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
isRemoteMediaPath: (mediaPath: string) => deps.isRemoteMediaPath(mediaPath),
|
|
||||||
loadSubtitlePosition: () => deps.loadSubtitlePosition(),
|
|
||||||
getCurrentMediaPath: () => deps.getCurrentMediaPath(),
|
|
||||||
getPendingSubtitlePosition: () => deps.getPendingSubtitlePosition(),
|
|
||||||
getSubtitlePositionsDir: () => deps.getSubtitlePositionsDir(),
|
|
||||||
setCurrentMediaPath: (nextPath: string | null) => deps.setCurrentMediaPath(nextPath),
|
|
||||||
clearPendingSubtitlePosition: () => deps.clearPendingSubtitlePosition(),
|
|
||||||
setSubtitlePosition: (position: SubtitlePosition | null) => deps.setSubtitlePosition(position),
|
|
||||||
broadcastSubtitlePosition: (position: SubtitlePosition | null) =>
|
|
||||||
deps.broadcastToOverlayWindows('subtitle-position:set', position),
|
|
||||||
getCurrentMediaTitle: () => deps.getCurrentMediaTitle(),
|
|
||||||
setCurrentMediaTitle: (title: string | null) => deps.setCurrentMediaTitle(title),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
export function createBuildHandleMultiCopyDigitMainDepsHandler<TSubtitleTimingTracker>(deps: {
|
|
||||||
getSubtitleTimingTracker: () => TSubtitleTimingTracker;
|
|
||||||
writeClipboardText: (text: string) => void;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
handleMultiCopyDigitCore: (
|
|
||||||
count: number,
|
|
||||||
options: {
|
|
||||||
subtitleTimingTracker: TSubtitleTimingTracker;
|
|
||||||
writeClipboardText: (text: string) => void;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
},
|
|
||||||
) => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getSubtitleTimingTracker: () => deps.getSubtitleTimingTracker(),
|
|
||||||
writeClipboardText: (text: string) => deps.writeClipboardText(text),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
handleMultiCopyDigitCore: (
|
|
||||||
count: number,
|
|
||||||
options: {
|
|
||||||
subtitleTimingTracker: TSubtitleTimingTracker;
|
|
||||||
writeClipboardText: (text: string) => void;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
},
|
|
||||||
) => deps.handleMultiCopyDigitCore(count, options),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildCopyCurrentSubtitleMainDepsHandler<TSubtitleTimingTracker>(deps: {
|
|
||||||
getSubtitleTimingTracker: () => TSubtitleTimingTracker;
|
|
||||||
writeClipboardText: (text: string) => void;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
copyCurrentSubtitleCore: (options: {
|
|
||||||
subtitleTimingTracker: TSubtitleTimingTracker;
|
|
||||||
writeClipboardText: (text: string) => void;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getSubtitleTimingTracker: () => deps.getSubtitleTimingTracker(),
|
|
||||||
writeClipboardText: (text: string) => deps.writeClipboardText(text),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
copyCurrentSubtitleCore: (options: {
|
|
||||||
subtitleTimingTracker: TSubtitleTimingTracker;
|
|
||||||
writeClipboardText: (text: string) => void;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) => deps.copyCurrentSubtitleCore(options),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildHandleMineSentenceDigitMainDepsHandler<
|
|
||||||
TSubtitleTimingTracker,
|
|
||||||
TAnkiIntegration,
|
|
||||||
>(deps: {
|
|
||||||
getSubtitleTimingTracker: () => TSubtitleTimingTracker;
|
|
||||||
getAnkiIntegration: () => TAnkiIntegration;
|
|
||||||
getCurrentSecondarySubText: () => string | undefined;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
logError: (message: string, err: unknown) => void;
|
|
||||||
handleMineSentenceDigitCore: (
|
|
||||||
count: number,
|
|
||||||
options: {
|
|
||||||
subtitleTimingTracker: TSubtitleTimingTracker;
|
|
||||||
ankiIntegration: TAnkiIntegration;
|
|
||||||
getCurrentSecondarySubText: () => string | undefined;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
logError: (message: string, err: unknown) => void;
|
|
||||||
},
|
|
||||||
) => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getSubtitleTimingTracker: () => deps.getSubtitleTimingTracker(),
|
|
||||||
getAnkiIntegration: () => deps.getAnkiIntegration(),
|
|
||||||
getCurrentSecondarySubText: () => deps.getCurrentSecondarySubText(),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
logError: (message: string, err: unknown) => deps.logError(message, err),
|
|
||||||
handleMineSentenceDigitCore: (
|
|
||||||
count: number,
|
|
||||||
options: {
|
|
||||||
subtitleTimingTracker: TSubtitleTimingTracker;
|
|
||||||
ankiIntegration: TAnkiIntegration;
|
|
||||||
getCurrentSecondarySubText: () => string | undefined;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
logError: (message: string, err: unknown) => void;
|
|
||||||
},
|
|
||||||
) => deps.handleMineSentenceDigitCore(count, options),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
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,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
import type { createAppendToMpvLogHandler, createShowMpvOsdHandler } from './mpv-osd-log';
|
|
||||||
|
|
||||||
type AppendToMpvLogMainDeps = Parameters<typeof createAppendToMpvLogHandler>[0];
|
|
||||||
type ShowMpvOsdMainDeps = Parameters<typeof createShowMpvOsdHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildAppendToMpvLogMainDepsHandler(deps: AppendToMpvLogMainDeps) {
|
|
||||||
return (): AppendToMpvLogMainDeps => ({
|
|
||||||
getLogPath: () => deps.getLogPath(),
|
|
||||||
dirname: (targetPath: string) => deps.dirname(targetPath),
|
|
||||||
mkdir: (targetPath: string, options: { recursive: boolean }) => deps.mkdir(targetPath, options),
|
|
||||||
appendFile: (targetPath: string, data: string, options: { encoding: 'utf8' }) =>
|
|
||||||
deps.appendFile(targetPath, data, options),
|
|
||||||
now: () => deps.now(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildShowMpvOsdMainDepsHandler(deps: ShowMpvOsdMainDeps) {
|
|
||||||
return (): ShowMpvOsdMainDeps => ({
|
|
||||||
appendToMpvLog: (message: string) => deps.appendToMpvLog(message),
|
|
||||||
showMpvOsdRuntime: (mpvClient, text, fallbackLog) =>
|
|
||||||
deps.showMpvOsdRuntime(mpvClient, text, fallbackLog),
|
|
||||||
getMpvClient: () => deps.getMpvClient(),
|
|
||||||
logInfo: (line: string) => deps.logInfo(line),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,27 +1,17 @@
|
|||||||
import { createAppendToMpvLogHandler, createShowMpvOsdHandler } from './mpv-osd-log';
|
import { createAppendToMpvLogHandler, createShowMpvOsdHandler } from './mpv-osd-log';
|
||||||
import {
|
|
||||||
createBuildAppendToMpvLogMainDepsHandler,
|
|
||||||
createBuildShowMpvOsdMainDepsHandler,
|
|
||||||
} from './mpv-osd-log-main-deps';
|
|
||||||
|
|
||||||
type AppendToMpvLogMainDeps = Parameters<typeof createBuildAppendToMpvLogMainDepsHandler>[0];
|
type AppendToMpvLogMainDeps = Parameters<typeof createAppendToMpvLogHandler>[0];
|
||||||
type ShowMpvOsdMainDeps = Parameters<typeof createBuildShowMpvOsdMainDepsHandler>[0];
|
type ShowMpvOsdMainDeps = Parameters<typeof createShowMpvOsdHandler>[0];
|
||||||
|
|
||||||
export function createMpvOsdRuntimeHandlers(deps: {
|
export function createMpvOsdRuntimeHandlers(deps: {
|
||||||
appendToMpvLogMainDeps: AppendToMpvLogMainDeps;
|
appendToMpvLogMainDeps: AppendToMpvLogMainDeps;
|
||||||
buildShowMpvOsdMainDeps: (appendToMpvLog: (message: string) => void) => ShowMpvOsdMainDeps;
|
buildShowMpvOsdMainDeps: (appendToMpvLog: (message: string) => void) => ShowMpvOsdMainDeps;
|
||||||
}) {
|
}) {
|
||||||
const appendToMpvLogMainDeps = createBuildAppendToMpvLogMainDepsHandler(
|
const appendToMpvLogRuntime = createAppendToMpvLogHandler(deps.appendToMpvLogMainDeps);
|
||||||
deps.appendToMpvLogMainDeps,
|
|
||||||
)();
|
|
||||||
const appendToMpvLogRuntime = createAppendToMpvLogHandler(appendToMpvLogMainDeps);
|
|
||||||
const appendToMpvLog = (message: string) => appendToMpvLogRuntime.appendToMpvLog(message);
|
const appendToMpvLog = (message: string) => appendToMpvLogRuntime.appendToMpvLog(message);
|
||||||
const flushMpvLog = async () => appendToMpvLogRuntime.flushMpvLog();
|
const flushMpvLog = async () => appendToMpvLogRuntime.flushMpvLog();
|
||||||
|
|
||||||
const showMpvOsdMainDeps = createBuildShowMpvOsdMainDepsHandler(
|
const showMpvOsdHandler = createShowMpvOsdHandler(deps.buildShowMpvOsdMainDeps(appendToMpvLog));
|
||||||
deps.buildShowMpvOsdMainDeps(appendToMpvLog),
|
|
||||||
)();
|
|
||||||
const showMpvOsdHandler = createShowMpvOsdHandler(showMpvOsdMainDeps);
|
|
||||||
const showMpvOsd = (text: string) => showMpvOsdHandler(text);
|
const showMpvOsd = (text: string) => showMpvOsdHandler(text);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
import type { createUpdateMpvSubtitleRenderMetricsHandler } from './mpv-subtitle-render-metrics';
|
|
||||||
|
|
||||||
type UpdateMpvSubtitleRenderMetricsMainDeps = Parameters<
|
|
||||||
typeof createUpdateMpvSubtitleRenderMetricsHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildUpdateMpvSubtitleRenderMetricsMainDepsHandler(
|
|
||||||
deps: UpdateMpvSubtitleRenderMetricsMainDeps,
|
|
||||||
) {
|
|
||||||
return (): UpdateMpvSubtitleRenderMetricsMainDeps => ({
|
|
||||||
getCurrentMetrics: () => deps.getCurrentMetrics(),
|
|
||||||
setCurrentMetrics: (metrics) => deps.setCurrentMetrics(metrics),
|
|
||||||
applyPatch: (current, patch) => deps.applyPatch(current, patch),
|
|
||||||
broadcastMetrics: (metrics) => deps.broadcastMetrics(metrics),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
import type { NumericShortcutRuntimeOptions } from '../../core/services/numeric-shortcut';
|
|
||||||
|
|
||||||
export function createBuildNumericShortcutRuntimeMainDepsHandler(
|
|
||||||
deps: NumericShortcutRuntimeOptions,
|
|
||||||
) {
|
|
||||||
return (): NumericShortcutRuntimeOptions => ({
|
|
||||||
globalShortcut: deps.globalShortcut,
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
setTimer: (handler: () => void, timeoutMs: number) => deps.setTimer(handler, timeoutMs),
|
|
||||||
clearTimer: (timer: ReturnType<typeof setTimeout>) => deps.clearTimer(timer),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
import type {
|
|
||||||
createCancelNumericShortcutSessionHandler,
|
|
||||||
createStartNumericShortcutSessionHandler,
|
|
||||||
} from './numeric-shortcut-session-handlers';
|
|
||||||
|
|
||||||
type CancelNumericShortcutSessionMainDeps = Parameters<
|
|
||||||
typeof createCancelNumericShortcutSessionHandler
|
|
||||||
>[0];
|
|
||||||
type StartNumericShortcutSessionMainDeps = Parameters<
|
|
||||||
typeof createStartNumericShortcutSessionHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildCancelNumericShortcutSessionMainDepsHandler(
|
|
||||||
deps: CancelNumericShortcutSessionMainDeps,
|
|
||||||
) {
|
|
||||||
return (): CancelNumericShortcutSessionMainDeps => ({
|
|
||||||
session: deps.session,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildStartNumericShortcutSessionMainDepsHandler(
|
|
||||||
deps: StartNumericShortcutSessionMainDeps,
|
|
||||||
) {
|
|
||||||
return (): StartNumericShortcutSessionMainDeps => ({
|
|
||||||
session: deps.session,
|
|
||||||
onDigit: (digit: number) => deps.onDigit(digit),
|
|
||||||
messages: deps.messages,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -2,13 +2,9 @@ import {
|
|||||||
createCancelNumericShortcutSessionHandler,
|
createCancelNumericShortcutSessionHandler,
|
||||||
createStartNumericShortcutSessionHandler,
|
createStartNumericShortcutSessionHandler,
|
||||||
} from './numeric-shortcut-session-handlers';
|
} from './numeric-shortcut-session-handlers';
|
||||||
import {
|
|
||||||
createBuildCancelNumericShortcutSessionMainDepsHandler,
|
|
||||||
createBuildStartNumericShortcutSessionMainDepsHandler,
|
|
||||||
} from './numeric-shortcut-session-main-deps';
|
|
||||||
|
|
||||||
type CancelNumericShortcutSessionMainDeps = Parameters<
|
type CancelNumericShortcutSessionMainDeps = Parameters<
|
||||||
typeof createBuildCancelNumericShortcutSessionMainDepsHandler
|
typeof createCancelNumericShortcutSessionHandler
|
||||||
>[0];
|
>[0];
|
||||||
|
|
||||||
export function createNumericShortcutSessionRuntimeHandlers(deps: {
|
export function createNumericShortcutSessionRuntimeHandlers(deps: {
|
||||||
@@ -19,14 +15,11 @@ export function createNumericShortcutSessionRuntimeHandlers(deps: {
|
|||||||
tryBeginMultiCopyOverlaySelection?: (timeoutMs: number) => boolean;
|
tryBeginMultiCopyOverlaySelection?: (timeoutMs: number) => boolean;
|
||||||
tryBeginMineSentenceOverlaySelection?: (timeoutMs: number) => boolean;
|
tryBeginMineSentenceOverlaySelection?: (timeoutMs: number) => boolean;
|
||||||
}) {
|
}) {
|
||||||
const cancelPendingMultiCopyMainDeps = createBuildCancelNumericShortcutSessionMainDepsHandler({
|
const cancelPendingMultiCopyHandler = createCancelNumericShortcutSessionHandler({
|
||||||
session: deps.multiCopySession,
|
session: deps.multiCopySession,
|
||||||
})();
|
});
|
||||||
const cancelPendingMultiCopyHandler = createCancelNumericShortcutSessionHandler(
|
|
||||||
cancelPendingMultiCopyMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const startPendingMultiCopyMainDeps = createBuildStartNumericShortcutSessionMainDepsHandler({
|
const startPendingMultiCopyHandler = createStartNumericShortcutSessionHandler({
|
||||||
session: deps.multiCopySession,
|
session: deps.multiCopySession,
|
||||||
onDigit: deps.onMultiCopyDigit,
|
onDigit: deps.onMultiCopyDigit,
|
||||||
messages: {
|
messages: {
|
||||||
@@ -34,32 +27,21 @@ export function createNumericShortcutSessionRuntimeHandlers(deps: {
|
|||||||
timeout: 'Copy timeout',
|
timeout: 'Copy timeout',
|
||||||
cancelled: 'Cancelled',
|
cancelled: 'Cancelled',
|
||||||
},
|
},
|
||||||
})();
|
});
|
||||||
const startPendingMultiCopyHandler = createStartNumericShortcutSessionHandler(
|
|
||||||
startPendingMultiCopyMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const cancelPendingMineSentenceMultipleMainDeps =
|
const cancelPendingMineSentenceMultipleHandler = createCancelNumericShortcutSessionHandler({
|
||||||
createBuildCancelNumericShortcutSessionMainDepsHandler({
|
session: deps.mineSentenceSession,
|
||||||
session: deps.mineSentenceSession,
|
});
|
||||||
})();
|
|
||||||
const cancelPendingMineSentenceMultipleHandler = createCancelNumericShortcutSessionHandler(
|
|
||||||
cancelPendingMineSentenceMultipleMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
const startPendingMineSentenceMultipleMainDeps =
|
const startPendingMineSentenceMultipleHandler = createStartNumericShortcutSessionHandler({
|
||||||
createBuildStartNumericShortcutSessionMainDepsHandler({
|
session: deps.mineSentenceSession,
|
||||||
session: deps.mineSentenceSession,
|
onDigit: deps.onMineSentenceDigit,
|
||||||
onDigit: deps.onMineSentenceDigit,
|
messages: {
|
||||||
messages: {
|
prompt: 'Mine how many lines? Press 1-9 (Esc to cancel)',
|
||||||
prompt: 'Mine how many lines? Press 1-9 (Esc to cancel)',
|
timeout: 'Mine sentence timeout',
|
||||||
timeout: 'Mine sentence timeout',
|
cancelled: 'Cancelled',
|
||||||
cancelled: 'Cancelled',
|
},
|
||||||
},
|
});
|
||||||
})();
|
|
||||||
const startPendingMineSentenceMultipleHandler = createStartNumericShortcutSessionHandler(
|
|
||||||
startPendingMineSentenceMultipleMainDeps,
|
|
||||||
);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
cancelPendingMultiCopy: () => cancelPendingMultiCopyHandler(),
|
cancelPendingMultiCopy: () => cancelPendingMultiCopyHandler(),
|
||||||
|
|||||||
@@ -1,25 +0,0 @@
|
|||||||
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(),
|
|
||||||
getModalWindow: () => deps.getModalWindow(),
|
|
||||||
createModalWindow: () => deps.createModalWindow(),
|
|
||||||
getModalGeometry: () => deps.getModalGeometry(),
|
|
||||||
setModalWindowBounds: (geometry) => deps.setModalWindowBounds(geometry),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
import type {
|
|
||||||
createAppendClipboardVideoToQueueHandler,
|
|
||||||
createHandleOverlayModalClosedHandler,
|
|
||||||
createSetOverlayVisibleHandler,
|
|
||||||
createToggleOverlayHandler,
|
|
||||||
} from './overlay-main-actions';
|
|
||||||
|
|
||||||
type SetOverlayVisibleMainDeps = Parameters<typeof createSetOverlayVisibleHandler>[0];
|
|
||||||
type ToggleOverlayMainDeps = Parameters<typeof createToggleOverlayHandler>[0];
|
|
||||||
type HandleOverlayModalClosedMainDeps = Parameters<typeof createHandleOverlayModalClosedHandler>[0];
|
|
||||||
type AppendClipboardVideoToQueueMainDeps = Parameters<
|
|
||||||
typeof createAppendClipboardVideoToQueueHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildSetOverlayVisibleMainDepsHandler(deps: SetOverlayVisibleMainDeps) {
|
|
||||||
return (): SetOverlayVisibleMainDeps => ({
|
|
||||||
setVisibleOverlayVisible: (visible: boolean) => deps.setVisibleOverlayVisible(visible),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildToggleOverlayMainDepsHandler(deps: ToggleOverlayMainDeps) {
|
|
||||||
return (): ToggleOverlayMainDeps => ({
|
|
||||||
toggleVisibleOverlay: () => deps.toggleVisibleOverlay(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildHandleOverlayModalClosedMainDepsHandler(
|
|
||||||
deps: HandleOverlayModalClosedMainDeps,
|
|
||||||
) {
|
|
||||||
return (): HandleOverlayModalClosedMainDeps => ({
|
|
||||||
handleOverlayModalClosedRuntime: (modal) => deps.handleOverlayModalClosedRuntime(modal),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildAppendClipboardVideoToQueueMainDepsHandler(
|
|
||||||
deps: AppendClipboardVideoToQueueMainDeps,
|
|
||||||
) {
|
|
||||||
return (): AppendClipboardVideoToQueueMainDeps => ({
|
|
||||||
appendClipboardVideoToQueueRuntime: (options) =>
|
|
||||||
deps.appendClipboardVideoToQueueRuntime(options),
|
|
||||||
getMpvClient: () => deps.getMpvClient(),
|
|
||||||
readClipboardText: () => deps.readClipboardText(),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
sendMpvCommand: (command: (string | number)[]) => deps.sendMpvCommand(command),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
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) =>
|
|
||||||
deps.setOverlayDebugVisualizationEnabledRuntime(
|
|
||||||
currentEnabled,
|
|
||||||
nextEnabled,
|
|
||||||
setCurrentEnabled,
|
|
||||||
),
|
|
||||||
getCurrentEnabled: () => deps.getCurrentEnabled(),
|
|
||||||
setCurrentEnabled: (enabled: boolean) => deps.setCurrentEnabled(enabled),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildOpenRuntimeOptionsPaletteMainDepsHandler(
|
|
||||||
deps: OpenRuntimeOptionsPaletteMainDeps,
|
|
||||||
) {
|
|
||||||
return (): OpenRuntimeOptionsPaletteMainDeps => ({
|
|
||||||
openRuntimeOptionsPaletteRuntime: () => deps.openRuntimeOptionsPaletteRuntime(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
import type {
|
|
||||||
createRefreshOverlayShortcutsHandler,
|
|
||||||
createRegisterOverlayShortcutsHandler,
|
|
||||||
createSyncOverlayShortcutsHandler,
|
|
||||||
createUnregisterOverlayShortcutsHandler,
|
|
||||||
} from './overlay-shortcuts-lifecycle';
|
|
||||||
|
|
||||||
type RegisterOverlayShortcutsMainDeps = Parameters<typeof createRegisterOverlayShortcutsHandler>[0];
|
|
||||||
type UnregisterOverlayShortcutsMainDeps = Parameters<
|
|
||||||
typeof createUnregisterOverlayShortcutsHandler
|
|
||||||
>[0];
|
|
||||||
type SyncOverlayShortcutsMainDeps = Parameters<typeof createSyncOverlayShortcutsHandler>[0];
|
|
||||||
type RefreshOverlayShortcutsMainDeps = Parameters<typeof createRefreshOverlayShortcutsHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildRegisterOverlayShortcutsMainDepsHandler(
|
|
||||||
deps: RegisterOverlayShortcutsMainDeps,
|
|
||||||
) {
|
|
||||||
return (): RegisterOverlayShortcutsMainDeps => ({
|
|
||||||
overlayShortcutsRuntime: deps.overlayShortcutsRuntime,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildUnregisterOverlayShortcutsMainDepsHandler(
|
|
||||||
deps: UnregisterOverlayShortcutsMainDeps,
|
|
||||||
) {
|
|
||||||
return (): UnregisterOverlayShortcutsMainDeps => ({
|
|
||||||
overlayShortcutsRuntime: deps.overlayShortcutsRuntime,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildSyncOverlayShortcutsMainDepsHandler(deps: SyncOverlayShortcutsMainDeps) {
|
|
||||||
return (): SyncOverlayShortcutsMainDeps => ({
|
|
||||||
overlayShortcutsRuntime: deps.overlayShortcutsRuntime,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildRefreshOverlayShortcutsMainDepsHandler(
|
|
||||||
deps: RefreshOverlayShortcutsMainDeps,
|
|
||||||
) {
|
|
||||||
return (): RefreshOverlayShortcutsMainDeps => ({
|
|
||||||
overlayShortcutsRuntime: deps.overlayShortcutsRuntime,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -4,46 +4,26 @@ import {
|
|||||||
createSyncOverlayShortcutsHandler,
|
createSyncOverlayShortcutsHandler,
|
||||||
createUnregisterOverlayShortcutsHandler,
|
createUnregisterOverlayShortcutsHandler,
|
||||||
} from './overlay-shortcuts-lifecycle';
|
} from './overlay-shortcuts-lifecycle';
|
||||||
import {
|
|
||||||
createBuildRefreshOverlayShortcutsMainDepsHandler,
|
|
||||||
createBuildRegisterOverlayShortcutsMainDepsHandler,
|
|
||||||
createBuildSyncOverlayShortcutsMainDepsHandler,
|
|
||||||
createBuildUnregisterOverlayShortcutsMainDepsHandler,
|
|
||||||
} from './overlay-shortcuts-lifecycle-main-deps';
|
|
||||||
|
|
||||||
type RegisterOverlayShortcutsMainDeps = Parameters<
|
type RegisterOverlayShortcutsMainDeps = Parameters<typeof createRegisterOverlayShortcutsHandler>[0];
|
||||||
typeof createBuildRegisterOverlayShortcutsMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createOverlayShortcutsRuntimeHandlers(deps: {
|
export function createOverlayShortcutsRuntimeHandlers(deps: {
|
||||||
overlayShortcutsRuntimeMainDeps: RegisterOverlayShortcutsMainDeps;
|
overlayShortcutsRuntimeMainDeps: RegisterOverlayShortcutsMainDeps;
|
||||||
}) {
|
}) {
|
||||||
const registerOverlayShortcutsMainDeps = createBuildRegisterOverlayShortcutsMainDepsHandler(
|
|
||||||
deps.overlayShortcutsRuntimeMainDeps,
|
|
||||||
)();
|
|
||||||
const registerOverlayShortcutsHandler = createRegisterOverlayShortcutsHandler(
|
const registerOverlayShortcutsHandler = createRegisterOverlayShortcutsHandler(
|
||||||
registerOverlayShortcutsMainDeps,
|
deps.overlayShortcutsRuntimeMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const unregisterOverlayShortcutsMainDeps = createBuildUnregisterOverlayShortcutsMainDepsHandler(
|
|
||||||
deps.overlayShortcutsRuntimeMainDeps,
|
|
||||||
)();
|
|
||||||
const unregisterOverlayShortcutsHandler = createUnregisterOverlayShortcutsHandler(
|
const unregisterOverlayShortcutsHandler = createUnregisterOverlayShortcutsHandler(
|
||||||
unregisterOverlayShortcutsMainDeps,
|
deps.overlayShortcutsRuntimeMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const syncOverlayShortcutsMainDeps = createBuildSyncOverlayShortcutsMainDepsHandler(
|
|
||||||
deps.overlayShortcutsRuntimeMainDeps,
|
|
||||||
)();
|
|
||||||
const syncOverlayShortcutsHandler = createSyncOverlayShortcutsHandler(
|
const syncOverlayShortcutsHandler = createSyncOverlayShortcutsHandler(
|
||||||
syncOverlayShortcutsMainDeps,
|
deps.overlayShortcutsRuntimeMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const refreshOverlayShortcutsMainDeps = createBuildRefreshOverlayShortcutsMainDepsHandler(
|
|
||||||
deps.overlayShortcutsRuntimeMainDeps,
|
|
||||||
)();
|
|
||||||
const refreshOverlayShortcutsHandler = createRefreshOverlayShortcutsHandler(
|
const refreshOverlayShortcutsHandler = createRefreshOverlayShortcutsHandler(
|
||||||
refreshOverlayShortcutsMainDeps,
|
deps.overlayShortcutsRuntimeMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -7,10 +7,6 @@ import {
|
|||||||
createBuildToggleVisibleOverlayMainDepsHandler,
|
createBuildToggleVisibleOverlayMainDepsHandler,
|
||||||
} from './overlay-visibility-actions-main-deps';
|
} from './overlay-visibility-actions-main-deps';
|
||||||
import { createSetOverlayVisibleHandler, createToggleOverlayHandler } from './overlay-main-actions';
|
import { createSetOverlayVisibleHandler, createToggleOverlayHandler } from './overlay-main-actions';
|
||||||
import {
|
|
||||||
createBuildSetOverlayVisibleMainDepsHandler,
|
|
||||||
createBuildToggleOverlayMainDepsHandler,
|
|
||||||
} from './overlay-main-actions-main-deps';
|
|
||||||
|
|
||||||
type SetVisibleOverlayVisibleMainDeps = Parameters<
|
type SetVisibleOverlayVisibleMainDeps = Parameters<
|
||||||
typeof createBuildSetVisibleOverlayVisibleMainDepsHandler
|
typeof createBuildSetVisibleOverlayVisibleMainDepsHandler
|
||||||
@@ -36,15 +32,13 @@ export function createOverlayVisibilityRuntime(deps: OverlayVisibilityRuntimeDep
|
|||||||
})();
|
})();
|
||||||
const toggleVisibleOverlay = createToggleVisibleOverlayHandler(toggleVisibleOverlayMainDeps);
|
const toggleVisibleOverlay = createToggleVisibleOverlayHandler(toggleVisibleOverlayMainDeps);
|
||||||
|
|
||||||
const setOverlayVisibleMainDeps = createBuildSetOverlayVisibleMainDepsHandler({
|
const setOverlayVisible = createSetOverlayVisibleHandler({
|
||||||
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
||||||
})();
|
});
|
||||||
const setOverlayVisible = createSetOverlayVisibleHandler(setOverlayVisibleMainDeps);
|
|
||||||
|
|
||||||
const toggleOverlayMainDeps = createBuildToggleOverlayMainDepsHandler({
|
const toggleOverlay = createToggleOverlayHandler({
|
||||||
toggleVisibleOverlay: () => toggleVisibleOverlay(),
|
toggleVisibleOverlay: () => toggleVisibleOverlay(),
|
||||||
})();
|
});
|
||||||
const toggleOverlay = createToggleOverlayHandler(toggleOverlayMainDeps);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
setVisibleOverlayVisible,
|
setVisibleOverlayVisible,
|
||||||
|
|||||||
@@ -1,53 +0,0 @@
|
|||||||
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(),
|
|
||||||
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),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import type { SecondarySubMode } from '../../types';
|
|
||||||
|
|
||||||
export function createBuildCycleSecondarySubModeMainDepsHandler(deps: {
|
|
||||||
getSecondarySubMode: () => SecondarySubMode;
|
|
||||||
setSecondarySubMode: (mode: SecondarySubMode) => void;
|
|
||||||
getLastSecondarySubToggleAtMs: () => number;
|
|
||||||
setLastSecondarySubToggleAtMs: (timestampMs: number) => void;
|
|
||||||
broadcastToOverlayWindows: (channel: string, mode: SecondarySubMode) => void;
|
|
||||||
showMpvOsd: (text: string) => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
getSecondarySubMode: () => deps.getSecondarySubMode(),
|
|
||||||
setSecondarySubMode: (mode: SecondarySubMode) => deps.setSecondarySubMode(mode),
|
|
||||||
getLastSecondarySubToggleAtMs: () => deps.getLastSecondarySubToggleAtMs(),
|
|
||||||
setLastSecondarySubToggleAtMs: (timestampMs: number) =>
|
|
||||||
deps.setLastSecondarySubToggleAtMs(timestampMs),
|
|
||||||
broadcastSecondarySubMode: (mode: SecondarySubMode) =>
|
|
||||||
deps.broadcastToOverlayWindows('secondary-subtitle:mode', mode),
|
|
||||||
showMpvOsd: (text: string) => deps.showMpvOsd(text),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,18 +1,8 @@
|
|||||||
import { createBuildCycleSecondarySubModeMainDepsHandler } from './secondary-sub-mode-main-deps';
|
import type { CycleSecondarySubModeDeps } from '../../core/services/subtitle-position';
|
||||||
|
|
||||||
type CycleSecondarySubModeMainDeps = Parameters<
|
|
||||||
typeof createBuildCycleSecondarySubModeMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type CycleSecondarySubModeDeps = ReturnType<
|
|
||||||
ReturnType<typeof createBuildCycleSecondarySubModeMainDepsHandler>
|
|
||||||
>;
|
|
||||||
|
|
||||||
export function createCycleSecondarySubModeRuntimeHandler(deps: {
|
export function createCycleSecondarySubModeRuntimeHandler(deps: {
|
||||||
cycleSecondarySubModeMainDeps: CycleSecondarySubModeMainDeps;
|
cycleSecondarySubModeMainDeps: CycleSecondarySubModeDeps;
|
||||||
cycleSecondarySubMode: (deps: CycleSecondarySubModeDeps) => void;
|
cycleSecondarySubMode: (deps: CycleSecondarySubModeDeps) => void;
|
||||||
}) {
|
}) {
|
||||||
const buildCycleSecondarySubModeMainDepsHandler = createBuildCycleSecondarySubModeMainDepsHandler(
|
return () => deps.cycleSecondarySubMode(deps.cycleSecondarySubModeMainDeps);
|
||||||
deps.cycleSecondarySubModeMainDeps,
|
|
||||||
);
|
|
||||||
return () => deps.cycleSecondarySubMode(buildCycleSecondarySubModeMainDepsHandler());
|
|
||||||
}
|
}
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
import type { createCriticalConfigErrorHandler, createReloadConfigHandler } from './startup-config';
|
|
||||||
|
|
||||||
type ReloadConfigMainDeps = Parameters<typeof createReloadConfigHandler>[0];
|
|
||||||
type CriticalConfigErrorMainDeps = Parameters<typeof createCriticalConfigErrorHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildReloadConfigMainDepsHandler(deps: ReloadConfigMainDeps) {
|
|
||||||
return (): ReloadConfigMainDeps => ({
|
|
||||||
reloadConfigStrict: () => deps.reloadConfigStrict(),
|
|
||||||
logInfo: (message: string) => deps.logInfo(message),
|
|
||||||
logDebug: (message: string) => deps.logDebug(message),
|
|
||||||
logWarning: (message: string) => deps.logWarning(message),
|
|
||||||
showDesktopNotification: (title: string, options: { body: string }) =>
|
|
||||||
deps.showDesktopNotification(title, options),
|
|
||||||
startConfigHotReload: () => deps.startConfigHotReload(),
|
|
||||||
shouldRefreshAnilistClientSecretState: deps.shouldRefreshAnilistClientSecretState
|
|
||||||
? () => deps.shouldRefreshAnilistClientSecretState?.() !== false
|
|
||||||
: undefined,
|
|
||||||
refreshAnilistClientSecretState: (options: { force: boolean }) =>
|
|
||||||
deps.refreshAnilistClientSecretState(options),
|
|
||||||
failHandlers: {
|
|
||||||
logError: (details: string) => deps.failHandlers.logError(details),
|
|
||||||
showErrorBox: (title: string, details: string) =>
|
|
||||||
deps.failHandlers.showErrorBox(title, details),
|
|
||||||
setExitCode: deps.failHandlers.setExitCode
|
|
||||||
? (code: number) => deps.failHandlers.setExitCode?.(code)
|
|
||||||
: undefined,
|
|
||||||
quit: () => deps.failHandlers.quit(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildCriticalConfigErrorMainDepsHandler(deps: CriticalConfigErrorMainDeps) {
|
|
||||||
return (): CriticalConfigErrorMainDeps => ({
|
|
||||||
getConfigPath: () => deps.getConfigPath(),
|
|
||||||
failHandlers: {
|
|
||||||
logError: (details: string) => deps.failHandlers.logError(details),
|
|
||||||
showErrorBox: (title: string, details: string) =>
|
|
||||||
deps.failHandlers.showErrorBox(title, details),
|
|
||||||
setExitCode: deps.failHandlers.setExitCode
|
|
||||||
? (code: number) => deps.failHandlers.setExitCode?.(code)
|
|
||||||
: undefined,
|
|
||||||
quit: () => deps.failHandlers.quit(),
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import type { AppLifecycleRuntimeRunnerParams } from '../startup-lifecycle';
|
|
||||||
|
|
||||||
export function createBuildAppLifecycleRuntimeRunnerMainDepsHandler(
|
|
||||||
deps: AppLifecycleRuntimeRunnerParams,
|
|
||||||
) {
|
|
||||||
return (): AppLifecycleRuntimeRunnerParams => ({
|
|
||||||
app: deps.app,
|
|
||||||
platform: deps.platform,
|
|
||||||
shouldStartApp: deps.shouldStartApp,
|
|
||||||
parseArgs: deps.parseArgs,
|
|
||||||
handleCliCommand: deps.handleCliCommand,
|
|
||||||
printHelp: deps.printHelp,
|
|
||||||
logNoRunningInstance: deps.logNoRunningInstance,
|
|
||||||
startControlServer: deps.startControlServer,
|
|
||||||
onReady: deps.onReady,
|
|
||||||
onWillQuitCleanup: deps.onWillQuitCleanup,
|
|
||||||
shouldRestoreWindowsOnActivate: deps.shouldRestoreWindowsOnActivate,
|
|
||||||
restoreWindowsOnActivate: deps.restoreWindowsOnActivate,
|
|
||||||
shouldQuitOnWindowAllClosed: deps.shouldQuitOnWindowAllClosed,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
import { createBuildStartupBootstrapRuntimeFactoryDepsHandler } from './startup-bootstrap-deps-builder';
|
import { createBuildStartupBootstrapRuntimeFactoryDepsHandler } from './startup-bootstrap-deps-builder';
|
||||||
import { createBuildAppLifecycleRuntimeRunnerMainDepsHandler } from './startup-lifecycle-main-deps';
|
import type { AppLifecycleRuntimeRunnerParams } from '../startup-lifecycle';
|
||||||
import { createBuildStartupBootstrapMainDepsHandler } from './startup-bootstrap-main-deps';
|
import { createBuildStartupBootstrapMainDepsHandler } from './startup-bootstrap-main-deps';
|
||||||
|
|
||||||
type AppLifecycleRuntimeRunnerMainDeps = Parameters<
|
|
||||||
typeof createBuildAppLifecycleRuntimeRunnerMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type StartupBootstrapMainDeps = Parameters<typeof createBuildStartupBootstrapMainDepsHandler>[0];
|
type StartupBootstrapMainDeps = Parameters<typeof createBuildStartupBootstrapMainDepsHandler>[0];
|
||||||
type StartupBootstrapRuntimeFactoryDeps = Parameters<
|
type StartupBootstrapRuntimeFactoryDeps = Parameters<
|
||||||
typeof createBuildStartupBootstrapRuntimeFactoryDepsHandler
|
typeof createBuildStartupBootstrapRuntimeFactoryDepsHandler
|
||||||
@@ -15,9 +12,9 @@ export function createStartupRuntimeHandlers<
|
|||||||
TStartupState,
|
TStartupState,
|
||||||
TStartupBootstrapRuntimeDeps = unknown,
|
TStartupBootstrapRuntimeDeps = unknown,
|
||||||
>(deps: {
|
>(deps: {
|
||||||
appLifecycleRuntimeRunnerMainDeps: AppLifecycleRuntimeRunnerMainDeps;
|
appLifecycleRuntimeRunnerMainDeps: AppLifecycleRuntimeRunnerParams;
|
||||||
createAppLifecycleRuntimeRunner: (
|
createAppLifecycleRuntimeRunner: (
|
||||||
params: AppLifecycleRuntimeRunnerMainDeps,
|
params: AppLifecycleRuntimeRunnerParams,
|
||||||
) => (args: TCliArgs) => void;
|
) => (args: TCliArgs) => void;
|
||||||
buildStartupBootstrapMainDeps: (
|
buildStartupBootstrapMainDeps: (
|
||||||
startAppLifecycle: (args: TCliArgs) => void,
|
startAppLifecycle: (args: TCliArgs) => void,
|
||||||
@@ -28,11 +25,8 @@ export function createStartupRuntimeHandlers<
|
|||||||
runStartupBootstrapRuntime: (deps: TStartupBootstrapRuntimeDeps) => TStartupState;
|
runStartupBootstrapRuntime: (deps: TStartupBootstrapRuntimeDeps) => TStartupState;
|
||||||
applyStartupState: (startupState: TStartupState) => void;
|
applyStartupState: (startupState: TStartupState) => void;
|
||||||
}) {
|
}) {
|
||||||
const appLifecycleRuntimeRunnerMainDeps = createBuildAppLifecycleRuntimeRunnerMainDepsHandler(
|
|
||||||
deps.appLifecycleRuntimeRunnerMainDeps,
|
|
||||||
)();
|
|
||||||
const appLifecycleRuntimeRunner = deps.createAppLifecycleRuntimeRunner(
|
const appLifecycleRuntimeRunner = deps.createAppLifecycleRuntimeRunner(
|
||||||
appLifecycleRuntimeRunnerMainDeps,
|
deps.appLifecycleRuntimeRunnerMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const startupBootstrapMainDeps = createBuildStartupBootstrapMainDepsHandler(
|
const startupBootstrapMainDeps = createBuildStartupBootstrapMainDepsHandler(
|
||||||
|
|||||||
@@ -1,52 +0,0 @@
|
|||||||
import type {
|
|
||||||
createLaunchBackgroundWarmupTaskHandler,
|
|
||||||
createStartBackgroundWarmupsHandler,
|
|
||||||
} from './startup-warmups';
|
|
||||||
|
|
||||||
type LaunchBackgroundWarmupTaskMainDeps = Parameters<
|
|
||||||
typeof createLaunchBackgroundWarmupTaskHandler
|
|
||||||
>[0];
|
|
||||||
type StartBackgroundWarmupsMainDeps = Parameters<typeof createStartBackgroundWarmupsHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildLaunchBackgroundWarmupTaskMainDepsHandler(
|
|
||||||
deps: LaunchBackgroundWarmupTaskMainDeps,
|
|
||||||
) {
|
|
||||||
return (): LaunchBackgroundWarmupTaskMainDeps => ({
|
|
||||||
now: () => deps.now(),
|
|
||||||
logDebug: (message: string) => deps.logDebug(message),
|
|
||||||
logWarn: (message: string) => deps.logWarn(message),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildStartBackgroundWarmupsMainDepsHandler(
|
|
||||||
deps: StartBackgroundWarmupsMainDeps,
|
|
||||||
) {
|
|
||||||
return (): StartBackgroundWarmupsMainDeps => ({
|
|
||||||
getStarted: () => deps.getStarted(),
|
|
||||||
setStarted: (started: boolean) => deps.setStarted(started),
|
|
||||||
isTexthookerOnlyMode: () => deps.isTexthookerOnlyMode(),
|
|
||||||
launchTask: (label: string, task: () => Promise<void>) => deps.launchTask(label, task),
|
|
||||||
createMecabTokenizerAndCheck: () => deps.createMecabTokenizerAndCheck(),
|
|
||||||
ensureYomitanExtensionLoaded: () => deps.ensureYomitanExtensionLoaded(),
|
|
||||||
prewarmSubtitleDictionaries: () => deps.prewarmSubtitleDictionaries(),
|
|
||||||
shouldWarmupMecab: () => deps.shouldWarmupMecab(),
|
|
||||||
shouldWarmupYomitanExtension: () => deps.shouldWarmupYomitanExtension(),
|
|
||||||
shouldWarmupSubtitleDictionaries: () => deps.shouldWarmupSubtitleDictionaries(),
|
|
||||||
shouldWarmupJellyfinRemoteSession: () => deps.shouldWarmupJellyfinRemoteSession(),
|
|
||||||
shouldAutoConnectJellyfinRemote: () => deps.shouldAutoConnectJellyfinRemote(),
|
|
||||||
startJellyfinRemoteSession: () => deps.startJellyfinRemoteSession(),
|
|
||||||
...(deps.onYomitanExtensionWarmupScheduled
|
|
||||||
? {
|
|
||||||
onYomitanExtensionWarmupScheduled: (promise: Promise<void>) =>
|
|
||||||
deps.onYomitanExtensionWarmupScheduled!(promise),
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
...(deps.onTokenizationWarmupScheduled
|
|
||||||
? {
|
|
||||||
onTokenizationWarmupScheduled: (promise: Promise<void>) =>
|
|
||||||
deps.onTokenizationWarmupScheduled!(promise),
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
logDebug: deps.logDebug,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
import type {
|
|
||||||
createLoadSubtitlePositionHandler,
|
|
||||||
createSaveSubtitlePositionHandler,
|
|
||||||
} from './subtitle-position';
|
|
||||||
|
|
||||||
type LoadSubtitlePositionMainDeps = Parameters<typeof createLoadSubtitlePositionHandler>[0];
|
|
||||||
type SaveSubtitlePositionMainDeps = Parameters<typeof createSaveSubtitlePositionHandler>[0];
|
|
||||||
|
|
||||||
export function createBuildLoadSubtitlePositionMainDepsHandler(deps: LoadSubtitlePositionMainDeps) {
|
|
||||||
return (): LoadSubtitlePositionMainDeps => ({
|
|
||||||
loadSubtitlePositionCore: () => deps.loadSubtitlePositionCore(),
|
|
||||||
setSubtitlePosition: (position) => deps.setSubtitlePosition(position),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildSaveSubtitlePositionMainDepsHandler(deps: SaveSubtitlePositionMainDeps) {
|
|
||||||
return (): SaveSubtitlePositionMainDeps => ({
|
|
||||||
saveSubtitlePositionCore: (position) => deps.saveSubtitlePositionCore(position),
|
|
||||||
setSubtitlePosition: (position) => deps.setSubtitlePosition(position),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import type { SubtitleProcessingControllerDeps } from '../../core/services/subtitle-processing-controller';
|
|
||||||
|
|
||||||
export function createBuildSubtitleProcessingControllerMainDepsHandler(
|
|
||||||
deps: SubtitleProcessingControllerDeps,
|
|
||||||
) {
|
|
||||||
return (): SubtitleProcessingControllerDeps => ({
|
|
||||||
tokenizeSubtitle: (text: string) => deps.tokenizeSubtitle(text),
|
|
||||||
emitSubtitle: (payload) => deps.emitSubtitle(payload),
|
|
||||||
onProcessingSettled: () => deps.onProcessingSettled?.(),
|
|
||||||
logDebug: deps.logDebug,
|
|
||||||
now: deps.now,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import test from 'node:test';
|
||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import { createPrefetchAwareSubtitleProcessingController } from './subtitle-processing-runtime';
|
||||||
|
import type { SubtitleData } from '../../types';
|
||||||
|
|
||||||
|
function flushMicrotasks(): Promise<void> {
|
||||||
|
return new Promise((resolve) => setTimeout(resolve, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
function createHarness() {
|
||||||
|
const events: string[] = [];
|
||||||
|
let resolveTokenization: ((value: SubtitleData | null) => void) | undefined;
|
||||||
|
const controller = createPrefetchAwareSubtitleProcessingController({
|
||||||
|
tokenizeSubtitle: () =>
|
||||||
|
new Promise<SubtitleData | null>((resolve) => {
|
||||||
|
resolveTokenization = resolve;
|
||||||
|
}),
|
||||||
|
emitSubtitlePayload: (payload, options) =>
|
||||||
|
events.push(
|
||||||
|
`emit:${payload.text}:tokens=${payload.tokens ? 'yes' : 'no'}:resume=${options.resumePrefetch}`,
|
||||||
|
),
|
||||||
|
resumePrefetch: () => events.push('resume'),
|
||||||
|
logDebug: () => {},
|
||||||
|
now: () => 0,
|
||||||
|
});
|
||||||
|
return {
|
||||||
|
events,
|
||||||
|
controller,
|
||||||
|
resolveTokenization: (value: SubtitleData | null) => resolveTokenization?.(value),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
test('subtitle processing resumes prefetch after the tokenized emit settles', async () => {
|
||||||
|
const { events, controller, resolveTokenization } = createHarness();
|
||||||
|
|
||||||
|
controller.onSubtitleChange('一行目');
|
||||||
|
await flushMicrotasks();
|
||||||
|
// The provisional plain payload is out, but tokenization is still pending.
|
||||||
|
assert.deepEqual(events, ['emit:一行目:tokens=no:resume=false']);
|
||||||
|
|
||||||
|
resolveTokenization({ text: '一行目', tokens: [] });
|
||||||
|
await flushMicrotasks();
|
||||||
|
await flushMicrotasks();
|
||||||
|
assert.deepEqual(events, [
|
||||||
|
'emit:一行目:tokens=no:resume=false',
|
||||||
|
'emit:一行目:tokens=yes:resume=false',
|
||||||
|
'resume',
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('subtitle processing resumes prefetch when tokenization fails without another emit', async () => {
|
||||||
|
const { events, controller, resolveTokenization } = createHarness();
|
||||||
|
|
||||||
|
controller.onSubtitleChange('一行目');
|
||||||
|
await flushMicrotasks();
|
||||||
|
assert.deepEqual(events, ['emit:一行目:tokens=no:resume=false']);
|
||||||
|
|
||||||
|
resolveTokenization(null);
|
||||||
|
await flushMicrotasks();
|
||||||
|
await flushMicrotasks();
|
||||||
|
assert.deepEqual(events, ['emit:一行目:tokens=no:resume=false', 'resume']);
|
||||||
|
});
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
import {
|
||||||
|
createSubtitleProcessingController,
|
||||||
|
type SubtitleProcessingControllerDeps,
|
||||||
|
} from '../../core/services/subtitle-processing-controller';
|
||||||
|
import type { SubtitleData } from '../../types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the main-process subtitle processing controller and ties it to the
|
||||||
|
* subtitle prefetch pause.
|
||||||
|
*
|
||||||
|
* Controller emits never release the prefetch pause: the first emit for an
|
||||||
|
* uncached line is the provisional plain payload, sent before tokenization
|
||||||
|
* starts, so resuming on it would put prefetch back in contention with the
|
||||||
|
* on-screen line for the single parser window. The pause is released once the
|
||||||
|
* controller has no work left, which covers the runs that end without an emit
|
||||||
|
* (suppressed duplicate, failed tokenization) as well as the ones that deliver
|
||||||
|
* a payload.
|
||||||
|
*/
|
||||||
|
export function createPrefetchAwareSubtitleProcessingController(deps: {
|
||||||
|
tokenizeSubtitle: SubtitleProcessingControllerDeps['tokenizeSubtitle'];
|
||||||
|
emitSubtitlePayload: (payload: SubtitleData, options: { resumePrefetch: boolean }) => void;
|
||||||
|
resumePrefetch: () => void;
|
||||||
|
logDebug: (message: string) => void;
|
||||||
|
now: () => number;
|
||||||
|
}) {
|
||||||
|
return createSubtitleProcessingController({
|
||||||
|
tokenizeSubtitle: deps.tokenizeSubtitle,
|
||||||
|
emitSubtitle: (payload) => deps.emitSubtitlePayload(payload, { resumePrefetch: false }),
|
||||||
|
onProcessingSettled: () => deps.resumePrefetch(),
|
||||||
|
logDebug: deps.logDebug,
|
||||||
|
now: deps.now,
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
import type { DictionaryBackend } from '../../types/config';
|
|
||||||
|
|
||||||
export function createBuildResolveTrayIconPathMainDepsHandler(deps: {
|
|
||||||
resolveTrayIconPathRuntime: (options: {
|
|
||||||
platform: string;
|
|
||||||
resourcesPath: string;
|
|
||||||
appPath: string;
|
|
||||||
dirname: string;
|
|
||||||
joinPath: (...parts: string[]) => string;
|
|
||||||
fileExists: (path: string) => boolean;
|
|
||||||
}) => string | null;
|
|
||||||
platform: string;
|
|
||||||
resourcesPath: string;
|
|
||||||
appPath: string;
|
|
||||||
dirname: string;
|
|
||||||
joinPath: (...parts: string[]) => string;
|
|
||||||
fileExists: (path: string) => boolean;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
resolveTrayIconPathRuntime: deps.resolveTrayIconPathRuntime,
|
|
||||||
platform: deps.platform,
|
|
||||||
resourcesPath: deps.resourcesPath,
|
|
||||||
appPath: deps.appPath,
|
|
||||||
dirname: deps.dirname,
|
|
||||||
joinPath: deps.joinPath,
|
|
||||||
fileExists: deps.fileExists,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildTrayMenuTemplateMainDepsHandler<TMenuItem>(deps: {
|
|
||||||
buildTrayMenuTemplateRuntime: (handlers: {
|
|
||||||
platform?: string;
|
|
||||||
openSessionHelp: () => void;
|
|
||||||
openChangelog: () => void;
|
|
||||||
openTexthookerInBrowser: () => void;
|
|
||||||
showTexthookerPage: boolean;
|
|
||||||
openFirstRunSetup: () => void;
|
|
||||||
showFirstRunSetup: boolean;
|
|
||||||
openWindowsMpvLauncherSetup: () => void;
|
|
||||||
showWindowsMpvLauncherSetup: boolean;
|
|
||||||
dictionaryBackend: DictionaryBackend;
|
|
||||||
openHachidoriSettings: () => void;
|
|
||||||
openYomitanSettings: () => void;
|
|
||||||
openConfigSettings: () => void;
|
|
||||||
openSyncUi: () => void;
|
|
||||||
openYoutubeBrowser: () => void;
|
|
||||||
exportLogs: () => void;
|
|
||||||
openJellyfinSetup: () => void;
|
|
||||||
showJellyfinDiscovery: boolean;
|
|
||||||
jellyfinDiscoveryActive: boolean;
|
|
||||||
toggleJellyfinDiscovery: (checked: boolean) => void;
|
|
||||||
openAnilistSetup: () => void;
|
|
||||||
checkForUpdates: () => void;
|
|
||||||
quitApp: () => void;
|
|
||||||
}) => TMenuItem[];
|
|
||||||
initializeOverlayRuntime: () => void;
|
|
||||||
isOverlayRuntimeInitialized: () => boolean;
|
|
||||||
openSessionHelpModal: () => void;
|
|
||||||
openChangelogModal: () => void;
|
|
||||||
openTexthookerInBrowser: () => void;
|
|
||||||
showTexthookerPage: () => boolean;
|
|
||||||
showFirstRunSetup: () => boolean;
|
|
||||||
openFirstRunSetupWindow: (force?: boolean) => void;
|
|
||||||
showWindowsMpvLauncherSetup: () => boolean;
|
|
||||||
getDictionaryBackend: () => DictionaryBackend;
|
|
||||||
openHachidoriSettings: () => void;
|
|
||||||
openYomitanSettings: () => void;
|
|
||||||
openConfigSettingsWindow: () => void;
|
|
||||||
openSyncUiWindow: () => void;
|
|
||||||
openYoutubeBrowserWindow: () => void;
|
|
||||||
exportLogs: () => void;
|
|
||||||
openJellyfinSetupWindow: () => void;
|
|
||||||
isJellyfinConfigured: () => boolean;
|
|
||||||
isJellyfinDiscoveryActive: () => boolean;
|
|
||||||
toggleJellyfinDiscovery: (checked: boolean) => void | Promise<void>;
|
|
||||||
platform?: string;
|
|
||||||
openAnilistSetupWindow: () => void;
|
|
||||||
checkForUpdates: () => void;
|
|
||||||
quitApp: () => void;
|
|
||||||
}) {
|
|
||||||
return () => ({
|
|
||||||
buildTrayMenuTemplateRuntime: deps.buildTrayMenuTemplateRuntime,
|
|
||||||
platform: deps.platform,
|
|
||||||
initializeOverlayRuntime: deps.initializeOverlayRuntime,
|
|
||||||
isOverlayRuntimeInitialized: deps.isOverlayRuntimeInitialized,
|
|
||||||
openSessionHelpModal: deps.openSessionHelpModal,
|
|
||||||
openChangelogModal: deps.openChangelogModal,
|
|
||||||
openTexthookerInBrowser: deps.openTexthookerInBrowser,
|
|
||||||
showTexthookerPage: deps.showTexthookerPage,
|
|
||||||
showFirstRunSetup: deps.showFirstRunSetup,
|
|
||||||
openFirstRunSetupWindow: deps.openFirstRunSetupWindow,
|
|
||||||
showWindowsMpvLauncherSetup: deps.showWindowsMpvLauncherSetup,
|
|
||||||
getDictionaryBackend: deps.getDictionaryBackend,
|
|
||||||
openHachidoriSettings: deps.openHachidoriSettings,
|
|
||||||
openYomitanSettings: deps.openYomitanSettings,
|
|
||||||
openConfigSettingsWindow: deps.openConfigSettingsWindow,
|
|
||||||
openSyncUiWindow: deps.openSyncUiWindow,
|
|
||||||
openYoutubeBrowserWindow: deps.openYoutubeBrowserWindow,
|
|
||||||
exportLogs: deps.exportLogs,
|
|
||||||
openJellyfinSetupWindow: deps.openJellyfinSetupWindow,
|
|
||||||
isJellyfinConfigured: deps.isJellyfinConfigured,
|
|
||||||
isJellyfinDiscoveryActive: deps.isJellyfinDiscoveryActive,
|
|
||||||
toggleJellyfinDiscovery: deps.toggleJellyfinDiscovery,
|
|
||||||
openAnilistSetupWindow: deps.openAnilistSetupWindow,
|
|
||||||
checkForUpdates: deps.checkForUpdates,
|
|
||||||
quitApp: deps.quitApp,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -7,16 +7,10 @@ import {
|
|||||||
createBuildTrayMenuTemplateHandler,
|
createBuildTrayMenuTemplateHandler,
|
||||||
createResolveTrayIconPathHandler,
|
createResolveTrayIconPathHandler,
|
||||||
} from './tray-main-actions';
|
} from './tray-main-actions';
|
||||||
import {
|
|
||||||
createBuildResolveTrayIconPathMainDepsHandler,
|
|
||||||
createBuildTrayMenuTemplateMainDepsHandler,
|
|
||||||
} from './tray-main-deps';
|
|
||||||
|
|
||||||
type ResolveTrayIconPathMainDeps = Parameters<
|
type ResolveTrayIconPathMainDeps = Parameters<typeof createResolveTrayIconPathHandler>[0];
|
||||||
typeof createBuildResolveTrayIconPathMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
type BuildTrayMenuTemplateMainDeps<TMenuItem> = Parameters<
|
type BuildTrayMenuTemplateMainDeps<TMenuItem> = Parameters<
|
||||||
typeof createBuildTrayMenuTemplateMainDepsHandler<TMenuItem>
|
typeof createBuildTrayMenuTemplateHandler<TMenuItem>
|
||||||
>[0];
|
>[0];
|
||||||
type EnsureTrayMainDeps<TTrayMenu> = Parameters<
|
type EnsureTrayMainDeps<TTrayMenu> = Parameters<
|
||||||
typeof createBuildEnsureTrayMainDepsHandler<TrayLike, TTrayMenu, TrayIconLike>
|
typeof createBuildEnsureTrayMainDepsHandler<TrayLike, TTrayMenu, TrayIconLike>
|
||||||
@@ -32,12 +26,8 @@ export function createTrayRuntimeHandlers<TMenuItem, TMenu>(deps: {
|
|||||||
destroyTrayDeps: DestroyTrayMainDeps;
|
destroyTrayDeps: DestroyTrayMainDeps;
|
||||||
buildMenuFromTemplate: (template: TMenuItem[]) => TMenu;
|
buildMenuFromTemplate: (template: TMenuItem[]) => TMenu;
|
||||||
}) {
|
}) {
|
||||||
const resolveTrayIconPath = createResolveTrayIconPathHandler(
|
const resolveTrayIconPath = createResolveTrayIconPathHandler(deps.resolveTrayIconPathDeps);
|
||||||
createBuildResolveTrayIconPathMainDepsHandler(deps.resolveTrayIconPathDeps)(),
|
const buildTrayMenuTemplate = createBuildTrayMenuTemplateHandler(deps.buildTrayMenuTemplateDeps);
|
||||||
);
|
|
||||||
const buildTrayMenuTemplate = createBuildTrayMenuTemplateHandler(
|
|
||||||
createBuildTrayMenuTemplateMainDepsHandler(deps.buildTrayMenuTemplateDeps)(),
|
|
||||||
);
|
|
||||||
const buildTrayMenu = () => deps.buildMenuFromTemplate(buildTrayMenuTemplate());
|
const buildTrayMenu = () => deps.buildMenuFromTemplate(buildTrayMenuTemplate());
|
||||||
|
|
||||||
const ensureTray = createEnsureTrayHandler(
|
const ensureTray = createEnsureTrayHandler(
|
||||||
|
|||||||
@@ -1,34 +0,0 @@
|
|||||||
import type {
|
|
||||||
createEnsureYomitanExtensionLoadedHandler,
|
|
||||||
createLoadYomitanExtensionHandler,
|
|
||||||
} from './yomitan-extension-loader';
|
|
||||||
|
|
||||||
type LoadYomitanExtensionMainDeps = Parameters<typeof createLoadYomitanExtensionHandler>[0];
|
|
||||||
type EnsureYomitanExtensionLoadedMainDeps = Parameters<
|
|
||||||
typeof createEnsureYomitanExtensionLoadedHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
export function createBuildLoadYomitanExtensionMainDepsHandler(deps: LoadYomitanExtensionMainDeps) {
|
|
||||||
return (): LoadYomitanExtensionMainDeps => ({
|
|
||||||
loadYomitanExtensionCore: (options) => deps.loadYomitanExtensionCore(options),
|
|
||||||
userDataPath: deps.userDataPath,
|
|
||||||
externalProfilePath: deps.externalProfilePath,
|
|
||||||
getYomitanParserWindow: () => deps.getYomitanParserWindow(),
|
|
||||||
setYomitanParserWindow: (window) => deps.setYomitanParserWindow(window),
|
|
||||||
setYomitanParserReadyPromise: (promise) => deps.setYomitanParserReadyPromise(promise),
|
|
||||||
setYomitanParserInitPromise: (promise) => deps.setYomitanParserInitPromise(promise),
|
|
||||||
setYomitanExtension: (extension) => deps.setYomitanExtension(extension),
|
|
||||||
setYomitanSession: (session) => deps.setYomitanSession(session),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createBuildEnsureYomitanExtensionLoadedMainDepsHandler(
|
|
||||||
deps: EnsureYomitanExtensionLoadedMainDeps,
|
|
||||||
) {
|
|
||||||
return (): EnsureYomitanExtensionLoadedMainDeps => ({
|
|
||||||
getYomitanExtension: () => deps.getYomitanExtension(),
|
|
||||||
getLoadInFlight: () => deps.getLoadInFlight(),
|
|
||||||
setLoadInFlight: (promise) => deps.setLoadInFlight(promise),
|
|
||||||
loadYomitanExtension: () => deps.loadYomitanExtension(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -3,17 +3,11 @@ import {
|
|||||||
createLoadYomitanExtensionHandler,
|
createLoadYomitanExtensionHandler,
|
||||||
} from './yomitan-extension-loader';
|
} from './yomitan-extension-loader';
|
||||||
import type { Extension } from 'electron';
|
import type { Extension } from 'electron';
|
||||||
import {
|
|
||||||
createBuildEnsureYomitanExtensionLoadedMainDepsHandler,
|
|
||||||
createBuildLoadYomitanExtensionMainDepsHandler,
|
|
||||||
} from './yomitan-extension-loader-main-deps';
|
|
||||||
|
|
||||||
type LoadYomitanExtensionMainDeps = Parameters<
|
type LoadYomitanExtensionMainDeps = Parameters<typeof createLoadYomitanExtensionHandler>[0];
|
||||||
typeof createBuildLoadYomitanExtensionMainDepsHandler
|
|
||||||
>[0];
|
|
||||||
|
|
||||||
type EnsureYomitanExtensionLoadedMainDeps = Omit<
|
type EnsureYomitanExtensionLoadedMainDeps = Omit<
|
||||||
Parameters<typeof createBuildEnsureYomitanExtensionLoadedMainDepsHandler>[0],
|
Parameters<typeof createEnsureYomitanExtensionLoadedHandler>[0],
|
||||||
'loadYomitanExtension'
|
'loadYomitanExtension'
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@@ -23,7 +17,7 @@ export type YomitanExtensionRuntimeDeps = LoadYomitanExtensionMainDeps &
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function createYomitanExtensionRuntime(deps: YomitanExtensionRuntimeDeps) {
|
export function createYomitanExtensionRuntime(deps: YomitanExtensionRuntimeDeps) {
|
||||||
const buildLoadYomitanExtensionMainDepsHandler = createBuildLoadYomitanExtensionMainDepsHandler({
|
const loadYomitanExtensionHandler = createLoadYomitanExtensionHandler({
|
||||||
loadYomitanExtensionCore: deps.loadYomitanExtensionCore,
|
loadYomitanExtensionCore: deps.loadYomitanExtensionCore,
|
||||||
userDataPath: deps.userDataPath,
|
userDataPath: deps.userDataPath,
|
||||||
externalProfilePath: deps.externalProfilePath,
|
externalProfilePath: deps.externalProfilePath,
|
||||||
@@ -34,20 +28,13 @@ export function createYomitanExtensionRuntime(deps: YomitanExtensionRuntimeDeps)
|
|||||||
setYomitanExtension: deps.setYomitanExtension,
|
setYomitanExtension: deps.setYomitanExtension,
|
||||||
setYomitanSession: deps.setYomitanSession,
|
setYomitanSession: deps.setYomitanSession,
|
||||||
});
|
});
|
||||||
const loadYomitanExtensionHandler = createLoadYomitanExtensionHandler(
|
|
||||||
buildLoadYomitanExtensionMainDepsHandler(),
|
|
||||||
);
|
|
||||||
|
|
||||||
const buildEnsureYomitanExtensionLoadedMainDepsHandler =
|
const ensureYomitanExtensionLoadedHandler = createEnsureYomitanExtensionLoadedHandler({
|
||||||
createBuildEnsureYomitanExtensionLoadedMainDepsHandler({
|
getYomitanExtension: deps.getYomitanExtension,
|
||||||
getYomitanExtension: deps.getYomitanExtension,
|
getLoadInFlight: deps.getLoadInFlight,
|
||||||
getLoadInFlight: deps.getLoadInFlight,
|
setLoadInFlight: deps.setLoadInFlight,
|
||||||
setLoadInFlight: deps.setLoadInFlight,
|
loadYomitanExtension: () => loadYomitanExtensionHandler(),
|
||||||
loadYomitanExtension: () => loadYomitanExtensionHandler(),
|
});
|
||||||
});
|
|
||||||
const ensureYomitanExtensionLoadedHandler = createEnsureYomitanExtensionLoadedHandler(
|
|
||||||
buildEnsureYomitanExtensionLoadedMainDepsHandler(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let lastNotifiedExtension: Extension | null = null;
|
let lastNotifiedExtension: Extension | null = null;
|
||||||
let notifyingExtension: Extension | null = null;
|
let notifyingExtension: Extension | null = null;
|
||||||
|
|||||||
Reference in new issue
Block a user