fix(desktop): name the composer video preview in Now Playing

Review follow-up to 3d94c0e. The composer attachment preview released the
media session on unmount but never claimed it on play, so while a queued
video played, Control Center showed either a bare Buzz entry or — since
`navigator.mediaSession.metadata` is page-global — the stale title of a
timeline video that had claimed the session earlier.

`onPlay` now claims with the attachment's filename (falling back to the
short-hash label the thumbnail already uses), and `onPause`/`onEnded` mark
the session paused, matching the inline player and the review overlay.
There is no channel subtitle: the attachment has not been posted yet, so
there is nothing honest to put there. The owner-scoped release added in
3d94c0e already covers teardown, so this only closes the metadata gap.

- `pnpm check`, `pnpm typecheck`, `pnpm test` (4958 desktop unit tests, all
  passing; the two `biome` warnings are pre-existing, in an unrelated E2E
  spec)
- Not covered: same gap as the other two surfaces — the claim wiring is JSX
  event handlers over the already-tested `mediaSession` module, and this
  package has no precedent for rendering a motion + Radix component tree in
  a unit test. Control Center metadata is invisible to Playwright and jsdom,
  so the outstanding manual macOS pass now also wants: attach a video, open
  its composer preview, play it, and confirm Control Center shows that
  filename rather than a previously-played timeline video.

Signed-off-by: Matt Toohey <contact@matttoohey.com>
This commit is contained in:
Matt Toohey
2026-08-17 21:24:15 +10:00
parent 599723af42
commit a0fa8a0133

View File

@@ -30,7 +30,12 @@ import {
AttachmentMedia,
AttachmentTitle,
} from "@/shared/ui/attachment";
import { useReleasingVideoRef } from "@/shared/ui/mediaSession";
import {
claimMediaSession,
markMediaSessionPaused,
type NowPlayingMetadata,
useReleasingVideoRef,
} from "@/shared/ui/mediaSession";
import { MODAL_BACKDROP_BLUR_CLASS } from "@/shared/ui/modalBackdrop";
import { Progress } from "@/shared/ui/progress";
import { Toggle } from "@/shared/ui/toggle";
@@ -293,6 +298,16 @@ const MediaAttachmentItem = React.forwardRef<
? rewriteRelayUrl(attachment.thumb)
: undefined;
// `navigator.mediaSession.metadata` is page-global, so a preview that played
// without claiming would leave Control Center showing whatever timeline video
// published last. No channel subtitle here — the attachment isn't posted yet.
const mediaSessionMetadata = React.useMemo<NowPlayingMetadata>(
() => ({
title: attachment.filename?.trim() || mediaLabel,
}),
[attachment.filename, mediaLabel],
);
// Only Buzz-hosted uploads have a content hash. URL-only provider media
// must remain externally hosted instead of being copied into storage by the
// image editor's save path.
@@ -442,6 +457,15 @@ const MediaAttachmentItem = React.forwardRef<
"relative max-h-[90vh] max-w-[90vw] rounded-lg",
isSpoilered && "blur-2xl brightness-75",
)}
onEnded={(event) =>
markMediaSessionPaused(event.currentTarget)
}
onPause={(event) =>
markMediaSessionPaused(event.currentTarget)
}
onPlay={(event) =>
claimMediaSession(event.currentTarget, mediaSessionMetadata)
}
/>
) : (
<img