Created
September 7, 2023 16:08
-
-
Save michael-wang/180445c1f1755057f933fb323c424776 to your computer and use it in GitHub Desktop.
[riverpod] Auth async provider as Listener (for RoRouter.refreshListenable)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
part 'auth.g.dart'; | |
// The key to become Listenable, is to implement Listenable... | |
// And notify listener when state changed of course. | |
@Riverpod(keepAlive: true) | |
class Auth extends _$Auth implements Listenable { | |
VoidCallback? _callback; | |
@override | |
void addListener(VoidCallback listener) { | |
_callback = listener; | |
} | |
@override | |
void removeListener(VoidCallback listener) { | |
if (_callback == listener) { | |
_callback = null; | |
} | |
} | |
@override | |
FutureOr<User?> build() async { | |
// Listen to self so we can notify listener's callback. | |
ref.listenSelf((_, __) { | |
if (state.isLoading) return; | |
_callback?.call(); | |
}); | |
// Listen to Firebase auth state. | |
fb.FirebaseAuth.instance.authStateChanges().listen(_firebaseAuthListener); | |
return null; | |
} | |
signIn(String email, String password) async { | |
await fb.FirebaseAuth.instance.signInWithEmailAndPassword(email: email, password: password); | |
} | |
signOut() async { | |
await fb.FirebaseAuth.instance.signOut(); | |
} | |
void _firebaseAuthListener(fb.User? fbUser) async { | |
update((_) async { | |
// Convert Firebase user to domain user. | |
return fbUser == null ? null : DomainUser(fbUser); | |
}); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
viud main() { | |
runApp( | |
ProviderScope( | |
child: App(), | |
), | |
); | |
} | |
class App extends ConsumerWidget with ScreenMixin { | |
const App({Key? key}) : super(key: key); | |
@override | |
Widget build(BuildContext context, WidgetRef ref) { | |
return ref.watch(routerProvider()).when( | |
data: (router) { | |
return MaterialApp.router( | |
routerConfig: router, | |
// ... | |
); | |
}, | |
error: //... | |
loading: //... | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
part 'router.g.dart'; | |
@riverpod | |
FutureOr<Raw<GoRouter>> router(RouterRef ref) async { | |
final user = await ref.watch(authProvider.future); | |
return GoRouter( | |
refreshListenable: ref.watch(authProvider.notifier), | |
routes: [ | |
//... | |
], | |
redirect: (context, state) { | |
final signedIn = user != null; | |
// redirect according to signed-in state. | |
} | |
); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment