FilledStacks / flutter-tutorials

The repo contains the source code for all the tutorials on the FilledStacks Youtube channel.
MIT License
4.75k stars 1.76k forks source link

046 - Dynamic links race condition? #108

Closed vtjiles closed 3 years ago

vtjiles commented 4 years ago

When launching the app with a handled dynamic link or notification, the code will navigate to a post and then navigate either to the login or home route which would cover up the post.

Am I missing something and this is not an issue? How have others dealt with initial navigation when using dynamic links and notifications?

[StartupViewModel]
Future handleStartUpLogic() async {
    await _dynamicLinkService.handleDynamicLinks();

    // Register for push notifications
    await _pushNotificationService.initialise();

    var hasLoggedInUser = await _authenticationService.isUserLoggedIn();

    if (hasLoggedInUser) {
      _navigationService.navigateTo(HomeViewRoute);
    } else {
      _navigationService.navigateTo(LoginViewRoute);
    }
  }

// [DynamicLinkService]
Future handleDynamicLinks() async {
    // Get the initial dynamic link if the app is opened with a dynamic link
    final PendingDynamicLinkData data =
        await FirebaseDynamicLinks.instance.getInitialLink();

    // handle link that has been retrieved
    _handleDeepLink(data);

    // Register a link callback to fire if the app is opened up from the background
    // using a dynamic link.
    FirebaseDynamicLinks.instance.onLink(
        onSuccess: (PendingDynamicLinkData dynamicLink) async {
      // handle link that has been retrieved
      _handleDeepLink(dynamicLink);
    }, onError: (OnLinkErrorException e) async {
      print('Link Failed: ${e.message}');
    });
  }
  void _handleDeepLink(PendingDynamicLinkData data) {
    final Uri deepLink = data?.link;
    if (deepLink != null) {
      print('_handleDeepLink | deeplink: $deepLink');

      var isPost = deepLink.pathSegments.contains('post');
      if (isPost) {
        var title = deepLink.queryParameters['title'];
        if (title != null) {
          _navigationService.navigateTo(CreatePostViewRoute, arguments: title);
        }
      }
    }
  }
fransiskapw commented 3 years ago

What seems to work for me is to move the await _dynamicLinkService.handleDynamicLinks(); and await _pushNotificationService.initialise(); after the handleStartUpLogic() - so the initial navigation (HomeViewRoute/ LoginViewRoute) will be called first, then the app will navigate to the dynamic link / push notification view

Future handleStartUpLogic() async {
    var hasLoggedInUser = await _authenticationService.isUserLoggedIn();

    if (hasLoggedInUser) {
      _navigationService.navigateTo(HomeViewRoute);
    } else {
      _navigationService.navigateTo(LoginViewRoute);
    }

    await _dynamicLinkService.handleDynamicLinks();

    // Register for push notifications
    await _pushNotificationService.initialise();
  }
vtjiles commented 3 years ago

I ended up doing the same and moving the initial dynamic link check into the startup navigation logic so that it could fire instead of, or after, the main screen depending on the link destination instead of when the service was initialized. Thanks for the suggestion. Had forgotten to close this.