controller.rs 7.5 KB

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