onNavigation method
clients will call resolver.next(true --> default)
to continue
navigation or resolver.next(false)
to abort navigation
example
Implementation
@override
void onNavigation(NavigationResolver resolver, StackRouter router) async {
// final authBloc = await GetIt.instance.get<AuthenticationBasicBloc>();
// the navigation is paused until resolver.next() is called with either
// true to resume/continue navigation or false to abort navigation
if (authBloc.state.authenticated && !authBloc.state.authenticationData!.expired) {
// if user is authenticated we continue
return resolver.next(true);
// lets check if the session has expired
} else if (authBloc.state.authenticated && authBloc.state.authenticationData!.expired) {
// let's try to force a fetch user so it triggers a refresh session if necessary
authBloc.fetchUser();
// if the user configured the refreshApiEndpoint, lets wait for it to return a refreshed session or failure
if (authBloc.config.refreshTokenAPIendpoint != null || authBloc.config.customRefreshTokenCallback != null) {
final Either<Failure, bool> result = await authBloc
.events()
.where(
(event) {
return event is RefreshTokenSuccess || event is RefreshTokenError;
},
)
.map((event) {
if (event is RefreshTokenSuccess) {
return right<Failure, bool>(true);
} else {
return left<Failure, bool>((event as RefreshTokenError).failure);
}
})
.timeout(const Duration(seconds: 10))
// lets give it a moment so the bloc/service set the new session on state
.delay(const Duration(milliseconds: 200))
// do nothing on error we still be checking if session have changed
.onErrorReturnWith(
(error, stackTrace) {
return left(UnknownFailure.fromException(error));
},
)
.first;
result.fold((l) {
resolver.next(false);
if (onRefreshTokenFailure != null) {
onRefreshTokenFailure?.call(router, l);
} else {
onUnauthorized?.call(router);
}
}, (r) {
return resolver.next(true);
});
} else {
resolver.next(false);
return onUnauthorized?.call(router);
}
// check if authentication have been checked if so there's nothing to do, abort
} else if (authBloc.initialAuthChecked) {
resolver.next(false);
// we redirect the user to our login page
return onUnauthorized?.call(router);
} else {
// for some reason this guard have been caller to soon on the app , common behavior on deeplink navigation
// lets wait for the auth to be checked and retry it again
authBloc.stream
.where((state) {
return state.authChecked;
})
.take(1)
.listen(
(event) {
onNavigation(resolver, router);
},
);
}
}