mirror of
https://github.com/block/buzz.git
synced 2026-10-29 21:41:33 +00:00
**Problem:** Playing a video in a Buzz chat made Buzz the macOS "Now Playing" app, and nothing ever gave that status back. WKWebView registers the session on the first audible `<video>` and keeps it until the element itself is torn down — unmounting the row only detaches the element, which holds the claim until it happens to be garbage collected. From then on the hardware play/pause key (and AirPods taps) reached Buzz instead of Music, sometimes audibly resuming a video the user had scrolled past. **Solution:** `useReleasingVideoRef` is a ref callback that pauses, detaches the source, and clears the Now Playing metadata when React drops a `<video>`. It is wired into the inline player, the review overlay, and the composer attachment preview. Detaching the source is what makes WebKit destroy the media session immediately instead of at GC time; holding the keys while a video is on screen stays unchanged, since that is how resume is supposed to work. Teardown cannot live in an effect cleanup: React nulls host refs during the mutation phase, so on unmount the existing cleanup only ever saw a null ref and the element escaped untouched — the inline position save moves into the ref cleanup for the same reason. StrictMode re-attaches a ref without re-applying props, so the release remembers the source it detached and restores it, or every video would render empty in development. Players now also publish `MediaMetadata` (filename/title plus channel) while playing so Control Center shows the video instead of a bare entry, and clear it on release. Clearing is scoped to the element that claimed the session, so an off-screen timeline row unmounting cannot wipe the metadata of the review overlay that is actually playing. The playback speed control moves to `VideoPlaybackSpeedControl.tsx` unchanged, keeping `VideoPlayer.tsx` under the file-size ratchet. ## Validation - `pnpm check`, `pnpm typecheck`, `pnpm test` (4958 desktop unit tests, including new `mediaSession` coverage that fails without the release and without the StrictMode restore) - `pnpm test:e2e:smoke` — 1050 passed, 5 failed. Two (`huddle-transcription` agent voices, `message-feedback-snapshots` profile hover) reproduce with these changes stashed; the other three pass on re-run with the changes applied. - Not covered: MediaRemote routing itself is invisible to both Playwright and jsdom, so the Control Center hand-back still needs a manual pass on macOS (play Music → play a chat video → switch channels → confirm the key controls Music again), including the review overlay and AirPods, plus the note's open question about notification sounds. Signed-off-by: Matt Toohey <contact@matttoohey.com>
Buzz
Desktop chat shell with:
- Tauri + React + TypeScript + Vite
- Tailwind CSS
- shadcn/ui-ready shared components
- Biome (lint/format/check)
- Feature-driven frontend structure
Scripts
pnpm dev- run the web frontendpnpm tauri dev- run the desktop apppnpm build- typecheck and build frontendpnpm typecheck- TypeScript checkspnpm lint- Biome lintpnpm format- Biome format (write)pnpm check- Biome check
Structure
src/shared- reusable app-wide code (ui,lib,styles)src/features- feature modules (vertical slices)src/app- top-level app composition