Reputation: 176
I've been trying to implement navigation from login page to home page based on authentication status from firebase. Untill now Ive had this simply done with bloc listener (therefore I know the whole auth thing works).
Flutter docs recomend using go_router for navigation so I want to use it, and following this docs I was able to achieve this- up to a point: https://github.com/flutter/packages/blob/main/packages/go_router/example/lib/async_redirection.dart
Problem: upon new events in the authentication stream, go_router redirect
is not called (and widgets are not rebuild), even if ChangeNotifier
trigger notifyListeners
.
In this whole picture I distinguish four components:
Do you have any hints on what am I doing wrong or missing here?
I know there are two thing I do differently from docs example:
I've read this question, but there are alternative solutions to my problem there, and before I try this I'd like to at least understand if this docs approach is doable : Reactive redirection using go_router and flutter_bloc with Auth and UnAuth Flow
ROUTER :
GoRouter(
redirect: (context, state) async {
// This part is different from docs example, as I use the firebase client directly here, not the AuthNotifier from context
final currentUser =
await RepositoryProvider.of<auth_repo.FirebaseAuthenticator>(
context,
listen: false)
.currentUserStream()
.first;
// CORRECT USER IS RECEIVED HERE
bool? isSignedIn = await currentUser?.isSignedIn();
final bool loggingIn = state.matchedLocation == '/login';
if (loggingIn || isSignedIn == null || isSignedIn == false) {
return '/login';
}
if (isSignedIn) {
return '/home';
}
return null;
},
routes: <RouteBase>[
GoRoute(
path: '/home',
builder: (BuildContext context, GoRouterState state) {
return const HomePage();
},
routes: <RouteBase>[
GoRoute(
path: 'account',
builder: (BuildContext context, GoRouterState state) {
return AccountPage();
},
),
],
),
GoRoute(
path: '/login',
builder: (BuildContext context, GoRouterState state) {
return const LoginPage();
},
),
],
);
AuthChangeNotifier
class AuthChangeNotifier extends ChangeNotifier {
Stream<auth_repo.User> userStream;
AuthChangeNotifier(this.userStream) {
userStream.asBroadcastStream().listen((_) {
notifyListeners(); // THIS GETS CALLED
});
}
}
AuthNotifier
class AuthNotifier extends InheritedNotifier<AuthChangeNotifier> {
AuthNotifier({
Key? key,
required auth_repo.AuthenticatorInterface authenticator,
required Widget child,
}) : super(
key: key,
notifier: AuthChangeNotifier(authenticator.currentUserStream()),
child: child,
);
static Stream<auth_repo.User> of(BuildContext context) {
final AuthChangeNotifier? result =
context.dependOnInheritedWidgetOfExactType<AuthNotifier>()!.notifier;
if (result == null) {
throw FlutterError(
'AuthNotifier.of() called with a context that does not contain an AuthNotifier.');
}
return result.userStream;
}
}
Use of AuthNotifier
// This part is different from docs, as before I use AuthNotifier, I instantiate all blocs and providers
return _blocProvider(
_repositoryProvider(
AuthNotifier(authenticator: _authenticator, child: const MyApp()),
),
);
Upvotes: 0
Views: 41