Files
buzz/desktop
Matt Toohey 599723af42 fix(desktop): release video elements so macOS media keys go back to Music
**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>
2026-09-02 15:13:34 +10:00
..
…

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 frontend
  • pnpm tauri dev - run the desktop app
  • pnpm build - typecheck and build frontend
  • pnpm typecheck - TypeScript checks
  • pnpm lint - Biome lint
  • pnpm 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