onNavigation method

  1. @override
void onNavigation(
  1. NavigationResolver resolver,
  2. StackRouter router
)

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);
          },
        );
  }
}