startup.dart 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. import 'dart:io';
  2. import 'package:appflowy/workspace/application/settings/prelude.dart';
  3. import 'package:appflowy_backend/appflowy_backend.dart';
  4. import 'package:flutter/foundation.dart';
  5. import 'package:flutter/material.dart';
  6. import 'package:get_it/get_it.dart';
  7. import 'deps_resolver.dart';
  8. import 'launch_configuration.dart';
  9. import 'plugin/plugin.dart';
  10. import 'tasks/prelude.dart';
  11. final getIt = GetIt.instance;
  12. abstract class EntryPoint {
  13. Widget create(LaunchConfiguration config);
  14. }
  15. class FlowyRunnerContext {
  16. final Directory applicationDataDirectory;
  17. FlowyRunnerContext({required this.applicationDataDirectory});
  18. }
  19. class FlowyRunner {
  20. static Future<FlowyRunnerContext> run(
  21. EntryPoint f,
  22. IntegrationMode mode, {
  23. LaunchConfiguration config = const LaunchConfiguration(
  24. autoRegistrationSupported: false,
  25. ),
  26. }) async {
  27. // Clear all the states in case of rebuilding.
  28. await getIt.reset();
  29. // Specify the env
  30. initGetIt(getIt, mode, f, config);
  31. final applicationDataDirectory =
  32. await getIt<ApplicationDataStorage>().getPath().then(
  33. (value) => Directory(value),
  34. );
  35. // add task
  36. final launcher = getIt<AppLauncher>();
  37. launcher.addTasks(
  38. [
  39. // handle platform errors.
  40. const PlatformErrorCatcherTask(),
  41. // localization
  42. const InitLocalizationTask(),
  43. // init the app window
  44. const InitAppWindowTask(),
  45. // Init Rust SDK
  46. InitRustSDKTask(directory: applicationDataDirectory),
  47. // Load Plugins, like document, grid ...
  48. const PluginLoadTask(),
  49. // init the app widget
  50. // ignore in test mode
  51. if (!mode.isUnitTest) ...[
  52. const HotKeyTask(),
  53. InitSupabaseTask(),
  54. const InitAppWidgetTask(),
  55. const InitPlatformServiceTask()
  56. ],
  57. ],
  58. );
  59. await launcher.launch(); // execute the tasks
  60. return FlowyRunnerContext(
  61. applicationDataDirectory: applicationDataDirectory,
  62. );
  63. }
  64. }
  65. Future<void> initGetIt(
  66. GetIt getIt,
  67. IntegrationMode env,
  68. EntryPoint f,
  69. LaunchConfiguration config,
  70. ) async {
  71. getIt.registerFactory<EntryPoint>(() => f);
  72. getIt.registerLazySingleton<FlowySDK>(() {
  73. return FlowySDK();
  74. });
  75. getIt.registerLazySingleton<AppLauncher>(
  76. () => AppLauncher(
  77. context: LaunchContext(
  78. getIt,
  79. env,
  80. config,
  81. ),
  82. ),
  83. );
  84. getIt.registerSingleton<PluginSandbox>(PluginSandbox());
  85. await DependencyResolver.resolve(getIt, env);
  86. }
  87. class LaunchContext {
  88. GetIt getIt;
  89. IntegrationMode env;
  90. LaunchConfiguration config;
  91. LaunchContext(this.getIt, this.env, this.config);
  92. }
  93. enum LaunchTaskType {
  94. dataProcessing,
  95. appLauncher,
  96. }
  97. /// The interface of an app launch task, which will trigger
  98. /// some nonresident indispensable task in app launching task.
  99. abstract class LaunchTask {
  100. const LaunchTask();
  101. LaunchTaskType get type => LaunchTaskType.dataProcessing;
  102. Future<void> initialize(LaunchContext context);
  103. }
  104. class AppLauncher {
  105. AppLauncher({
  106. required this.context,
  107. });
  108. final LaunchContext context;
  109. final List<LaunchTask> tasks = [];
  110. void addTask(LaunchTask task) {
  111. tasks.add(task);
  112. }
  113. void addTasks(Iterable<LaunchTask> tasks) {
  114. this.tasks.addAll(tasks);
  115. }
  116. Future<void> launch() async {
  117. for (final task in tasks) {
  118. await task.initialize(context);
  119. }
  120. }
  121. }
  122. enum IntegrationMode {
  123. develop,
  124. release,
  125. unitTest,
  126. integrationTest;
  127. // test mode
  128. bool get isTest => isUnitTest || isIntegrationTest;
  129. bool get isUnitTest => this == IntegrationMode.unitTest;
  130. bool get isIntegrationTest => this == IntegrationMode.integrationTest;
  131. // release mode
  132. bool get isRelease => this == IntegrationMode.release;
  133. // develop mode
  134. bool get isDevelop => this == IntegrationMode.develop;
  135. }
  136. IntegrationMode integrationEnv() {
  137. if (Platform.environment.containsKey('FLUTTER_TEST')) {
  138. return IntegrationMode.unitTest;
  139. }
  140. if (kReleaseMode) {
  141. return IntegrationMode.release;
  142. }
  143. return IntegrationMode.develop;
  144. }