diff --git a/docs/subagents/INDEX.md b/docs/subagents/INDEX.md index b728b6c..8404fcb 100644 --- a/docs/subagents/INDEX.md +++ b/docs/subagents/INDEX.md @@ -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-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-20T10:14: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-20T10:15:51Z` | | `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-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` | diff --git a/docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md b/docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md index 5772098..07f0a9e 100644 --- a/docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md +++ b/docs/subagents/agents/codex-task85-20260219T233711Z-46hc.md @@ -9,6 +9,10 @@ ## Current Work (newest first) +- [2026-02-20T10:15:51Z] progress: extracted overlay window factory composition from `src/main.ts` into `src/main/runtime/overlay-window-runtime-handlers.ts`; `main.ts` now composes overlay/main/invisible window handlers via one runtime factory. +- [2026-02-20T10:15:51Z] progress: added `src/main/runtime/overlay-window-runtime-handlers.test.ts` for composed window handler wiring. +- [2026-02-20T10:15:51Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + focused suites pass for `overlay-window-runtime-handlers*`, `overlay-window-factory*`, `overlay-runtime-bootstrap*`, `tray-runtime-handlers*`, and `cli-command-context-factory*` (9/9). +- [2026-02-20T10:15:51Z] scope: staging `src/main.ts`, new overlay-window runtime module/tests, and subagent bookkeeping only. - [2026-02-20T10:14:17Z] progress: extracted tray composition wiring from `src/main.ts` into `src/main/runtime/tray-runtime-handlers.ts`; `main.ts` now composes `resolveTrayIconPath`/`buildTrayMenu`/`ensureTray`/`destroyTray` through one factory. - [2026-02-20T10:14:17Z] progress: added `src/main/runtime/tray-runtime-handlers.test.ts` covering composed tray handler behavior. - [2026-02-20T10:14:17Z] test: `bun run build` pass (expected macOS helper Swift cache fallback) + focused suites pass for `tray-runtime-handlers*`, `tray-main-actions*`, `tray-main-deps*`, `tray-runtime*`, `tray-lifecycle*`, `cli-command-context-factory*`, and `overlay-visibility-runtime*` (12/12). diff --git a/src/main.ts b/src/main.ts index 92ff3e5..432dec2 100644 --- a/src/main.ts +++ b/src/main.ts @@ -381,16 +381,7 @@ import { } from './main/runtime/overlay-runtime-main-actions-main-deps'; import { createIpcRuntimeHandlers } from './main/runtime/ipc-runtime-handlers'; import { createBuildMpvCommandFromIpcRuntimeMainDepsHandler } from './main/runtime/ipc-mpv-command-main-deps'; -import { - createCreateInvisibleWindowHandler, - createCreateMainWindowHandler, - createCreateOverlayWindowHandler, -} from './main/runtime/overlay-window-factory'; -import { - createBuildCreateInvisibleWindowMainDepsHandler, - createBuildCreateMainWindowMainDepsHandler, - createBuildCreateOverlayWindowMainDepsHandler, -} from './main/runtime/overlay-window-factory-main-deps'; +import { createOverlayWindowRuntimeHandlers } from './main/runtime/overlay-window-runtime-handlers'; import { createBuildInitializeOverlayRuntimeBootstrapMainDepsHandler, createBuildOpenYomitanSettingsMainDepsHandler, @@ -2991,14 +2982,19 @@ const createCliCommandContextHandler = createCliCommandContextFactory({ logWarn: (message: string) => logger.warn(message), logError: (message: string, err: unknown) => logger.error(message, err), }); -const createOverlayWindowHandler = createCreateOverlayWindowHandler( - createBuildCreateOverlayWindowMainDepsHandler({ +const { + createOverlayWindow: createOverlayWindowHandler, + createMainWindow: createMainWindowHandler, + createInvisibleWindow: createInvisibleWindowHandler, +} = createOverlayWindowRuntimeHandlers({ + createOverlayWindowDeps: { createOverlayWindowCore: (kind, options) => createOverlayWindowCore(kind, options), isDev, getOverlayDebugVisualizationEnabled: () => appState.overlayDebugVisualizationEnabled, ensureOverlayWindowLevel: (window) => ensureOverlayWindowLevel(window), onRuntimeOptionsChanged: () => broadcastRuntimeOptionsChanged(), - setOverlayDebugVisualizationEnabled: (enabled) => setOverlayDebugVisualizationEnabled(enabled), + setOverlayDebugVisualizationEnabled: (enabled) => + setOverlayDebugVisualizationEnabled(enabled), isOverlayVisible: (windowKind) => windowKind === 'visible' ? overlayManager.getVisibleOverlayVisible() @@ -3012,20 +3008,10 @@ const createOverlayWindowHandler = createCreateOverlayWindowHandler( - createBuildCreateMainWindowMainDepsHandler({ - createOverlayWindow: (kind) => createOverlayWindow(kind), - setMainWindow: (window) => overlayManager.setMainWindow(window), - })(), -); -const createInvisibleWindowHandler = createCreateInvisibleWindowHandler( - createBuildCreateInvisibleWindowMainDepsHandler({ - createOverlayWindow: (kind) => createOverlayWindow(kind), - setInvisibleWindow: (window) => overlayManager.setInvisibleWindow(window), - })(), -); + }, + setMainWindow: (window) => overlayManager.setMainWindow(window), + setInvisibleWindow: (window) => overlayManager.setInvisibleWindow(window), +}); const { resolveTrayIconPath: resolveTrayIconPathHandler, buildTrayMenu: buildTrayMenuHandler, diff --git a/src/main/runtime/overlay-window-runtime-handlers.test.ts b/src/main/runtime/overlay-window-runtime-handlers.test.ts new file mode 100644 index 0000000..50de0d3 --- /dev/null +++ b/src/main/runtime/overlay-window-runtime-handlers.test.ts @@ -0,0 +1,44 @@ +import assert from 'node:assert/strict'; +import test from 'node:test'; +import { createOverlayWindowRuntimeHandlers } from './overlay-window-runtime-handlers'; + +test('overlay window runtime handlers compose create/main/invisible handlers', () => { + let mainWindow: { kind: string } | null = null; + let invisibleWindow: { kind: string } | null = null; + let debugEnabled = false; + const calls: string[] = []; + + const runtime = createOverlayWindowRuntimeHandlers({ + createOverlayWindowDeps: { + createOverlayWindowCore: (kind) => ({ kind }), + isDev: true, + getOverlayDebugVisualizationEnabled: () => debugEnabled, + ensureOverlayWindowLevel: () => calls.push('ensure-level'), + onRuntimeOptionsChanged: () => calls.push('runtime-options-changed'), + setOverlayDebugVisualizationEnabled: (enabled) => { + debugEnabled = enabled; + }, + isOverlayVisible: (kind) => kind === 'visible', + tryHandleOverlayShortcutLocalFallback: () => false, + onWindowClosed: (kind) => calls.push(`closed:${kind}`), + }, + setMainWindow: (window) => { + mainWindow = window; + }, + setInvisibleWindow: (window) => { + invisibleWindow = window; + }, + }); + + assert.deepEqual(runtime.createOverlayWindow('visible'), { kind: 'visible' }); + assert.deepEqual(runtime.createOverlayWindow('invisible'), { kind: 'invisible' }); + + assert.deepEqual(runtime.createMainWindow(), { kind: 'visible' }); + assert.deepEqual(mainWindow, { kind: 'visible' }); + + assert.deepEqual(runtime.createInvisibleWindow(), { kind: 'invisible' }); + assert.deepEqual(invisibleWindow, { kind: 'invisible' }); + + assert.equal(debugEnabled, false); + assert.deepEqual(calls, []); +}); diff --git a/src/main/runtime/overlay-window-runtime-handlers.ts b/src/main/runtime/overlay-window-runtime-handlers.ts new file mode 100644 index 0000000..5fbb980 --- /dev/null +++ b/src/main/runtime/overlay-window-runtime-handlers.ts @@ -0,0 +1,42 @@ +import { + createCreateInvisibleWindowHandler, + createCreateMainWindowHandler, + createCreateOverlayWindowHandler, +} from './overlay-window-factory'; +import { + createBuildCreateInvisibleWindowMainDepsHandler, + createBuildCreateMainWindowMainDepsHandler, + createBuildCreateOverlayWindowMainDepsHandler, +} from './overlay-window-factory-main-deps'; + +type CreateOverlayWindowMainDeps = Parameters< + typeof createBuildCreateOverlayWindowMainDepsHandler +>[0]; + +export function createOverlayWindowRuntimeHandlers(deps: { + createOverlayWindowDeps: CreateOverlayWindowMainDeps; + setMainWindow: (window: TWindow | null) => void; + setInvisibleWindow: (window: TWindow | null) => void; +}) { + const createOverlayWindow = createCreateOverlayWindowHandler( + createBuildCreateOverlayWindowMainDepsHandler(deps.createOverlayWindowDeps)(), + ); + const createMainWindow = createCreateMainWindowHandler( + createBuildCreateMainWindowMainDepsHandler({ + createOverlayWindow: (kind) => createOverlayWindow(kind), + setMainWindow: (window) => deps.setMainWindow(window), + })(), + ); + const createInvisibleWindow = createCreateInvisibleWindowHandler( + createBuildCreateInvisibleWindowMainDepsHandler({ + createOverlayWindow: (kind) => createOverlayWindow(kind), + setInvisibleWindow: (window) => deps.setInvisibleWindow(window), + })(), + ); + + return { + createOverlayWindow, + createMainWindow, + createInvisibleWindow, + }; +}