From d68c359124e609bcf010f3c2fbc2e6d55d91e926 Mon Sep 17 00:00:00 2001 From: sudacode Date: Sun, 29 Mar 2026 15:31:59 -0700 Subject: [PATCH] fix: finalize v0.10.0 release prep --- CHANGELOG.md | 2 + ...lay-toggle-getting-immediately-restored.md | 69 ++++++++++++++++++ ...-while-overlay-subtitle-sidebar-is-open.md | 72 +++++++++++++++++++ changes/247-pr-36-ci-fix.md | 6 -- docs-site/changelog.md | 2 + src/renderer/handlers/keyboard.test.ts | 20 ++++++ 6 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 backlog/tasks/task-248 - Fix-macOS-visible-overlay-toggle-getting-immediately-restored.md create mode 100644 backlog/tasks/task-250 - Restore-macOS-mpv-passthrough-while-overlay-subtitle-sidebar-is-open.md delete mode 100644 changes/247-pr-36-ci-fix.md diff --git a/CHANGELOG.md b/CHANGELOG.md index ca4f85c..873a18a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ ### Fixed - Stats: Fixed stats startup so the immersion tracker can run when `Bun.serve` is unavailable. - Stats: Stats server now falls back to a Node `http` listener in Electron/runtime paths that do not expose Bun. +- Overlay: Fixed the macOS visible-overlay toggle path so manual hides stay hidden and the plugin uses the explicit visible-overlay toggle command. +- Subtitle Sidebar: Restored macOS mpv passthrough while the overlay subtitle sidebar is open so clicks outside the sidebar can refocus mpv and keep native keybindings working. ### Internal - Release: Added a maintained source coverage lane that shards Bun coverage one test file at a time and merges LCOV output into `coverage/test-src/lcov.info`. diff --git a/backlog/tasks/task-248 - Fix-macOS-visible-overlay-toggle-getting-immediately-restored.md b/backlog/tasks/task-248 - Fix-macOS-visible-overlay-toggle-getting-immediately-restored.md new file mode 100644 index 0000000..1430d7a --- /dev/null +++ b/backlog/tasks/task-248 - Fix-macOS-visible-overlay-toggle-getting-immediately-restored.md @@ -0,0 +1,69 @@ +--- +id: TASK-248 +title: Fix macOS visible overlay toggle getting immediately restored +status: Done +assignee: [] +created_date: '2026-03-29 10:03' +updated_date: '2026-03-29 22:14' +labels: [] +dependencies: [] +references: + - /Users/sudacode/projects/japanese/SubMiner/plugin/subminer/process.lua + - /Users/sudacode/projects/japanese/SubMiner/plugin/subminer/ui.lua + - /Users/sudacode/projects/japanese/SubMiner/src/core/services/cli-command.ts + - >- + /Users/sudacode/projects/japanese/SubMiner/src/main/overlay-visibility-runtime.ts +--- + +## Description + + +Investigate and fix the visible overlay toggle path on macOS so the user can reliably hide the overlay after it has been shown. The current behavior can ignore the toggle or hide the overlay briefly before it is restored immediately. + + +## Acceptance Criteria + +- [x] #1 Pressing the visible-overlay toggle hides the overlay when it is currently shown on macOS. +- [x] #2 A manual hide is not immediately undone by startup or readiness flows. +- [x] #3 The mpv/plugin toggle path matches the intended visible-overlay toggle behavior. +- [x] #4 Regression tests cover the failing toggle path. + + +## Implementation Plan + + +1. Reproduce the toggle/re-show logic from code paths around mpv plugin control commands and auto-play readiness. +2. Add regression coverage for manual toggle-off staying hidden through readiness completion. +3. Patch the plugin/control path so manual visible-overlay toggles are not undone by readiness auto-show. +4. Run targeted tests, then the relevant verification lane. + + +## Implementation Notes + + +Root cause: the mpv plugin readiness callback (`subminer-autoplay-ready`) could re-issue `--show-visible-overlay` after a manual toggle/hide. Initial fix only suppressed the next readiness restore, but repeated readiness callbacks in the same media session could still re-show the overlay. The plugin toggle path also still used legacy `--toggle` instead of the explicit visible-overlay command. + +Implemented a session-scoped suppression flag in the Lua plugin so a manual hide/toggle during the pause-until-ready window blocks readiness auto-show for the rest of the current auto-start session, then resets on the next auto-start session. + +Added Lua regression coverage for both behaviors: manual toggle-off stays hidden through readiness completion, repeated readiness callbacks in the same session stay suppressed, and `subminer-toggle` emits `--toggle-visible-overlay` rather than legacy `--toggle`. + +Follow-up investigation found a second issue in `src/core/services/cli-command.ts`: pure visible-overlay toggle commands still ran the MPV connect/start path (`connectMpvClient`) because `--toggle` and `--toggle-visible-overlay` were classified as start-like commands. That side effect could retrigger startup visibility work even after the plugin-side fix. + +Updated CLI command handling so only `--start` reconnects MPV. Pure toggle/show/hide overlay commands still initialize overlay runtime when needed, but they no longer restart/reconnect the MPV control path. + +Renderer/modal follow-ups: restored focused-overlay mpv y-chord proxy in `src/renderer/handlers/keyboard.ts`, added a modal-close guard in `src/main/overlay-runtime.ts` so modal teardown does not re-show a manually hidden overlay, and added a duplicate-toggle debounce in `src/main/runtime/overlay-visibility-actions.ts` to ignore near-simultaneous toggle requests inside the main process. + +2026-03-29: added regression for repeated subminer-autoplay-ready signals after manual y-t hide. Root cause: Lua plugin suppression only blocked the first ready-time restore, so later ready callbacks in the same media session could re-show the visible overlay. Updated plugin suppression to remain active for the full current auto-start session and reset on the next auto-start trigger. + +2026-03-29: live mpv log showed repeated `subminer-autoplay-ready` script messages from Electron during paused startup, each triggering plugin `--show-visible-overlay` and immediate re-show. Fixed `src/main/runtime/autoplay-ready-gate.ts` so plugin readiness is signaled once per media while paused retry loops only re-issue `pause=false` instead of re-signaling readiness. + +2026-03-29: Added window-level guard for stray visible-overlay re-show on macOS. `src/core/services/overlay-window.ts` now immediately re-hides the visible overlay window on `show` if overlay state is false, covering native/Electron re-show paths that bypass normal visibility actions. Regression: `src/core/services/overlay-window.test.ts`. Verified with full gate and rebuilt unsigned mac bundle. + +2026-03-29: added a blur-path guard for the visible overlay window. `src/core/services/overlay-window.ts` now skips topmost restacking when a visible-overlay blur fires after overlay state already flipped off, covering a macOS hide-in-flight path that could immediately reassert the window. Regression coverage added in `src/core/services/overlay-window.test.ts`; verified with targeted overlay tests, full gate, and rebuilt unsigned mac bundle. + + +## Final Summary + + +Confirmed with user that macOS `y-t` now works. Cleaned the patch set down to the remaining justified fixes: explicit visible-overlay plugin toggle/suppression, pure-toggle CLI no longer reconnects MPV, autoplay-ready signaling only fires once per media, and the final visible-overlay blur guard that stops macOS restacking after a manual hide. Full gate passed again before commit `c939c580` (`fix: stabilize macOS visible overlay toggle`). + diff --git a/backlog/tasks/task-250 - Restore-macOS-mpv-passthrough-while-overlay-subtitle-sidebar-is-open.md b/backlog/tasks/task-250 - Restore-macOS-mpv-passthrough-while-overlay-subtitle-sidebar-is-open.md new file mode 100644 index 0000000..7977bdd --- /dev/null +++ b/backlog/tasks/task-250 - Restore-macOS-mpv-passthrough-while-overlay-subtitle-sidebar-is-open.md @@ -0,0 +1,72 @@ +--- +id: TASK-250 +title: Restore macOS mpv passthrough while overlay subtitle sidebar is open +status: Done +assignee: + - '@codex' +created_date: '2026-03-29 10:10' +updated_date: '2026-03-29 10:23' +labels: + - bug + - macos + - subtitle-sidebar + - overlay + - mpv +dependencies: [] +references: + - >- + /Users/sudacode/projects/japanese/SubMiner/src/renderer/overlay-mouse-ignore.ts + - >- + /Users/sudacode/projects/japanese/SubMiner/src/renderer/modals/subtitle-sidebar.ts + - /Users/sudacode/projects/japanese/SubMiner/src/renderer/handlers/keyboard.ts + - >- + /Users/sudacode/projects/japanese/SubMiner/src/renderer/modals/subtitle-sidebar.test.ts + - >- + /Users/sudacode/projects/japanese/SubMiner/src/renderer/overlay-mouse-ignore.test.ts +priority: high +--- + +## Description + + +When the overlay-layout subtitle sidebar is open on macOS, users should still be able to click through outside the sidebar and return keyboard focus to mpv so native mpv keybindings continue to work. The sidebar should stay interactive when hovered or focused, but it must not make the whole visible overlay behave like a blocking modal. + + +## Acceptance Criteria + +- [x] #1 Opening the overlay-layout subtitle sidebar does not keep the entire visible overlay mouse-interactive outside sidebar hover or focus. +- [x] #2 With the subtitle sidebar open, clicking outside the sidebar can refocus mpv so native mpv keybindings continue to work. +- [x] #3 Focused regression coverage exists for overlay-layout sidebar passthrough behavior on mouse-ignore state changes. + + +## Implementation Plan + + +1. Add renderer regression coverage for overlay-layout subtitle sidebar passthrough so open-but-unhovered sidebar no longer holds global mouse interaction. +2. Update overlay mouse-ignore gating to keep the subtitle sidebar interactive only while hovered or otherwise actively interacting, instead of treating overlay layout as a blocking modal. +3. Run focused renderer tests for subtitle sidebar and mouse-ignore behavior, then update task notes/criteria with the verified outcome. + + +## Implementation Notes + + +Confirmed the regression only affects the default overlay-layout subtitle sidebar: open sidebar state was treated as a blocking overlay modal, which prevented click-through outside the sidebar and stranded native mpv keybindings until focus was manually recovered. + +Added a failing regression in src/renderer/modals/subtitle-sidebar.test.ts for overlay-layout passthrough before changing the gate. + +Verification: bun test src/renderer/modals/subtitle-sidebar.test.ts src/renderer/overlay-mouse-ignore.test.ts; bun run typecheck + +User reported the first renderer-only fix did not resolve the macOS issue in practice. Reopening investigation to trace visible-overlay window focus and hit-testing outside the renderer mouse-ignore gate. + +Follow-up root cause: sidebar hover handlers were attached to the full-screen `.subtitle-sidebar-modal` shell instead of the actual sidebar panel. On the transparent visible overlay that shell spans the viewport, so sidebar-active state could persist outside the panel and keep the overlay interactive longer than intended. + +Updated the sidebar modal to track hover/focus on `subtitleSidebarContent` and derive sidebar interaction state from panel hover or focus-within before recomputing mouse passthrough. + +Verification refresh: bun test src/renderer/modals/subtitle-sidebar.test.ts src/renderer/overlay-mouse-ignore.test.ts; bun run typecheck + + +## Final Summary + + +Restored overlay subtitle sidebar passthrough in two layers. First, the visible overlay mouse-ignore gate no longer treats the subtitle sidebar as a global blocking modal. Second, the sidebar panel now tracks interaction on the real sidebar content instead of the full-screen modal shell, and keeps itself active only while the panel is hovered or focused. Added regressions for overlay-layout passthrough and focus-within behavior. Verification: `bun test src/renderer/modals/subtitle-sidebar.test.ts src/renderer/overlay-mouse-ignore.test.ts` and `bun run typecheck`. + diff --git a/changes/247-pr-36-ci-fix.md b/changes/247-pr-36-ci-fix.md deleted file mode 100644 index 74397c8..0000000 --- a/changes/247-pr-36-ci-fix.md +++ /dev/null @@ -1,6 +0,0 @@ -type: changed -area: core - -- Refactored startup, query, and workflow code into focused modules. -- Added repo-local workflow plugin shims and updated internal docs and verification helpers. -- Expanded tests around launcher, runtime, stats, and immersion-tracker behavior. diff --git a/docs-site/changelog.md b/docs-site/changelog.md index 5c3c7d2..750d53f 100644 --- a/docs-site/changelog.md +++ b/docs-site/changelog.md @@ -4,6 +4,8 @@ - Fixed stats startup so the immersion tracker can run when `Bun.serve` is unavailable. - Added a Node `http` fallback for Electron/runtime paths that do not expose Bun, so stats keeps working there too. - Updated Discord Rich Presence to the maintained `@xhayper/discord-rpc` wrapper. +- Fixed the macOS visible-overlay toggle path so manual hides stay hidden and the plugin uses the explicit visible-overlay toggle command. +- Restored macOS mpv passthrough while the overlay subtitle sidebar is open so clicks outside the sidebar can refocus mpv and keep native keybindings working. ## v0.9.3 (2026-03-25) - Moved YouTube primary subtitle language defaults to `youtube.primarySubLanguages`. diff --git a/src/renderer/handlers/keyboard.test.ts b/src/renderer/handlers/keyboard.test.ts index c4ba4c8..a197098 100644 --- a/src/renderer/handlers/keyboard.test.ts +++ b/src/renderer/handlers/keyboard.test.ts @@ -518,6 +518,26 @@ test('popup-visible mpv keybindings still fire for bound keys', async () => { } }); +test('visible-layer y-t dispatches mpv plugin toggle while overlay owns focus', async () => { + const { handlers, testGlobals } = createKeyboardHandlerHarness(); + + try { + await handlers.setupMpvInputForwarding(); + + testGlobals.dispatchKeydown({ key: 'y', code: 'KeyY' }); + testGlobals.dispatchKeydown({ key: 't', code: 'KeyT' }); + + assert.equal( + testGlobals.mpvCommands.some( + (command) => command[0] === 'script-message' && command[1] === 'subminer-toggle', + ), + true, + ); + } finally { + testGlobals.restore(); + } +}); + test('keyboard mode: controller helpers dispatch popup audio play/cycle and scroll bridge commands', async () => { const { ctx, handlers, testGlobals } = createKeyboardHandlerHarness();