diff --git a/lib/collections/assets.gen.dart b/lib/collections/assets.gen.dart index fa7cfee7..2dd9650e 100644 --- a/lib/collections/assets.gen.dart +++ b/lib/collections/assets.gen.dart @@ -44,6 +44,13 @@ class Assets { static const String spotubeLogoSvg = 'assets/spotube-logo.svg'; static const AssetGenImage spotubeLogoAndroid12 = AssetGenImage('assets/spotube-logo_android12.png'); + static const AssetGenImage spotubeNightlyLogoForeground = + AssetGenImage('assets/spotube-nightly-logo-foreground.jpg'); + static const AssetGenImage spotubeNightlyLogoPng = + AssetGenImage('assets/spotube-nightly-logo.png'); + static const String spotubeNightlyLogoSvg = 'assets/spotube-nightly-logo.svg'; + static const AssetGenImage spotubeNightlyLogoAndroid12 = + AssetGenImage('assets/spotube-nightly-logo_android12.png'); static const AssetGenImage spotubeScreenshot = AssetGenImage('assets/spotube-screenshot.png'); static const AssetGenImage spotubeBanner = @@ -65,6 +72,10 @@ class Assets { spotubeLogoPng, spotubeLogoSvg, spotubeLogoAndroid12, + spotubeNightlyLogoForeground, + spotubeNightlyLogoPng, + spotubeNightlyLogoSvg, + spotubeNightlyLogoAndroid12, spotubeScreenshot, spotubeBanner, success, diff --git a/lib/collections/intents.dart b/lib/collections/intents.dart index 4b5deac0..8c7ea73b 100644 --- a/lib/collections/intents.dart +++ b/lib/collections/intents.dart @@ -1,5 +1,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_desktop_tools/flutter_desktop_tools.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:spotube/components/player/player_controls.dart'; @@ -8,7 +9,6 @@ import 'package:spotube/models/logger.dart'; import 'package:spotube/provider/proxy_playlist/proxy_playlist_provider.dart'; import 'package:spotube/services/audio_player/audio_player.dart'; import 'package:spotube/utils/platform.dart'; -import 'package:window_manager/window_manager.dart'; class PlayPauseIntent extends Intent { final WidgetRef ref; @@ -115,7 +115,7 @@ class CloseAppAction extends Action { @override invoke(intent) { if (kIsDesktop) { - windowManager.close(); + DesktopTools.window.close(); } else { SystemNavigator.pop(); } diff --git a/lib/components/root/sidebar.dart b/lib/components/root/sidebar.dart index dcbc2c39..0dc8b5b4 100644 --- a/lib/components/root/sidebar.dart +++ b/lib/components/root/sidebar.dart @@ -69,8 +69,17 @@ class Sidebar extends HookConsumerWidget { Color.lerp(bg, Colors.black, 0.45)!, ); - final sidebarTileList = - useMemoized(() => getSidebarTileList(context.l10n), [context.l10n]); + final sidebarTileList = useMemoized( + () => getSidebarTileList(context.l10n), + [context.l10n], + ); + + useEffect(() { + if (controller.selectedIndex != selectedIndex) { + controller.selectIndex(selectedIndex); + } + return null; + }, [selectedIndex]); useEffect(() { controller.addListener(() { diff --git a/lib/components/shared/page_window_title_bar.dart b/lib/components/shared/page_window_title_bar.dart index 0d35a428..b1086eed 100644 --- a/lib/components/shared/page_window_title_bar.dart +++ b/lib/components/shared/page_window_title_bar.dart @@ -4,7 +4,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/utils/platform.dart'; import 'package:titlebar_buttons/titlebar_buttons.dart'; -import 'package:window_manager/window_manager.dart'; import 'dart:math'; import 'package:flutter/foundation.dart' show kIsWeb; import 'dart:io' show Platform; @@ -18,7 +17,7 @@ final closeNotification = DesktopTools.createNotification( LocalNotificationAction(text: 'Close The App'), ], )?..onClickAction = (value) { - windowManager.close(); + DesktopTools.window.close(); }; class PageWindowTitleBar extends StatefulHookConsumerWidget @@ -114,16 +113,16 @@ class WindowTitleBarButtons extends HookConsumerWidget { Future onClose() async { if (preferences.closeBehavior == CloseBehavior.close) { - await windowManager.close(); + await DesktopTools.window.close(); } else { - await windowManager.hide(); + await DesktopTools.window.hide(); await closeNotification?.show(); } } useEffect(() { if (kIsDesktop) { - windowManager.isMaximized().then((value) { + DesktopTools.window.isMaximized().then((value) { isMaximized.value = value; }); } @@ -160,14 +159,14 @@ class WindowTitleBarButtons extends HookConsumerWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ MinimizeWindowButton( - onPressed: windowManager.minimize, + onPressed: DesktopTools.window.minimize, colors: colors, ), if (isMaximized.value != true) MaximizeWindowButton( colors: colors, onPressed: () { - windowManager.maximize(); + DesktopTools.window.maximize(); isMaximized.value = true; }, ) @@ -175,7 +174,7 @@ class WindowTitleBarButtons extends HookConsumerWidget { RestoreWindowButton( colors: colors, onPressed: () { - windowManager.unmaximize(); + DesktopTools.window.unmaximize(); isMaximized.value = false; }, ), @@ -195,16 +194,16 @@ class WindowTitleBarButtons extends HookConsumerWidget { children: [ DecoratedMinimizeButton( type: type, - onPressed: windowManager.minimize, + onPressed: DesktopTools.window.minimize, ), DecoratedMaximizeButton( type: type, onPressed: () async { - if (await windowManager.isMaximized()) { - await windowManager.unmaximize(); + if (await DesktopTools.window.isMaximized()) { + await DesktopTools.window.unmaximize(); isMaximized.value = false; } else { - await windowManager.maximize(); + await DesktopTools.window.maximize(); isMaximized.value = true; } }, diff --git a/lib/extensions/duration.dart b/lib/extensions/duration.dart index c8612425..ff670b1a 100644 --- a/lib/extensions/duration.dart +++ b/lib/extensions/duration.dart @@ -37,3 +37,13 @@ extension DurationToHumanReadableString on Duration { abbreviated: abbreviated, ); } + +extension ParseDuration on Duration { + static Duration fromString(String duration) { + final parts = duration.split(':').reversed.toList(); + final seconds = int.parse(parts[0]); + final minutes = parts.length > 1 ? int.parse(parts[1]) : 0; + final hours = parts.length > 2 ? int.parse(parts[2]) : 0; + return Duration(hours: hours, minutes: minutes, seconds: seconds); + } +} diff --git a/lib/main.dart b/lib/main.dart index fa1a53b7..595cc1e0 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -204,9 +204,7 @@ class SpotubeState extends ConsumerState { GlobalWidgetsLocalizations.delegate, GlobalCupertinoLocalizations.delegate, ], - routeInformationParser: router.routeInformationParser, - routerDelegate: router.routerDelegate, - routeInformationProvider: router.routeInformationProvider, + routerConfig: router, debugShowCheckedModeBanner: false, title: 'Spotube', builder: (context, child) { @@ -229,22 +227,22 @@ class SpotubeState extends ConsumerState { LogicalKeySet(LogicalKeyboardKey.comma, LogicalKeyboardKey.control): NavigationIntent(router, "/settings"), LogicalKeySet( - LogicalKeyboardKey.keyB, + LogicalKeyboardKey.digit1, LogicalKeyboardKey.control, LogicalKeyboardKey.shift, ): HomeTabIntent(ref, tab: HomeTabs.browse), LogicalKeySet( - LogicalKeyboardKey.keyS, + LogicalKeyboardKey.digit2, LogicalKeyboardKey.control, LogicalKeyboardKey.shift, ): HomeTabIntent(ref, tab: HomeTabs.search), LogicalKeySet( - LogicalKeyboardKey.keyL, + LogicalKeyboardKey.digit3, LogicalKeyboardKey.control, LogicalKeyboardKey.shift, ): HomeTabIntent(ref, tab: HomeTabs.library), LogicalKeySet( - LogicalKeyboardKey.keyY, + LogicalKeyboardKey.digit4, LogicalKeyboardKey.control, LogicalKeyboardKey.shift, ): HomeTabIntent(ref, tab: HomeTabs.lyrics), diff --git a/lib/pages/root/root_app.dart b/lib/pages/root/root_app.dart index 9f343539..9e6610c5 100644 --- a/lib/pages/root/root_app.dart +++ b/lib/pages/root/root_app.dart @@ -1,5 +1,6 @@ import 'dart:async'; +import 'package:collection/collection.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; @@ -39,6 +40,21 @@ class RootApp extends HookConsumerWidget { final downloader = ref.watch(downloadManagerProvider); final scaffoldMessenger = ScaffoldMessenger.of(context); final theme = Theme.of(context); + final location = GoRouterState.of(context).matchedLocation; + + useEffect(() { + final newIndex = rootPaths.entries.firstWhereOrNull((e) { + if (e.value == "/" || location == "/") { + return location == e.value; + } + return location.startsWith(e.value); + })?.key; + if (newIndex != null) { + index.value = newIndex; + } + + return null; + }, [location]); useEffect(() { WidgetsBinding.instance.addPostFrameCallback((_) async {