refactor(main): modularize runtime and harden anilist setup flow

This commit is contained in:
2026-02-19 16:04:59 -08:00
parent 58f28b7b55
commit 162be118e1
73 changed files with 4413 additions and 1251 deletions

View File

@@ -1,11 +1,11 @@
project_name: 'SubMiner'
default_status: 'To Do'
statuses: ['To Do', 'In Progress', 'Done']
project_name: "SubMiner"
default_status: "To Do"
statuses: ["To Do", "In Progress", "Done"]
labels: []
milestones: []
date_format: yyyy-mm-dd
max_column_width: 20
default_editor: 'nvim'
default_editor: "nvim"
auto_open_browser: false
default_port: 6420
remote_operations: true
@@ -13,4 +13,4 @@ auto_commit: false
bypass_git_hooks: false
check_active_branches: true
active_branch_days: 30
task_prefix: 'task'
task_prefix: "task"

View File

@@ -0,0 +1,43 @@
---
id: TASK-29.3
title: Fix AniList OAuth callback token handling in setup window
status: Done
assignee: []
created_date: '2026-02-19 16:56'
labels:
- anilist
- oauth
- bug
dependencies: []
parent_task_id: TASK-29
priority: high
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
AniList login flow shows unsupported_grant_type after auth because setup window does not consume callback URL token and persist it.
Need robust callback handling for both query and hash access_token forms and graceful close/success UX.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 AniList setup flow persists access token from callback URL query/hash
- [x] #2 Setup window closes and state updates to resolved when token captured
- [x] #3 No unsafe navigation regressions in AniList setup window
<!-- AC:END -->
## Definition of Done
<!-- DOD:BEGIN -->
- [x] #1 Build passes
- [x] #2 Targeted AniList runtime tests pass
<!-- DOD:END -->
## Implementation Notes
<!-- SECTION:IMPLEMENTATION_NOTES:BEGIN -->
- Added robust AniList callback token parsing for query/hash and `subminer://anilist-setup?...` deep links.
- Added app-level protocol handling (`open-url` + second-instance argv deep link parsing) so browser callback buttons resolve even when setup window is not navigating.
- Added/updated targeted AniList setup runtime tests and verified build + runtime test pass.
<!-- SECTION:IMPLEMENTATION_NOTES:END -->

View File

@@ -4,19 +4,19 @@ title: Add error boundary and recovery in renderer overlay
status: Done
assignee: []
created_date: '2026-02-14 01:01'
updated_date: '2026-02-19 21:50'
updated_date: '2026-02-19 23:18'
labels:
- renderer
- reliability
- error-handling
dependencies: []
priority: medium
ordinal: 60000
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Add a top-level error boundary in the renderer orchestrator that catches unhandled errors in modals and rendering logic, displays a user-friendly error message, and recovers without crashing the overlay.
## Motivation
@@ -39,9 +39,7 @@ If a renderer modal throws (e.g., jimaku API timeout, DOM manipulation error, ma
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 Unhandled errors in modal flows are caught and do not crash the overlay.
- [x] #2 After an error, the overlay returns to a functional state (subtitles render, shortcuts work).
- [x] #3 A brief toast/notification informs the user that an error occurred.
@@ -52,6 +50,7 @@ If a renderer modal throws (e.g., jimaku API timeout, DOM manipulation error, ma
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
- Added renderer recovery module with guarded callback boundaries and global `window.onerror` / `window.unhandledrejection` handlers.
- Recovery now uses modal close/cancel APIs (including Kiku cancel) to preserve cleanup semantics and avoid hanging pending callbacks.
- Added overlay recovery toast UI and contextual recovery logging payloads.
@@ -61,3 +60,4 @@ If a renderer modal throws (e.g., jimaku API timeout, DOM manipulation error, ma
- `bun run build`
- `bun run test:core:dist`
<!-- SECTION:NOTES:END -->

View File

@@ -5,13 +5,14 @@ status: Done
assignee:
- codex-main
created_date: '2026-02-14 02:02'
updated_date: '2026-02-19 08:21'
updated_date: '2026-02-19 23:18'
labels:
- config
- developer-experience
- error-handling
dependencies: []
priority: medium
ordinal: 66000
---
## Description

View File

@@ -1,34 +0,0 @@
---
id: TASK-65
title: Add overlay drag-drop playlist loading and clipboard append shortcut
status: Done
assignee: []
created_date: '2026-02-18 13:10'
updated_date: '2026-02-18 13:10'
labels: []
dependencies: []
---
## Description
Implement direct playlist control from the overlay:
- Drag/drop video files onto overlay:
- default drop: replace current playback with dropped set (first `replace`, remainder `append`)
- `Shift` + drop: append all dropped files
- `Ctrl/Cmd+A`: read clipboard text, if it resolves to a supported local video file path, append it to mpv playlist.
## Implementation Steps
- [x] Add TDD coverage for drop path parsing, command mode generation, and clipboard path parsing (`src/core/services/overlay-drop.test.ts`).
- [x] Implement drop/clipboard parser + mpv command-builder utility (`src/core/services/overlay-drop.ts`).
- [x] Wire renderer drag/drop handling and mpv command dispatch (`src/renderer/renderer.ts`).
- [x] Add IPC API for clipboard append flow (`src/types.ts`, `src/preload.ts`, `src/core/services/ipc.ts`, `src/main/dependencies.ts`).
- [x] Implement main-process clipboard validation + append behavior (`src/main.ts`).
- [x] Add fixed keyboard shortcut hook (`Ctrl/Cmd+A`) in renderer keyboard handler (`src/renderer/handlers/keyboard.ts`, `src/renderer/renderer.ts`).
- [x] Update docs for new interaction model (`docs/usage.md`, `docs/configuration.md`).
## Verification
- `bun run build`
- `node --test dist/core/services/overlay-drop.test.js dist/core/services/ipc.test.js`

View File

@@ -4,7 +4,7 @@ title: Run Electron app as background tray service with IPC startup
status: Done
assignee: []
created_date: '2026-02-18 08:48'
updated_date: '2026-02-19 21:50'
updated_date: '2026-02-19 23:18'
labels:
- electron
- tray
@@ -12,6 +12,7 @@ labels:
- desktop-entry
dependencies: []
priority: high
ordinal: 61000
---
## Description

View File

@@ -4,7 +4,7 @@ title: Make wrapper stop auto-sending --start by default
status: Done
assignee: []
created_date: '2026-02-18 09:47'
updated_date: '2026-02-18 10:02'
updated_date: '2026-02-19 23:18'
labels:
- launcher
- wrapper
@@ -12,6 +12,7 @@ labels:
- background-mode
dependencies: []
priority: high
ordinal: 68000
---
## Description

View File

@@ -4,12 +4,13 @@ title: Allow trailing commas in JSONC config parsing
status: Done
assignee: []
created_date: '2026-02-18 10:13'
updated_date: '2026-02-18 10:13'
updated_date: '2026-02-19 23:18'
labels:
- config
- jsonc
dependencies: []
priority: medium
ordinal: 67000
---
## Description

View File

@@ -5,13 +5,14 @@ status: Done
assignee:
- codex-main
created_date: '2026-02-18 11:35'
updated_date: '2026-02-19 08:27'
updated_date: '2026-02-19 23:18'
labels:
- config
- validation
- safety
dependencies: []
priority: high
ordinal: 65000
---
## Description

View File

@@ -5,13 +5,14 @@ status: Done
assignee:
- codex-main
created_date: '2026-02-18 11:35'
updated_date: '2026-02-19 09:05'
updated_date: '2026-02-19 23:18'
labels:
- config
- launcher
- consistency
dependencies: []
priority: high
ordinal: 63000
---
## Description

View File

@@ -5,13 +5,14 @@ status: Done
assignee:
- codex-main
created_date: '2026-02-19 08:38'
updated_date: '2026-02-19 08:40'
updated_date: '2026-02-19 23:18'
labels:
- config
- anki
- cleanup
dependencies: []
priority: medium
ordinal: 64000
---
## Description

View File

@@ -0,0 +1,56 @@
---
id: TASK-85
title: Refactor large files for maintainability and readability
status: In Progress
assignee: []
created_date: '2026-02-19 09:46'
updated_date: '2026-02-19 10:01'
labels:
- architecture
- refactor
- maintainability
dependencies: []
priority: medium
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Several core files are oversized and high-coupling (`src/main.ts`, `src/anki-integration.ts`, `src/config/service.ts`, `src/core/services/immersion-tracker-service.ts`). This task tracks phased, behavior-preserving decomposition plus guardrails and generated-launcher workflow cleanup.
<!-- SECTION:DESCRIPTION:END -->
## Suggestions
<!-- SECTION:SUGGESTIONS:BEGIN -->
- Use seam tests before each extraction.
- Keep `src/main.ts` + `src/anki-integration.ts` as thin composition/coordinator layers.
- Formalize `subminer` as generated artifact only.
<!-- SECTION:SUGGESTIONS:END -->
## Action Steps
<!-- SECTION:PLAN:BEGIN -->
1. Add file-budget guardrails and baseline report.
2. Split `src/main.ts` into runtime domain modules.
3. Split `src/anki-integration.ts` into focused collaborators.
4. Split `src/config/service.ts` by load/migrate/validate/warn phases.
5. Split immersion tracker service by state, persistence, sync responsibilities.
6. Clarify generated launcher artifact workflow and docs.
7. Run full build/test gate and publish maintainability report.
<!-- SECTION:PLAN:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [ ] #1 `src/main.ts` reduced to orchestration-focused module with extracted runtime domains
- [ ] #2 `src/anki-integration.ts` reduced to facade with helper collaborators
- [ ] #3 Config and immersion tracker services decomposed without behavior regressions
- [ ] #4 `subminer` generated artifact ownership/workflow documented and enforced
- [ ] #5 Full build + config/core tests pass after refactor
<!-- AC:END -->
## Definition of Done
<!-- DOD:BEGIN -->
- [ ] #1 Plan at `docs/plans/2026-02-19-repo-maintainability-refactor-plan.md` executed or decomposed into child tasks
- [ ] #2 Regression coverage added for extracted seams
- [ ] #3 Docs updated for architecture and contributor workflow changes
<!-- DOD:END -->

View File

@@ -0,0 +1,38 @@
---
id: TASK-86
title: Include config validation issue details in user notifications
status: Done
assignee: []
created_date: '2026-02-19 17:24'
updated_date: '2026-02-19 23:18'
labels: []
dependencies: []
priority: medium
ordinal: 62000
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
When config validation finds non-fatal issues, users should see concise per-issue details in notification body (not only issue count) so they can fix config quickly without checking logs.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 Startup notification body includes per-issue details (path + message) for config validation warnings.
- [x] #2 Hot-reload validation warning notifications include per-issue details in notification body.
- [x] #3 Notification text remains concise and does not exceed practical desktop notification limits.
- [x] #4 Automated tests cover notification body formatting with detailed issues.
<!-- AC:END -->
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
Added `buildConfigWarningNotificationBody` to format concise multi-line warning details (path+message, line limit + overflow count). Startup warnings now use this formatter for desktop notification body. Config hot-reload runtime now emits non-fatal validation warnings via `onValidationWarnings(configPath, warnings)` and main process surfaces them through desktop notifications. Added tests for formatter output, startup notification body content, and hot-reload warning callback behavior.
<!-- SECTION:NOTES:END -->
## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Config validation notifications now include concrete issue details in the notification body instead of only a count. Startup and hot-reload warning paths both surface per-issue `path: message` lines with concise truncation safeguards. Added regression tests covering formatter output and both notification paths.
<!-- SECTION:FINAL_SUMMARY:END -->

View File

@@ -0,0 +1,37 @@
---
id: TASK-87
title: Fix plugin --start flow so tokenization/frequency/N+1 initialize correctly
status: Done
assignee: []
created_date: '2026-02-19 19:05'
updated_date: '2026-02-19 23:18'
labels: []
dependencies: []
priority: medium
ordinal: 69000
---
## Description
<!-- SECTION:DESCRIPTION:BEGIN -->
Plugin startup flow (`--texthooker` then `--start`) can miss tokenization initialization, which makes frequency highlighting and N+1 appear broken even when dictionaries/config are correct. Ensure `--start` initializes overlay runtime when needed, including second-instance handoff mode.
<!-- SECTION:DESCRIPTION:END -->
## Acceptance Criteria
<!-- AC:BEGIN -->
- [x] #1 `--start` initializes overlay runtime when runtime is not yet initialized.
- [x] #2 `second-instance --start` is ignored only when overlay runtime is already initialized.
- [x] #3 Regression tests cover both `--start` behaviors and pass.
<!-- AC:END -->
## Implementation Notes
<!-- SECTION:NOTES:BEGIN -->
Root cause: subtitle tokenization path in `src/main.ts` only runs when overlay windows exist; command runtime did not initialize overlay runtime for `--start`, especially visible in plugin handoff (`--texthooker` -> `--start`). Updated `src/core/services/cli-command.ts` to initialize overlay runtime for `--start`, and narrowed second-instance ignore behavior to already-initialized runtime only. Added regression tests in `src/core/services/cli-command.test.ts`.
<!-- SECTION:NOTES:END -->
## Final Summary
<!-- SECTION:FINAL_SUMMARY:BEGIN -->
Fixed plugin/start regression by ensuring `--start` initializes overlay runtime when needed and no longer gets dropped in second-instance handoff before runtime init. Added/updated CLI command tests; targeted suite passes.
<!-- SECTION:FINAL_SUMMARY:END -->