app_widget.dart 5.1 KB

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