The compare page predates the r2 upload provider: r2 versions fell
through to a URL-safety check that throws on app-relative upload URLs,
so their panels rendered nothing and registered no player — the shared
controls drove an empty list and nothing played.
- add an R2Panel mapping a plain video element over the app upload
route to the shared adapter, using the same playback-url resolution
as the main video page
- make play/pause state detection work without the YouTube API loaded
(numeric fallback), so bunny/r2-only comparisons can pause
- re-sync panels that drift more than 350ms from the source player
once per second so playback stays aligned, not just starts aligned
Verified against the running app: both versions play in lockstep
(0.000s measured drift), pause together, and seek together.
Co-Authored-By: Claude Fable 5 <[email protected]>
Comment content was stored with newlines intact but rendered inside <p>
elements with default white-space, collapsing line breaks into single
spaces. Add whitespace-pre-wrap (and break-words) to the comment/reply
render wrappers in the comments pane and the compare-versions view.
Replace per-frame React state updates with ref-based tracking and direct DOM
mutation for the progress bar, playhead, and timecode. React state is now
throttled to ~4 commits/sec (~250ms), eliminating unnecessary re-renders on
every animation frame during playback.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>