startup.dart 4.3 KB

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