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

Issue with go router - go to details page #142

Open
Schokiii93 opened this issue Apr 12, 2024 · 0 comments
Open

Issue with go router - go to details page #142

Schokiii93 opened this issue Apr 12, 2024 · 0 comments

Comments

@Schokiii93
Copy link

Hi guys,

I've developed course manager app that fits specific requirements of a sports club that I am a member of. The app fulfills the following main function:

Users (or participants in our sports group) can navigate from the homepage to an overview page that lists all available courses.
By clicking on one of the courses, you will be taken to a detail page where you can then register for and cancel the course.

I use firebase for the data structure. Each event is assigned a unique ID from the firestore collection.

Now I would like to implement a "Share" button on the detail page. By clicking on it, a link should be generated and moved to the clipboard so that I can then send it via Whatsapp, for example. Users who click on it should be taken directly to the details page.

I have already defined the following routes:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );
  await dotenv.load();

  await FirebaseAppCheck.instance.activate(
    webProvider:
        ReCaptchaV3Provider('####'),
    //androidProvider: AndroidProvider.debug,
    androidProvider: AndroidProvider.playIntegrity,
    appleProvider: AppleProvider.deviceCheck,
  );

  runApp(const ProviderScope(child: MyApp()));
}

class MyApp extends StatelessWidget {
  /// Constructs a [MyApp]
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp.router(
      routerConfig: _router,
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: const [Locale('de', 'DE')],
      debugShowCheckedModeBanner: false,
      title: 'myApp',
      theme: getThemeData(),
    );
  }
}

final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();

/// The route configuration.
final GoRouter _router = GoRouter(
  navigatorKey: navigatorKey,
  initialLocation: '/',
  routes: <RouteBase>[
    GoRoute(
      path: '/',
      builder: (BuildContext context, GoRouterState state) {
        return StreamBuilder(
          stream: FirebaseAuth.instance.authStateChanges(),
          builder: (context, snapshot) {
            if (snapshot.connectionState == ConnectionState.waiting) {
              return Loading();
            }
            if (snapshot.hasData) {
              return Consumer(
                builder: (BuildContext context, WidgetRef ref, Widget? child) {
                  final userProfileAsync = ref.watch(userProfileProvider);
                  return userProfileAsync.when(
                    data: (userData) {
                      if (userData != null) {
                        //check if user has already been activated
                        bool accountActivated = userData.accountActivated;
                        return accountActivated
                            ? const MainScreen()
                            : const AccountNotActivatedScreen();
                      } else {
                        //other events
                        return Center(
                          child: Loading(),
                        );
                      }
                    },
                    loading: () => Scaffold(body: Loading()),
                    error: (error, stackTrace) {
                      return const Text(
                          'Fehler beim Abrufen der Benutzerdaten');
                    },
                  );
                },
              );
            }
            return const LoginScreen();
          },
        );
      },
      routes: <RouteBase>[
        GoRoute(
          path: 'events/:eventId',
          builder: (BuildContext context, GoRouterState state) {
            final id = state.pathParameters['eventId']!;
            return EventDetailsPage(eventId: id);
          },
        ),
      ],
    ),
  ],
);

As you can see, there is a GoRoute defined which gets the eventId (the event id comes from firestore).

Futhermore, I created a details page. This is the place where the share button should be included. I think the only interesting thing should be the "_copyLinkToClipboard" function and the share button I added:

class EventDetailsPage extends ConsumerStatefulWidget {
  final String eventId;
  const EventDetailsPage({super.key, required this.eventId});

  @override
  ConsumerState<EventDetailsPage> createState() => _EventDetailsPageState();
}

class _EventDetailsPageState extends ConsumerState<EventDetailsPage> {
...some code

  @override
  void initState() {
    super.initState();
    initializeDateFormatting('de_DE'); //initialize system language
    ...some more code
  }

  void _copyLinkToClipboard(BuildContext context) {
    String currentUrl = 'paravertikale-augsburg.de/event/${widget.eventId}';
    Clipboard.setData(ClipboardData(text: currentUrl));
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('Link zur Veranstaltung kopiert')),
    );
  }

  @override
  Widget build(BuildContext context) {
    final streamData = ref.read(userProfileProvider);
    final futureEvent = ref.watch(eventDetailsProvider(widget.eventId));

    return Scaffold(
      body: _isLoading
          ? Platform.isIOS
              ? const Center(
                  child:
                      CupertinoActivityIndicator(radius: 20, animating: true))
              : Loading()
          : futureEvent.when(
              loading: () => Platform.isIOS
                  ? const Center(
                      child: CupertinoActivityIndicator(
                          radius: 20, animating: true))
                  : Loading(),
              error: (error, stack) => Text("Error: $error"),
              data: (eventData) {
                return streamData.when(
                  error: (error, stackTrace) => Text(error.toString()),
                  loading: () => Platform.isIOS
                      ? const Center(
                          child: CupertinoActivityIndicator(
                              radius: 20, animating: true))
                      : Loading(),
                  data: ((data) => Stack(
                        children: [
                          CustomScrollView(
                            slivers: [

                              ...some boring extra code in between

                                                    Expanded(
                                                        flex: 5,
                                                        child: AutoSizeText(
                                                          maxFontSize: 18,
                                                          maxLines: 2,
                                                          "Dieser Kurs wird $_lowerCaseRecurrenceType wiederholt",
                                                          textAlign:
                                                              TextAlign.start,
                                                        )),
                                                    const SizedBox(width: 20),
                                                    
                                                    **IconButton(
                                                      onPressed: () {
                                                        _copyLinkToClipboard(
                                                            context);
                                                      },
                                                      icon: const Icon(
                                                          FontAwesomeIcons
                                                              .share),
                                                    ),**
                                                    
                                               ... and lots of more code

I added this to my androidmanisfest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
    <application android:label="ParaVertikale" android:name="${applicationName}" android:icon="@mipmap/ic_launcher">
        <activity android:name=".MainActivity" android:enableOnBackInvokedCallback="true" android:exported="true" android:launchMode="singleTop" android:theme="@style/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize" android:roundIcon="@mipmap/round_launcher">
            <!-- Specifies an Android theme to apply to this Activity as soon as
                 the Android process has started. This theme is visible to the user
                 while the Flutter UI initializes. After that, this theme continues
                 to determine the Window background behind the Flutter UI. -->
            <meta-data android:name="io.flutter.embedding.android.NormalTheme" android:resource="@style/NormalTheme"/>
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
            <meta-data android:name="flutter_deeplinking_enabled" android:value="true" />
            <intent-filter android:autoVerify="true">
                <action android:name="android.intent.action.VIEW" />
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <data android:scheme="http" android:host="paravertikale-augsburg.de"/>
                <data android:scheme="https" android:host="paravertikale-augsburg.de"/>
                <data android:pathPattern="/event/.*" />
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data android:name="flutterEmbedding" android:value="2"/>
    </application>
</manifest>

The thing is, I don't know why it doesn't work and I don't know how to generate a dynamic link that points to the event details.

Can anyone help me with this?
Thanks and regards
Dennis

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

1 participant