mirror of
https://github.com/ksyasuda/SubMiner.git
synced 2026-02-27 18:22:41 -08:00
refactor: extract yomitan runtime wiring from main
This commit is contained in:
@@ -6,7 +6,7 @@ Read first. Keep concise.
|
|||||||
| ------------ | -------------- | ---------------------------------------------------- | --------- | ------------------------------------- | ---------------------- |
|
| ------------ | -------------- | ---------------------------------------------------- | --------- | ------------------------------------- | ---------------------- |
|
||||||
| `codex-generate-minecard-image-20260220T112900Z-vsxr` | `codex-generate-minecard-image` | `Generate media fallbacks (GIF) from assets/minecard.webm and wire README/docs fallback markup` | `done` | `docs/subagents/agents/codex-generate-minecard-image-20260220T112900Z-vsxr.md` | `2026-02-20T11:35:30Z` |
|
| `codex-generate-minecard-image-20260220T112900Z-vsxr` | `codex-generate-minecard-image` | `Generate media fallbacks (GIF) from assets/minecard.webm and wire README/docs fallback markup` | `done` | `docs/subagents/agents/codex-generate-minecard-image-20260220T112900Z-vsxr.md` | `2026-02-20T11:35:30Z` |
|
||||||
| `codex-main` | `planner-exec` | `Fix frequency/N+1 regression in plugin --start flow` | `in_progress` | `docs/subagents/agents/codex-main.md` | `2026-02-19T19:36:46Z` |
|
| `codex-main` | `planner-exec` | `Fix frequency/N+1 regression in plugin --start flow` | `in_progress` | `docs/subagents/agents/codex-main.md` | `2026-02-19T19:36:46Z` |
|
||||||
| `codex-task85-20260219T233711Z-46hc` | `codex-task85` | `Resume TASK-85 maintainability refactor from latest handoff point` | `in_progress` | `docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md` | `2026-02-20T09:51:57Z` |
|
| `codex-task85-20260219T233711Z-46hc` | `codex-task85` | `Resume TASK-85 maintainability refactor from latest handoff point` | `in_progress` | `docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md` | `2026-02-20T09:59:54Z` |
|
||||||
| `codex-config-validation-20260219T172015Z-iiyf` | `codex-config-validation` | `Find root cause of config validation error for ~/.config/SubMiner/config.jsonc` | `completed` | `docs/subagents/agents/codex-config-validation-20260219T172015Z-iiyf.md` | `2026-02-19T17:26:17Z` |
|
| `codex-config-validation-20260219T172015Z-iiyf` | `codex-config-validation` | `Find root cause of config validation error for ~/.config/SubMiner/config.jsonc` | `completed` | `docs/subagents/agents/codex-config-validation-20260219T172015Z-iiyf.md` | `2026-02-19T17:26:17Z` |
|
||||||
| `codex-task85-20260219T233711Z-46hc` | `codex-task85` | `Resume TASK-85 maintainability refactor from latest handoff point` | `in_progress` | `docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md` | `2026-02-20T02:56:34Z` |
|
| `codex-task85-20260219T233711Z-46hc` | `codex-task85` | `Resume TASK-85 maintainability refactor from latest handoff point` | `in_progress` | `docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md` | `2026-02-20T02:56:34Z` |
|
||||||
| `codex-anilist-deeplink-20260219T233926Z` | `anilist-deeplink` | `Fix external subminer:// AniList callback handling from browser` | `done` | `docs/subagents/agents/codex-anilist-deeplink-20260219T233926Z.md` | `2026-02-19T23:59:21Z` |
|
| `codex-anilist-deeplink-20260219T233926Z` | `anilist-deeplink` | `Fix external subminer:// AniList callback handling from browser` | `done` | `docs/subagents/agents/codex-anilist-deeplink-20260219T233926Z.md` | `2026-02-19T23:59:21Z` |
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
|
|
||||||
## Current Work (newest first)
|
## Current Work (newest first)
|
||||||
|
|
||||||
|
- [2026-02-20T09:59:54Z] progress: pivot batch completed: extracted Yomitan extension runtime wiring from `src/main.ts` into new module `src/main/runtime/yomitan-extension-runtime.ts` and replaced `main.ts` setup with `createYomitanExtensionRuntime(...)`.
|
||||||
|
- [2026-02-20T09:59:54Z] progress: added regression coverage for extracted composition in `src/main/runtime/yomitan-extension-runtime.test.ts`; finalized remaining inline `build*MainDepsHandler(),` constructor sites in `src/main.ts` (count now 0).
|
||||||
|
- [2026-02-20T09:59:54Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + targeted suites pass for `yomitan-extension-runtime*`, `yomitan-extension-loader*`, `mpv-subtitle-render-metrics*`, `overlay-window-layout*`, `mining-actions*`, `ipc-bridge-actions*`, `cli-command-context*`, `startup-warmups*` (30/30).
|
||||||
|
- [2026-02-20T09:59:54Z] scope: staging `src/main.ts`, new Yomitan runtime module/tests, and subagent bookkeeping only; unrelated workspace deltas remain excluded.
|
||||||
- [2026-02-20T09:51:57Z] progress: completed another 2-slice safe batch (10 normalized sites) by prebuilding finalized deps for stop/run Jellyfin command handlers, app lifecycle runner, initial-args handler, MPV event binding, and numeric/overlay-shortcut related setup.
|
- [2026-02-20T09:51:57Z] progress: completed another 2-slice safe batch (10 normalized sites) by prebuilding finalized deps for stop/run Jellyfin command handlers, app lifecycle runner, initial-args handler, MPV event binding, and numeric/overlay-shortcut related setup.
|
||||||
- [2026-02-20T09:51:57Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + targeted suites pass for `jellyfin-command-dispatch*`, `jellyfin-remote-session-lifecycle`, `app-lifecycle-*`, `initial-args*`, `mpv-main-event-*`, `numeric-shortcut-*`, `overlay-shortcuts-lifecycle*`, and `anki-actions` (39/39).
|
- [2026-02-20T09:51:57Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + targeted suites pass for `jellyfin-command-dispatch*`, `jellyfin-remote-session-lifecycle`, `app-lifecycle-*`, `initial-args*`, `mpv-main-event-*`, `numeric-shortcut-*`, `overlay-shortcuts-lifecycle*`, and `anki-actions` (39/39).
|
||||||
- [2026-02-20T09:51:57Z] scope: committing only `src/main.ts` + subagent bookkeeping files; unrelated workspace noise still excluded.
|
- [2026-02-20T09:51:57Z] scope: committing only `src/main.ts` + subagent bookkeeping files; unrelated workspace noise still excluded.
|
||||||
|
|||||||
91
src/main.ts
91
src/main.ts
@@ -428,14 +428,7 @@ import {
|
|||||||
createBuildInitializeOverlayRuntimeBootstrapMainDepsHandler,
|
createBuildInitializeOverlayRuntimeBootstrapMainDepsHandler,
|
||||||
createBuildOpenYomitanSettingsMainDepsHandler,
|
createBuildOpenYomitanSettingsMainDepsHandler,
|
||||||
} from './main/runtime/app-runtime-main-deps';
|
} from './main/runtime/app-runtime-main-deps';
|
||||||
import {
|
import { createYomitanExtensionRuntime } from './main/runtime/yomitan-extension-runtime';
|
||||||
createEnsureYomitanExtensionLoadedHandler,
|
|
||||||
createLoadYomitanExtensionHandler,
|
|
||||||
} from './main/runtime/yomitan-extension-loader';
|
|
||||||
import {
|
|
||||||
createBuildEnsureYomitanExtensionLoadedMainDepsHandler,
|
|
||||||
createBuildLoadYomitanExtensionMainDepsHandler,
|
|
||||||
} from './main/runtime/yomitan-extension-loader-main-deps';
|
|
||||||
import { createBuildInitializeOverlayRuntimeOptionsHandler } from './main/runtime/overlay-runtime-options';
|
import { createBuildInitializeOverlayRuntimeOptionsHandler } from './main/runtime/overlay-runtime-options';
|
||||||
import { createBuildInitializeOverlayRuntimeMainDepsHandler } from './main/runtime/overlay-runtime-options-main-deps';
|
import { createBuildInitializeOverlayRuntimeMainDepsHandler } from './main/runtime/overlay-runtime-options-main-deps';
|
||||||
import { createBuildCliCommandContextDepsHandler } from './main/runtime/cli-command-context-deps';
|
import { createBuildCliCommandContextDepsHandler } from './main/runtime/cli-command-context-deps';
|
||||||
@@ -2374,8 +2367,10 @@ const buildUpdateMpvSubtitleRenderMetricsMainDepsHandler =
|
|||||||
broadcastToOverlayWindows('mpv-subtitle-render-metrics:set', metrics);
|
broadcastToOverlayWindows('mpv-subtitle-render-metrics:set', metrics);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const updateMpvSubtitleRenderMetricsMainDeps =
|
||||||
|
buildUpdateMpvSubtitleRenderMetricsMainDepsHandler();
|
||||||
const updateMpvSubtitleRenderMetricsRuntime = createUpdateMpvSubtitleRenderMetricsHandler(
|
const updateMpvSubtitleRenderMetricsRuntime = createUpdateMpvSubtitleRenderMetricsHandler(
|
||||||
buildUpdateMpvSubtitleRenderMetricsMainDepsHandler(),
|
updateMpvSubtitleRenderMetricsMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
function updateMpvSubtitleRenderMetrics(patch: Partial<MpvSubtitleRenderMetrics>): void {
|
function updateMpvSubtitleRenderMetrics(patch: Partial<MpvSubtitleRenderMetrics>): void {
|
||||||
@@ -2525,16 +2520,17 @@ const buildEnforceOverlayLayerOrderMainDepsHandler =
|
|||||||
getInvisibleWindow: () => overlayManager.getInvisibleWindow(),
|
getInvisibleWindow: () => overlayManager.getInvisibleWindow(),
|
||||||
ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window as BrowserWindow),
|
ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window as BrowserWindow),
|
||||||
});
|
});
|
||||||
|
const enforceOverlayLayerOrderMainDeps = buildEnforceOverlayLayerOrderMainDepsHandler();
|
||||||
const enforceOverlayLayerOrder = createEnforceOverlayLayerOrderHandler(
|
const enforceOverlayLayerOrder = createEnforceOverlayLayerOrderHandler(
|
||||||
buildEnforceOverlayLayerOrderMainDepsHandler(),
|
enforceOverlayLayerOrderMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
async function loadYomitanExtension(): Promise<Extension | null> {
|
async function loadYomitanExtension(): Promise<Extension | null> {
|
||||||
return loadYomitanExtensionHandler();
|
return yomitanExtensionRuntime.loadYomitanExtension();
|
||||||
}
|
}
|
||||||
|
|
||||||
async function ensureYomitanExtensionLoaded(): Promise<Extension | null> {
|
async function ensureYomitanExtensionLoaded(): Promise<Extension | null> {
|
||||||
return ensureYomitanExtensionLoadedHandler();
|
return yomitanExtensionRuntime.ensureYomitanExtensionLoaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
function createOverlayWindow(kind: 'visible' | 'invisible'): BrowserWindow {
|
function createOverlayWindow(kind: 'visible' | 'invisible'): BrowserWindow {
|
||||||
@@ -2811,8 +2807,9 @@ const buildRefreshKnownWordCacheMainDepsHandler = createBuildRefreshKnownWordCac
|
|||||||
getAnkiIntegration: () => appState.ankiIntegration,
|
getAnkiIntegration: () => appState.ankiIntegration,
|
||||||
missingIntegrationMessage: 'AnkiConnect integration not enabled',
|
missingIntegrationMessage: 'AnkiConnect integration not enabled',
|
||||||
});
|
});
|
||||||
|
const refreshKnownWordCacheMainDeps = buildRefreshKnownWordCacheMainDepsHandler();
|
||||||
const refreshKnownWordCacheHandler = createRefreshKnownWordCacheHandler(
|
const refreshKnownWordCacheHandler = createRefreshKnownWordCacheHandler(
|
||||||
buildRefreshKnownWordCacheMainDepsHandler(),
|
refreshKnownWordCacheMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildTriggerFieldGroupingMainDepsHandler = createBuildTriggerFieldGroupingMainDepsHandler({
|
const buildTriggerFieldGroupingMainDepsHandler = createBuildTriggerFieldGroupingMainDepsHandler({
|
||||||
@@ -2820,8 +2817,9 @@ const buildTriggerFieldGroupingMainDepsHandler = createBuildTriggerFieldGrouping
|
|||||||
showMpvOsd: (text) => showMpvOsd(text),
|
showMpvOsd: (text) => showMpvOsd(text),
|
||||||
triggerFieldGroupingCore,
|
triggerFieldGroupingCore,
|
||||||
});
|
});
|
||||||
|
const triggerFieldGroupingMainDeps = buildTriggerFieldGroupingMainDepsHandler();
|
||||||
const triggerFieldGroupingHandler = createTriggerFieldGroupingHandler(
|
const triggerFieldGroupingHandler = createTriggerFieldGroupingHandler(
|
||||||
buildTriggerFieldGroupingMainDepsHandler(),
|
triggerFieldGroupingMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildMarkLastCardAsAudioCardMainDepsHandler =
|
const buildMarkLastCardAsAudioCardMainDepsHandler =
|
||||||
@@ -2830,8 +2828,10 @@ const buildMarkLastCardAsAudioCardMainDepsHandler =
|
|||||||
showMpvOsd: (text) => showMpvOsd(text),
|
showMpvOsd: (text) => showMpvOsd(text),
|
||||||
markLastCardAsAudioCardCore,
|
markLastCardAsAudioCardCore,
|
||||||
});
|
});
|
||||||
|
const markLastCardAsAudioCardMainDeps =
|
||||||
|
buildMarkLastCardAsAudioCardMainDepsHandler();
|
||||||
const markLastCardAsAudioCardHandler = createMarkLastCardAsAudioCardHandler(
|
const markLastCardAsAudioCardHandler = createMarkLastCardAsAudioCardHandler(
|
||||||
buildMarkLastCardAsAudioCardMainDepsHandler(),
|
markLastCardAsAudioCardMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildMineSentenceCardMainDepsHandler = createBuildMineSentenceCardMainDepsHandler({
|
const buildMineSentenceCardMainDepsHandler = createBuildMineSentenceCardMainDepsHandler({
|
||||||
@@ -2851,8 +2851,9 @@ const buildHandleMultiCopyDigitMainDepsHandler = createBuildHandleMultiCopyDigit
|
|||||||
showMpvOsd: (text) => showMpvOsd(text),
|
showMpvOsd: (text) => showMpvOsd(text),
|
||||||
handleMultiCopyDigitCore,
|
handleMultiCopyDigitCore,
|
||||||
});
|
});
|
||||||
|
const handleMultiCopyDigitMainDeps = buildHandleMultiCopyDigitMainDepsHandler();
|
||||||
const handleMultiCopyDigitHandler = createHandleMultiCopyDigitHandler(
|
const handleMultiCopyDigitHandler = createHandleMultiCopyDigitHandler(
|
||||||
buildHandleMultiCopyDigitMainDepsHandler(),
|
handleMultiCopyDigitMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildCopyCurrentSubtitleMainDepsHandler = createBuildCopyCurrentSubtitleMainDepsHandler({
|
const buildCopyCurrentSubtitleMainDepsHandler = createBuildCopyCurrentSubtitleMainDepsHandler({
|
||||||
@@ -2861,8 +2862,9 @@ const buildCopyCurrentSubtitleMainDepsHandler = createBuildCopyCurrentSubtitleMa
|
|||||||
showMpvOsd: (text) => showMpvOsd(text),
|
showMpvOsd: (text) => showMpvOsd(text),
|
||||||
copyCurrentSubtitleCore,
|
copyCurrentSubtitleCore,
|
||||||
});
|
});
|
||||||
|
const copyCurrentSubtitleMainDeps = buildCopyCurrentSubtitleMainDepsHandler();
|
||||||
const copyCurrentSubtitleHandler = createCopyCurrentSubtitleHandler(
|
const copyCurrentSubtitleHandler = createCopyCurrentSubtitleHandler(
|
||||||
buildCopyCurrentSubtitleMainDepsHandler(),
|
copyCurrentSubtitleMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildHandleMineSentenceDigitMainDepsHandler =
|
const buildHandleMineSentenceDigitMainDepsHandler =
|
||||||
@@ -2879,8 +2881,9 @@ const buildHandleMineSentenceDigitMainDepsHandler =
|
|||||||
},
|
},
|
||||||
handleMineSentenceDigitCore,
|
handleMineSentenceDigitCore,
|
||||||
});
|
});
|
||||||
|
const handleMineSentenceDigitMainDeps = buildHandleMineSentenceDigitMainDepsHandler();
|
||||||
const handleMineSentenceDigitHandler = createHandleMineSentenceDigitHandler(
|
const handleMineSentenceDigitHandler = createHandleMineSentenceDigitHandler(
|
||||||
buildHandleMineSentenceDigitMainDepsHandler(),
|
handleMineSentenceDigitMainDeps,
|
||||||
);
|
);
|
||||||
const buildSetVisibleOverlayVisibleMainDepsHandler =
|
const buildSetVisibleOverlayVisibleMainDepsHandler =
|
||||||
createBuildSetVisibleOverlayVisibleMainDepsHandler({
|
createBuildSetVisibleOverlayVisibleMainDepsHandler({
|
||||||
@@ -2899,8 +2902,10 @@ const buildSetVisibleOverlayVisibleMainDepsHandler =
|
|||||||
setMpvSubVisibilityRuntime(appState.mpvClient, mpvSubVisible);
|
setMpvSubVisibilityRuntime(appState.mpvClient, mpvSubVisible);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const setVisibleOverlayVisibleMainDeps =
|
||||||
|
buildSetVisibleOverlayVisibleMainDepsHandler();
|
||||||
const setVisibleOverlayVisibleHandler = createSetVisibleOverlayVisibleHandler(
|
const setVisibleOverlayVisibleHandler = createSetVisibleOverlayVisibleHandler(
|
||||||
buildSetVisibleOverlayVisibleMainDepsHandler(),
|
setVisibleOverlayVisibleMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildSetInvisibleOverlayVisibleMainDepsHandler =
|
const buildSetInvisibleOverlayVisibleMainDepsHandler =
|
||||||
@@ -2913,16 +2918,19 @@ const buildSetInvisibleOverlayVisibleMainDepsHandler =
|
|||||||
syncInvisibleOverlayMousePassthrough: () =>
|
syncInvisibleOverlayMousePassthrough: () =>
|
||||||
overlayVisibilityRuntime.syncInvisibleOverlayMousePassthrough(),
|
overlayVisibilityRuntime.syncInvisibleOverlayMousePassthrough(),
|
||||||
});
|
});
|
||||||
|
const setInvisibleOverlayVisibleMainDeps =
|
||||||
|
buildSetInvisibleOverlayVisibleMainDepsHandler();
|
||||||
const setInvisibleOverlayVisibleHandler = createSetInvisibleOverlayVisibleHandler(
|
const setInvisibleOverlayVisibleHandler = createSetInvisibleOverlayVisibleHandler(
|
||||||
buildSetInvisibleOverlayVisibleMainDepsHandler(),
|
setInvisibleOverlayVisibleMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildToggleVisibleOverlayMainDepsHandler = createBuildToggleVisibleOverlayMainDepsHandler({
|
const buildToggleVisibleOverlayMainDepsHandler = createBuildToggleVisibleOverlayMainDepsHandler({
|
||||||
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(),
|
getVisibleOverlayVisible: () => overlayManager.getVisibleOverlayVisible(),
|
||||||
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
||||||
});
|
});
|
||||||
|
const toggleVisibleOverlayMainDeps = buildToggleVisibleOverlayMainDepsHandler();
|
||||||
const toggleVisibleOverlayHandler = createToggleVisibleOverlayHandler(
|
const toggleVisibleOverlayHandler = createToggleVisibleOverlayHandler(
|
||||||
buildToggleVisibleOverlayMainDepsHandler(),
|
toggleVisibleOverlayMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildToggleInvisibleOverlayMainDepsHandler =
|
const buildToggleInvisibleOverlayMainDepsHandler =
|
||||||
@@ -2930,15 +2938,18 @@ const buildToggleInvisibleOverlayMainDepsHandler =
|
|||||||
getInvisibleOverlayVisible: () => overlayManager.getInvisibleOverlayVisible(),
|
getInvisibleOverlayVisible: () => overlayManager.getInvisibleOverlayVisible(),
|
||||||
setInvisibleOverlayVisible: (visible) => setInvisibleOverlayVisible(visible),
|
setInvisibleOverlayVisible: (visible) => setInvisibleOverlayVisible(visible),
|
||||||
});
|
});
|
||||||
|
const toggleInvisibleOverlayMainDeps =
|
||||||
|
buildToggleInvisibleOverlayMainDepsHandler();
|
||||||
const toggleInvisibleOverlayHandler = createToggleInvisibleOverlayHandler(
|
const toggleInvisibleOverlayHandler = createToggleInvisibleOverlayHandler(
|
||||||
buildToggleInvisibleOverlayMainDepsHandler(),
|
toggleInvisibleOverlayMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildSetOverlayVisibleMainDepsHandler = createBuildSetOverlayVisibleMainDepsHandler({
|
const buildSetOverlayVisibleMainDepsHandler = createBuildSetOverlayVisibleMainDepsHandler({
|
||||||
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
setVisibleOverlayVisible: (visible) => setVisibleOverlayVisible(visible),
|
||||||
});
|
});
|
||||||
|
const setOverlayVisibleMainDeps = buildSetOverlayVisibleMainDepsHandler();
|
||||||
const setOverlayVisibleHandler = createSetOverlayVisibleHandler(
|
const setOverlayVisibleHandler = createSetOverlayVisibleHandler(
|
||||||
buildSetOverlayVisibleMainDepsHandler(),
|
setOverlayVisibleMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildToggleOverlayMainDepsHandler = createBuildToggleOverlayMainDepsHandler({
|
const buildToggleOverlayMainDepsHandler = createBuildToggleOverlayMainDepsHandler({
|
||||||
@@ -2950,8 +2961,10 @@ const buildHandleOverlayModalClosedMainDepsHandler =
|
|||||||
createBuildHandleOverlayModalClosedMainDepsHandler({
|
createBuildHandleOverlayModalClosedMainDepsHandler({
|
||||||
handleOverlayModalClosedRuntime: (modal) => overlayModalRuntime.handleOverlayModalClosed(modal),
|
handleOverlayModalClosedRuntime: (modal) => overlayModalRuntime.handleOverlayModalClosed(modal),
|
||||||
});
|
});
|
||||||
|
const handleOverlayModalClosedMainDeps =
|
||||||
|
buildHandleOverlayModalClosedMainDepsHandler();
|
||||||
const handleOverlayModalClosedHandler = createHandleOverlayModalClosedHandler(
|
const handleOverlayModalClosedHandler = createHandleOverlayModalClosedHandler(
|
||||||
buildHandleOverlayModalClosedMainDepsHandler(),
|
handleOverlayModalClosedMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildAppendClipboardVideoToQueueMainDepsHandler =
|
const buildAppendClipboardVideoToQueueMainDepsHandler =
|
||||||
@@ -2964,8 +2977,10 @@ const buildAppendClipboardVideoToQueueMainDepsHandler =
|
|||||||
sendMpvCommandRuntime(appState.mpvClient, command);
|
sendMpvCommandRuntime(appState.mpvClient, command);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const appendClipboardVideoToQueueMainDeps =
|
||||||
|
buildAppendClipboardVideoToQueueMainDepsHandler();
|
||||||
const appendClipboardVideoToQueueHandler = createAppendClipboardVideoToQueueHandler(
|
const appendClipboardVideoToQueueHandler = createAppendClipboardVideoToQueueHandler(
|
||||||
buildAppendClipboardVideoToQueueMainDepsHandler(),
|
appendClipboardVideoToQueueMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildMpvCommandFromIpcRuntimeMainDepsHandler =
|
const buildMpvCommandFromIpcRuntimeMainDepsHandler =
|
||||||
@@ -2993,18 +3008,23 @@ const buildMpvCommandFromIpcRuntimeMainDepsHandler =
|
|||||||
const buildHandleMpvCommandFromIpcMainDepsHandler =
|
const buildHandleMpvCommandFromIpcMainDepsHandler =
|
||||||
createBuildHandleMpvCommandFromIpcMainDepsHandler({
|
createBuildHandleMpvCommandFromIpcMainDepsHandler({
|
||||||
handleMpvCommandFromIpcRuntime,
|
handleMpvCommandFromIpcRuntime,
|
||||||
buildMpvCommandDeps: () => buildMpvCommandFromIpcRuntimeMainDepsHandler(),
|
buildMpvCommandDeps: () => mpvCommandFromIpcRuntimeMainDeps,
|
||||||
});
|
});
|
||||||
|
const mpvCommandFromIpcRuntimeMainDeps = buildMpvCommandFromIpcRuntimeMainDepsHandler();
|
||||||
|
const handleMpvCommandFromIpcMainDeps =
|
||||||
|
buildHandleMpvCommandFromIpcMainDepsHandler();
|
||||||
const handleMpvCommandFromIpcHandler = createHandleMpvCommandFromIpcHandler(
|
const handleMpvCommandFromIpcHandler = createHandleMpvCommandFromIpcHandler(
|
||||||
buildHandleMpvCommandFromIpcMainDepsHandler(),
|
handleMpvCommandFromIpcMainDeps,
|
||||||
);
|
);
|
||||||
|
|
||||||
const buildRunSubsyncManualFromIpcMainDepsHandler =
|
const buildRunSubsyncManualFromIpcMainDepsHandler =
|
||||||
createBuildRunSubsyncManualFromIpcMainDepsHandler({
|
createBuildRunSubsyncManualFromIpcMainDepsHandler({
|
||||||
runManualFromIpc: (request: SubsyncManualRunRequest) => subsyncRuntime.runManualFromIpc(request),
|
runManualFromIpc: (request: SubsyncManualRunRequest) => subsyncRuntime.runManualFromIpc(request),
|
||||||
});
|
});
|
||||||
|
const runSubsyncManualFromIpcMainDeps =
|
||||||
|
buildRunSubsyncManualFromIpcMainDepsHandler();
|
||||||
const runSubsyncManualFromIpcHandler = createRunSubsyncManualFromIpcHandler(
|
const runSubsyncManualFromIpcHandler = createRunSubsyncManualFromIpcHandler(
|
||||||
buildRunSubsyncManualFromIpcMainDepsHandler(),
|
runSubsyncManualFromIpcMainDeps,
|
||||||
);
|
);
|
||||||
const buildCliCommandContextMainDepsHandler = createBuildCliCommandContextMainDepsHandler({
|
const buildCliCommandContextMainDepsHandler = createBuildCliCommandContextMainDepsHandler({
|
||||||
appState,
|
appState,
|
||||||
@@ -3048,8 +3068,9 @@ const buildCliCommandContextMainDepsHandler = createBuildCliCommandContextMainDe
|
|||||||
logWarn: (message: string) => logger.warn(message),
|
logWarn: (message: string) => logger.warn(message),
|
||||||
logError: (message: string, err: unknown) => logger.error(message, err),
|
logError: (message: string, err: unknown) => logger.error(message, err),
|
||||||
});
|
});
|
||||||
|
const cliCommandContextMainDeps = buildCliCommandContextMainDepsHandler();
|
||||||
const buildCliCommandContextDepsHandler = createBuildCliCommandContextDepsHandler(
|
const buildCliCommandContextDepsHandler = createBuildCliCommandContextDepsHandler(
|
||||||
buildCliCommandContextMainDepsHandler(),
|
cliCommandContextMainDeps,
|
||||||
);
|
);
|
||||||
const createOverlayWindowHandler = createCreateOverlayWindowHandler<BrowserWindow>(
|
const createOverlayWindowHandler = createCreateOverlayWindowHandler<BrowserWindow>(
|
||||||
createBuildCreateOverlayWindowMainDepsHandler<BrowserWindow>({
|
createBuildCreateOverlayWindowMainDepsHandler<BrowserWindow>({
|
||||||
@@ -3137,7 +3158,7 @@ const destroyTrayHandler = createDestroyTrayHandler(
|
|||||||
},
|
},
|
||||||
})(),
|
})(),
|
||||||
);
|
);
|
||||||
const buildLoadYomitanExtensionMainDepsHandler = createBuildLoadYomitanExtensionMainDepsHandler({
|
const yomitanExtensionRuntime = createYomitanExtensionRuntime({
|
||||||
loadYomitanExtensionCore,
|
loadYomitanExtensionCore,
|
||||||
userDataPath: USER_DATA_PATH,
|
userDataPath: USER_DATA_PATH,
|
||||||
getYomitanParserWindow: () => appState.yomitanParserWindow,
|
getYomitanParserWindow: () => appState.yomitanParserWindow,
|
||||||
@@ -3153,22 +3174,12 @@ const buildLoadYomitanExtensionMainDepsHandler = createBuildLoadYomitanExtension
|
|||||||
setYomitanExtension: (extension) => {
|
setYomitanExtension: (extension) => {
|
||||||
appState.yomitanExt = extension;
|
appState.yomitanExt = extension;
|
||||||
},
|
},
|
||||||
});
|
|
||||||
const loadYomitanExtensionHandler = createLoadYomitanExtensionHandler(
|
|
||||||
buildLoadYomitanExtensionMainDepsHandler(),
|
|
||||||
);
|
|
||||||
const buildEnsureYomitanExtensionLoadedMainDepsHandler =
|
|
||||||
createBuildEnsureYomitanExtensionLoadedMainDepsHandler({
|
|
||||||
getYomitanExtension: () => appState.yomitanExt,
|
getYomitanExtension: () => appState.yomitanExt,
|
||||||
getLoadInFlight: () => yomitanLoadInFlight,
|
getLoadInFlight: () => yomitanLoadInFlight,
|
||||||
setLoadInFlight: (promise) => {
|
setLoadInFlight: (promise) => {
|
||||||
yomitanLoadInFlight = promise;
|
yomitanLoadInFlight = promise;
|
||||||
},
|
},
|
||||||
loadYomitanExtension: () => loadYomitanExtension(),
|
|
||||||
});
|
});
|
||||||
const ensureYomitanExtensionLoadedHandler = createEnsureYomitanExtensionLoadedHandler(
|
|
||||||
buildEnsureYomitanExtensionLoadedMainDepsHandler(),
|
|
||||||
);
|
|
||||||
const buildInitializeOverlayRuntimeOptionsHandler = createBuildInitializeOverlayRuntimeOptionsHandler(
|
const buildInitializeOverlayRuntimeOptionsHandler = createBuildInitializeOverlayRuntimeOptionsHandler(
|
||||||
createBuildInitializeOverlayRuntimeMainDepsHandler({
|
createBuildInitializeOverlayRuntimeMainDepsHandler({
|
||||||
appState,
|
appState,
|
||||||
|
|||||||
96
src/main/runtime/yomitan-extension-runtime.test.ts
Normal file
96
src/main/runtime/yomitan-extension-runtime.test.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import assert from 'node:assert/strict';
|
||||||
|
import test from 'node:test';
|
||||||
|
import type { Extension } from 'electron';
|
||||||
|
import { createYomitanExtensionRuntime } from './yomitan-extension-runtime';
|
||||||
|
|
||||||
|
test('yomitan extension runtime reuses in-flight ensure load and clears it after resolve', async () => {
|
||||||
|
let extension: Extension | null = null;
|
||||||
|
let inFlight: Promise<Extension | null> | null = null;
|
||||||
|
let parserWindow: unknown = null;
|
||||||
|
let readyPromise: Promise<void> | null = null;
|
||||||
|
let initPromise: Promise<boolean> | null = null;
|
||||||
|
let loadCalls = 0;
|
||||||
|
const releaseLoadState: { releaseLoad: ((value: Extension | null) => void) | null } = {
|
||||||
|
releaseLoad: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
const runtime = createYomitanExtensionRuntime({
|
||||||
|
loadYomitanExtensionCore: async (options) => {
|
||||||
|
loadCalls += 1;
|
||||||
|
options.setYomitanParserWindow(null);
|
||||||
|
options.setYomitanParserReadyPromise(Promise.resolve());
|
||||||
|
options.setYomitanParserInitPromise(Promise.resolve(true));
|
||||||
|
return await new Promise<Extension | null>((resolve) => {
|
||||||
|
releaseLoadState.releaseLoad = (value) => {
|
||||||
|
options.setYomitanExtension(value);
|
||||||
|
resolve(value);
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
userDataPath: '/tmp',
|
||||||
|
getYomitanParserWindow: () => parserWindow as never,
|
||||||
|
setYomitanParserWindow: (window) => {
|
||||||
|
parserWindow = window;
|
||||||
|
},
|
||||||
|
setYomitanParserReadyPromise: (promise) => {
|
||||||
|
readyPromise = promise as Promise<void> | null;
|
||||||
|
},
|
||||||
|
setYomitanParserInitPromise: (promise) => {
|
||||||
|
initPromise = promise as Promise<boolean> | null;
|
||||||
|
},
|
||||||
|
setYomitanExtension: (next) => {
|
||||||
|
extension = next;
|
||||||
|
},
|
||||||
|
getYomitanExtension: () => extension,
|
||||||
|
getLoadInFlight: () => inFlight,
|
||||||
|
setLoadInFlight: (promise) => {
|
||||||
|
inFlight = promise;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const first = runtime.ensureYomitanExtensionLoaded();
|
||||||
|
const second = runtime.ensureYomitanExtensionLoaded();
|
||||||
|
assert.equal(loadCalls, 1);
|
||||||
|
assert.ok(inFlight);
|
||||||
|
assert.equal(parserWindow, null);
|
||||||
|
assert.ok(readyPromise);
|
||||||
|
assert.ok(initPromise);
|
||||||
|
|
||||||
|
const fakeExtension = { id: 'yomitan' } as Extension;
|
||||||
|
const releaseLoad = releaseLoadState.releaseLoad;
|
||||||
|
if (!releaseLoad) {
|
||||||
|
throw new Error('expected in-flight yomitan load resolver');
|
||||||
|
}
|
||||||
|
releaseLoad(fakeExtension);
|
||||||
|
assert.equal(await first, fakeExtension);
|
||||||
|
assert.equal(await second, fakeExtension);
|
||||||
|
assert.equal(extension, fakeExtension);
|
||||||
|
assert.equal(inFlight, null);
|
||||||
|
|
||||||
|
const third = await runtime.ensureYomitanExtensionLoaded();
|
||||||
|
assert.equal(third, fakeExtension);
|
||||||
|
assert.equal(loadCalls, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('yomitan extension runtime direct load delegates to core', async () => {
|
||||||
|
let loadCalls = 0;
|
||||||
|
|
||||||
|
const runtime = createYomitanExtensionRuntime({
|
||||||
|
loadYomitanExtensionCore: async () => {
|
||||||
|
loadCalls += 1;
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
userDataPath: '/tmp',
|
||||||
|
getYomitanParserWindow: () => null,
|
||||||
|
setYomitanParserWindow: () => {},
|
||||||
|
setYomitanParserReadyPromise: () => {},
|
||||||
|
setYomitanParserInitPromise: () => {},
|
||||||
|
setYomitanExtension: () => {},
|
||||||
|
getYomitanExtension: () => null,
|
||||||
|
getLoadInFlight: () => null,
|
||||||
|
setLoadInFlight: () => {},
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(await runtime.loadYomitanExtension(), null);
|
||||||
|
assert.equal(loadCalls, 1);
|
||||||
|
});
|
||||||
50
src/main/runtime/yomitan-extension-runtime.ts
Normal file
50
src/main/runtime/yomitan-extension-runtime.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { createEnsureYomitanExtensionLoadedHandler, createLoadYomitanExtensionHandler } from './yomitan-extension-loader';
|
||||||
|
import {
|
||||||
|
createBuildEnsureYomitanExtensionLoadedMainDepsHandler,
|
||||||
|
createBuildLoadYomitanExtensionMainDepsHandler,
|
||||||
|
} from './yomitan-extension-loader-main-deps';
|
||||||
|
|
||||||
|
type LoadYomitanExtensionMainDeps = Parameters<
|
||||||
|
typeof createBuildLoadYomitanExtensionMainDepsHandler
|
||||||
|
>[0];
|
||||||
|
|
||||||
|
type EnsureYomitanExtensionLoadedMainDeps = Omit<
|
||||||
|
Parameters<typeof createBuildEnsureYomitanExtensionLoadedMainDepsHandler>[0],
|
||||||
|
'loadYomitanExtension'
|
||||||
|
>;
|
||||||
|
|
||||||
|
export type YomitanExtensionRuntimeDeps = LoadYomitanExtensionMainDeps &
|
||||||
|
EnsureYomitanExtensionLoadedMainDeps;
|
||||||
|
|
||||||
|
export function createYomitanExtensionRuntime(deps: YomitanExtensionRuntimeDeps) {
|
||||||
|
const buildLoadYomitanExtensionMainDepsHandler = createBuildLoadYomitanExtensionMainDepsHandler({
|
||||||
|
loadYomitanExtensionCore: deps.loadYomitanExtensionCore,
|
||||||
|
userDataPath: deps.userDataPath,
|
||||||
|
getYomitanParserWindow: deps.getYomitanParserWindow,
|
||||||
|
setYomitanParserWindow: deps.setYomitanParserWindow,
|
||||||
|
setYomitanParserReadyPromise: deps.setYomitanParserReadyPromise,
|
||||||
|
setYomitanParserInitPromise: deps.setYomitanParserInitPromise,
|
||||||
|
setYomitanExtension: deps.setYomitanExtension,
|
||||||
|
});
|
||||||
|
const loadYomitanExtensionHandler = createLoadYomitanExtensionHandler(
|
||||||
|
buildLoadYomitanExtensionMainDepsHandler(),
|
||||||
|
);
|
||||||
|
|
||||||
|
const buildEnsureYomitanExtensionLoadedMainDepsHandler =
|
||||||
|
createBuildEnsureYomitanExtensionLoadedMainDepsHandler({
|
||||||
|
getYomitanExtension: deps.getYomitanExtension,
|
||||||
|
getLoadInFlight: deps.getLoadInFlight,
|
||||||
|
setLoadInFlight: deps.setLoadInFlight,
|
||||||
|
loadYomitanExtension: () => loadYomitanExtensionHandler(),
|
||||||
|
});
|
||||||
|
const ensureYomitanExtensionLoadedHandler = createEnsureYomitanExtensionLoadedHandler(
|
||||||
|
buildEnsureYomitanExtensionLoadedMainDepsHandler(),
|
||||||
|
);
|
||||||
|
|
||||||
|
return {
|
||||||
|
loadYomitanExtension: (): Promise<ReturnType<typeof deps.getYomitanExtension>> =>
|
||||||
|
loadYomitanExtensionHandler(),
|
||||||
|
ensureYomitanExtensionLoaded: (): Promise<ReturnType<typeof deps.getYomitanExtension>> =>
|
||||||
|
ensureYomitanExtensionLoadedHandler(),
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user