Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RouteGuard not working with auto tabs routes #1278

Closed
AlaaEldeenYsr opened this issue Nov 15, 2022 · 21 comments
Closed

RouteGuard not working with auto tabs routes #1278

AlaaEldeenYsr opened this issue Nov 15, 2022 · 21 comments

Comments

@AlaaEldeenYsr
Copy link

No description provided.

@KernelPanic92
Copy link

can you provide the sample code to reproduce the bug? The issue written like this is not workable 😔

@AlaaEldeenYsr
Copy link
Author

AlaaEldeenYsr commented Nov 16, 2022

I have here 4 tabs routes with AuthGuard attached to the NotificationsPage
the problem is when I navigate to the NotificationsPage the AuthGuard never get executed

part 'app_router.gr.dart';

@MaterialAutoRouter(
  replaceInRouteName: 'Page,Route',
  routes: <AutoRoute>[
    AutoRoute(
      page: HomePage,
      initial: true,
      children: [
        AutoRoute(
          page: LandingPage,
          initial: true,
          maintainState: true,
        ),
        AutoRoute(
          page: SchoolsListingPage,
          maintainState: true,
        ),
        AutoRoute(
          page: NotificationsPage,
          maintainState: true,
          guards: [AuthGuard],
        ),
        AutoRoute(
          page: NavigationMenuPage,
          maintainState: true,
        ),
      ],
    ),
    AutoRoute(
      page: AuthPage,
    ),
  ],
)
class AppRouter extends _$AppRouter {
  AppRouter() : super(authGuard: AuthGuard());

  static AppRouter get i => sl();
}

class AuthGuard extends AutoRouteGuard {
  @override
  void onNavigation(NavigationResolver resolver, StackRouter router) async {
    if (AuthHelper.isAuthenticated) {
      resolver.next(true);
    } else {
      await router.push(AuthRoute());
      if (AuthHelper.isAuthenticated) {
        resolver.next(true);
      }
    }
  }
}
    return AutoTabsRouter(
      routes: [
        LandingRoute(),
        SchoolsListingRoute(),
        NotificationsRoute(),
        NavigationMenuRoute(),
      ],
      builder: (context, child, animation) {
        final tabsRouter = AutoTabsRouter.of(context);

        return Scaffold(
          body: FadeTransition(
            opacity: animation,
            child: child,
          ),
          bottomNavigationBar: BottomNavigationBar(
            onTap: tabsRouter.setActiveIndex,
            currentIndex: tabsRouter.activeIndex,
            items: [
              BottomNavigationBarItem(icon: Assets.icons.homeSvg.svg(), label: "الرئيسية"),
              BottomNavigationBarItem(icon: Assets.icons.gridSvg.svg(), label: "بحث المدارس"),
              BottomNavigationBarItem(icon: Assets.icons.gridSvg.svg(), label: "الاشعارات"),
              BottomNavigationBarItem(icon: Assets.icons.nav.svg(), label: "القائمة"),
            ],
          ),
        );
      },
    );

@AlaaEldeenYsr
Copy link
Author

@KernelPanic92 Sample code above to reproduce the issue

@AlaaEldeenYsr AlaaEldeenYsr changed the title RouteGuard not working with AutoTabsScaffold routes RouteGuard not working with auto tabs routes Nov 16, 2022
@AlaaEldeenYsr
Copy link
Author

Support please @KernelPanic92

@Milad-Akarie
Copy link
Owner

@AlaaEldeenYsr AutoRouteGuard does not work with tabs yet, I'm considering working on it in the couple next days.
what are you expecting to happen thu?

@MpEliaz
Copy link

MpEliaz commented Nov 24, 2022

@Milad-Akarie pls! here same issue

@17martix
Copy link

facing same issue

@balaji101010
Copy link

Same issiuuu!!

@TerenceLimjc
Copy link

@Milad-Akarie any workarounds/alternatives that we can use to get around this issue? If you could share any article that'd help greatly :)

Also, this library is amazing so far, thanks for the hard work :)

@moneer-muntazah
Copy link

I was just gonna post a reproduction of this issue. Very confusing that the feature works with AutoRouter but not with AutoTabsRouter @Milad-Akarie I have another issue related to AutoTabsRouter #1275 please have a look

@Milad-Akarie
Copy link
Owner

@moneer-muntazah @TerenceLimjc guarding tab routes is not that simple especially tab routes that use pageView or tabView, in the these views routes are already added to the stack.
right now I'm working on a big refactor, after that I'll try to solve this issue.

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

@kitsuniru
Copy link

Will v6 fix that issue?

@skosyrskyv
Copy link

skosyrskyv commented Mar 23, 2023

Yes, it doesn't work because it's just a switcher inside. This will never work in current realization because switching pages without a router.
But I have solution: you can wrap your screen (https://pub.dev/packages/auto_route#wrapping-routes) and control access to your screen.

@github-actions
Copy link

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions

@adar2378
Copy link
Contributor

adar2378 commented Oct 3, 2023

Is there any progress on this? @Milad-Akarie

@CoderJerry
Copy link

Any progress on this

@Milad-Akarie
Copy link
Owner

@adar2378 @CoderJerry this is not a bug, guarding tabs is not supported.

@KernelPanic92
Copy link

KernelPanic92 commented Oct 18, 2023

@AlaaEldeenYsr This management doesn't make much sense from a functional standpoint: why give the user the ability to navigate to that element and then penalize them as soon as they do? A good interface should never allow the user to make a mistake.
What is your real goal here?
From what I can gather, IMHO, you have these options:

  • Disable the BottomNavigationItem when the user is not logged in.
  • Intercept the tap on the BottomNavigationItem and display an alert to request login before proceeding.
  • Change the content of Notifications based on the user's login status.
  • Create two sub-routes for Notifications, one for the logged-in user and one for the non-logged-in user.
  • Move the notification navigation button elsewhere and handle it in a specific way.

@adar2378
Copy link
Contributor

@Milad-Akarie I think maybe we should support it. Because reevaluate does not work on tab router. I have this use case

  • User accesses HomeTabRouter
  • User get's logged
  • context.router.reevaluateGuards() does not takes the user to login page because HomeTabRouter does not support guarding.

Do you recommend any other to take user to login page when there were logged out after the HomeTabRouter was pushed?

My router setup looks like this

AutoRoute(
          path: '/login',
          page: LoginRouter.page,
          children: loginRoutes,
        ),

        AutoRoute(
          page: HomeTabRouter.page,
          path: '/',
          guards: [
            if (accountsUsersDataBloc != null)
              UserRegistrationGuard(accountsUsersDataBloc),
          ],
          children: [
            AutoRoute(
              page: HomeTab.page,
              path: 'home',
              initial: true,
            ),
            AutoRoute(
              page: EmptyTab.page,
              path: 'empty',
            ),
            AutoRoute(
              path: 'settings',
              page: SettingsTab.page,
            ),
          ],
        ),

@wamynobe
Copy link

wamynobe commented Jan 5, 2024

What about get all these RouteMatch classes

void setupRoutes(List<PageRouteInfo> routes) {
    final routesToPush = _matchAllOrReportFailure(routes)!; //<------ get all these RouteMatch instances
    if (_routeData.hasPendingChildren) {
      final preMatchedRoute = _routeData.pendingChildren.last;
      final correspondingRouteIndex = routesToPush.indexWhere(
        (r) => r.key == preMatchedRoute.key,
      );
      if (correspondingRouteIndex != -1) {
        routesToPush[correspondingRouteIndex] = preMatchedRoute;
        _previousIndex = _activeIndex;
        _activeIndex = correspondingRouteIndex;
      }
    }

    if (routesToPush.isNotEmpty) {
      _pushAll(routesToPush);
    }
    _routeData.pendingChildren.clear();
  }

Then in setActiveIndex() function we check if we can navigate by checking if guard exist or not. If guard existed we call guard.onNavigation(...) function to execute resolver.redirect(...) that will push the LoginScreen.

void setActiveIndex(int index, {bool notify = true}) async {
    assert(index >= 0 && index < _pages.length);

    if (_activeIndex != index) {
      final match = routesToPush[index]; //<--- all RouteMatch instances we got when setupRoutes
      final canNavigate = _canNaviagate(...) //<--- check if we can navigate
      if (canNavigate) { //<--- if can navigate we update tab's index
        _previousIndex = _activeIndex;
        _activeIndex = index;
        if (notify) {
          notifyAll();
        }
      }
    }
  }

I do not know whether this approach works well or causes any errors. Just an idea!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests