diff --git a/client/lib/core/router/app_router.dart b/client/lib/core/router/app_router.dart index 70378a0..5de2657 100644 --- a/client/lib/core/router/app_router.dart +++ b/client/lib/core/router/app_router.dart @@ -22,21 +22,38 @@ import '../../features/products/product_provider.dart'; import '../../shared/models/recipe.dart'; import '../../shared/models/saved_recipe.dart'; +// Notifies GoRouter when auth state changes without recreating the router. +class _RouterNotifier extends ChangeNotifier { + _RouterNotifier(Ref ref) { + ref.listen(authProvider, (_, __) => notifyListeners()); + } +} + final routerProvider = Provider((ref) { - final authState = ref.watch(authProvider); + final notifier = _RouterNotifier(ref); + ref.onDispose(notifier.dispose); return GoRouter( - initialLocation: '/home', + initialLocation: '/loading', + refreshListenable: notifier, redirect: (context, state) { + // Use ref.read — this runs inside GoRouter, not inside a Riverpod build. + final authState = ref.read(authProvider); final isLoggedIn = authState.status == AuthStatus.authenticated; final isAuthRoute = state.matchedLocation.startsWith('/auth'); - if (authState.status == AuthStatus.unknown) return null; + // Show splash until the stored-token check completes. + if (authState.status == AuthStatus.unknown) return '/loading'; if (!isLoggedIn && !isAuthRoute) return '/auth/login'; if (isLoggedIn && isAuthRoute) return '/home'; return null; }, routes: [ + // Splash shown while auth status is unknown. + GoRoute( + path: '/loading', + builder: (_, __) => const _SplashScreen(), + ), GoRoute( path: '/auth/login', builder: (_, __) => const LoginScreen(), @@ -118,6 +135,15 @@ final routerProvider = Provider((ref) { ); }); +class _SplashScreen extends StatelessWidget { + const _SplashScreen(); + + @override + Widget build(BuildContext context) => const Scaffold( + body: Center(child: CircularProgressIndicator()), + ); +} + class _InvalidRoute extends StatelessWidget { const _InvalidRoute();