diff --git a/lib/components/Album/AlbumView.dart b/lib/components/Album/AlbumView.dart index a6f927db..78c96093 100644 --- a/lib/components/Album/AlbumView.dart +++ b/lib/components/Album/AlbumView.dart @@ -1,6 +1,7 @@ import 'package:flutter/material.dart'; 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:spotify/spotify.dart'; import 'package:spotube/components/Shared/HeartButton.dart'; @@ -59,6 +60,7 @@ class AlbumView extends HookConsumerWidget { titleImage: albumArt, tracksSnapshot: tracksSnapshot, album: album, + routePath: "/album/${album.id}", onPlay: ([track]) { if (tracksSnapshot.asData?.value != null) { playPlaylist( diff --git a/lib/components/Home/Home.dart b/lib/components/Home/Home.dart index 69bfce40..15495d51 100644 --- a/lib/components/Home/Home.dart +++ b/lib/components/Home/Home.dart @@ -23,6 +23,7 @@ import 'package:spotube/hooks/usePaginatedFutureProvider.dart'; import 'package:spotube/hooks/useUpdateChecker.dart'; import 'package:spotube/models/Logger.dart'; import 'package:spotube/provider/SpotifyRequests.dart'; +import 'package:spotube/utils/platform.dart'; List spotifyScopes = [ "playlist-modify-public", @@ -73,7 +74,7 @@ class Home extends HookConsumerWidget { child: MoveWindow(), ), Expanded(child: MoveWindow()), - if (!Platform.isMacOS && !Platform.isAndroid && !Platform.isIOS) + if (!Platform.isMacOS && !kIsMobile) const TitleBarActionButtons(), ], )) @@ -98,7 +99,7 @@ class Home extends HookConsumerWidget { child: Scaffold( body: Column( children: [ - Platform.isAndroid || Platform.isIOS + kIsMobile ? titleBarContents : WindowTitleBarBox(child: titleBarContents), Expanded( diff --git a/lib/components/LoaderShimmers/ShimmerArtistProfile.dart b/lib/components/LoaderShimmers/ShimmerArtistProfile.dart index 0fa1dbe6..ccabeb64 100644 --- a/lib/components/LoaderShimmers/ShimmerArtistProfile.dart +++ b/lib/components/LoaderShimmers/ShimmerArtistProfile.dart @@ -44,7 +44,7 @@ class ShimmerArtistProfile extends HookWidget { ), ), const SizedBox(width: 10), - const Flexible(child: ShimmerTrackTile()), + const Flexible(child: ShimmerTrackTile(noSliver: true)), ], ); } diff --git a/lib/components/LoaderShimmers/ShimmerTrackTile.dart b/lib/components/LoaderShimmers/ShimmerTrackTile.dart index abf45b16..e9160bcf 100644 --- a/lib/components/LoaderShimmers/ShimmerTrackTile.dart +++ b/lib/components/LoaderShimmers/ShimmerTrackTile.dart @@ -3,7 +3,12 @@ import 'package:skeleton_text/skeleton_text.dart'; import 'package:spotube/extensions/ShimmerColorTheme.dart'; class ShimmerTrackTile extends StatelessWidget { - const ShimmerTrackTile({Key? key}) : super(key: key); + final bool noSliver; + + const ShimmerTrackTile({ + Key? key, + this.noSliver = false, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -13,25 +18,35 @@ class ShimmerTrackTile extends StatelessWidget { .extension()! .shimmerBackgroundColor!; - return Padding( - padding: const EdgeInsets.only(top: 30), - child: ListView.builder( - scrollDirection: Axis.vertical, - physics: const NeverScrollableScrollPhysics(), - itemCount: 5, - shrinkWrap: true, - itemBuilder: (BuildContext context, int index) { - return Container( - margin: const EdgeInsets.symmetric(horizontal: 20), - child: Row( + final single = Container( + margin: const EdgeInsets.symmetric(horizontal: 20), + child: Row( + children: [ + SkeletonAnimation( + shimmerColor: shimmerColor, + borderRadius: BorderRadius.circular(20), + shimmerDuration: 1000, + child: Container( + width: 50, + height: 50, + decoration: BoxDecoration( + color: shimmerBackgroundColor, + borderRadius: BorderRadius.circular(10), + ), + margin: const EdgeInsets.only(top: 10), + ), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ SkeletonAnimation( shimmerColor: shimmerColor, borderRadius: BorderRadius.circular(20), shimmerDuration: 1000, child: Container( - width: 50, - height: 50, + height: 15, decoration: BoxDecoration( color: shimmerBackgroundColor, borderRadius: BorderRadius.circular(10), @@ -39,46 +54,41 @@ class ShimmerTrackTile extends StatelessWidget { margin: const EdgeInsets.only(top: 10), ), ), - const SizedBox(width: 10), - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - SkeletonAnimation( - shimmerColor: shimmerColor, - borderRadius: BorderRadius.circular(20), - shimmerDuration: 1000, - child: Container( - height: 15, - decoration: BoxDecoration( - color: shimmerBackgroundColor, - borderRadius: BorderRadius.circular(10), - ), - margin: const EdgeInsets.only(top: 10), - ), - ), - SkeletonAnimation( - shimmerColor: shimmerColor, - borderRadius: BorderRadius.circular(20), - shimmerDuration: 1000, - child: Container( - constraints: BoxConstraints( - maxWidth: MediaQuery.of(context).size.width * .8), - height: 10, - decoration: BoxDecoration( - color: shimmerBackgroundColor, - borderRadius: BorderRadius.circular(10), - ), - margin: const EdgeInsets.only(top: 10), - ), - ), - ], + SkeletonAnimation( + shimmerColor: shimmerColor, + borderRadius: BorderRadius.circular(20), + shimmerDuration: 1000, + child: Container( + constraints: BoxConstraints( + maxWidth: MediaQuery.of(context).size.width * .8), + height: 10, + decoration: BoxDecoration( + color: shimmerBackgroundColor, + borderRadius: BorderRadius.circular(10), + ), + margin: const EdgeInsets.only(top: 10), ), ), ], ), - ); - }, + ), + ], + ), + ); + + if (noSliver) { + return ListView.builder( + shrinkWrap: true, + itemCount: 5, + physics: const NeverScrollableScrollPhysics(), + itemBuilder: (context, _) => single, + ); + } + + return SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) => single, + childCount: 5, ), ); } diff --git a/lib/components/Player/PlayerView.dart b/lib/components/Player/PlayerView.dart index f4d35317..6d580bc3 100644 --- a/lib/components/Player/PlayerView.dart +++ b/lib/components/Player/PlayerView.dart @@ -1,6 +1,5 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter/material.dart'; -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'; @@ -12,6 +11,7 @@ import 'package:spotube/components/Shared/SpotubeMarqueeText.dart'; import 'package:spotube/helpers/artists-to-clickable-artists.dart'; import 'package:spotube/helpers/image-to-url-string.dart'; import 'package:spotube/hooks/useBreakpoints.dart'; +import 'package:spotube/hooks/useCustomStatusBarColor.dart'; import 'package:spotube/hooks/usePaletteColor.dart'; import 'package:spotube/provider/Playback.dart'; @@ -46,29 +46,10 @@ class PlayerView extends HookConsumerWidget { final PaletteColor paletteColor = usePaletteColor(context, albumArt, ref); - final backgroundColor = Theme.of(context).backgroundColor; - - useEffect(() { - SystemChrome.setSystemUIOverlayStyle( - SystemUiOverlayStyle( - statusBarColor: paletteColor.color, // status bar color - ), - ); - return; - }, [paletteColor.color]); - - useEffect(() { - return () { - SystemChrome.setSystemUIOverlayStyle( - SystemUiOverlayStyle( - statusBarColor: backgroundColor, // status bar color - statusBarIconBrightness: backgroundColor.computeLuminance() > 0.179 - ? Brightness.dark - : Brightness.light, - ), - ); - }; - }, []); + useCustomStatusBarColor( + paletteColor.color, + GoRouter.of(context).location == "/player", + ); return SafeArea( child: Scaffold( diff --git a/lib/components/Playlist/PlaylistView.dart b/lib/components/Playlist/PlaylistView.dart index 25e4f744..b6701d44 100644 --- a/lib/components/Playlist/PlaylistView.dart +++ b/lib/components/Playlist/PlaylistView.dart @@ -2,6 +2,7 @@ import 'dart:convert'; 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:spotube/components/Shared/HeartButton.dart'; import 'package:spotube/components/Shared/TrackCollectionView.dart'; @@ -80,6 +81,7 @@ class PlaylistView extends HookConsumerWidget { } }, showShare: playlist.id != "user-liked-tracks", + routePath: "/playlist/${playlist.id}", onShare: () { final data = "https://open.spotify.com/playlist/${playlist.id}"; Clipboard.setData( diff --git a/lib/components/Settings/Settings.dart b/lib/components/Settings/Settings.dart index 9a1f9b42..ce28fea8 100644 --- a/lib/components/Settings/Settings.dart +++ b/lib/components/Settings/Settings.dart @@ -13,6 +13,7 @@ import 'package:spotube/models/SpotifyMarkets.dart'; import 'package:spotube/models/SpotubeTrack.dart'; import 'package:spotube/provider/Auth.dart'; import 'package:spotube/provider/UserPreferences.dart'; +import 'package:spotube/utils/platform.dart'; import 'package:url_launcher/url_launcher_string.dart'; class Settings extends HookConsumerWidget { @@ -56,7 +57,7 @@ class Settings extends HookConsumerWidget { constraints: const BoxConstraints(maxWidth: 1366), child: ListView( children: [ - if (!Platform.isAndroid && !Platform.isIOS) ...[ + if (!kIsMobile) ...[ SettingsHotKeyTile( title: "Next track global shortcut", currentHotKey: preferences.nextTrackHotKey, diff --git a/lib/components/Shared/DownloadTrackButton.dart b/lib/components/Shared/DownloadTrackButton.dart index d085b6d0..f11493dd 100644 --- a/lib/components/Shared/DownloadTrackButton.dart +++ b/lib/components/Shared/DownloadTrackButton.dart @@ -9,6 +9,7 @@ import 'package:spotube/helpers/getLyrics.dart'; import 'package:spotube/models/SpotubeTrack.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/UserPreferences.dart'; +import 'package:spotube/utils/platform.dart'; import 'package:youtube_explode_dart/youtube_explode_dart.dart'; import 'package:path_provider/path_provider.dart' as path_provider; import 'package:path/path.dart' as path; @@ -30,7 +31,7 @@ class DownloadTrackButton extends HookConsumerWidget { final _downloadTrack = useCallback(() async { if (track == null) return; - if ((Platform.isAndroid || Platform.isIOS) && + if ((kIsMobile) && !await Permission.storage.isGranted && !await Permission.storage.isPermanentlyDenied) { final status = await Permission.storage.request(); diff --git a/lib/components/Shared/PageWindowTitleBar.dart b/lib/components/Shared/PageWindowTitleBar.dart index 10a3225d..01611613 100644 --- a/lib/components/Shared/PageWindowTitleBar.dart +++ b/lib/components/Shared/PageWindowTitleBar.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'package:bitsdojo_window/bitsdojo_window.dart'; import 'package:flutter/material.dart'; +import 'package:spotube/utils/platform.dart'; class TitleBarActionButtons extends StatelessWidget { final Color? color; @@ -67,19 +68,22 @@ class PageWindowTitleBar extends StatelessWidget }) : super(key: key); @override Size get preferredSize => Size.fromHeight( - !Platform.isIOS && !Platform.isAndroid ? appWindow.titleBarHeight : 35, + (kIsDesktop ? appWindow.titleBarHeight : 35), ); @override Widget build(BuildContext context) { - if (Platform.isIOS || Platform.isAndroid) { + if (kIsMobile) { return PreferredSize( preferredSize: const Size.fromHeight(300), - child: Row( - children: [ - if (leading != null) leading!, - Expanded(child: Center(child: center)), - ], + child: Container( + color: backgroundColor, + child: Row( + children: [ + if (leading != null) leading!, + Expanded(child: Center(child: center)), + ], + ), ), ); } @@ -94,7 +98,7 @@ class PageWindowTitleBar extends StatelessWidget ), if (leading != null) leading!, Expanded(child: MoveWindow(child: Center(child: center))), - if (!Platform.isMacOS && !Platform.isIOS && !Platform.isAndroid) + if (!Platform.isMacOS && !kIsMobile) TitleBarActionButtons(color: foregroundColor) ], ), diff --git a/lib/components/Shared/TrackCollectionView.dart b/lib/components/Shared/TrackCollectionView.dart index 9b125450..ddcaba32 100644 --- a/lib/components/Shared/TrackCollectionView.dart +++ b/lib/components/Shared/TrackCollectionView.dart @@ -1,14 +1,17 @@ import 'package:cached_network_image/cached_network_image.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/components/LoaderShimmers/ShimmerTrackTile.dart'; import 'package:spotube/components/Shared/PageWindowTitleBar.dart'; import 'package:spotube/components/Shared/TracksTableView.dart'; import 'package:spotube/helpers/simple-track-to-track.dart'; +import 'package:spotube/hooks/useCustomStatusBarColor.dart'; import 'package:spotube/hooks/usePaletteColor.dart'; import 'package:spotube/models/Logger.dart'; import 'package:flutter/material.dart'; import 'package:spotify/spotify.dart'; +import 'package:spotube/utils/platform.dart'; class TrackCollectionView extends HookConsumerWidget { final logger = getLogger(TrackCollectionView); @@ -25,6 +28,8 @@ class TrackCollectionView extends HookConsumerWidget { final bool showShare; final bool isOwned; + + final String routePath; TrackCollectionView({ required this.title, required this.id, @@ -33,6 +38,7 @@ class TrackCollectionView extends HookConsumerWidget { required this.isPlaying, required this.onPlay, required this.onShare, + required this.routePath, this.heartBtn, this.album, this.description, @@ -83,6 +89,11 @@ class TrackCollectionView extends HookConsumerWidget { final collapsed = useState(false); + useCustomStatusBarColor( + color?.color ?? Theme.of(context).backgroundColor, + GoRouter.of(context).location == routePath, + ); + useEffect(() { listener() { if (controller.position.pixels >= 400 && !collapsed.value) { @@ -99,142 +110,135 @@ class TrackCollectionView extends HookConsumerWidget { return SafeArea( child: Scaffold( - appBar: PageWindowTitleBar( - backgroundColor: - tracksSnapshot.asData?.value != null ? color?.color : null, - foregroundColor: tracksSnapshot.asData?.value != null - ? color?.titleTextColor + appBar: (kIsDesktop) + ? PageWindowTitleBar( + backgroundColor: color?.color, + foregroundColor: color?.titleTextColor, + leading: Row( + children: [BackButton(color: color?.titleTextColor)], + ), + ) : null, - leading: Row( - children: [ - BackButton( - color: tracksSnapshot.asData?.value != null - ? color?.titleTextColor - : null, - ) - ], - ), - ), - body: tracksSnapshot.when( - data: (tracks) { - return CustomScrollView( - controller: controller, - slivers: [ - SliverAppBar( - actions: collapsed.value ? buttons : null, - floating: false, - pinned: true, - expandedHeight: 400, - automaticallyImplyLeading: false, - primary: true, - title: collapsed.value - ? Text( - title, - style: - Theme.of(context).textTheme.headline4?.copyWith( - color: color?.titleTextColor, - fontWeight: FontWeight.w600, - ), - ) - : null, - backgroundColor: color?.color.withOpacity(0.8), - flexibleSpace: LayoutBuilder(builder: (context, constrains) { - return FlexibleSpaceBar( - background: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: [ - color?.color ?? Colors.transparent, - Theme.of(context).canvasColor, - ], - begin: const FractionalOffset(0, 0), - end: const FractionalOffset(0, 1), - tileMode: TileMode.clamp, - ), - ), - child: Material( - type: MaterialType.transparency, - child: Padding( - padding: const EdgeInsets.symmetric( - horizontal: 20, - vertical: 20, + body: CustomScrollView( + controller: controller, + slivers: [ + SliverAppBar( + actions: collapsed.value ? buttons : null, + floating: false, + pinned: true, + expandedHeight: 400, + automaticallyImplyLeading: kIsMobile, + iconTheme: IconThemeData(color: color?.titleTextColor), + primary: true, + backgroundColor: color?.color, + title: collapsed.value + ? Text( + title, + style: Theme.of(context).textTheme.headline4?.copyWith( + color: color?.titleTextColor, + fontWeight: FontWeight.w600, ), - child: Wrap( - spacing: 20, - runSpacing: 20, - crossAxisAlignment: WrapCrossAlignment.center, - alignment: WrapAlignment.center, - runAlignment: WrapAlignment.center, - children: [ - Container( - constraints: - const BoxConstraints(maxHeight: 200), - child: ClipRRect( - borderRadius: BorderRadius.circular(10), - child: CachedNetworkImage( - imageUrl: titleImage, - ), + ) + : null, + flexibleSpace: LayoutBuilder(builder: (context, constrains) { + return FlexibleSpaceBar( + background: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + color?.color ?? Colors.transparent, + Theme.of(context).canvasColor, + ], + begin: const FractionalOffset(0, 0), + end: const FractionalOffset(0, 1), + tileMode: TileMode.clamp, + ), + ), + child: Material( + type: MaterialType.transparency, + child: Padding( + padding: const EdgeInsets.symmetric( + horizontal: 20, + vertical: 20, + ), + child: Wrap( + spacing: 20, + runSpacing: 20, + crossAxisAlignment: WrapCrossAlignment.center, + alignment: WrapAlignment.center, + runAlignment: WrapAlignment.center, + children: [ + Container( + constraints: + const BoxConstraints(maxHeight: 200), + child: ClipRRect( + borderRadius: BorderRadius.circular(10), + child: CachedNetworkImage( + imageUrl: titleImage, ), ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ + ), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: + MainAxisAlignment.spaceBetween, + children: [ + Text( + title, + style: Theme.of(context) + .textTheme + .headline4 + ?.copyWith( + color: color?.titleTextColor, + fontWeight: FontWeight.w600, + ), + ), + if (description != null) Text( - title, + description!, style: Theme.of(context) .textTheme - .headline4 + .bodyLarge ?.copyWith( - color: color?.titleTextColor, - fontWeight: FontWeight.w600, + color: color?.bodyTextColor, ), + maxLines: 2, + overflow: TextOverflow.fade, ), - if (description != null) - Text( - description!, - style: Theme.of(context) - .textTheme - .bodyLarge - ?.copyWith( - color: color?.bodyTextColor, - ), - maxLines: 2, - overflow: TextOverflow.fade, - ), - const SizedBox(height: 10), - Row( - mainAxisSize: MainAxisSize.min, - children: buttons, - ), - ], - ) - ], - ), + const SizedBox(height: 10), + Row( + mainAxisSize: MainAxisSize.min, + children: buttons, + ), + ], + ) + ], ), ), ), - ); - }), - ), - TracksTableView( - tracks is! List - ? tracks - .map((track) => simpleTrackToTrack(track, album!)) - .toList() - : tracks, - onTrackPlayButtonPressed: onPlay, - playlistId: id, - userPlaylist: isOwned, - ), - ], - ); - }, - error: (error, _) => Text("Error $error"), - loading: () => const ShimmerTrackTile(), - ), - ), + ), + ); + }), + ), + tracksSnapshot.when( + data: (tracks) { + return TracksTableView( + tracks is! List + ? tracks + .map((track) => simpleTrackToTrack(track, album!)) + .toList() + : tracks, + onTrackPlayButtonPressed: onPlay, + playlistId: id, + userPlaylist: isOwned, + ); + }, + error: (error, _) => + SliverToBoxAdapter(child: Text("Error $error")), + loading: () => const ShimmerTrackTile(), + ), + ], + )), ); } } diff --git a/lib/components/Shared/TracksTableView.dart b/lib/components/Shared/TracksTableView.dart index 9b6f4869..70bd9069 100644 --- a/lib/components/Shared/TracksTableView.dart +++ b/lib/components/Shared/TracksTableView.dart @@ -97,77 +97,5 @@ class TracksTableView extends HookConsumerWidget { }).toList() ]), ); - - return Container( - color: Theme.of(context).backgroundColor, - child: Scrollbar( - child: ListView( - children: [ - if (heading != null) heading!, - Row( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - "#", - textAlign: TextAlign.center, - style: tableHeadStyle, - ), - ), - Expanded( - child: Row( - children: [ - Text( - "Title", - style: tableHeadStyle, - overflow: TextOverflow.ellipsis, - ), - ], - ), - ), - // used alignment of this table-head - if (breakpoint.isMoreThan(Breakpoints.md)) ...[ - const SizedBox(width: 100), - Expanded( - child: Row( - children: [ - Text( - "Album", - overflow: TextOverflow.ellipsis, - style: tableHeadStyle, - ), - ], - ), - ) - ], - if (!breakpoint.isSm) ...[ - const SizedBox(width: 10), - Text("Time", style: tableHeadStyle), - const SizedBox(width: 10), - ], - const SizedBox(width: 40), - ], - ), - ...tracks.asMap().entries.map((track) { - String? thumbnailUrl = imageToUrlString( - track.value.album?.images, - index: (track.value.album?.images?.length ?? 1) - 1, - ); - String duration = - "${track.value.duration?.inMinutes.remainder(60)}:${zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}"; - return TrackTile( - playback, - playlistId: playlistId, - track: track, - duration: duration, - thumbnailUrl: thumbnailUrl, - userPlaylist: userPlaylist, - onTrackPlayButtonPressed: onTrackPlayButtonPressed, - ); - }).toList() - ], - ), - ), - ); } } diff --git a/lib/hooks/useCustomStatusBarColor.dart b/lib/hooks/useCustomStatusBarColor.dart new file mode 100644 index 00000000..da2e5c47 --- /dev/null +++ b/lib/hooks/useCustomStatusBarColor.dart @@ -0,0 +1,38 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; + +void useCustomStatusBarColor(Color color, bool isCurrentRoute) { + final context = useContext(); + final backgroundColor = Theme.of(context).backgroundColor; + resetStatusbar() => SystemChrome.setSystemUIOverlayStyle( + SystemUiOverlayStyle( + statusBarColor: backgroundColor, // status bar color + statusBarIconBrightness: backgroundColor.computeLuminance() > 0.179 + ? Brightness.dark + : Brightness.light, + ), + ); + + final statusBarColor = SystemChrome.latestStyle?.statusBarColor; + + useEffect(() { + if (isCurrentRoute && statusBarColor != color) { + SystemChrome.setSystemUIOverlayStyle( + SystemUiOverlayStyle( + statusBarColor: color, // status bar color + statusBarIconBrightness: color.computeLuminance() > 0.179 + ? Brightness.dark + : Brightness.light, + ), + ); + } else if (!isCurrentRoute && statusBarColor == color) { + resetStatusbar(); + } + return; + }, [color, isCurrentRoute, statusBarColor]); + + useEffect(() { + return resetStatusbar; + }, []); +} diff --git a/lib/hooks/useHotKeys.dart b/lib/hooks/useHotKeys.dart index 94ad8f5a..e4989870 100644 --- a/lib/hooks/useHotKeys.dart +++ b/lib/hooks/useHotKeys.dart @@ -7,6 +7,7 @@ import 'package:spotube/hooks/playback.dart'; import 'package:spotube/models/GlobalKeyActions.dart'; import 'package:spotube/provider/Playback.dart'; import 'package:spotube/provider/UserPreferences.dart'; +import 'package:spotube/utils/platform.dart'; useHotKeys(WidgetRef ref) { final playback = ref.watch(playbackProvider); @@ -20,7 +21,7 @@ useHotKeys(WidgetRef ref) { final _playOrPause = useTogglePlayPause(playback); useEffect(() { - if (Platform.isIOS || Platform.isAndroid) return null; + if (kIsMobile) return null; _hotKeys = [ GlobalKeyActions( HotKey(KeyCode.space, scope: HotKeyScope.inapp), diff --git a/lib/main.dart b/lib/main.dart index eee7f9ba..4e6291cc 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,13 +16,9 @@ import 'package:spotube/provider/YouTube.dart'; import 'package:spotube/themes/dark-theme.dart'; import 'package:spotube/themes/light-theme.dart'; import 'package:spotube/utils/AudioPlayerHandler.dart'; +import 'package:spotube/utils/platform.dart'; void main() async { - // await JustAudioBackground.init( - // androidNotificationChannelId: 'oss.krtirtho.Spotube', - // androidNotificationChannelName: 'Spotube', - // androidNotificationOngoing: true, - // ); AudioPlayerHandler audioPlayerHandler = await AudioService.init( builder: () => AudioPlayerHandler(), config: const AudioServiceConfig( @@ -31,12 +27,11 @@ void main() async { androidNotificationOngoing: true, ), ); - if (!Platform.isAndroid && !Platform.isIOS) { + if (kIsDesktop) { WidgetsFlutterBinding.ensureInitialized(); await hotKeyManager.unregisterAll(); doWhenWindowReady(() { - appWindow.minSize = - Size(Platform.isAndroid || Platform.isIOS ? 280 : 359, 700); + appWindow.minSize = const Size(359, 700); appWindow.alignment = Alignment.center; appWindow.title = "Spotube"; appWindow.maximize(); @@ -75,6 +70,7 @@ class Spotube extends HookConsumerWidget { .watch(userPreferencesProvider.select((s) => s.backgroundColorScheme)); final player = ref.watch(audioPlayerProvider); final youtube = ref.watch(youtubeProvider); + useEffect(() { return () { player.dispose(); diff --git a/lib/models/GoRouteDeclarations.dart b/lib/models/GoRouteDeclarations.dart index 3d91cc0b..75666930 100644 --- a/lib/models/GoRouteDeclarations.dart +++ b/lib/models/GoRouteDeclarations.dart @@ -67,8 +67,8 @@ GoRouter createGoRouter() => GoRouter( GoRoute( path: "/player", pageBuilder: (context, state) { - return SpotubePage( - child: const PlayerView(), + return const SpotubePage( + child: PlayerView(), ); }, ) diff --git a/lib/provider/Auth.dart b/lib/provider/Auth.dart index 260b794d..40cdc4e2 100644 --- a/lib/provider/Auth.dart +++ b/lib/provider/Auth.dart @@ -72,7 +72,9 @@ class Auth extends PersistedChangeNotifier { _clientSecret = map["clientSecret"]; _accessToken = map["accessToken"]; _refreshToken = map["refreshToken"]; - _expiration = DateTime.tryParse(map["expiration"]); + _expiration = map["expiration"] != null + ? DateTime.tryParse(map["expiration"]) + : _expiration; } @override diff --git a/lib/utils/platform.dart b/lib/utils/platform.dart new file mode 100644 index 00000000..b7e2e090 --- /dev/null +++ b/lib/utils/platform.dart @@ -0,0 +1,5 @@ +import 'dart:io'; + +final kIsDesktop = Platform.isLinux || Platform.isWindows || Platform.isMacOS; + +final kIsMobile = Platform.isAndroid || Platform.isIOS;