Skip to content

fix(playback): input guards, media-time replays, auto-pause, loop rebinding, hover-pause ownership, timeline (#108 #111 #121 #127 #128 #129 #130 #131 #137 #142 #150 #151 #152 #155) - #166

Merged
moikdev merged 6 commits into
masterfrom
fix/batch2-playback
Oct 4, 2026

Conversation

@moikdev

@moikdev moikdev commented Oct 4, 2026

Copy link
Copy Markdown
Owner

Stacked on #165 (base fix/batch2-anki). The chain is #163 → #164 → #165 → this PR. They all touch the subtitle/translation model wiring (src/models/subs/init.ts), so the independent branches conflicted. Merge in that order.

Playback, input and timeline fixes from the 30 Sep / 2 Oct audits.

Fixes

Input

Replay / auto-pause

Timeline

Visible changes

Only the subtitle timeline changes: a cue spanning the whole 30 s window now draws a full-width marker, and markers no longer extend past the bar's edges. I could not capture a screenshot, because the in-player timeline isn't rendered by the repo's fixture harness and needs a live player.

Verification

  • pnpm exec tsc --noEmit: clean. pnpm lint: 0 errors.
  • pnpm test:unit (full stack): 48 files and 430 tests pass. New tests:
    • inputTargets.test.ts, inputHandlers.test.ts: real handlers with DOM doubles.
    • slowReplay.test.ts, replayVideoClip.test.ts: fake media clock.
    • cuePlayback.test.ts, playbackWiring.test.ts: the real video/subtitle Effector graph.
    • cueWindow.test.ts: randomized comparison against a full scan, overlap policy, click geometry.
    • getCurrentSubs.test.ts, videoClock.test.ts.
  • pnpm build + pnpm test (Chromium regressions): all PASS, 0 runtime errors. A new browser check covers [P2] Leaving subtitles resumes playback after a newer manual pause #142: hover pauses, leaving resumes, and a manual play+pause made over the line survives leaving it. I confirmed that this check fails without the fix.
  • I ran the audit evidence tests for [P2] Old slow-replay timers override newer speed choices and cut subsequent replay short #108 and [P2] Disabled extension still intercepts keyboard and mouse playback controls #111 (slow-replay, disabled-input, which assert the buggy behaviour). The disabled-input cases no longer reproduce. The slow-replay doubles have no addEventListener and can't drive the new media-time code; slowReplay.test.ts and playbackWiring.test.ts cover those scenarios instead.

🤖 Generated with Claude Code

moikdev and others added 5 commits October 4, 2026 16:53
…, plaintext-only editors and links (#111, #127, #128, #137)

- #111: keyboard shortcuts and mouse bindings do nothing while the
  extension is disabled, so the site gets its keys and buttons back.
- #127: toggle shortcuts (D, B, T, R, L, \, H) act once per press and
  ignore OS auto-repeat; the speed steps (, and .) keep repeating.
- #128: editable targets use isContentEditable / the contenteditable
  inheritance rules (plaintext-only included) and the composed path, so
  typing in any editor, even inside a shadow root, is never intercepted.
- #137: an assigned middle/side-button action leaves links, dialogs and
  menus layered over the player to the browser.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…ons (#108, #129, #130, #131, #142)

- #108: slow replay ends in media time (watchMediaWindow) and restores the
  current speed setting, not the one captured at start; a newer slow
  replay, a speed change, a new video or disabling the extension cancels
  it, so an old timer can no longer override a newer speed or cut a later
  replay short.
- #129: replay pauses only when playback runs through the cue end; a seek
  forward past it (or backward) hands the video back without pausing the
  new scene. Any explicit seek (transcript, timeline, history) cancels it.
- #130: when captions change, an active loop follows the same line (same
  id and text, e.g. a delay resync) or ends; it never keeps seeking to a
  window from the old captions.
- #131: auto-pause also pauses when sparse time updates skip the 250 ms
  window, as long as normal playback crossed the cue end; seeks never
  pause, and resuming does not pause at the same line again.
- #142: the hover pause is dropped once playback starts by any other
  means, so leaving the subtitles never resumes a newer manual pause; it
  is also reset when the video element is replaced. Disabling the
  extension stops replays and loops it started (#111).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…es, click relative to the bar (#150, #151, #152)

- #151: the timeline indexes the track once and finds visible cues with a
  binary search; a frame whose time and width are unchanged (paused
  video) does no work and publishes no state.
- #152: visibility is interval overlap (end > from && start < to), so a
  cue spanning the whole window shows; markers are clipped to the window.
- #150: a click maps clientX through the timeline's own rectangle
  (clamped) instead of the clicked element's offsetX.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…active at a boundary (#121)

getCurrentSubs (primary) and the secondary-track selection now use
start <= t < end and ignore zero-length cues; genuine overlaps stay.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…f keeping both (#155)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@moikdev

moikdev commented Oct 4, 2026 •

Copy link
Copy Markdown
Owner Author

Hermes review failed

Hermes could not produce a code-review verdict for this head SHA.

Engine: agy/gemini-3.8-flash-high
Review mode: full
Head: de657a260b7eff538e356ec150acc425d1262d88
Generated: 2026-10-04T11:31:22+00:00
Failure phase: engine

Safe summary:

agy failed (3)
STDOUT:
STDERR:
error: Individual quota reached. Please upgrade your subscription to increase your limits. Resets in 91h32m44s.
AGY_ERROR: {"short_error":"RESOURCE_EXHAUSTED (code 429): Individual quota reached. Please upgrade your subscription to increase your limits. Resets in 91h32m44s.","status":"RESOURCE_EXHAUSTED","error_code":429,"code_kind":"http","retryable":true,"error_id":"c5e77849-fbff-4d65-ba98-eda2dfdea9cf-1"}

Local logs: /home/moik/.hermes/logs/review-bot/himotoki-sub.log

@moikdev

moikdev commented Oct 4, 2026

Copy link
Copy Markdown
Owner Author

/hermes review

@moikdev
moikdev changed the base branch from fix/batch2-anki to master October 4, 2026 11:29
@moikdev
moikdev merged commit 2c9c2df into master Oct 4, 2026
2 of 3 checks passed
@moikdev
moikdev deleted the fix/batch2-playback branch October 4, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment