I am trying to figure out how to make use of Firebase's onAuthStateChanges()
stream to use as a Listenable in the refreshListenable
parameter from the go_router package to redirect whenever the authState changes.
In additon I am using flutter_riverpod for State Mangement.
My code looks like this so far:
I created a simple AuthService class (shrinked down to the most important parts):
abstract class BaseAuthService {
Stream<bool> get isLoggedIn;
Future<bool> signInWithEmailAndPassword({ required String email, required String password });
}
class AuthService implements BaseAuthService {
final Reader _read;
const AuthService(this._read);
FirebaseAuth get auth => _read(firebaseAuthProvider);
@override
Stream<bool> get isLoggedIn => auth.authStateChanges().map((User? user) => user != null);
@override
Future<bool> signInWithEmailAndPassword({ required String email, required String password }) async {
try {
await auth.signInWithEmailAndPassword(email: email, password: password);
return true;
} on FirebaseAuthException catch (e) {
...
} catch (e) {
...
}
return false;
}
Next I created these providers:
final firebaseAuthProvider = Provider.autoDispose<FirebaseAuth>((ref) => FirebaseAuth.instance);
final authServiceProvider = Provider.autoDispose<AuthService>((ref) => AuthService(ref.read));
As mentioned before, I would like to somehow listen to these authChanges and pass them to the router:
final router = GoRouter(
refreshListenable: ???
redirect: (GoRouterState state) {
bool isLoggedIn = ???
if (!isLoggedIn && !onAuthRoute) redirect to /signin;
}
)
According to the go_router documentation, you can simply use the following method: https://gorouter.dev/redirection#refreshing-with-a-stream
GoRouterRefreshStream(_fooBloc.stream)
UPDATE: 20/9/2022
This class is removed from go_router 5.0, and there is no alternative class provided in go_router. The reason being that this class is unrelated to routing and should not be included in go_router. To migrate existing applications that use this class, one can copy the class to their code and own the implementation directly.
import 'dart:async';
import 'package:flutter/foundation.dart';
class GoRouterRefreshStream extends ChangeNotifier {
GoRouterRefreshStream(Stream<dynamic> stream) {
notifyListeners();
_subscription = stream.asBroadcastStream().listen(
(dynamic _) => notifyListeners(),
);
}
late final StreamSubscription<dynamic> _subscription;
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}