app_widget.dart 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. import 'package:appflowy/workspace/application/settings/notifications/notification_settings_cubit.dart';
  2. import 'prelude.dart';
  3. import 'package:flutter/material.dart';
  4. import 'package:flutter_bloc/flutter_bloc.dart';
  5. import 'package:go_router/go_router.dart';
  6. import 'package:easy_localization/easy_localization.dart';
  7. import 'package:appflowy_editor/appflowy_editor.dart' hide Log;
  8. import 'package:appflowy_backend/log.dart';
  9. import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart';
  10. import 'package:flowy_infra/theme.dart';
  11. import 'package:flowy_infra_ui/flowy_infra_ui.dart';
  12. import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
  13. import 'package:appflowy/workspace/application/local_notifications/notification_service.dart';
  14. import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart';
  15. import 'package:appflowy/user/application/user_settings_service.dart';
  16. import 'package:appflowy/startup/startup.dart';
  17. class InitAppWidgetTask extends LaunchTask {
  18. const InitAppWidgetTask();
  19. @override
  20. LaunchTaskType get type => LaunchTaskType.appLauncher;
  21. @override
  22. Future<void> initialize(LaunchContext context) async {
  23. WidgetsFlutterBinding.ensureInitialized();
  24. await NotificationService.initialize();
  25. final widget = context.getIt<EntryPoint>().create(context.config);
  26. final appearanceSetting =
  27. await UserSettingsBackendService().getAppearanceSetting();
  28. final dateTimeSettings =
  29. await UserSettingsBackendService().getDateTimeSettings();
  30. // If the passed-in context is not the same as the context of the
  31. // application widget, the application widget will be rebuilt.
  32. final app = ApplicationWidget(
  33. key: ValueKey(context),
  34. appearanceSetting: appearanceSetting,
  35. dateTimeSettings: dateTimeSettings,
  36. appTheme: await appTheme(appearanceSetting.theme),
  37. child: widget,
  38. );
  39. Bloc.observer = ApplicationBlocObserver();
  40. runApp(
  41. EasyLocalization(
  42. supportedLocales: const [
  43. // In alphabetical order
  44. Locale('ar', 'SA'),
  45. Locale('ca', 'ES'),
  46. Locale('de', 'DE'),
  47. Locale('en'),
  48. Locale('es', 'VE'),
  49. Locale('eu', 'ES'),
  50. Locale('fr', 'FR'),
  51. Locale('fr', 'CA'),
  52. Locale('hu', 'HU'),
  53. Locale('id', 'ID'),
  54. Locale('it', 'IT'),
  55. Locale('ja', 'JP'),
  56. Locale('ko', 'KR'),
  57. Locale('pl', 'PL'),
  58. Locale('pt', 'BR'),
  59. Locale('ru', 'RU'),
  60. Locale('sv'),
  61. Locale('tr', 'TR'),
  62. Locale('uk', 'UA'),
  63. Locale('ur'),
  64. Locale('vi', 'VN'),
  65. Locale('zh', 'CN'),
  66. Locale('zh', 'TW'),
  67. Locale('fa'),
  68. ],
  69. path: 'assets/translations',
  70. fallbackLocale: const Locale('en'),
  71. useFallbackTranslations: true,
  72. saveLocale: false,
  73. child: app,
  74. ),
  75. );
  76. return;
  77. }
  78. }
  79. class ApplicationWidget extends StatefulWidget {
  80. const ApplicationWidget({
  81. super.key,
  82. required this.child,
  83. required this.appTheme,
  84. required this.appearanceSetting,
  85. required this.dateTimeSettings,
  86. });
  87. final Widget child;
  88. final AppTheme appTheme;
  89. final AppearanceSettingsPB appearanceSetting;
  90. final DateTimeSettingsPB dateTimeSettings;
  91. @override
  92. State<ApplicationWidget> createState() => _ApplicationWidgetState();
  93. }
  94. class _ApplicationWidgetState extends State<ApplicationWidget> {
  95. late final GoRouter routerConfig;
  96. @override
  97. void initState() {
  98. super.initState();
  99. // avoid rebuild routerConfig when the appTheme is changed.
  100. routerConfig = generateRouter(widget.child);
  101. }
  102. @override
  103. Widget build(BuildContext context) {
  104. return MultiBlocProvider(
  105. providers: [
  106. BlocProvider<AppearanceSettingsCubit>(
  107. create: (_) => AppearanceSettingsCubit(
  108. widget.appearanceSetting,
  109. widget.dateTimeSettings,
  110. widget.appTheme,
  111. )..readLocaleWhenAppLaunch(context),
  112. ),
  113. BlocProvider<NotificationSettingsCubit>(
  114. create: (_) => getIt<NotificationSettingsCubit>(),
  115. ),
  116. BlocProvider<DocumentAppearanceCubit>(
  117. create: (_) => DocumentAppearanceCubit()..fetch(),
  118. ),
  119. ],
  120. child: BlocBuilder<AppearanceSettingsCubit, AppearanceSettingsState>(
  121. builder: (context, state) => MaterialApp.router(
  122. builder: overlayManagerBuilder(),
  123. debugShowCheckedModeBanner: false,
  124. theme: state.lightTheme,
  125. darkTheme: state.darkTheme,
  126. themeMode: state.themeMode,
  127. localizationsDelegates: context.localizationDelegates +
  128. [AppFlowyEditorLocalizations.delegate],
  129. supportedLocales: context.supportedLocales,
  130. locale: state.locale,
  131. routerConfig: routerConfig,
  132. ),
  133. ),
  134. );
  135. }
  136. }
  137. class AppGlobals {
  138. static GlobalKey<NavigatorState> rootNavKey = GlobalKey();
  139. static NavigatorState get nav => rootNavKey.currentState!;
  140. }
  141. class ApplicationBlocObserver extends BlocObserver {
  142. @override
  143. // ignore: unnecessary_overrides
  144. void onTransition(Bloc bloc, Transition transition) {
  145. // Log.debug("[current]: ${transition.currentState} \n\n[next]: ${transition.nextState}");
  146. // Log.debug("${transition.nextState}");
  147. super.onTransition(bloc, transition);
  148. }
  149. @override
  150. void onError(BlocBase bloc, Object error, StackTrace stackTrace) {
  151. Log.debug(error);
  152. super.onError(bloc, error, stackTrace);
  153. }
  154. // @override
  155. // void onEvent(Bloc bloc, Object? event) {
  156. // Log.debug("$event");
  157. // super.onEvent(bloc, event);
  158. // }
  159. }
  160. Future<AppTheme> appTheme(String themeName) async {
  161. if (themeName.isEmpty) {
  162. return AppTheme.fallback;
  163. } else {
  164. try {
  165. return await AppTheme.fromName(themeName);
  166. } catch (e) {
  167. return AppTheme.fallback;
  168. }
  169. }
  170. }