startup.dart 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. // this task should be first task, for handling platform errors.
  40. // don't catch errors in test mode
  41. if (!mode.isUnitTest) const PlatformErrorCatcherTask(),
  42. // localization
  43. const InitLocalizationTask(),
  44. // init the app window
  45. const InitAppWindowTask(),
  46. // Init Rust SDK
  47. InitRustSDKTask(directory: applicationDataDirectory),
  48. // Load Plugins, like document, grid ...
  49. const PluginLoadTask(),
  50. // init the app widget
  51. // ignore in test mode
  52. if (!mode.isUnitTest) ...[
  53. const HotKeyTask(),
  54. InitSupabaseTask(),
  55. const InitAppWidgetTask(),
  56. const InitPlatformServiceTask()
  57. ],
  58. ],
  59. );
  60. await launcher.launch(); // execute the tasks
  61. return FlowyRunnerContext(
  62. applicationDataDirectory: applicationDataDirectory,
  63. );
  64. }
  65. }
  66. Future<void> initGetIt(
  67. GetIt getIt,
  68. IntegrationMode env,
  69. EntryPoint f,
  70. LaunchConfiguration config,
  71. ) async {
  72. getIt.registerFactory<EntryPoint>(() => f);
  73. getIt.registerLazySingleton<FlowySDK>(() {
  74. return FlowySDK();
  75. });
  76. getIt.registerLazySingleton<AppLauncher>(
  77. () => AppLauncher(
  78. context: LaunchContext(
  79. getIt,
  80. env,
  81. config,
  82. ),
  83. ),
  84. );
  85. getIt.registerSingleton<PluginSandbox>(PluginSandbox());
  86. await DependencyResolver.resolve(getIt, env);
  87. }
  88. class LaunchContext {
  89. GetIt getIt;
  90. IntegrationMode env;
  91. LaunchConfiguration config;
  92. LaunchContext(this.getIt, this.env, this.config);
  93. }
  94. enum LaunchTaskType {
  95. dataProcessing,
  96. appLauncher,
  97. }
  98. /// The interface of an app launch task, which will trigger
  99. /// some nonresident indispensable task in app launching task.
  100. abstract class LaunchTask {
  101. const LaunchTask();
  102. LaunchTaskType get type => LaunchTaskType.dataProcessing;
  103. Future<void> initialize(LaunchContext context);
  104. }
  105. class AppLauncher {
  106. AppLauncher({
  107. required this.context,
  108. });
  109. final LaunchContext context;
  110. final List<LaunchTask> tasks = [];
  111. void addTask(LaunchTask task) {
  112. tasks.add(task);
  113. }
  114. void addTasks(Iterable<LaunchTask> tasks) {
  115. this.tasks.addAll(tasks);
  116. }
  117. Future<void> launch() async {
  118. for (final task in tasks) {
  119. await task.initialize(context);
  120. }
  121. }
  122. }
  123. enum IntegrationMode {
  124. develop,
  125. release,
  126. unitTest,
  127. integrationTest;
  128. // test mode
  129. bool get isTest => isUnitTest || isIntegrationTest;
  130. bool get isUnitTest => this == IntegrationMode.unitTest;
  131. bool get isIntegrationTest => this == IntegrationMode.integrationTest;
  132. // release mode
  133. bool get isRelease => this == IntegrationMode.release;
  134. // develop mode
  135. bool get isDevelop => this == IntegrationMode.develop;
  136. }
  137. IntegrationMode integrationEnv() {
  138. if (Platform.environment.containsKey('FLUTTER_TEST')) {
  139. return IntegrationMode.unitTest;
  140. }
  141. if (kReleaseMode) {
  142. return IntegrationMode.release;
  143. }
  144. return IntegrationMode.develop;
  145. }