✨ Rebuilt router with go router
This commit is contained in:
@@ -3,7 +3,7 @@ import 'package:groovybox/logic/audio_handler.dart';
|
|||||||
import 'package:groovybox/logic/window_helpers.dart';
|
import 'package:groovybox/logic/window_helpers.dart';
|
||||||
import 'package:groovybox/providers/audio_provider.dart';
|
import 'package:groovybox/providers/audio_provider.dart';
|
||||||
import 'package:groovybox/providers/theme_provider.dart';
|
import 'package:groovybox/providers/theme_provider.dart';
|
||||||
import 'package:groovybox/ui/shell.dart';
|
import 'package:groovybox/router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
import 'package:audio_service/audio_service.dart' as audio_service;
|
import 'package:audio_service/audio_service.dart' as audio_service;
|
||||||
@@ -52,14 +52,15 @@ class GroovyApp extends ConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final themeMode = ref.watch(themeProvider);
|
final themeMode = ref.watch(themeProvider);
|
||||||
|
final router = ref.watch(routerProvider);
|
||||||
|
|
||||||
return MaterialApp(
|
return MaterialApp.router(
|
||||||
title: 'GroovyBox',
|
title: 'GroovyBox',
|
||||||
debugShowCheckedModeBanner: false,
|
debugShowCheckedModeBanner: false,
|
||||||
theme: ref.watch(lightThemeProvider),
|
theme: ref.watch(lightThemeProvider),
|
||||||
darkTheme: ref.watch(darkThemeProvider),
|
darkTheme: ref.watch(darkThemeProvider),
|
||||||
themeMode: themeMode,
|
themeMode: themeMode,
|
||||||
home: const Shell(),
|
routerConfig: router,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
lib/router.dart
Normal file
59
lib/router.dart
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import 'package:go_router/go_router.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:groovybox/data/db.dart';
|
||||||
|
import 'package:groovybox/data/playlist_repository.dart';
|
||||||
|
import 'package:groovybox/ui/screens/album_detail_screen.dart';
|
||||||
|
import 'package:groovybox/ui/screens/library_screen.dart';
|
||||||
|
import 'package:groovybox/ui/screens/player_screen.dart';
|
||||||
|
import 'package:groovybox/ui/screens/playlist_detail_screen.dart';
|
||||||
|
import 'package:groovybox/ui/screens/settings_screen.dart';
|
||||||
|
import 'package:groovybox/ui/shell.dart';
|
||||||
|
|
||||||
|
// Route names
|
||||||
|
class AppRoutes {
|
||||||
|
static const String library = '/';
|
||||||
|
static const String player = '/player';
|
||||||
|
static const String settings = '/settings';
|
||||||
|
static const String albumDetail = '/album';
|
||||||
|
static const String playlistDetail = '/playlist';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Router provider that can be accessed from anywhere in the app
|
||||||
|
final routerProvider = Provider<GoRouter>((ref) {
|
||||||
|
return GoRouter(
|
||||||
|
initialLocation: AppRoutes.library,
|
||||||
|
routes: [
|
||||||
|
ShellRoute(
|
||||||
|
builder: (context, state, child) => Shell(child: child),
|
||||||
|
routes: [
|
||||||
|
GoRoute(
|
||||||
|
path: AppRoutes.library,
|
||||||
|
builder: (context, state) => const LibraryScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: AppRoutes.player,
|
||||||
|
builder: (context, state) => const PlayerScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: AppRoutes.settings,
|
||||||
|
builder: (context, state) => const SettingsScreen(),
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: AppRoutes.albumDetail,
|
||||||
|
builder: (context, state) {
|
||||||
|
final album = state.extra as AlbumData;
|
||||||
|
return AlbumDetailScreen(album: album);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
path: AppRoutes.playlistDetail,
|
||||||
|
builder: (context, state) {
|
||||||
|
final playlist = state.extra as Playlist;
|
||||||
|
return PlaylistDetailScreen(playlist: playlist);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -14,6 +14,7 @@ import 'package:groovybox/data/track_repository.dart';
|
|||||||
import 'package:groovybox/logic/lrc_providers.dart';
|
import 'package:groovybox/logic/lrc_providers.dart';
|
||||||
import 'package:groovybox/logic/lyrics_parser.dart';
|
import 'package:groovybox/logic/lyrics_parser.dart';
|
||||||
import 'package:groovybox/logic/metadata_service.dart';
|
import 'package:groovybox/logic/metadata_service.dart';
|
||||||
|
import 'package:groovybox/logic/window_helpers.dart';
|
||||||
import 'package:groovybox/providers/audio_provider.dart';
|
import 'package:groovybox/providers/audio_provider.dart';
|
||||||
import 'package:groovybox/providers/db_provider.dart';
|
import 'package:groovybox/providers/db_provider.dart';
|
||||||
import 'package:groovybox/providers/lrc_fetcher_provider.dart';
|
import 'package:groovybox/providers/lrc_fetcher_provider.dart';
|
||||||
@@ -151,7 +152,12 @@ class PlayerScreen extends HookConsumerWidget {
|
|||||||
builder: (context) {
|
builder: (context) {
|
||||||
if (isMobile) {
|
if (isMobile) {
|
||||||
return Padding(
|
return Padding(
|
||||||
padding: EdgeInsets.only(top: devicePadding.top + 40),
|
padding: EdgeInsets.only(
|
||||||
|
top:
|
||||||
|
devicePadding.top +
|
||||||
|
40 +
|
||||||
|
(isDesktopPlatform() ? 28 : 0),
|
||||||
|
),
|
||||||
child: _MobileLayout(
|
child: _MobileLayout(
|
||||||
player: player,
|
player: player,
|
||||||
viewMode: viewMode,
|
viewMode: viewMode,
|
||||||
@@ -171,7 +177,8 @@ class PlayerScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
// IconButton
|
// IconButton
|
||||||
Positioned(
|
Positioned(
|
||||||
top: MediaQuery.of(context).padding.top + 16,
|
top:
|
||||||
|
devicePadding.top + 16 + (isDesktopPlatform() ? 28 : 0),
|
||||||
left: 16,
|
left: 16,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: const Icon(Symbols.keyboard_arrow_down),
|
icon: const Icon(Symbols.keyboard_arrow_down),
|
||||||
@@ -1149,7 +1156,10 @@ class _ViewToggleButton extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Positioned(
|
return Positioned(
|
||||||
top: MediaQuery.of(context).padding.top + 16,
|
top:
|
||||||
|
MediaQuery.of(context).padding.top +
|
||||||
|
16 +
|
||||||
|
(isDesktopPlatform() ? 28 : 0),
|
||||||
right: 16,
|
right: 16,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
icon: Icon(getIcon()),
|
icon: Icon(getIcon()),
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:groovybox/data/track_repository.dart';
|
import 'package:groovybox/data/track_repository.dart';
|
||||||
import 'package:groovybox/providers/settings_provider.dart';
|
import 'package:groovybox/providers/settings_provider.dart';
|
||||||
import 'package:groovybox/providers/watch_folder_provider.dart';
|
import 'package:groovybox/providers/watch_folder_provider.dart';
|
||||||
@@ -434,6 +435,8 @@ class SettingsScreen extends ConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
// Gap for mini player
|
||||||
|
const Gap(80),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:groovybox/data/track_repository.dart';
|
import 'package:groovybox/data/track_repository.dart';
|
||||||
import 'package:groovybox/logic/lyrics_parser.dart';
|
import 'package:groovybox/logic/lyrics_parser.dart';
|
||||||
import 'package:groovybox/logic/window_helpers.dart';
|
import 'package:groovybox/logic/window_helpers.dart';
|
||||||
import 'package:groovybox/providers/settings_provider.dart';
|
import 'package:groovybox/providers/settings_provider.dart';
|
||||||
import 'package:groovybox/ui/screens/settings_screen.dart';
|
import 'package:groovybox/router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:path/path.dart' as p;
|
import 'package:path/path.dart' as p;
|
||||||
@@ -68,7 +69,9 @@ class _WindowMaximizeListener extends WindowListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Shell extends HookConsumerWidget {
|
class Shell extends HookConsumerWidget {
|
||||||
const Shell({super.key});
|
final Widget child;
|
||||||
|
|
||||||
|
const Shell({super.key, required this.child});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -106,11 +109,7 @@ class Shell extends HookConsumerWidget {
|
|||||||
|
|
||||||
final pageActionsButton = [
|
final pageActionsButton = [
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () => context.push(AppRoutes.settings),
|
||||||
Navigator.of(
|
|
||||||
context,
|
|
||||||
).push(MaterialPageRoute(builder: (context) => SettingsScreen()));
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.settings),
|
icon: const Icon(Symbols.settings),
|
||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
constraints: BoxConstraints(),
|
constraints: BoxConstraints(),
|
||||||
@@ -169,10 +168,7 @@ class Shell extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Symbols.home),
|
icon: Icon(Symbols.home),
|
||||||
onPressed: () => Navigator.of(context).pushAndRemoveUntil(
|
onPressed: () => context.go(AppRoutes.library),
|
||||||
MaterialPageRoute(builder: (context) => const LibraryScreen()),
|
|
||||||
(route) => false,
|
|
||||||
),
|
|
||||||
iconSize: 16,
|
iconSize: 16,
|
||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
constraints: BoxConstraints(),
|
constraints: BoxConstraints(),
|
||||||
@@ -246,13 +242,8 @@ class Shell extends HookConsumerWidget {
|
|||||||
// Settings button
|
// Settings button
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Symbols.settings),
|
icon: Icon(Symbols.settings),
|
||||||
onPressed: () {
|
onPressed: () =>
|
||||||
Navigator.of(context).push(
|
context.go(AppRoutes.settings),
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => SettingsScreen(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
iconSize: 16,
|
iconSize: 16,
|
||||||
padding: EdgeInsets.all(8),
|
padding: EdgeInsets.all(8),
|
||||||
constraints: BoxConstraints(),
|
constraints: BoxConstraints(),
|
||||||
@@ -391,7 +382,7 @@ class Shell extends HookConsumerWidget {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
// Main Content
|
// Main Content
|
||||||
Positioned.fill(child: LibraryScreen()),
|
Positioned.fill(child: child),
|
||||||
// Mini Player
|
// Mini Player
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 0,
|
left: 0,
|
||||||
@@ -420,7 +411,7 @@ class Shell extends HookConsumerWidget {
|
|||||||
child: Stack(
|
child: Stack(
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [
|
children: [
|
||||||
Positioned.fill(child: LibraryScreen()),
|
Positioned.fill(child: child),
|
||||||
Positioned(left: 0, right: 0, bottom: 0, child: MiniPlayer()),
|
Positioned(left: 0, right: 0, bottom: 0, child: MiniPlayer()),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -544,6 +544,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.3"
|
version: "2.1.3"
|
||||||
|
go_router:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: go_router
|
||||||
|
sha256: f02fd7d2a4dc512fec615529824fdd217fecb3a3d3de68360293a551f21634b3
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "14.8.1"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ dependencies:
|
|||||||
flutter_cache_manager: ^3.4.1
|
flutter_cache_manager: ^3.4.1
|
||||||
material_symbols_icons: ^4.2892.0
|
material_symbols_icons: ^4.2892.0
|
||||||
window_manager: ^0.5.1
|
window_manager: ^0.5.1
|
||||||
|
go_router: ^14.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user