From b7349851999995591cfad973d28807761f70019e Mon Sep 17 00:00:00 2001 From: Kingkor Roy Tirtho Date: Sun, 5 Jan 2025 16:32:14 +0600 Subject: [PATCH] refactor: track page --- .../adaptive/adaptive_pop_sheet_list.dart | 1 - lib/components/track_tile/track_options.dart | 112 +++++++++++------- lib/pages/track/track.dart | 79 ++++++------ 3 files changed, 112 insertions(+), 80 deletions(-) diff --git a/lib/components/adaptive/adaptive_pop_sheet_list.dart b/lib/components/adaptive/adaptive_pop_sheet_list.dart index d81ca977..95d3fae7 100644 --- a/lib/components/adaptive/adaptive_pop_sheet_list.dart +++ b/lib/components/adaptive/adaptive_pop_sheet_list.dart @@ -110,7 +110,6 @@ class AdaptivePopSheetList extends StatelessWidget { backgroundColor: context.theme.colorScheme.card, builder: (context) { return ListView.builder( - physics: const NeverScrollableScrollPhysics(), itemCount: childrenModified.length, shrinkWrap: true, itemBuilder: (context, index) { diff --git a/lib/components/track_tile/track_options.dart b/lib/components/track_tile/track_options.dart index ec2fd2f0..14514cde 100644 --- a/lib/components/track_tile/track_options.dart +++ b/lib/components/track_tile/track_options.dart @@ -1,10 +1,10 @@ import 'dart:io'; -import 'package:flutter/material.dart' hide Page; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:spotify/spotify.dart' hide Offset; @@ -69,16 +69,20 @@ class TrackOptions extends HookConsumerWidget { void actionShare(BuildContext context, Track track) { final data = "https://open.spotify.com/track/${track.id}"; Clipboard.setData(ClipboardData(text: data)).then((_) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - width: 300, - behavior: SnackBarBehavior.floating, - content: Text( - context.l10n.copied_to_clipboard(data), - textAlign: TextAlign.center, - ), - ), - ); + if (context.mounted) { + showToast( + context: context, + location: ToastLocation.topRight, + builder: (context, overlay) { + return SurfaceCard( + child: Text( + context.l10n.copied_to_clipboard(data), + textAlign: TextAlign.center, + ), + ); + }, + ); + } }); } @@ -161,7 +165,6 @@ class TrackOptions extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { - final scaffoldMessenger = ScaffoldMessenger.of(context); final mediaQuery = MediaQuery.of(context); final router = GoRouter.of(context); final ThemeData(:colorScheme) = Theme.of(context); @@ -220,36 +223,57 @@ class TrackOptions extends HookConsumerWidget { case TrackOptionValue.addToQueue: await playback.addTrack(track); if (context.mounted) { - scaffoldMessenger.showSnackBar( - SnackBar( - content: Text( - context.l10n.added_track_to_queue(track.name!), - ), - ), + showToast( + context: context, + location: ToastLocation.topRight, + builder: (context, overlay) { + return SurfaceCard( + child: Text( + context.l10n.added_track_to_queue(track.name!), + textAlign: TextAlign.center, + ), + ); + }, ); } break; case TrackOptionValue.playNext: playback.addTracksAtFirst([track]); - scaffoldMessenger.showSnackBar( - SnackBar( - content: Text( - context.l10n.track_will_play_next(track.name!), - ), - ), - ); + + if (context.mounted) { + showToast( + context: context, + location: ToastLocation.topRight, + builder: (context, overlay) { + return SurfaceCard( + child: Text( + context.l10n.track_will_play_next(track.name!), + textAlign: TextAlign.center, + ), + ); + }, + ); + } break; case TrackOptionValue.removeFromQueue: playback.removeTrack(track.id!); - scaffoldMessenger.showSnackBar( - SnackBar( - content: Text( - context.l10n.removed_track_from_queue( - track.name!, - ), - ), - ), - ); + + if (context.mounted) { + showToast( + context: context, + location: ToastLocation.topRight, + builder: (context, overlay) { + return SurfaceCard( + child: Text( + context.l10n.removed_track_from_queue( + track.name!, + ), + textAlign: TextAlign.center, + ), + ); + }, + ); + } break; case TrackOptionValue.favorite: favorites.toggleTrackLike(track); @@ -286,7 +310,10 @@ class TrackOptions extends HookConsumerWidget { case TrackOptionValue.details: showDialog( context: context, - builder: (context) => TrackDetailsDialog(track: track), + builder: (context) => ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 400), + child: TrackDetailsDialog(track: track), + ), ); break; case TrackOptionValue.download: @@ -299,8 +326,7 @@ class TrackOptions extends HookConsumerWidget { }, icon: icon ?? const Icon(SpotubeIcons.moreHorizontal), headings: [ - ListTile( - dense: true, + Basic( leading: AspectRatio( aspectRatio: 1, child: ClipRRect( @@ -316,8 +342,7 @@ class TrackOptions extends HookConsumerWidget { track.name!, maxLines: 1, overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.titleMedium, - ), + ).semiBold(), subtitle: Align( alignment: Alignment.centerLeft, child: ArtistLink( @@ -449,7 +474,7 @@ class TrackOptions extends HookConsumerWidget { leading: Assets.logos.songlinkTransparent.image( width: 22, height: 22, - color: colorScheme.onSurface.withOpacity(0.5), + color: colorScheme.foreground.withOpacity(0.5), ), child: Text(context.l10n.song_link), ), @@ -471,11 +496,6 @@ class TrackOptions extends HookConsumerWidget { adaptivePopSheetList.showDropdownMenu(context, offsetFromRect); }; - return ListTileTheme( - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - child: adaptivePopSheetList, - ); + return adaptivePopSheetList; } } diff --git a/lib/pages/track/track.dart b/lib/pages/track/track.dart index 30f2e998..54563bfe 100644 --- a/lib/pages/track/track.dart +++ b/lib/pages/track/track.dart @@ -1,8 +1,8 @@ import 'dart:ui'; -import 'package:flutter/material.dart'; import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:skeletonizer/skeletonizer.dart'; import 'package:spotube/collections/fake.dart'; import 'package:spotube/collections/spotube_icons.dart'; @@ -32,7 +32,7 @@ class TrackPage extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { - final ThemeData(:textTheme, :colorScheme) = Theme.of(context); + final ThemeData(:typography, :colorScheme) = Theme.of(context); final mediaQuery = MediaQuery.of(context); final playlist = ref.watch(audioPlayerProvider); @@ -53,12 +53,15 @@ class TrackPage extends HookConsumerWidget { } return Scaffold( - appBar: const TitleBar( - automaticallyImplyLeading: true, - backgroundColor: Colors.transparent, - ), - extendBodyBehindAppBar: true, - body: Stack( + headers: const [ + TitleBar( + automaticallyImplyLeading: true, + backgroundColor: Colors.transparent, + surfaceBlur: 0, + ) + ], + floatingHeader: true, + child: Stack( children: [ Positioned.fill( child: Container( @@ -71,7 +74,7 @@ class TrackPage extends HookConsumerWidget { ), fit: BoxFit.cover, colorFilter: ColorFilter.mode( - colorScheme.surface.withOpacity(0.5), + colorScheme.background.withOpacity(0.5), BlendMode.srcOver, ), alignment: Alignment.topCenter, @@ -89,7 +92,7 @@ class TrackPage extends HookConsumerWidget { decoration: BoxDecoration( gradient: LinearGradient( colors: [ - colorScheme.surface, + colorScheme.background, Colors.transparent, ], begin: Alignment.topCenter, @@ -125,8 +128,7 @@ class TrackPage extends HookConsumerWidget { children: [ Text( track.name!, - style: textTheme.titleLarge, - ), + ).large().semiBold(), const Gap(10), Row( mainAxisSize: MainAxisSize.min, @@ -170,9 +172,10 @@ class TrackPage extends HookConsumerWidget { if (!isActive && !playlist.tracks .containsBy(track, (t) => t.id)) - OutlinedButton.icon( - icon: const Icon(SpotubeIcons.queueAdd), - label: Text(context.l10n.queue), + Button.outline( + leading: + const Icon(SpotubeIcons.queueAdd), + child: Text(context.l10n.queue), onPressed: () { playlistNotifier.addTrack(track); }, @@ -181,27 +184,37 @@ class TrackPage extends HookConsumerWidget { if (!isActive && !playlist.tracks .containsBy(track, (t) => t.id)) - IconButton.outlined( - icon: - const Icon(SpotubeIcons.lightning), - tooltip: context.l10n.play_next, - onPressed: () { - playlistNotifier - .addTracksAtFirst([track]); - }, + Tooltip( + tooltip: TooltipContainer( + child: Text(context.l10n.play_next), + ), + child: IconButton.outline( + icon: const Icon( + SpotubeIcons.lightning), + onPressed: () { + playlistNotifier + .addTracksAtFirst([track]); + }, + ), ), const Gap(5), - IconButton.filled( - tooltip: isActive - ? context.l10n.pause_playback - : context.l10n.play, - icon: Icon( - isActive - ? SpotubeIcons.pause - : SpotubeIcons.play, - color: colorScheme.onPrimary, + Tooltip( + tooltip: TooltipContainer( + child: Text( + isActive + ? context.l10n.pause_playback + : context.l10n.play, + ), + ), + child: IconButton.primary( + shape: ButtonShape.circle, + icon: Icon( + isActive + ? SpotubeIcons.pause + : SpotubeIcons.play, + ), + onPressed: onPlay, ), - onPressed: onPlay, ), const Gap(5), if (mediaQuery.smAndDown)