feat(audio): persistent audio player across room navigation
Proposed changes
Playing an audio message attachment used to stop the moment you switched or closed the conversation, because the <audio> element lived inside the message component and was destroyed when the message list unmounted.
This PR makes audio playback persistent:
- A single shared
<audio>element is hoisted above the room layout into a newMediaPlayerProvider. Because it lives above the room, it survives navigation and message-list unmounting, so playback continues uninterrupted. - A "Now playing" card pinned to the bottom of the sidebar reflects the shared player — play/pause, seek, playback speed (1x / 1.5x / 2x), and a shortcut back to the originating conversation.
- In-message audio controls now drive the same shared element, so starting playback in a message and the sidebar card stay in sync.
- Signed-URL expiry recovery (previously in
useReloadOnError) is ported into the provider so the persistent element keeps recovering expired media URLs mid-playback.
Architecture
| Piece | Responsibility |
|---|---|
providers/MediaPlayerProvider | Owns the single hidden <audio> element + playback state (track, playing, currentTime, duration, playbackRate) and actions (play, toggle, seek, cyclePlaybackRate, close, isActive). |
components/AudioPlayer/AudioPlayerControls | Reusable play / seek / time / speed controls (with a compact mode for the sidebar). |
sidebar/sections/NowPlayingSection | The sidebar "Now playing" card, re-attaching to the shared player. |
AudioAttachment | Drives the shared player instead of a self-contained widget. |
Message metadata (rid, mid, sender) is threaded through the attachment chain so the card can show the sender and jump back to the conversation.
How to test
- Open a conversation containing an audio attachment and start playback.
- Switch to another room or close the conversation — playback continues.
- The "Now playing" card appears at the bottom of the sidebar; verify play/pause, seek, speed cycling, and the jump-back shortcut.
Further comments
UI follows the sidebar card placement. The provider is placement-agnostic, so a floating / footer / topbar dock could reuse the same context later.
Follow-up (TODO)
The in-message/card controls (apps/meteor/client/components/AudioPlayer/AudioPlayerControls.tsx) are a temporary local copy of a controlled component being upstreamed to Fuselage: RocketChat/fuselage#2052. Once that ships in @rocket.chat/fuselage, delete the local copy (and formatPlaybackTime) and import AudioPlayerControls from @rocket.chat/fuselage instead.
Task: ARCH-2202
Summary by CodeRabbit
-
New Features
- Added a persistent audio playback experience that continues across room navigation.
- Added a “Now playing” sidebar card with play/pause, seek, playback speed, and a shortcut back to the original conversation.
-
Bug Fixes
- Improved audio playback reliability when switching or closing conversations.
-
Documentation
- Added release notes entry for the new audio experience.