diff --git a/lib/app/app_theme.dart b/lib/app/app_theme.dart index 78962ae..834ed70 100644 --- a/lib/app/app_theme.dart +++ b/lib/app/app_theme.dart @@ -40,6 +40,7 @@ class AppTheme { ), sliderTheme: const SliderThemeData( thumbShape: LineThumbShape(), + trackHeight: 8, ), appBarTheme: AppBarTheme( systemOverlayStyle: systemOverlayStyle(theme), diff --git a/lib/app/player/components/artwork.dart b/lib/app/player/components/artwork.dart index b64cc9b..1c15650 100644 --- a/lib/app/player/components/artwork.dart +++ b/lib/app/player/components/artwork.dart @@ -11,7 +11,7 @@ class Artwork extends StatelessWidget { @override Widget build(BuildContext context) { return Padding( - padding: const EdgeInsets.all(24.0), + padding: const EdgeInsets.symmetric(vertical: 24, horizontal: 48), child: ValueListenableBuilder( valueListenable: context.read().nowPlaying, builder: (context, media, child) => StreamBuilder( diff --git a/lib/app/player/components/seekbar.dart b/lib/app/player/components/seekbar.dart index 2fa5974..a85dd37 100644 --- a/lib/app/player/components/seekbar.dart +++ b/lib/app/player/components/seekbar.dart @@ -64,7 +64,7 @@ class LineThumbShape extends SliderComponentShape { final Size thumbSize; const LineThumbShape({ - this.thumbSize = const Size(8, 32), + this.thumbSize = const Size(6, 36), }); @override diff --git a/lib/app/player/large_player_sheet.dart b/lib/app/player/large_player_sheet.dart index 994cf4e..83c3519 100644 --- a/lib/app/player/large_player_sheet.dart +++ b/lib/app/player/large_player_sheet.dart @@ -91,147 +91,156 @@ class _LargePlayerSheetState extends State ], ), ), - ValueListenableBuilder( - valueListenable: context.read().nowPlaying, - builder: (context, media, _) { - return Card.outlined( - elevation: 0, - margin: const EdgeInsets.symmetric(horizontal: 10), - child: ListTile( - onTap: showPlayerQueue, - title: Text( - media.title, + seekBarView(context), + const SizedBox(height: 12), + actionsView(context), + const SizedBox(height: 36), + queueView(context), + const SizedBox(height: 12), + ], + ), + ); + } + + Widget queueView(BuildContext context) { + return ValueListenableBuilder( + valueListenable: context.read().nowPlaying, + builder: (context, media, _) { + return Card.outlined( + elevation: 0, + margin: const EdgeInsets.symmetric(horizontal: 10), + child: ListTile( + onTap: showPlayerQueue, + title: Text( + media.title, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + subtitle: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + media.author, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Selector>( + selector: (_, provider) => provider.playlist, + builder: (context, playlist, _) => Text( + "${playlist.indexOf(media) + 1}/${playlist.length}" + " \u2022 ${playlistInfo(context)}", maxLines: 1, overflow: TextOverflow.ellipsis, ), - subtitle: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisSize: MainAxisSize.min, - children: [ - Text( - media.author, - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - Selector>( - selector: (_, provider) => provider.playlist, - builder: (context, playlist, _) => Text( - "${playlist.indexOf(media) + 1}/${playlist.length}" - " \u2022 ${playlistInfo(context)}", - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ) - ], - ), - leading: const Icon(Icons.playlist_play_rounded), - trailing: const Icon(Icons.keyboard_arrow_right_rounded), - ), - ); - }, - ), - const SizedBox(height: 16), - // SeekBar - ValueListenableBuilder( - valueListenable: context.read().nowPlaying, - builder: (context, media, _) => StreamBuilder( - stream: context.read().player.positionStream, - builder: (context, currentPosition) => Padding( - padding: const EdgeInsets.symmetric( - horizontal: 12, - vertical: 8, - ), - child: Row( - children: [ - SizedBox( - width: currentPosition.data?.inHours == 0 ? 48 : 72, - child: Text(currentPosition.data.formatHHMM()), - ), - Expanded( - child: Selector( - selector: (_, provider) => provider.buffering, - builder: (context, buffering, child) { - if (media.duration == null) return const SizedBox(); - final player = context.read().player; - return SeekBar( - buffering: buffering, - duration: media.duration!, - position: currentPosition.data ?? Duration.zero, - bufferedPosition: player.bufferedPosition, - onChangeEnd: (v) => player.seek(v), - ); - }, - ), - ), - SizedBox( - width: media.duration?.inHours == 0 ? 48 : 72, - child: Text(media.duration.formatHHMM()), - ), - ], - ), - ), + ) + ], ), + leading: const Icon(Icons.playlist_play_rounded), + trailing: const Icon(Icons.keyboard_arrow_right_rounded), ), + ); + }, + ); + } - const SizedBox(height: 16), - - StreamBuilder( - stream: context.read().player.playerStateStream, - initialData: context.read().player.playerState, - builder: (context, playerState) => Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Selector>( - selector: (_, provider) => provider.playlist, - child: const Icon(Icons.skip_previous_rounded), - builder: (_, __, icon) => IconButton( - onPressed: context.read().hasPrevious - ? context.read().previousTrack - : null, - icon: icon!, - ), - ), - const SizedBox(width: 30), - Selector( + Widget seekBarView(BuildContext context) { + return ValueListenableBuilder( + valueListenable: context.read().nowPlaying, + builder: (context, media, _) => StreamBuilder( + stream: context.read().player.positionStream, + builder: (context, currentPosition) => Padding( + padding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 8, + ), + child: Row( + children: [ + SizedBox( + width: currentPosition.data?.inHours == 0 ? 48 : 72, + child: Text(currentPosition.data.formatHHMM()), + ), + Expanded( + child: Selector( selector: (_, provider) => provider.buffering, - builder: (_, loading, child) => FloatingActionButton.small( - elevation: 0, - highlightElevation: 1, - hoverElevation: 1, - focusElevation: 1, - onPressed: loading - ? null - : switch (playerState.requireData.playing) { - true => context.read().player.pause, - false => context.read().player.play, - }, - child: loading - ? child - : switch (playerState.requireData.playing) { - true => const Icon(Icons.pause_rounded), - false => const Icon(Icons.play_arrow_rounded), - }, - ), - child: const Padding( - padding: EdgeInsets.all(8.0), - child: CircularProgressIndicator(strokeWidth: 2), - ), + builder: (context, buffering, child) { + if (media.duration == null) return const SizedBox(); + final player = context.read().player; + return SeekBar( + buffering: buffering, + duration: media.duration!, + position: currentPosition.data ?? Duration.zero, + bufferedPosition: player.bufferedPosition, + onChangeEnd: (v) => player.seek(v), + ); + }, ), - const SizedBox(width: 30), - Selector>( - selector: (_, provider) => provider.playlist, - child: const Icon(Icons.skip_next_rounded), - builder: (context, _, icon) => IconButton( - onPressed: context.read().hasNext - ? context.read().nextTrack - : null, - icon: icon!, - ), - ), - ], + ), + SizedBox( + width: media.duration?.inHours == 0 ? 48 : 72, + child: Text(media.duration.formatHHMM()), + ), + ], + ), + ), + ), + ); + } + + Widget actionsView(BuildContext context) { + return StreamBuilder( + stream: context.read().player.playerStateStream, + initialData: context.read().player.playerState, + builder: (context, playerState) => Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Selector>( + selector: (_, provider) => provider.playlist, + child: const Icon(Icons.skip_previous_rounded), + builder: (_, __, icon) => IconButton( + onPressed: context.read().hasPrevious + ? context.read().previousTrack + : null, + icon: icon!, + ), + ), + const SizedBox(width: 30), + Selector( + selector: (_, provider) => provider.buffering, + builder: (_, loading, child) => FloatingActionButton( + elevation: 0, + highlightElevation: 1, + hoverElevation: 1, + focusElevation: 1, + onPressed: loading + ? null + : switch (playerState.requireData.playing) { + true => context.read().player.pause, + false => context.read().player.play, + }, + child: loading + ? child + : switch (playerState.requireData.playing) { + true => const Icon(Icons.pause_rounded), + false => const Icon(Icons.play_arrow_rounded), + }, + ), + child: const Padding( + padding: EdgeInsets.all(8.0), + child: CircularProgressIndicator(strokeWidth: 2), + ), + ), + const SizedBox(width: 30), + Selector>( + selector: (_, provider) => provider.playlist, + child: const Icon(Icons.skip_next_rounded), + builder: (context, _, icon) => IconButton( + onPressed: context.read().hasNext + ? context.read().nextTrack + : null, + icon: icon!, ), ), - const SizedBox(height: 32), ], ), ); diff --git a/lib/app/player/player_queue_sheet.dart b/lib/app/player/player_queue_sheet.dart index 31fb15c..fd0571d 100644 --- a/lib/app/player/player_queue_sheet.dart +++ b/lib/app/player/player_queue_sheet.dart @@ -14,7 +14,7 @@ class PlayerQueueSheet extends StatelessWidget { return DraggableScrollableSheet( expand: false, snap: true, - shouldCloseOnMinExtent: false, + // shouldCloseOnMinExtent: false, Should or Not??? Can't decide !! minChildSize: 0.5, builder: (context, scrollController) => Column( children: [