diff --git a/lib/presentation/app_widget.dart b/lib/presentation/app_widget.dart index 9ff9ce6..b43f852 100644 --- a/lib/presentation/app_widget.dart +++ b/lib/presentation/app_widget.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:loader_overlay/loader_overlay.dart'; import '../application/auth/auth_bloc.dart'; import '../application/language/language_bloc.dart'; @@ -7,6 +8,7 @@ import '../common/theme/theme.dart'; import '../common/constant/app_constant.dart'; import '../injection.dart'; import '../l10n/app_localizations.dart'; +import 'components/loading/loading_overlay.dart'; import 'router/app_router.dart'; import 'router/app_router_observer.dart'; @@ -27,20 +29,27 @@ class _AppWidgetState extends State { BlocProvider(create: (context) => getIt()), BlocProvider(create: (context) => getIt()), ], - child: BlocBuilder( - builder: (context, state) { - return MaterialApp.router( - debugShowCheckedModeBanner: false, - title: AppConstant.appName, - locale: state.language.locale, - supportedLocales: AppLocalizations.supportedLocales, - localizationsDelegates: AppLocalizations.localizationsDelegates, - theme: ThemeApp.theme, - routerConfig: _appRouter.config( - navigatorObservers: () => [AppRouteObserver()], - ), - ); - }, + child: GlobalLoaderOverlay( + useDefaultLoading: false, + overlayWidgetBuilder: (progress) => LoadingOverlay(), + overlayColor: AppColor.black.withOpacity(0.35), + child: BlocBuilder( + builder: (context, state) { + return MaterialApp.router( + debugShowCheckedModeBanner: false, + title: AppConstant.appName, + locale: state.language.locale, + supportedLocales: AppLocalizations.supportedLocales, + localizationsDelegates: AppLocalizations.localizationsDelegates, + theme: ThemeApp.theme, + routerConfig: _appRouter.config( + navigatorObservers: () => [ + AppRouteObserver(), + ], + ), + ); + }, + ), ), ); } diff --git a/lib/presentation/components/loading/loading_overlay.dart b/lib/presentation/components/loading/loading_overlay.dart new file mode 100644 index 0000000..a711771 --- /dev/null +++ b/lib/presentation/components/loading/loading_overlay.dart @@ -0,0 +1,23 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_spinkit/flutter_spinkit.dart'; + +import '../../../common/theme/theme.dart'; + +class LoadingOverlay extends StatelessWidget { + const LoadingOverlay({super.key}); + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + width: 64, + height: 64, + decoration: BoxDecoration( + color: AppColor.white, + borderRadius: BorderRadius.circular(AppValue.radius), + ), + child: SpinKitCircle(color: AppColor.primary, size: 32.0), + ), + ); + } +} diff --git a/lib/presentation/pages/profile/profile_page.dart b/lib/presentation/pages/profile/profile_page.dart index 3422a74..8d1a577 100644 --- a/lib/presentation/pages/profile/profile_page.dart +++ b/lib/presentation/pages/profile/profile_page.dart @@ -2,6 +2,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:line_icons/line_icons.dart'; +import 'package:loader_overlay/loader_overlay.dart'; import '../../../application/auth/logout_form/logout_form_bloc.dart'; import '../../../common/theme/theme.dart'; @@ -23,16 +24,31 @@ class ProfilePage extends StatelessWidget implements AutoRouteWrapper { @override Widget build(BuildContext context) { - return BlocListener( - listener: (context, state) { - state.failureOrAuthOption.fold( - () => null, - (either) => either.fold( - (f) => AppFlushbar.showAuthFailureToast(context, f), - (_) => context.router.replace(const LoginRoute()), - ), - ); - }, + return MultiBlocListener( + listeners: [ + BlocListener( + listener: (context, state) { + state.failureOrAuthOption.fold( + () => null, + (either) => either.fold( + (f) => AppFlushbar.showAuthFailureToast(context, f), + (_) => context.router.replace(const LoginRoute()), + ), + ); + }, + ), + BlocListener( + listenWhen: (previous, current) => + previous.isSubmitting != current.isSubmitting, + listener: (context, state) { + if (state.isSubmitting) { + context.loaderOverlay.show(); + } else { + context.loaderOverlay.hide(); + } + }, + ), + ], child: Scaffold( backgroundColor: AppColor.background, body: CustomScrollView( diff --git a/pubspec.lock b/pubspec.lock index 2b762bf..c9f4571 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -73,6 +73,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + back_button_interceptor: + dependency: transitive + description: + name: back_button_interceptor + sha256: b85977faabf4aeb95164b3b8bf81784bed4c54ea1aef90a036ab6927ecf80c5a + url: "https://pub.dev" + source: hosted + version: "8.0.4" bloc: dependency: transitive description: @@ -741,6 +749,14 @@ packages: url: "https://pub.dev" source: hosted version: "5.1.1" + loader_overlay: + dependency: "direct main" + description: + name: loader_overlay + sha256: "285c9ccab9a42a392ba948bd0b14376fd0ee9ddd7b63e3018bcd54460fd3e021" + url: "https://pub.dev" + source: hosted + version: "5.0.0" logging: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 725ca40..c3e9f7f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -39,6 +39,7 @@ dependencies: image_picker: ^1.1.2 table_calendar: ^3.2.0 package_info_plus: ^8.3.1 + loader_overlay: ^5.0.0 dev_dependencies: flutter_test: