createRouter function

GoRouter createRouter(
  1. BuildContext context
)

Implementation

GoRouter createRouter(BuildContext context) {
  final AuthenticationBloc authBloc = context.read<AuthenticationBloc>();
  final StartupCubit startupCubit = context.read<StartupCubit>();

  return GoRouter(
    navigatorKey: navigatorKey,
    initialLocation: AppRoutes.splash,
    observers: <NavigatorObserver>[SentryNavigatorObserver()],
    refreshListenable: GoRouterRefreshStream.merge(<Stream<dynamic>>[authBloc.stream, startupCubit.stream]),
    redirect: (BuildContext context, GoRouterState state) {
      final AuthenticationStatus authStatus = context.read<AuthenticationBloc>().state.status;
      final StartupState startupState = context.read<StartupCubit>().state;

      return resolveRedirect(
        isJailbroken: startupState.isJailbroken,
        startupStatus: startupState.status,
        authStatus: authStatus,
        location: state.matchedLocation,
      );
    },
    routes: <RouteBase>[
      GoRoute(path: AppRoutes.splash, builder: (BuildContext context, GoRouterState state) => const SplashView()),
      GoRoute(
        path: AppRoutes.jailbreak,
        builder: (BuildContext context, GoRouterState state) {
          final JailbreakAppException? exception = context.read<StartupCubit>().state.jailbreakException;
          // jailbreakException is guaranteed non-null here — the redirect
          // only sends to this route when isJailbroken is true, which
          // requires jailbreakDetected status and a populated exception.
          return JailbreakView(exception: exception!);
        },
      ),
      GoRoute(path: AppRoutes.login, builder: (BuildContext context, GoRouterState state) => const LoginPage()),
      GoRoute(path: AppRoutes.home, builder: (BuildContext context, GoRouterState state) => const HomePage()),
      GoRoute(path: AppRoutes.onboarding, builder: (BuildContext context, GoRouterState state) => const OnboardingView()),
    ],
    // Defense-in-depth backstop: the redirect guard above should resolve
    // every state to a known route, but if some future case ever slips
    // through unmatched, this renders an app-styled screen instead of
    // Flutter's default (unstyled) error widget.
    errorBuilder: (BuildContext context, GoRouterState state) => const _RouteErrorView(),
  );
}