diff --git a/flutter_client/lib/player/now_playing_screen.dart b/flutter_client/lib/player/now_playing_screen.dart index ff518406..804c4ef3 100644 --- a/flutter_client/lib/player/now_playing_screen.dart +++ b/flutter_client/lib/player/now_playing_screen.dart @@ -113,20 +113,21 @@ class _NowPlayingScreenState extends ConsumerState { overflow: TextOverflow.ellipsis, ), ], - const SizedBox(height: 32), - _SeekRow(position: pos, duration: dur, fs: fs, ref: ref), - const SizedBox(height: 24), - _PrimaryControls( - fs: fs, - ref: ref, - isPlaying: isPlaying, - ), const SizedBox(height: 24), _SecondaryControls( fs: fs, actions: actions, shuffleOn: shuffleOn, repeatMode: repeatMode, + media: media, + ), + const SizedBox(height: 8), + _SeekRow(position: pos, duration: dur, fs: fs, ref: ref), + const SizedBox(height: 24), + _PrimaryControls( + fs: fs, + ref: ref, + isPlaying: isPlaying, ), const SizedBox(height: 24), ], @@ -219,48 +220,14 @@ class _TitleRow extends StatelessWidget { @override Widget build(BuildContext context) { - // Stack: title centered absolutely in the row; like + kebab pinned - // to the right edge. Padding on the title equals the actions' width - // so it stays optically centered without colliding with them. - return SizedBox( - height: 32, - child: Stack( - alignment: Alignment.center, - children: [ - Padding( - padding: const EdgeInsets.symmetric(horizontal: 64), - child: Text( - media.title, - style: TextStyle(color: fs.parchment, fontSize: 22), - maxLines: 1, - overflow: TextOverflow.ellipsis, - textAlign: TextAlign.center, - ), - ), - Positioned( - right: 0, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - LikeButton(kind: LikeKind.track, id: media.id, size: 22), - TrackActionsButton( - track: TrackRef( - id: media.id, - title: media.title, - albumId: (media.extras?['album_id'] as String?) ?? '', - albumTitle: media.album ?? '', - artistId: (media.extras?['artist_id'] as String?) ?? '', - artistName: media.artist ?? '', - durationSec: media.duration?.inSeconds ?? 0, - streamUrl: '', - ), - hideQueueActions: true, - ), - ], - ), - ), - ], - ), + // Title-only — like + kebab moved into _SecondaryControls above + // the seek bar so they share the same row as shuffle/repeat/queue. + return Text( + media.title, + style: TextStyle(color: fs.parchment, fontSize: 22), + maxLines: 1, + overflow: TextOverflow.ellipsis, + textAlign: TextAlign.center, ); } } @@ -365,17 +332,23 @@ class _PrimaryControls extends StatelessWidget { } } +/// Action row sitting just above the seek bar. Holds shuffle / repeat +/// / queue plus the like + kebab that used to live in the title row, +/// so the title can sit truly centered above and this row carries +/// every per-track action in one place. class _SecondaryControls extends StatelessWidget { const _SecondaryControls({ required this.fs, required this.actions, required this.shuffleOn, required this.repeatMode, + required this.media, }); final FabledSwordTheme fs; final PlayerActions actions; final bool shuffleOn; final AudioServiceRepeatMode repeatMode; + final MediaItem media; @override Widget build(BuildContext context) { @@ -411,6 +384,20 @@ class _SecondaryControls extends StatelessWidget { icon: Icon(Icons.queue_music, color: fs.ash), onPressed: () => GoRouter.of(context).push('/queue'), ), + LikeButton(kind: LikeKind.track, id: media.id, size: 22), + TrackActionsButton( + track: TrackRef( + id: media.id, + title: media.title, + albumId: (media.extras?['album_id'] as String?) ?? '', + albumTitle: media.album ?? '', + artistId: (media.extras?['artist_id'] as String?) ?? '', + artistName: media.artist ?? '', + durationSec: media.duration?.inSeconds ?? 0, + streamUrl: '', + ), + hideQueueActions: true, + ), ], ); }