diff --git a/lib/components/playbutton_view/playbutton_view.dart b/lib/components/playbutton_view/playbutton_view.dart index 7520f313..dd8dc371 100644 --- a/lib/components/playbutton_view/playbutton_view.dart +++ b/lib/components/playbutton_view/playbutton_view.dart @@ -51,6 +51,8 @@ class PlaybuttonView extends StatelessWidget { @override Widget build(BuildContext context) { + final scale = context.theme.scaling; + return SliverLayoutBuilder( builder: (context, constrains) => HookBuilder(builder: (context) { final isGrid = useState(constrains.mdAndUp); @@ -100,10 +102,10 @@ class PlaybuttonView extends StatelessWidget { (true, _) => SliverGrid.builder( itemCount: isLoading ? 6 : itemCount + 1, gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent( - maxCrossAxisExtent: 150 * context.theme.scaling, - mainAxisExtent: 225 * context.theme.scaling, - crossAxisSpacing: 8, - mainAxisSpacing: 8, + maxCrossAxisExtent: 150 * scale, + mainAxisExtent: 225 * scale, + crossAxisSpacing: 12 * scale, + mainAxisSpacing: 12 * scale, ), itemBuilder: (context, index) { if (isLoading) { diff --git a/lib/modules/library/user_albums.dart b/lib/modules/library/user_albums.dart index b460f22e..a3f14fba 100644 --- a/lib/modules/library/user_albums.dart +++ b/lib/modules/library/user_albums.dart @@ -48,6 +48,7 @@ class UserAlbums extends HookConsumerWidget { } return SafeArea( + bottom: false, child: Scaffold( child: RefreshTrigger( // onRefresh: () async { @@ -89,6 +90,7 @@ class UserAlbums extends HookConsumerWidget { AlbumCard.tile(albums[index]), ), ), + const SliverSafeArea(sliver: SliverGap(10)), ], ), ), diff --git a/lib/modules/library/user_artists.dart b/lib/modules/library/user_artists.dart index eaf5afb3..576298ce 100644 --- a/lib/modules/library/user_artists.dart +++ b/lib/modules/library/user_artists.dart @@ -53,6 +53,7 @@ class UserArtists extends HookConsumerWidget { } return SafeArea( + bottom: false, child: Scaffold( child: RefreshTrigger( // onRefresh: () async { @@ -117,6 +118,7 @@ class UserArtists extends HookConsumerWidget { }, ); }), + const SliverSafeArea(sliver: SliverGap(10)), ], ), ), diff --git a/lib/modules/library/user_playlists.dart b/lib/modules/library/user_playlists.dart index 1b1bf110..58462bf9 100644 --- a/lib/modules/library/user_playlists.dart +++ b/lib/modules/library/user_playlists.dart @@ -82,6 +82,7 @@ class UserPlaylists extends HookConsumerWidget { // ref.invalidate(favoritePlaylistsProvider); // }, child: SafeArea( + bottom: false, child: InterScrollbar( controller: controller, child: CustomScrollView( @@ -139,6 +140,7 @@ class UserPlaylists extends HookConsumerWidget { }, ), ), + const SliverSafeArea(sliver: SliverGap(10)), ], ), ), diff --git a/lib/modules/lyrics/zoom_controls.dart b/lib/modules/lyrics/zoom_controls.dart index 73beb4ae..b4eeb9d6 100644 --- a/lib/modules/lyrics/zoom_controls.dart +++ b/lib/modules/lyrics/zoom_controls.dart @@ -1,5 +1,6 @@ -import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:spotube/collections/spotube_icons.dart'; @@ -32,7 +33,7 @@ class ZoomControls extends HookWidget { @override Widget build(BuildContext context) { final actions = [ - IconButton( + IconButton.ghost( icon: decreaseIcon, onPressed: () { if (value == min) return; @@ -40,7 +41,7 @@ class ZoomControls extends HookWidget { }, ), Text("$value$unit"), - IconButton( + IconButton.ghost( icon: increaseIcon, onPressed: () { if (value == max) return; @@ -50,27 +51,28 @@ class ZoomControls extends HookWidget { ]; return Container( - decoration: BoxDecoration( - color: Theme.of(context).cardColor.withOpacity(0.7), - borderRadius: BorderRadius.circular(10), - ), constraints: BoxConstraints( maxHeight: direction == Axis.horizontal ? 50 : 200, maxWidth: direction == Axis.vertical ? 50 : double.infinity, ), margin: const EdgeInsets.all(8), - child: direction == Axis.horizontal - ? Row( - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.min, - children: actions, - ) - : Column( - mainAxisAlignment: MainAxisAlignment.end, - mainAxisSize: MainAxisSize.min, - verticalDirection: VerticalDirection.up, - children: actions, - ), + child: SurfaceCard( + surfaceBlur: context.theme.surfaceBlur, + surfaceOpacity: context.theme.surfaceOpacity, + padding: EdgeInsets.zero, + child: direction == Axis.horizontal + ? Row( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + children: actions, + ) + : Column( + mainAxisAlignment: MainAxisAlignment.end, + mainAxisSize: MainAxisSize.min, + verticalDirection: VerticalDirection.up, + children: actions, + ), + ), ); } } diff --git a/lib/modules/player/player.dart b/lib/modules/player/player.dart index 3f19fbf0..014e6aef 100644 --- a/lib/modules/player/player.dart +++ b/lib/modules/player/player.dart @@ -367,12 +367,6 @@ class PlayerView extends HookConsumerWidget { topRight: Radius.circular(20), ), ), - constraints: BoxConstraints( - maxHeight: MediaQuery.of(context) - .size - .height * - 0.8, - ), builder: (context) => const LyricsPage(isModal: true), ); diff --git a/lib/pages/lyrics/lyrics.dart b/lib/pages/lyrics/lyrics.dart index 17e552e6..679ef78e 100644 --- a/lib/pages/lyrics/lyrics.dart +++ b/lib/pages/lyrics/lyrics.dart @@ -1,13 +1,11 @@ -import 'dart:ui'; - import 'package:flutter_hooks/flutter_hooks.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:spotube/collections/spotube_icons.dart'; import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/components/image/universal_image.dart'; -import 'package:spotube/extensions/constrains.dart'; import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/image.dart'; import 'package:spotube/hooks/utils/use_custom_status_bar_color.dart'; @@ -35,7 +33,6 @@ class LyricsPage extends HookConsumerWidget { [playlist.activeTrack?.album?.images], ); final palette = usePaletteColor(albumArt, ref); - final mediaQuery = MediaQuery.of(context); final route = ModalRoute.of(context); final selectedIndex = useState(0); @@ -47,17 +44,28 @@ class LyricsPage extends HookConsumerWidget { Widget tabbar = Padding( padding: const EdgeInsets.all(10), - child: Opacity( - opacity: 0.8, - child: Tabs( - index: selectedIndex.value, - onChanged: (index) => selectedIndex.value = index, - tabs: [ - Text(context.l10n.synced), - Text(context.l10n.plain), - ], - ), - ), + child: isModal + ? TabList( + index: selectedIndex.value, + children: [ + TabButton( + onPressed: () => selectedIndex.value = 0, + child: Text(context.l10n.synced), + ), + TabButton( + onPressed: () => selectedIndex.value = 1, + child: Text(context.l10n.plain), + ), + ], + ) + : Tabs( + index: selectedIndex.value, + onChanged: (index) => selectedIndex.value = index, + tabs: [ + Text(context.l10n.synced), + Text(context.l10n.plain), + ], + ), ); tabbar = Row( @@ -89,57 +97,53 @@ class LyricsPage extends HookConsumerWidget { canPop: true, onPopInvokedWithResult: (_, __) => resetStatusBar(), child: SafeArea( - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 15, sigmaY: 15), - child: Container( - clipBehavior: Clip.hardEdge, - decoration: BoxDecoration( - color: Theme.of(context).colorScheme.background.withOpacity(.4), - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(10), - topRight: Radius.circular(10), - ), - ), - child: Column( - children: [ - const SizedBox(height: 5), - Container( - height: 7, - width: 150, - decoration: BoxDecoration( - color: palette.titleTextColor, - borderRadius: BorderRadius.circular(10), - ), + bottom: false, + child: SurfaceCard( + surfaceBlur: context.theme.surfaceBlur, + surfaceOpacity: context.theme.surfaceOpacity, + padding: EdgeInsets.zero, + borderRadius: BorderRadius.zero, + borderWidth: 0, + child: Column( + children: [ + const SizedBox(height: 5), + Container( + height: 7, + width: 150, + decoration: BoxDecoration( + color: palette.titleTextColor, + borderRadius: BorderRadius.circular(10), ), - AppBar( - leading: [tabbar], - backgroundColor: Colors.transparent, - trailing: [ - IconButton.ghost( - icon: const Icon(SpotubeIcons.minimize), - onPressed: () => Navigator.of(context).pop(), - ), - const SizedBox(width: 5), + ), + Row( + children: [ + Expanded( + child: tabbar, + ), + IconButton.ghost( + icon: const Icon(SpotubeIcons.minimize), + onPressed: () => Navigator.of(context).pop(), + ), + const SizedBox(width: 5), + ], + ), + Expanded( + child: IndexedStack( + index: selectedIndex.value, + children: [ + SyncedLyrics(palette: palette, isModal: isModal), + PlainLyrics(palette: palette, isModal: isModal), ], ), - Expanded( - child: IndexedStack( - index: selectedIndex.value, - children: [ - SyncedLyrics(palette: palette, isModal: isModal), - PlainLyrics(palette: palette, isModal: isModal), - ], - ), - ), - ], - ), + ), + ], ), ), ), ); } return SafeArea( - bottom: mediaQuery.mdAndUp, + bottom: false, child: Scaffold( floatingHeader: true, headers: [ @@ -157,13 +161,14 @@ class LyricsPage extends HookConsumerWidget { image: UniversalImage.imageProvider(albumArt), fit: BoxFit.cover, ), - borderRadius: const BorderRadius.only( - bottomLeft: Radius.circular(10), - ), ), margin: const EdgeInsets.only(bottom: 10), - child: BackdropFilter( - filter: ImageFilter.blur(sigmaX: 5, sigmaY: 5), + child: SurfaceCard( + surfaceBlur: context.theme.surfaceBlur, + surfaceOpacity: context.theme.surfaceOpacity, + padding: EdgeInsets.zero, + borderRadius: BorderRadius.zero, + borderWidth: 0, child: ColoredBox( color: palette.color.withOpacity(.7), child: SafeArea( diff --git a/lib/pages/lyrics/plain_lyrics.dart b/lib/pages/lyrics/plain_lyrics.dart index 7c571d5f..6246fd79 100644 --- a/lib/pages/lyrics/plain_lyrics.dart +++ b/lib/pages/lyrics/plain_lyrics.dart @@ -1,9 +1,8 @@ import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:palette_generator/palette_generator.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/modules/lyrics/zoom_controls.dart'; import 'package:spotube/components/shimmers/shimmer_lyrics.dart'; @@ -30,7 +29,7 @@ class PlainLyrics extends HookConsumerWidget { final playlist = ref.watch(audioPlayerProvider); final lyricsQuery = ref.watch(syncedLyricsProvider(playlist.activeTrack)); final mediaQuery = MediaQuery.of(context); - final textTheme = Theme.of(context).textTheme; + final typography = Theme.of(context).typography; final textZoomLevel = useState(defaultTextZoom); @@ -44,9 +43,8 @@ class PlainLyrics extends HookConsumerWidget { child: Text( playlist.activeTrack?.name ?? "", style: mediaQuery.mdAndUp - ? textTheme.displaySmall - : textTheme.headlineMedium?.copyWith( - fontSize: 25, + ? typography.h3 + : typography.h4.copyWith( color: palette.titleTextColor, ), ), @@ -54,10 +52,8 @@ class PlainLyrics extends HookConsumerWidget { Center( child: Text( playlist.activeTrack?.artists?.asString() ?? "", - style: (mediaQuery.mdAndUp - ? textTheme.headlineSmall - : textTheme.titleLarge) - ?.copyWith(color: palette.bodyTextColor), + style: (mediaQuery.mdAndUp ? typography.h4 : typography.large) + .copyWith(color: palette.bodyTextColor), ), ) ], @@ -79,7 +75,7 @@ class PlainLyrics extends HookConsumerWidget { children: [ Text( context.l10n.no_lyrics_available, - style: textTheme.bodyLarge?.copyWith( + style: typography.large.copyWith( color: palette.bodyTextColor, ), textAlign: TextAlign.center, diff --git a/lib/pages/lyrics/synced_lyrics.dart b/lib/pages/lyrics/synced_lyrics.dart index 59bd863a..1367fa5a 100644 --- a/lib/pages/lyrics/synced_lyrics.dart +++ b/lib/pages/lyrics/synced_lyrics.dart @@ -1,10 +1,9 @@ import 'dart:async'; -import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; -import 'package:gap/gap.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:palette_generator/palette_generator.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/modules/lyrics/zoom_controls.dart'; import 'package:spotube/components/shimmers/shimmer_lyrics.dart'; @@ -37,7 +36,7 @@ class SyncedLyrics extends HookConsumerWidget { Widget build(BuildContext context, ref) { final playlist = ref.watch(audioPlayerProvider); - final mediaQuery = MediaQuery.of(context); + final mediaQuery = MediaQuery.sizeOf(context); final controller = useAutoScrollController(); final delay = ref.watch(syncedLyricsDelayProvider); @@ -54,7 +53,7 @@ class SyncedLyrics extends HookConsumerWidget { useSyncedLyrics(ref, lyricsState.asData?.value.lyricsMap ?? {}, delay); final textZoomLevel = useState(defaultTextZoom); - final textTheme = Theme.of(context).textTheme; + final typography = Theme.of(context).typography; ref.listen( audioPlayerProvider.select((s) => s.activeTrack), @@ -69,11 +68,11 @@ class SyncedLyrics extends HookConsumerWidget { ); final headlineTextStyle = (mediaQuery.mdAndUp - ? textTheme.displaySmall - : textTheme.headlineMedium?.copyWith(fontSize: 25)) - ?.copyWith(color: palette.titleTextColor); + ? typography.h3 + : typography.h4.copyWith(fontSize: 25)) + .copyWith(color: palette.titleTextColor); - final bodyTextTheme = textTheme.bodyLarge?.copyWith( + final bodyTextTheme = typography.large.copyWith( color: palette.bodyTextColor, ); @@ -115,9 +114,8 @@ class SyncedLyrics extends HookConsumerWidget { preferredSize: const Size.fromHeight(40), child: Text( playlist.activeTrack?.artists?.asString() ?? "", - style: mediaQuery.mdAndUp - ? textTheme.headlineSmall - : textTheme.titleLarge, + style: + mediaQuery.mdAndUp ? typography.h4 : typography.x2Large, ), ), ), @@ -144,7 +142,7 @@ class SyncedLyrics extends HookConsumerWidget { ? Container( padding: index == lyricValue.lyrics.length - 1 ? EdgeInsets.only( - bottom: mediaQuery.size.height / 2, + bottom: mediaQuery.height / 2, ) : null, ) @@ -165,31 +163,34 @@ class SyncedLyrics extends HookConsumerWidget { (textZoomLevel.value / 100), ), textAlign: TextAlign.center, - child: InkWell( - onTap: () async { - final time = Duration( - seconds: - lyricSlice.time.inSeconds - delay, - ); - if (time > audioPlayer.duration || - time.isNegative) { - return; - } - audioPlayer.seek(time); - }, - child: Builder(builder: (context) { - return StrokeText( - text: lyricSlice.text, - textStyle: - DefaultTextStyle.of(context).style, - textColor: isActive - ? Colors.white - : palette.bodyTextColor, - strokeColor: isActive - ? Colors.black - : Colors.transparent, - ); - }), + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () async { + final time = Duration( + seconds: + lyricSlice.time.inSeconds - delay, + ); + if (time > audioPlayer.duration || + time.isNegative) { + return; + } + audioPlayer.seek(time); + }, + child: Builder(builder: (context) { + return StrokeText( + text: lyricSlice.text, + textStyle: + DefaultTextStyle.of(context).style, + textColor: isActive + ? Colors.white + : palette.bodyTextColor, + strokeColor: isActive + ? Colors.black + : Colors.transparent, + ); + }), + ), ), ), ), @@ -231,7 +232,7 @@ class SyncedLyrics extends HookConsumerWidget { ), TextSpan( text: " Plain Lyrics ", - style: textTheme.bodyLarge?.copyWith( + style: typography.large.copyWith( color: palette.bodyTextColor, fontWeight: FontWeight.bold, ), diff --git a/lib/pages/root/root_app.dart b/lib/pages/root/root_app.dart index b8d4d166..cdb56910 100644 --- a/lib/pages/root/root_app.dart +++ b/lib/pages/root/root_app.dart @@ -1,6 +1,5 @@ import 'dart:async'; -import 'package:collection/collection.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; @@ -180,37 +179,16 @@ class RootApp extends HookConsumerWidget { return getSidebarTileList(context.l10n).map((s) => s.name).toList(); }, []); - final bottomPlayerKey = useMemoized(() => GlobalKey(), []); - final navigationBarKey = useMemoized(() => GlobalKey(), []); - - final bottomPadding = useMemoized(() { - return [bottomPlayerKey, navigationBarKey] - .map((k) => - (k.currentContext?.findRenderObject() as RenderBox?) - ?.size - .height ?? - 0) - .sum; - }, [bottomPlayerKey, navigationBarKey]); - final scaffold = MediaQuery.removeViewInsets( context: context, removeBottom: true, child: Scaffold( - footers: [ - BottomPlayer(key: bottomPlayerKey), - SpotubeNavigationBar(key: navigationBarKey), + footers: const [ + BottomPlayer(), + SpotubeNavigationBar(), ], floatingFooter: true, - // Fix for safe are not working for bottom bar - child: MediaQuery( - data: MediaQuery.of(context).copyWith( - padding: MediaQuery.of(context).padding.copyWith( - bottom: bottomPadding, - ), - ), - child: Sidebar(child: child), - ), + child: Sidebar(child: child), ), ); diff --git a/pubspec.lock b/pubspec.lock index 34306fef..d441371d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1955,8 +1955,8 @@ packages: dependency: "direct main" description: path: "." - ref: "5359958464a57235f0f34c43a4623356a32459a0" - resolved-ref: "5359958464a57235f0f34c43a4623356a32459a0" + ref: fix-scaffold-footer-safearea + resolved-ref: "8ede34e1e3270ec3839192a7a6453e19cd00f9ab" url: "https://github.com/KRTirtho/shadcn_flutter.git" source: git version: "0.0.24" diff --git a/pubspec.yaml b/pubspec.yaml index 198bc949..f00c298f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -103,7 +103,7 @@ dependencies: shadcn_flutter: git: url: https://github.com/KRTirtho/shadcn_flutter.git - ref: 5359958464a57235f0f34c43a4623356a32459a0 + ref: fix-scaffold-footer-safearea shared_preferences: ^2.2.3 shelf: ^1.4.1 shelf_router: ^1.1.4