controller.rs 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. use crate::entities::workspace::*;
  2. use crate::manager::FolderManager;
  3. use crate::{
  4. dart_notification::*,
  5. errors::*,
  6. event_map::{FolderCouldServiceV1, WorkspaceUser},
  7. services::{
  8. persistence::{FolderPersistence, FolderPersistenceTransaction, WorkspaceChangeset},
  9. read_local_workspace_apps, TrashController,
  10. },
  11. };
  12. use flowy_database::kv::KV;
  13. use flowy_folder_data_model::revision::{AppRevision, WorkspaceRevision};
  14. use std::sync::Arc;
  15. pub struct WorkspaceController {
  16. pub user: Arc<dyn WorkspaceUser>,
  17. persistence: Arc<FolderPersistence>,
  18. pub(crate) trash_controller: Arc<TrashController>,
  19. cloud_service: Arc<dyn FolderCouldServiceV1>,
  20. }
  21. impl WorkspaceController {
  22. pub(crate) fn new(
  23. user: Arc<dyn WorkspaceUser>,
  24. persistence: Arc<FolderPersistence>,
  25. trash_can: Arc<TrashController>,
  26. cloud_service: Arc<dyn FolderCouldServiceV1>,
  27. ) -> Self {
  28. Self {
  29. user,
  30. persistence,
  31. trash_controller: trash_can,
  32. cloud_service,
  33. }
  34. }
  35. pub(crate) async fn create_workspace_from_params(
  36. &self,
  37. params: CreateWorkspaceParams,
  38. ) -> Result<WorkspaceRevision, FlowyError> {
  39. let workspace = self.create_workspace_on_server(params.clone()).await?;
  40. let user_id = self.user.user_id()?;
  41. let token = self.user.token()?;
  42. let workspaces = self
  43. .persistence
  44. .begin_transaction(|transaction| {
  45. let _ = transaction.create_workspace(&user_id, workspace.clone())?;
  46. transaction.read_workspaces(&user_id, None)
  47. })
  48. .await?
  49. .into_iter()
  50. .map(|workspace_rev| workspace_rev.into())
  51. .collect();
  52. let repeated_workspace = RepeatedWorkspace { items: workspaces };
  53. send_dart_notification(&token, FolderNotification::UserCreateWorkspace)
  54. .payload(repeated_workspace)
  55. .send();
  56. set_current_workspace(&workspace.id);
  57. Ok(workspace)
  58. }
  59. #[allow(dead_code)]
  60. pub(crate) async fn update_workspace(&self, params: UpdateWorkspaceParams) -> Result<(), FlowyError> {
  61. let changeset = WorkspaceChangeset::new(params.clone());
  62. let workspace_id = changeset.id.clone();
  63. let workspace = self
  64. .persistence
  65. .begin_transaction(|transaction| {
  66. let _ = transaction.update_workspace(changeset)?;
  67. let user_id = self.user.user_id()?;
  68. self.read_local_workspace(workspace_id.clone(), &user_id, &transaction)
  69. })
  70. .await?;
  71. send_dart_notification(&workspace_id, FolderNotification::WorkspaceUpdated)
  72. .payload(workspace)
  73. .send();
  74. let _ = self.update_workspace_on_server(params)?;
  75. Ok(())
  76. }
  77. #[allow(dead_code)]
  78. pub(crate) async fn delete_workspace(&self, workspace_id: &str) -> Result<(), FlowyError> {
  79. let user_id = self.user.user_id()?;
  80. let token = self.user.token()?;
  81. let repeated_workspace = self
  82. .persistence
  83. .begin_transaction(|transaction| {
  84. let _ = transaction.delete_workspace(workspace_id)?;
  85. self.read_local_workspaces(None, &user_id, &transaction)
  86. })
  87. .await?;
  88. send_dart_notification(&token, FolderNotification::UserDeleteWorkspace)
  89. .payload(repeated_workspace)
  90. .send();
  91. let _ = self.delete_workspace_on_server(workspace_id)?;
  92. Ok(())
  93. }
  94. pub(crate) async fn open_workspace(&self, params: WorkspaceId) -> Result<Workspace, FlowyError> {
  95. let user_id = self.user.user_id()?;
  96. if let Some(workspace_id) = params.value {
  97. let workspace = self
  98. .persistence
  99. .begin_transaction(|transaction| self.read_local_workspace(workspace_id, &user_id, &transaction))
  100. .await?;
  101. set_current_workspace(&workspace.id);
  102. Ok(workspace)
  103. } else {
  104. Err(FlowyError::workspace_id().context("Opened workspace id should not be empty"))
  105. }
  106. }
  107. pub(crate) async fn read_current_workspace_apps(&self) -> Result<Vec<AppRevision>, FlowyError> {
  108. let workspace_id = get_current_workspace()?;
  109. let app_revs = self
  110. .persistence
  111. .begin_transaction(|transaction| {
  112. read_local_workspace_apps(&workspace_id, self.trash_controller.clone(), &transaction)
  113. })
  114. .await?;
  115. // TODO: read from server
  116. Ok(app_revs)
  117. }
  118. #[tracing::instrument(level = "debug", skip(self, transaction), err)]
  119. pub(crate) fn read_local_workspaces<'a>(
  120. &self,
  121. workspace_id: Option<String>,
  122. user_id: &str,
  123. transaction: &'a (dyn FolderPersistenceTransaction + 'a),
  124. ) -> Result<RepeatedWorkspace, FlowyError> {
  125. let workspace_id = workspace_id.to_owned();
  126. let workspaces = transaction
  127. .read_workspaces(user_id, workspace_id)?
  128. .into_iter()
  129. .map(|workspace_rev| workspace_rev.into())
  130. .collect();
  131. Ok(RepeatedWorkspace { items: workspaces })
  132. }
  133. pub(crate) fn read_local_workspace<'a>(
  134. &self,
  135. workspace_id: String,
  136. user_id: &str,
  137. transaction: &'a (dyn FolderPersistenceTransaction + 'a),
  138. ) -> Result<Workspace, FlowyError> {
  139. let mut workspace_revs = transaction.read_workspaces(user_id, Some(workspace_id.clone()))?;
  140. if workspace_revs.is_empty() {
  141. return Err(FlowyError::record_not_found().context(format!("{} workspace not found", workspace_id)));
  142. }
  143. debug_assert_eq!(workspace_revs.len(), 1);
  144. let workspace = workspace_revs
  145. .drain(..1)
  146. .map(|workspace_rev| workspace_rev.into())
  147. .collect::<Vec<Workspace>>()
  148. .pop()
  149. .unwrap();
  150. Ok(workspace)
  151. }
  152. }
  153. impl WorkspaceController {
  154. #[tracing::instrument(level = "trace", skip(self), err)]
  155. async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<WorkspaceRevision, FlowyError> {
  156. let token = self.user.token()?;
  157. self.cloud_service.create_workspace(&token, params).await
  158. }
  159. #[tracing::instrument(level = "trace", skip(self), err)]
  160. fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), FlowyError> {
  161. let (token, server) = (self.user.token()?, self.cloud_service.clone());
  162. tokio::spawn(async move {
  163. match server.update_workspace(&token, params).await {
  164. Ok(_) => {}
  165. Err(e) => {
  166. // TODO: retry?
  167. log::error!("Update workspace failed: {:?}", e);
  168. }
  169. }
  170. });
  171. Ok(())
  172. }
  173. #[tracing::instrument(level = "trace", skip(self), err)]
  174. fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), FlowyError> {
  175. let params = WorkspaceId {
  176. value: Some(workspace_id.to_string()),
  177. };
  178. let (token, server) = (self.user.token()?, self.cloud_service.clone());
  179. tokio::spawn(async move {
  180. match server.delete_workspace(&token, params).await {
  181. Ok(_) => {}
  182. Err(e) => {
  183. // TODO: retry?
  184. log::error!("Delete workspace failed: {:?}", e);
  185. }
  186. }
  187. });
  188. Ok(())
  189. }
  190. }
  191. pub async fn notify_workspace_setting_did_change(
  192. folder_manager: &Arc<FolderManager>,
  193. view_id: &str,
  194. ) -> FlowyResult<()> {
  195. let user_id = folder_manager.user.user_id()?;
  196. let token = folder_manager.user.token()?;
  197. let workspace_id = get_current_workspace()?;
  198. let workspace_setting = folder_manager
  199. .persistence
  200. .begin_transaction(|transaction| {
  201. let workspace = folder_manager.workspace_controller.read_local_workspace(
  202. workspace_id.clone(),
  203. &user_id,
  204. &transaction,
  205. )?;
  206. let setting = match transaction.read_view(view_id) {
  207. Ok(latest_view) => CurrentWorkspaceSetting {
  208. workspace,
  209. latest_view: Some(latest_view.into()),
  210. },
  211. Err(_) => CurrentWorkspaceSetting {
  212. workspace,
  213. latest_view: None,
  214. },
  215. };
  216. Ok(setting)
  217. })
  218. .await?;
  219. send_dart_notification(&token, FolderNotification::WorkspaceSetting)
  220. .payload(workspace_setting)
  221. .send();
  222. Ok(())
  223. }
  224. const CURRENT_WORKSPACE_ID: &str = "current_workspace_id";
  225. pub fn set_current_workspace(workspace_id: &str) {
  226. KV::set_str(CURRENT_WORKSPACE_ID, workspace_id.to_owned());
  227. }
  228. pub fn get_current_workspace() -> Result<String, FlowyError> {
  229. match KV::get_str(CURRENT_WORKSPACE_ID) {
  230. None => {
  231. Err(FlowyError::record_not_found()
  232. .context("Current workspace not found or should call open workspace first"))
  233. }
  234. Some(workspace_id) => Ok(workspace_id),
  235. }
  236. }