Skip to content

feat: persistent audio mini-player docked above bottom nav#487

Merged
barrydeen merged 1 commit intomainfrom
feat/persistent-audio-player
Apr 23, 2026
Merged

feat: persistent audio mini-player docked above bottom nav#487
barrydeen merged 1 commit intomainfrom
feat/persistent-audio-player

Conversation

@barrydeen
Copy link
Copy Markdown
Owner

Summary

  • Replaces the basic inline audio widget with a global mini-player that persists across feed scrolling and tab navigation, with system notification / lock-screen transport controls via MediaSessionService.
  • Two-state dock: collapsed shows the author's avatar and display name with rewind-15 / play-pause / forward-15; swipe up to expand for a scrub slider, speed cycling (0.75→2.0x), and a close button. Swipe down to collapse.
  • Single ExoPlayer owned by AudioPlayerController; the inline tap-to-play widget now reflects global playback state and hands off to the controller. Starting audio pauses any active PiP video so they don't fight.

Architecture

  • AudioPlayerController — singleton with StateFlow<AudioPlaybackState> exposing play/togglePlayPause/seekTo/skipForward/skipBackward/cycleSpeed/close.
  • AudioMediaSession — parallel to the existing VideoMediaSession; both register with the renamed WispPlaybackService (was VideoPlaybackService) which keeps the service alive while either session is active.
  • FloatingAudioPlayer mounts in the root Scaffold's bottomBar slot above WispBottomBar so content naturally reserves space rather than being covered.
  • RichContent gets an optional authorPubkey; PostCard passes event.pubkey so AudioTrack carries the kind-0 name + avatar into the dock.

Test plan

  • Play an mp3 in the feed — inline player starts audio and the mini-player slides up above the bottom nav.
  • Scroll the feed / switch tabs — player persists, audio uninterrupted, inline widget in the originating note mirrors playing state.
  • Collapsed state shows author avatar + name + transport controls only (no slider, speed, or close).
  • Swipe up to expand reveals slider / speed chip / close; swipe down collapses. Tap row also toggles.
  • Scrub slider seeks; ±15 s buttons skip; speed chip cycles 0.75 → 1 → 1.25 → 1.5 → 2.
  • Notification shade + lock-screen show title/artist/art with pause/resume.
  • Starting a video while audio is playing pauses audio to avoid double-play.
  • Close (×) kills the player and dismisses the notification.
  • Swipe app from recents while paused → service stops. While playing → notification persists until closed.

Replaces the basic inline audio widget with a global mini-player that persists
across feed scrolling and tab navigation. Playback continues with system
notification / lock-screen transport controls via MediaSessionService.

The dock has two states: a collapsed row showing the author's avatar and name
with rewind-15 / play-pause / forward-15; swipe up to expand for a scrub slider,
speed cycling, and close. Single ExoPlayer is owned by AudioPlayerController
and shared with the inline tap-to-play widget, which now reflects global
playback state.
@barrydeen barrydeen merged commit 5853db2 into main Apr 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant