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

iOS deep links are not working when app comes from a terminated state using the Authenticator pre-built widget. #5731

Open
3 of 14 tasks
ramon-san opened this issue Nov 27, 2024 · 4 comments
Assignees
Labels
Authenticator Issues related to the Authenticator UI Component bug Something is not working; the issue has reproducible steps and has been reproduced

Comments

@ramon-san
Copy link

ramon-san commented Nov 27, 2024

Description

I just finished setting up my app's deep link structure as per the Flutter documentation and it all works well except for the iOS launch of deep links when using the Authenticator pre-built widget.

The Android version of my code works just fine and even when app is terminated it opens the deep link as expected, the issue only occurs in iOS when the app comes from a terminated state. I attach two videos of what I'm talking about:

authentication_video.mov
noauthentication_video.mov

The first video uses the Authenticator pre-built widget as outlined in the code that appears next to the simulator, here you can see that deep link doesn't work when app comes from terminated state, when app is already launched it works just fine. The second video uses the bare-bone MaterialApp widget as seen in the code next to the simulator and in this case the app coming from a terminated state properly handles the deep link.

In the video that doesn't use Authenticator the first screen is different (no stores are displayed) becuase my API requires an authenticated user, not because anything else changed in the code.

In the first video it is clearly seen that the terminated app doesn't handle deep links correctly, the first time you open this it just stays in the home page (the "/" route) without navigating to the complete path. In the second video it is clear that the deep link works as intended, taking the user to the complete path (the "/help" route).

I was wondering if this is a known issue or if there is some clear problem with my implementation. The complete structure of my main.dart file is the following:

// Dart libraries
import 'dart:convert';
// External libraries
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:amplify_flutter/amplify_flutter.dart';
import 'package:amplify_api/amplify_api.dart';
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_analytics_pinpoint/amplify_analytics_pinpoint.dart';
import 'package:flutter_stripe/flutter_stripe.dart';
import 'package:go_router/go_router.dart';
import 'package:amplify_authenticator/amplify_authenticator.dart';
// Utilities
import 'package:pey/utils/rest_api_manager.dart';
import 'package:pey/routes.dart';
// Components
import 'package:pey/components/main/splash_screen.dart';
import 'package:pey/components/main/initialization_error.dart';
// Models
import 'package:pey/models/cart.dart';
import 'package:pey/models/store.dart';
// Configs
import 'package:pey/configs/amplify.dart';

Future<void> configureAmplify() async {
  try {
    if (Amplify.isConfigured) {
      safePrint("Amplify is already configured 🎉");
      return;
    }

    await Amplify.addPlugins([
      AmplifyAnalyticsPinpoint(),
      AmplifyAuthCognito(),
      AmplifyAPI(),
    ]);

    await Amplify.configure(jsonEncode(amplifyConfig));
    safePrint("Successfully configured Amplify 🎉");
  } on Exception catch (e) {
    safePrint('An error occurred configuring Amplify: $e');
    rethrow;
  }
}

Future<void> configureStripe() async {
  String merchantId = "merchant.com.pey";
  try {
    final publishableKey = await RestApi.fetchStripePublishableKey();
    Stripe.publishableKey = publishableKey;
    Stripe.merchantIdentifier = merchantId;
    await Stripe.instance.applySettings();
    safePrint("Successfully configured Stripe 🎉");
  } catch (e) {
    safePrint('An error occurred configuring Stripe: $e');
    rethrow;
  }
}

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(const InitializationWrapper());
}

class InitializationWrapper extends StatefulWidget {
  const InitializationWrapper({super.key});

  @override
  State<InitializationWrapper> createState() => _InitializationWrapperState();
}

class _InitializationWrapperState extends State<InitializationWrapper> {
  late Future<void> _initializationFuture;
  final GoRouter _router = router;

  @override
  void initState() {
    super.initState();
    _initializationFuture = _initialize();
  }

  Future<void> _initialize() async {
    await configureAmplify();
    await configureStripe();
  }

  void _retryInitialization() {
    setState(() {
      _initializationFuture = _initialize();
    });
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: _initializationFuture,
      builder: (context, snapshot) {
        if (snapshot.hasError) {
          return MaterialApp(
            home: InitializationError(
              error: snapshot.error?.toString(),
              onRetry: _retryInitialization,
            ),
          );
        }

        if (snapshot.connectionState == ConnectionState.done) {
          return MultiProvider(
            providers: [
              ChangeNotifierProvider(create: (context) => CartModel()),
              ChangeNotifierProvider(create: (context) => StoreModel())
            ],
            child: Authenticator(
              child: MaterialApp.router(
                routerConfig: _router,
                theme: ThemeData(
                  colorScheme: ColorScheme.fromSeed(
                    seedColor: const Color(0xFF0067F1),
                    primary: const Color(0xFF0067F1),
                  ),
                  useMaterial3: true,
                ),
                builder: Authenticator.builder(),
              ),
            ),
          );
        }

        return const MaterialApp(
          home: SplashScreen(),
        );
      },
    );
  }
}

I was trying to narrow down the causes of failure given this GitHub issue which stated that conditional statements when launching the MaterialApp caused issues; this turned out to be true and it seems the culprit right now is Authenticator. I first want to fix the Authenticator which clearly causes the issue and then see if my other conditions (SplashScreen and InitializationError) also affect the deep link behavior. In the video examples I showed above the Widget build(BuildContext context) { ... } used the simplified versions of the code that appear in the videos.

This issue in the Flutter repo goes deep into the functionality of deep links in iOS when app comes from a terminated state.

Categories

  • Analytics
  • API (REST)
  • API (GraphQL)
  • Auth
  • Authenticator
  • DataStore
  • Notifications (Push)
  • Storage

Steps to Reproduce

Already explained in the description, try to configure flutter deep links with an app that uses Amplify's pre-built Authenticator widget.

Screenshots

No response

Platforms

  • iOS
  • Android
  • Web
  • macOS
  • Windows
  • Linux

Flutter Version

3.24.3

Amplify Flutter Version

^2.0.0

Deployment Method

AWS CDK

Schema

No response

@github-actions github-actions bot added pending-triage This issue is in the backlog of issues to triage pending-maintainer-response Pending response from a maintainer of this repository labels Nov 27, 2024
@ekjotmultani
Copy link
Member

Hi @ramon-san, thank you for taking the time to raise this issue as well as the extraordinary detail in describing the problem. We will investigate this issue and get back to you when we have an update.

@github-actions github-actions bot removed the pending-maintainer-response Pending response from a maintainer of this repository label Nov 27, 2024
@ekjotmultani ekjotmultani self-assigned this Nov 27, 2024
@ekjotmultani ekjotmultani added the Authenticator Issues related to the Authenticator UI Component label Nov 27, 2024
@ekjotmultani
Copy link
Member

Hi @ramon-san, I have been able to reproduce this issue. It will be tracked as a bug and I will report back to this issue when we have a fix.

@ekjotmultani ekjotmultani added the bug Something is not working; the issue has reproducible steps and has been reproduced label Dec 4, 2024
@github-actions github-actions bot removed the pending-triage This issue is in the backlog of issues to triage label Dec 4, 2024
@ramon-san
Copy link
Author

Hello, was wondering if there is any ETA on this bug fix. Accessing specific areas of the app through a QR code is core functionality of what I'm building so a fix to this bug would be huge. If the time to fix this will be very long (more than a month) please let me know so that I start building a personalized Auth solution that doesn't cause this issue.

@github-actions github-actions bot added the pending-maintainer-response Pending response from a maintainer of this repository label Dec 11, 2024
@Equartey
Copy link
Contributor

Hi @ramon-san, we currently do not have a ETA on the fix for this. We will post any updates we have here as we can.

@github-actions github-actions bot removed the pending-maintainer-response Pending response from a maintainer of this repository label Dec 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Authenticator Issues related to the Authenticator UI Component bug Something is not working; the issue has reproducible steps and has been reproduced
Projects
None yet
Development

No branches or pull requests

3 participants