manager.rs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. use crate::entities::view::ViewDataFormatPB;
  2. use crate::entities::{ViewLayoutTypePB, ViewPB, WorkspacePB};
  3. use crate::services::folder_editor::FolderRevisionMergeable;
  4. use crate::{
  5. entities::workspace::RepeatedWorkspacePB,
  6. errors::FlowyResult,
  7. event_map::{FolderCouldServiceV1, WorkspaceDatabase, WorkspaceUser},
  8. notification::{send_notification, FolderNotification},
  9. services::{
  10. folder_editor::FolderEditor, persistence::FolderPersistence, set_current_workspace,
  11. AppController, TrashController, ViewController, WorkspaceController,
  12. },
  13. };
  14. use bytes::Bytes;
  15. use flowy_document::editor::initial_read_me;
  16. use flowy_error::FlowyError;
  17. use flowy_revision::{
  18. RevisionManager, RevisionPersistence, RevisionPersistenceConfiguration, RevisionWebSocket,
  19. };
  20. use folder_model::user_default;
  21. use lazy_static::lazy_static;
  22. use lib_infra::future::FutureResult;
  23. use crate::services::persistence::rev_sqlite::{
  24. SQLiteFolderRevisionPersistence, SQLiteFolderRevisionSnapshotPersistence,
  25. };
  26. use crate::services::{clear_current_workspace, get_current_workspace};
  27. use flowy_client_sync::client_folder::FolderPad;
  28. use std::convert::TryFrom;
  29. use std::{collections::HashMap, fmt::Formatter, sync::Arc};
  30. use tokio::sync::RwLock as TokioRwLock;
  31. use ws_model::ws_revision::ServerRevisionWSData;
  32. lazy_static! {
  33. static ref INIT_FOLDER_FLAG: TokioRwLock<HashMap<String, bool>> =
  34. TokioRwLock::new(HashMap::new());
  35. }
  36. const FOLDER_ID: &str = "folder";
  37. const FOLDER_ID_SPLIT: &str = ":";
  38. #[derive(Clone)]
  39. pub struct FolderId(String);
  40. impl FolderId {
  41. pub fn new(user_id: &str) -> Self {
  42. Self(format!("{}{}{}", user_id, FOLDER_ID_SPLIT, FOLDER_ID))
  43. }
  44. }
  45. impl std::fmt::Display for FolderId {
  46. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  47. f.write_str(FOLDER_ID)
  48. }
  49. }
  50. impl std::fmt::Debug for FolderId {
  51. fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
  52. f.write_str(FOLDER_ID)
  53. }
  54. }
  55. impl AsRef<str> for FolderId {
  56. fn as_ref(&self) -> &str {
  57. &self.0
  58. }
  59. }
  60. pub struct FolderManager {
  61. pub user: Arc<dyn WorkspaceUser>,
  62. pub(crate) persistence: Arc<FolderPersistence>,
  63. pub(crate) workspace_controller: Arc<WorkspaceController>,
  64. pub(crate) app_controller: Arc<AppController>,
  65. pub(crate) view_controller: Arc<ViewController>,
  66. pub(crate) trash_controller: Arc<TrashController>,
  67. web_socket: Arc<dyn RevisionWebSocket>,
  68. pub(crate) folder_editor: Arc<TokioRwLock<Option<Arc<FolderEditor>>>>,
  69. }
  70. impl FolderManager {
  71. pub async fn new(
  72. user: Arc<dyn WorkspaceUser>,
  73. cloud_service: Arc<dyn FolderCouldServiceV1>,
  74. database: Arc<dyn WorkspaceDatabase>,
  75. data_processors: ViewDataProcessorMap,
  76. web_socket: Arc<dyn RevisionWebSocket>,
  77. ) -> Self {
  78. if let Ok(user_id) = user.user_id() {
  79. // Reset the flag if the folder manager gets initialized, otherwise,
  80. // the folder_editor will not be initialized after flutter hot reload.
  81. INIT_FOLDER_FLAG
  82. .write()
  83. .await
  84. .insert(user_id.to_owned(), false);
  85. }
  86. let folder_editor = Arc::new(TokioRwLock::new(None));
  87. let persistence = Arc::new(FolderPersistence::new(
  88. database.clone(),
  89. folder_editor.clone(),
  90. ));
  91. let trash_controller = Arc::new(TrashController::new(
  92. persistence.clone(),
  93. cloud_service.clone(),
  94. user.clone(),
  95. ));
  96. let view_controller = Arc::new(ViewController::new(
  97. user.clone(),
  98. persistence.clone(),
  99. cloud_service.clone(),
  100. trash_controller.clone(),
  101. data_processors,
  102. ));
  103. let app_controller = Arc::new(AppController::new(
  104. user.clone(),
  105. persistence.clone(),
  106. trash_controller.clone(),
  107. cloud_service.clone(),
  108. ));
  109. let workspace_controller = Arc::new(WorkspaceController::new(
  110. user.clone(),
  111. persistence.clone(),
  112. trash_controller.clone(),
  113. cloud_service.clone(),
  114. ));
  115. Self {
  116. user,
  117. persistence,
  118. workspace_controller,
  119. app_controller,
  120. view_controller,
  121. trash_controller,
  122. web_socket,
  123. folder_editor,
  124. }
  125. }
  126. // pub fn network_state_changed(&self, new_type: NetworkType) {
  127. // match new_type {
  128. // NetworkType::UnknownNetworkType => {},
  129. // NetworkType::Wifi => {},
  130. // NetworkType::Cell => {},
  131. // NetworkType::Ethernet => {},
  132. // }
  133. // }
  134. pub async fn did_receive_ws_data(&self, data: Bytes) {
  135. let result = ServerRevisionWSData::try_from(data);
  136. match result {
  137. Ok(data) => match self.folder_editor.read().await.clone() {
  138. None => {},
  139. Some(editor) => match editor.receive_ws_data(data).await {
  140. Ok(_) => {},
  141. Err(e) => tracing::error!("Folder receive data error: {:?}", e),
  142. },
  143. },
  144. Err(e) => {
  145. tracing::error!("Folder ws data parser failed: {:?}", e);
  146. },
  147. }
  148. }
  149. /// Called immediately after the application launched with the user sign in/sign up.
  150. #[tracing::instrument(level = "trace", skip(self), err)]
  151. pub async fn initialize(&self, user_id: &str, token: &str) -> FlowyResult<()> {
  152. let mut write_guard = INIT_FOLDER_FLAG.write().await;
  153. if let Some(is_init) = write_guard.get(user_id) {
  154. if *is_init {
  155. return Ok(());
  156. }
  157. }
  158. tracing::debug!("Initialize folder editor");
  159. let folder_id = FolderId::new(user_id);
  160. self.persistence.initialize(user_id, &folder_id).await?;
  161. let pool = self.persistence.db_pool()?;
  162. let object_id = folder_id.as_ref();
  163. let disk_cache = SQLiteFolderRevisionPersistence::new(user_id, pool.clone());
  164. let configuration = RevisionPersistenceConfiguration::new(200, false);
  165. let rev_persistence = RevisionPersistence::new(user_id, object_id, disk_cache, configuration);
  166. let rev_compactor = FolderRevisionMergeable();
  167. const FOLDER_SP_PREFIX: &str = "folder";
  168. let snapshot_object_id = format!("{}:{}", FOLDER_SP_PREFIX, object_id);
  169. let snapshot_persistence =
  170. SQLiteFolderRevisionSnapshotPersistence::new(&snapshot_object_id, pool);
  171. let rev_manager = RevisionManager::new(
  172. user_id,
  173. folder_id.as_ref(),
  174. rev_persistence,
  175. rev_compactor,
  176. snapshot_persistence,
  177. );
  178. let folder_editor = FolderEditor::new(
  179. user_id,
  180. &folder_id,
  181. token,
  182. rev_manager,
  183. self.web_socket.clone(),
  184. )
  185. .await?;
  186. *self.folder_editor.write().await = Some(Arc::new(folder_editor));
  187. self.app_controller.initialize()?;
  188. self.view_controller.initialize()?;
  189. write_guard.insert(user_id.to_owned(), true);
  190. Ok(())
  191. }
  192. pub async fn get_current_workspace(&self) -> FlowyResult<WorkspacePB> {
  193. let user_id = self.user.user_id()?;
  194. let workspace_id = get_current_workspace(&user_id)?;
  195. let workspace = self
  196. .persistence
  197. .begin_transaction(|transaction| {
  198. self
  199. .workspace_controller
  200. .read_workspace(workspace_id, &user_id, &transaction)
  201. })
  202. .await?;
  203. Ok(workspace)
  204. }
  205. pub async fn initialize_with_new_user(
  206. &self,
  207. user_id: &str,
  208. token: &str,
  209. view_data_format: ViewDataFormatPB,
  210. ) -> FlowyResult<()> {
  211. DefaultFolderBuilder::build(
  212. token,
  213. user_id,
  214. self.persistence.clone(),
  215. self.view_controller.clone(),
  216. || (view_data_format.clone(), Bytes::from(initial_read_me())),
  217. )
  218. .await?;
  219. self.initialize(user_id, token).await
  220. }
  221. /// Called when the current user logout
  222. ///
  223. pub async fn clear(&self, user_id: &str) {
  224. self.view_controller.clear_latest_view();
  225. clear_current_workspace(user_id);
  226. *self.folder_editor.write().await = None;
  227. }
  228. }
  229. struct DefaultFolderBuilder();
  230. impl DefaultFolderBuilder {
  231. async fn build<F: Fn() -> (ViewDataFormatPB, Bytes)>(
  232. token: &str,
  233. user_id: &str,
  234. persistence: Arc<FolderPersistence>,
  235. view_controller: Arc<ViewController>,
  236. create_view_fn: F,
  237. ) -> FlowyResult<()> {
  238. let workspace_rev = user_default::create_default_workspace();
  239. tracing::debug!(
  240. "Create user:{} default workspace:{}",
  241. user_id,
  242. workspace_rev.id
  243. );
  244. set_current_workspace(user_id, &workspace_rev.id);
  245. for app in workspace_rev.apps.iter() {
  246. for (index, view) in app.belongings.iter().enumerate() {
  247. let (view_data_type, view_data) = create_view_fn();
  248. if index == 0 {
  249. let _ = view_controller.set_latest_view(&view.id);
  250. let layout_type = ViewLayoutTypePB::from(view.layout.clone());
  251. view_controller
  252. .create_view(&view.id, &view.name, view_data_type, layout_type, view_data)
  253. .await?;
  254. }
  255. }
  256. }
  257. let folder = FolderPad::new(vec![workspace_rev.clone()], vec![])?;
  258. let folder_id = FolderId::new(user_id);
  259. persistence.save_folder(user_id, &folder_id, folder).await?;
  260. let repeated_workspace = RepeatedWorkspacePB {
  261. items: vec![workspace_rev.into()],
  262. };
  263. send_notification(token, FolderNotification::DidCreateWorkspace)
  264. .payload(repeated_workspace)
  265. .send();
  266. Ok(())
  267. }
  268. }
  269. pub trait ViewDataProcessor {
  270. /// Closes the view and releases the resources that this view has in
  271. /// the backend
  272. fn close_view(&self, view_id: &str) -> FutureResult<(), FlowyError>;
  273. /// Gets the data of the this view.
  274. /// For example, the data can be used to duplicate the view.
  275. fn get_view_data(&self, view: &ViewPB) -> FutureResult<Bytes, FlowyError>;
  276. /// Create a view with the pre-defined data.
  277. /// For example, the initial data of the grid/calendar/kanban board when
  278. /// you create a new view.
  279. fn create_view_with_build_in_data(
  280. &self,
  281. user_id: &str,
  282. view_id: &str,
  283. name: &str,
  284. layout: ViewLayoutTypePB,
  285. data_format: ViewDataFormatPB,
  286. ext: HashMap<String, String>,
  287. ) -> FutureResult<(), FlowyError>;
  288. /// Create a view with custom data
  289. fn create_view_with_custom_data(
  290. &self,
  291. user_id: &str,
  292. view_id: &str,
  293. name: &str,
  294. data: Vec<u8>,
  295. layout: ViewLayoutTypePB,
  296. ext: HashMap<String, String>,
  297. ) -> FutureResult<(), FlowyError>;
  298. fn data_types(&self) -> Vec<ViewDataFormatPB>;
  299. }
  300. pub type ViewDataProcessorMap =
  301. Arc<HashMap<ViewDataFormatPB, Arc<dyn ViewDataProcessor + Send + Sync>>>;