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

[Question] Parallel routes auto redirect #35

Closed
fabriciovergara opened this issue Apr 11, 2020 · 2 comments
Closed

[Question] Parallel routes auto redirect #35

fabriciovergara opened this issue Apr 11, 2020 · 2 comments

Comments

@fabriciovergara
Copy link

fabriciovergara commented Apr 11, 2020

Hi, I'm quite new to flutter world and I've been trying something to implement automatic route redirect based on current authentication state. I haven't found material about that and most of them is to have manual implementation that in a authenticated route keep listening if was unauthenticated, and then navigate back.

Then I got more or less the result that I was looking applying something that I used in RN and Native projects, but I wonder if there is any suggested way to do so.

                          -> HomePage -> SettingsPage
App -> AuthenticationPage  
                          -> LoginPage -> RegisterPage

When user login on LoginPage, it would navigate automatically to HomePage
When user logout on SettingsPage, it would navigate automatically to LoginPage

class AuthenticationPage extends StatefulWidget {
  const AuthenticationPage({Key key}) : super(key: key);

  @override
  _AuthenticationPageState createState() => _AuthenticationPageState();
}

class _AuthenticationPageState extends ModularState<AuthenticationPage, AuthenticationController> {
  @override
  void initState() {
    super.initState();
    // addPostFrameCallback is documented to be triggered only once, then listener is discarded
    WidgetsBinding.instance.addPostFrameCallback((_) => autorun((_) => _onRegisterNavigation()));
  }

  void _onRegisterNavigation() {
    final AuthenticationState authenticationState = controller.authenticationState;
    if (authenticationState is AuthenticatedAuthenticationState) {
      Get.offNamedUntil("/home", ModalRoute.withName(Modular.initialRoute)).then((_) => _onHandleRouteReturn());
    } else if (authenticationState is UnauthenticatedAuthenticationState) {
      Get.offNamedUntil("/login", ModalRoute.withName(Modular.initialRoute)).then((_) => _onHandleRouteReturn());
    } else {
      throw UnimplementedError("Not supported $authenticationState");
    }
  }

  void _onHandleRouteReturn() {
    if (!Get.key.currentState.canPop()) {
      SystemNavigator.pop();
    }
  }

  @override
  Widget build(BuildContext context) {
    return Container(
      width: 0,
      height: 0,
      color: Theme.of(context).backgroundColor,
    );
  }
}
@jonataslaw
Copy link
Owner

Its implementation is totally correct! Are you experiencing any problems with this or just want to confirm that you are doing everything right? Everything seems to be ok for me, and even following good practices.

Personally use SchedulerBinding.instance instead of WidgetsBinding.instance, because it allows you to listen to the end of the build method outside a Stateful and create a "SplashScreen" screen (similar to your authentication screen) to be more user friendly and display a loading, and put all authentication logic in my class's controller.
I also use modular, and my approach is no more correct than yours, maybe it's a different, but equivalent standard, and your logic is correct.
Even though you were a beginner, you managed to do everything correctly. I just wouldn't use SystemNavigator.pop(); because I’ve already had apps rejected on the AppleStore for "unexpected app exit". Test this first on iOS, and see that there is backGesture, and if it makes the app exit, if so, change your code to:

if (! Get.key.currentState.canPop () && GetPlatform.isAndroid) {
      SystemNavigator.pop();
 }

In android this behavior is expected, but in iOS it goes against human guidelines, and you can face problems.

If your application is only android, there is no need to follow this tip.
If your application has a web/PWA version, don't use Flutter's Platform.isAndroid, it imports Dart: io which is incompatible with the WEB (I had to create GetPlatform precisely to give full web support, and I left this Get API exposed for those who need to use it).

@fabriciovergara
Copy link
Author

fabriciovergara commented Apr 12, 2020

Thanks for your feedback, I'll take a look in this SchedulerBinding documentatio - I was trying to find something like that, but WidgetBinding was looking too much as ViewLayer stuff to put in the Controller/ViewModel

And yes, i just wanted to confirm if this approach is correct using your library.

I have to add this SystemNavigator.pop() because after user press back from /home it's redirect to this empty screen, that shouldn't be visible in this time being considering /home /login as the first item of the navigation stack, I just wanted to close the app when reach this point.

Tried to handle with RouteObserver instead of listening a Future, but for some reason it wasn't been called when I get back to / path, was trying to read the source code, but haven't found the reason yet.

Edit: Acabei de ver que voce tem um repositorio em portugues.
Muito obrigado pelas dicas e por esta biblioteca :)

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

No branches or pull requests

2 participants