Skip to content

Commit

Permalink
Use GoRouter redirects to handle app startup state changes
Browse files Browse the repository at this point in the history
  • Loading branch information
bizz84 committed Mar 17, 2024
1 parent a756a90 commit 82677dd
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 35 deletions.
11 changes: 6 additions & 5 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:starter_architecture_flutter_firebase/firebase_options.dart';
import 'package:starter_architecture_flutter_firebase/src/app.dart';
import 'package:starter_architecture_flutter_firebase/src/app_startup.dart';
import 'package:starter_architecture_flutter_firebase/src/localization/string_hardcoded.dart';
// ignore:depend_on_referenced_packages
import 'package:flutter_web_plugins/url_strategy.dart';
Expand All @@ -14,11 +15,11 @@ Future<void> main() async {
// * Register error handlers. For more info, see:
// * https://docs.flutter.dev/testing/errors
registerErrorHandlers();
// * Initialize Firebase
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
// * Entry point of the app
runApp(ProviderScope(
child: AppStartupWidget(
onLoaded: (context) => const MyApp(),
),
runApp(const ProviderScope(
child: MyApp(),
));
}

Expand Down
45 changes: 18 additions & 27 deletions lib/src/app_startup.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:starter_architecture_flutter_firebase/firebase_options.dart';
import 'package:starter_architecture_flutter_firebase/src/constants/app_sizes.dart';
import 'package:starter_architecture_flutter_firebase/src/features/onboarding/data/onboarding_repository.dart';

Expand All @@ -20,12 +18,7 @@ Future<void> appStartup(AppStartupRef ref) async {
ref.invalidate(onboardingRepositoryProvider);
});
// await for all initialization code to be complete before returning
await Future.wait([
// Firebase init
Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform),
// list of providers to be warmed up
ref.watch(onboardingRepositoryProvider.future)
]);
await ref.watch(onboardingRepositoryProvider.future);
}

/// Widget class to manage asynchronous app initialization
Expand All @@ -52,11 +45,10 @@ class AppStartupLoadingWidget extends StatelessWidget {

@override
Widget build(BuildContext context) {
return const MaterialApp(
home: Scaffold(
body: Center(
child: CircularProgressIndicator(),
),
return Scaffold(
appBar: AppBar(),
body: const Center(
child: CircularProgressIndicator(),
),
);
}
Expand All @@ -70,20 +62,19 @@ class AppStartupErrorWidget extends StatelessWidget {

@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(message, style: Theme.of(context).textTheme.headlineSmall),
gapH16,
ElevatedButton(
onPressed: onRetry,
child: const Text('Retry'),
),
],
),
return Scaffold(
appBar: AppBar(),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(message, style: Theme.of(context).textTheme.headlineSmall),
gapH16,
ElevatedButton(
onPressed: onRetry,
child: const Text('Retry'),
),
],
),
),
);
Expand Down
29 changes: 26 additions & 3 deletions lib/src/routing/app_router.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:starter_architecture_flutter_firebase/src/app_startup.dart';
import 'package:starter_architecture_flutter_firebase/src/features/authentication/data/firebase_auth_repository.dart';
import 'package:starter_architecture_flutter_firebase/src/features/authentication/presentation/custom_profile_screen.dart';
import 'package:starter_architecture_flutter_firebase/src/features/authentication/presentation/custom_sign_in_screen.dart';
Expand Down Expand Up @@ -40,16 +41,23 @@ enum AppRoute {
}

@riverpod
// ignore: unsupported_provider_value
GoRouter goRouter(GoRouterRef ref) {
// rebuild GoRouter when app startup state changes
final appStartupState = ref.watch(appStartupProvider);
final authRepository = ref.watch(authRepositoryProvider);
final onboardingRepository =
ref.watch(onboardingRepositoryProvider).requireValue;
return GoRouter(
initialLocation: '/signIn',
navigatorKey: _rootNavigatorKey,
debugLogDiagnostics: true,
redirect: (context, state) {
if (appStartupState.isLoading) {
return '/loading';
}
if (appStartupState.hasError) {
return '/error';
}
final onboardingRepository =
ref.read(onboardingRepositoryProvider).requireValue;
final didCompleteOnboarding = onboardingRepository.isOnboardingComplete();
final path = state.uri.path;
if (!didCompleteOnboarding) {
Expand All @@ -75,6 +83,21 @@ GoRouter goRouter(GoRouterRef ref) {
},
refreshListenable: GoRouterRefreshStream(authRepository.authStateChanges()),
routes: [
GoRoute(
path: '/loading',
pageBuilder: (context, state) => const NoTransitionPage(
child: AppStartupLoadingWidget(),
),
),
GoRoute(
path: '/error',
pageBuilder: (context, state) => NoTransitionPage(
child: AppStartupErrorWidget(
message: 'App initialization failed',
onRetry: () => ref.invalidate(appStartupProvider),
),
),
),
GoRoute(
path: '/onboarding',
name: AppRoute.onboarding.name,
Expand Down

0 comments on commit 82677dd

Please sign in to comment.