Rebuilt router with go router

This commit is contained in:
2025-12-20 14:10:49 +08:00
parent 149383155f
commit 902f5589f5
7 changed files with 99 additions and 26 deletions

View File

@@ -3,7 +3,7 @@ import 'package:groovybox/logic/audio_handler.dart';
import 'package:groovybox/logic/window_helpers.dart';
import 'package:groovybox/providers/audio_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:media_kit/media_kit.dart';
import 'package:audio_service/audio_service.dart' as audio_service;
@@ -52,14 +52,15 @@ class GroovyApp extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final themeMode = ref.watch(themeProvider);
final router = ref.watch(routerProvider);
return MaterialApp(
return MaterialApp.router(
title: 'GroovyBox',
debugShowCheckedModeBanner: false,
theme: ref.watch(lightThemeProvider),
darkTheme: ref.watch(darkThemeProvider),
themeMode: themeMode,
home: const Shell(),
routerConfig: router,
);
}
}

59
lib/router.dart Normal file
View 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);
},
),
],
),
],
);
});

View File

@@ -14,6 +14,7 @@ import 'package:groovybox/data/track_repository.dart';
import 'package:groovybox/logic/lrc_providers.dart';
import 'package:groovybox/logic/lyrics_parser.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/db_provider.dart';
import 'package:groovybox/providers/lrc_fetcher_provider.dart';
@@ -151,7 +152,12 @@ class PlayerScreen extends HookConsumerWidget {
builder: (context) {
if (isMobile) {
return Padding(
padding: EdgeInsets.only(top: devicePadding.top + 40),
padding: EdgeInsets.only(
top:
devicePadding.top +
40 +
(isDesktopPlatform() ? 28 : 0),
),
child: _MobileLayout(
player: player,
viewMode: viewMode,
@@ -171,7 +177,8 @@ class PlayerScreen extends HookConsumerWidget {
),
// IconButton
Positioned(
top: MediaQuery.of(context).padding.top + 16,
top:
devicePadding.top + 16 + (isDesktopPlatform() ? 28 : 0),
left: 16,
child: IconButton(
icon: const Icon(Symbols.keyboard_arrow_down),
@@ -1149,7 +1156,10 @@ class _ViewToggleButton extends StatelessWidget {
}
return Positioned(
top: MediaQuery.of(context).padding.top + 16,
top:
MediaQuery.of(context).padding.top +
16 +
(isDesktopPlatform() ? 28 : 0),
right: 16,
child: IconButton(
icon: Icon(getIcon()),

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:gap/gap.dart';
import 'package:groovybox/data/track_repository.dart';
import 'package:groovybox/providers/settings_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),
],
),
),

View File

@@ -4,11 +4,12 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:gap/gap.dart';
import 'package:go_router/go_router.dart';
import 'package:groovybox/data/track_repository.dart';
import 'package:groovybox/logic/lyrics_parser.dart';
import 'package:groovybox/logic/window_helpers.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:material_symbols_icons/symbols.dart';
import 'package:path/path.dart' as p;
@@ -68,7 +69,9 @@ class _WindowMaximizeListener extends WindowListener {
}
class Shell extends HookConsumerWidget {
const Shell({super.key});
final Widget child;
const Shell({super.key, required this.child});
@override
Widget build(BuildContext context, WidgetRef ref) {
@@ -106,11 +109,7 @@ class Shell extends HookConsumerWidget {
final pageActionsButton = [
IconButton(
onPressed: () {
Navigator.of(
context,
).push(MaterialPageRoute(builder: (context) => SettingsScreen()));
},
onPressed: () => context.push(AppRoutes.settings),
icon: const Icon(Symbols.settings),
padding: EdgeInsets.all(8),
constraints: BoxConstraints(),
@@ -169,10 +168,7 @@ class Shell extends HookConsumerWidget {
),
IconButton(
icon: Icon(Symbols.home),
onPressed: () => Navigator.of(context).pushAndRemoveUntil(
MaterialPageRoute(builder: (context) => const LibraryScreen()),
(route) => false,
),
onPressed: () => context.go(AppRoutes.library),
iconSize: 16,
padding: EdgeInsets.all(8),
constraints: BoxConstraints(),
@@ -246,13 +242,8 @@ class Shell extends HookConsumerWidget {
// Settings button
IconButton(
icon: Icon(Symbols.settings),
onPressed: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SettingsScreen(),
),
);
},
onPressed: () =>
context.go(AppRoutes.settings),
iconSize: 16,
padding: EdgeInsets.all(8),
constraints: BoxConstraints(),
@@ -391,7 +382,7 @@ class Shell extends HookConsumerWidget {
child: Stack(
children: [
// Main Content
Positioned.fill(child: LibraryScreen()),
Positioned.fill(child: child),
// Mini Player
Positioned(
left: 0,
@@ -420,7 +411,7 @@ class Shell extends HookConsumerWidget {
child: Stack(
fit: StackFit.expand,
children: [
Positioned.fill(child: LibraryScreen()),
Positioned.fill(child: child),
Positioned(left: 0, right: 0, bottom: 0, child: MiniPlayer()),
],
),

View File

@@ -544,6 +544,14 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: transitive
description:

View File

@@ -61,6 +61,7 @@ dependencies:
flutter_cache_manager: ^3.4.1
material_symbols_icons: ^4.2892.0
window_manager: ^0.5.1
go_router: ^14.2.0
dev_dependencies:
flutter_test: