import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:moneymgr_mobile/routes/login/login_screen.dart'; import 'package:moneymgr_mobile/routes/login/manual_auth_screen.dart'; import 'package:moneymgr_mobile/routes/settings/settings_screen.dart'; import 'package:moneymgr_mobile/services/auth_state.dart'; import 'package:moneymgr_mobile/services/router/routes_list.dart'; import 'package:moneymgr_mobile/widgets/scaffold_with_navigation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; part 'router.g.dart'; /// The router config for the app. @riverpod GoRouter router(Ref ref) { // Local notifier for the current auth state. The purpose of this notifier is // to provide a [Listenable] to the [GoRouter] exposed by this provider. final authStateNotifier = ValueNotifier(AuthState.unknown); ref ..onDispose(authStateNotifier.dispose) ..listen(currentAuthStateProvider, (_, value) { authStateNotifier.value = value; }); // This is the only place you need to define your navigation items. The items // will be propagated automatically to the router and the navigation bar/rail // of the scaffold. // // To configure the authentication state needed to access a particular item, // see [AuthState] enum. final navigationItems = [ NavigationItem( path: '/products', body: (_) => const Text("product screen"), icon: Icons.widgets_outlined, selectedIcon: Icons.widgets, label: 'Products', routes: [ GoRoute( path: ':id', builder: (_, state) { final id = int.parse(state.pathParameters['id']!); return Text("product screen $id"); }, ), ], ), NavigationItem( path: '/profile', body: (_) => const Text("Profile"), icon: Icons.person_outline, selectedIcon: Icons.person, label: 'Profile', ), ]; final router = GoRouter( debugLogDiagnostics: true, initialLocation: navigationItems.first.path, routes: [ GoRoute(path: homePage, builder: (_, __) => const Scaffold()), GoRoute(path: authPage, builder: (_, __) => const LoginScreen()), GoRoute( path: manualAuthPage, builder: (_, __) => const ManualAuthScreen(), ), GoRoute(path: settingsPage, builder: (_, __) => const SettingsScreen()), // Configuration for the bottom navigation bar routes. The routes themselves // should be defined in [navigationItems]. Modification to this [ShellRoute] // config is rarely needed. ShellRoute( builder: (_, __, child) => child, routes: [ for (final (index, item) in navigationItems.indexed) GoRoute( path: item.path, pageBuilder: (context, _) => NoTransitionPage( child: ScaffoldWithNavigation( selectedIndex: index, navigationItems: navigationItems, child: item.body(context), ), ), routes: item.routes, ), ], ), ], refreshListenable: authStateNotifier, redirect: (_, state) { // Get the current auth state. final authState = ref.read(currentAuthStateProvider); // Check if the current path is allowed for the current auth state. If not, // redirect to the redirect target of the current auth state. if (authState.allowedPaths?.contains(state.fullPath) == false) { return authState.redirectPath; } // If the current path is allowed for the current auth state, don't redirect. return null; }, ); ref.onDispose(router.dispose); return router; }