|
| 1 | +import 'package:firebase_core/firebase_core.dart'; |
| 2 | +import 'package:flutter/material.dart'; |
| 3 | +import 'package:flutter_riverpod/flutter_riverpod.dart'; |
| 4 | +import 'package:riverpod_annotation/riverpod_annotation.dart'; |
| 5 | +import 'package:starter_architecture_flutter_firebase/firebase_options.dart'; |
| 6 | +import 'package:starter_architecture_flutter_firebase/src/constants/app_sizes.dart'; |
| 7 | +import 'package:starter_architecture_flutter_firebase/src/features/onboarding/data/onboarding_repository.dart'; |
| 8 | + |
| 9 | +part 'app_startup.g.dart'; |
| 10 | + |
| 11 | +@Riverpod(keepAlive: true) |
| 12 | +Future<void> appStartup(AppStartupRef ref) async { |
| 13 | + // await for all initialization code to be complete before returning |
| 14 | + await Future.wait([ |
| 15 | + // Firebase init |
| 16 | + Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform), |
| 17 | + // list of providers to be warmed up |
| 18 | + ref.watch(onboardingRepositoryProvider.future) |
| 19 | + ]); |
| 20 | +} |
| 21 | + |
| 22 | +/// Widget class to manage asynchronous app initialization |
| 23 | +class AppStartupWidget extends ConsumerWidget { |
| 24 | + const AppStartupWidget({super.key, required this.onLoaded}); |
| 25 | + final WidgetBuilder onLoaded; |
| 26 | + |
| 27 | + @override |
| 28 | + Widget build(BuildContext context, WidgetRef ref) { |
| 29 | + final appStartupState = ref.watch(appStartupProvider); |
| 30 | + return appStartupState.when( |
| 31 | + data: (_) => onLoaded(context), |
| 32 | + loading: () => const AppStartupLoadingWidget(), |
| 33 | + error: (e, st) => AppStartupErrorWidget( |
| 34 | + message: e.toString(), |
| 35 | + onRetry: () { |
| 36 | + ref.invalidate(onboardingRepositoryProvider); |
| 37 | + ref.invalidate(appStartupProvider); |
| 38 | + }, |
| 39 | + ), |
| 40 | + ); |
| 41 | + } |
| 42 | +} |
| 43 | + |
| 44 | +class AppStartupLoadingWidget extends StatelessWidget { |
| 45 | + const AppStartupLoadingWidget({super.key}); |
| 46 | + |
| 47 | + @override |
| 48 | + Widget build(BuildContext context) { |
| 49 | + return const MaterialApp( |
| 50 | + home: Scaffold( |
| 51 | + body: Center( |
| 52 | + child: CircularProgressIndicator(), |
| 53 | + ), |
| 54 | + ), |
| 55 | + ); |
| 56 | + } |
| 57 | +} |
| 58 | + |
| 59 | +class AppStartupErrorWidget extends StatelessWidget { |
| 60 | + const AppStartupErrorWidget( |
| 61 | + {super.key, required this.message, required this.onRetry}); |
| 62 | + final String message; |
| 63 | + final VoidCallback onRetry; |
| 64 | + |
| 65 | + @override |
| 66 | + Widget build(BuildContext context) { |
| 67 | + return MaterialApp( |
| 68 | + home: Scaffold( |
| 69 | + body: Center( |
| 70 | + child: Column( |
| 71 | + mainAxisSize: MainAxisSize.min, |
| 72 | + children: [ |
| 73 | + Text(message, style: Theme.of(context).textTheme.headlineSmall), |
| 74 | + gapH16, |
| 75 | + ElevatedButton( |
| 76 | + onPressed: onRetry, |
| 77 | + child: const Text('Retry'), |
| 78 | + ), |
| 79 | + ], |
| 80 | + ), |
| 81 | + ), |
| 82 | + ), |
| 83 | + ); |
| 84 | + } |
| 85 | +} |
0 commit comments