| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  | use crate::{
 | 
					
						
							|  |  |  |     errors::*,
 | 
					
						
							|  |  |  |     module::{WorkspaceDatabase, WorkspaceUser},
 | 
					
						
							| 
									
										
										
										
											2021-11-08 10:43:14 +08:00
										 |  |  |     notify::*,
 | 
					
						
							|  |  |  |     services::{helper::spawn, read_local_workspace_apps, server::Server, AppController, TrashCan, ViewController},
 | 
					
						
							|  |  |  |     sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql},
 | 
					
						
							| 
									
										
										
										
											2021-09-07 23:30:43 +08:00
										 |  |  | };
 | 
					
						
							| 
									
										
										
										
											2021-11-08 23:15:29 +08:00
										 |  |  | use chrono::Utc;
 | 
					
						
							| 
									
										
										
										
											2021-11-08 19:19:02 +08:00
										 |  |  | use flowy_database::SqliteConnection;
 | 
					
						
							|  |  |  | use flowy_infra::kv::KV;
 | 
					
						
							| 
									
										
										
										
											2021-11-08 23:15:29 +08:00
										 |  |  | use flowy_workspace_infra::{
 | 
					
						
							|  |  |  |     entities::{app::RepeatedApp, workspace::*},
 | 
					
						
							|  |  |  |     user_default,
 | 
					
						
							|  |  |  | };
 | 
					
						
							| 
									
										
										
										
											2021-11-09 13:29:31 +08:00
										 |  |  | use std::sync::{
 | 
					
						
							|  |  |  |     atomic::{AtomicBool, Ordering},
 | 
					
						
							|  |  |  |     Arc,
 | 
					
						
							|  |  |  | };
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static INIT_WORKSPACE: AtomicBool = AtomicBool::new(false);
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:08:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 14:37:45 +08:00
										 |  |  | pub struct WorkspaceController {
 | 
					
						
							| 
									
										
										
										
											2021-07-18 23:56:36 +08:00
										 |  |  |     pub user: Arc<dyn WorkspaceUser>,
 | 
					
						
							| 
									
										
										
										
											2021-10-05 14:37:45 +08:00
										 |  |  |     pub(crate) workspace_sql: Arc<WorkspaceTableSql>,
 | 
					
						
							|  |  |  |     pub(crate) view_controller: Arc<ViewController>,
 | 
					
						
							|  |  |  |     pub(crate) database: Arc<dyn WorkspaceDatabase>,
 | 
					
						
							|  |  |  |     pub(crate) app_controller: Arc<AppController>,
 | 
					
						
							| 
									
										
										
										
											2021-10-13 11:10:29 +08:00
										 |  |  |     pub(crate) trash_can: Arc<TrashCan>,
 | 
					
						
							| 
									
										
										
										
											2021-09-01 22:50:22 +08:00
										 |  |  |     server: Server,
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:08:20 +08:00
										 |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | impl WorkspaceController {
 | 
					
						
							| 
									
										
										
										
											2021-09-01 22:50:22 +08:00
										 |  |  |     pub(crate) fn new(
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |         user: Arc<dyn WorkspaceUser>,
 | 
					
						
							|  |  |  |         database: Arc<dyn WorkspaceDatabase>,
 | 
					
						
							|  |  |  |         app_controller: Arc<AppController>,
 | 
					
						
							| 
									
										
										
										
											2021-09-11 20:09:46 +08:00
										 |  |  |         view_controller: Arc<ViewController>,
 | 
					
						
							| 
									
										
										
										
											2021-10-13 11:10:29 +08:00
										 |  |  |         trash_can: Arc<TrashCan>,
 | 
					
						
							| 
									
										
										
										
											2021-09-01 22:50:22 +08:00
										 |  |  |         server: Server,
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |     ) -> Self {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 23:30:43 +08:00
										 |  |  |         let workspace_sql = Arc::new(WorkspaceTableSql {});
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |         Self {
 | 
					
						
							|  |  |  |             user,
 | 
					
						
							| 
									
										
										
										
											2021-09-07 23:30:43 +08:00
										 |  |  |             workspace_sql,
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |             database,
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |             app_controller,
 | 
					
						
							| 
									
										
										
										
											2021-09-11 20:09:46 +08:00
										 |  |  |             view_controller,
 | 
					
						
							| 
									
										
										
										
											2021-10-13 11:10:29 +08:00
										 |  |  |             trash_can,
 | 
					
						
							| 
									
										
										
										
											2021-09-01 22:50:22 +08:00
										 |  |  |             server,
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:08:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 13:29:31 +08:00
										 |  |  |     fn init(&self) -> Result<(), WorkspaceError> {
 | 
					
						
							|  |  |  |         if INIT_WORKSPACE.load(Ordering::SeqCst) {
 | 
					
						
							|  |  |  |             return Ok(());
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         log::debug!("workspace initialize");
 | 
					
						
							|  |  |  |         INIT_WORKSPACE.store(true, Ordering::SeqCst);
 | 
					
						
							| 
									
										
										
										
											2021-11-08 10:57:33 +08:00
										 |  |  |         let _ = self.server.init();
 | 
					
						
							| 
									
										
										
										
											2021-10-17 22:44:51 +08:00
										 |  |  |         let _ = self.trash_can.init()?;
 | 
					
						
							| 
									
										
										
										
											2021-10-05 14:37:45 +08:00
										 |  |  |         let _ = self.view_controller.init()?;
 | 
					
						
							| 
									
										
										
										
											2021-10-30 17:19:50 +08:00
										 |  |  |         let _ = self.app_controller.init()?;
 | 
					
						
							| 
									
										
										
										
											2021-11-08 23:15:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-05 14:37:45 +08:00
										 |  |  |         Ok(())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 13:29:31 +08:00
										 |  |  |     pub fn user_did_login(&self) -> WorkspaceResult<()> {
 | 
					
						
							|  |  |  |         // TODO: (nathan) do something here
 | 
					
						
							|  |  |  |         let _ = self.init()?;
 | 
					
						
							|  |  |  |         Ok(())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub fn user_did_logout(&self) {
 | 
					
						
							|  |  |  |         // TODO: (nathan) do something here
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2021-11-08 23:15:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 13:29:31 +08:00
										 |  |  |     pub fn user_session_expired(&self) {
 | 
					
						
							|  |  |  |         // TODO: (nathan) do something here
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2021-11-08 23:15:29 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 11:07:20 +08:00
										 |  |  |     pub async fn user_did_sign_up(&self) -> WorkspaceResult<()> {
 | 
					
						
							| 
									
										
										
										
											2021-11-08 23:15:29 +08:00
										 |  |  |         log::debug!("Create user default workspace");
 | 
					
						
							|  |  |  |         let time = Utc::now();
 | 
					
						
							|  |  |  |         let mut workspace = user_default::create_default_workspace(time);
 | 
					
						
							|  |  |  |         let apps = workspace.take_apps().into_inner();
 | 
					
						
							| 
									
										
										
										
											2021-11-09 11:07:20 +08:00
										 |  |  |         let cloned_workspace = workspace.clone();
 | 
					
						
							| 
									
										
										
										
											2021-11-08 23:15:29 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |         let _ = self.create_workspace(workspace).await?;
 | 
					
						
							|  |  |  |         for mut app in apps {
 | 
					
						
							|  |  |  |             let views = app.take_belongings().into_inner();
 | 
					
						
							|  |  |  |             let _ = self.app_controller.create_app(app).await?;
 | 
					
						
							|  |  |  |             for view in views {
 | 
					
						
							|  |  |  |                 let _ = self.view_controller.create_view(view).await?;
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 11:07:20 +08:00
										 |  |  |         let token = self.user.token()?;
 | 
					
						
							|  |  |  |         let repeated_workspace = RepeatedWorkspace {
 | 
					
						
							|  |  |  |             items: vec![cloned_workspace],
 | 
					
						
							|  |  |  |         };
 | 
					
						
							| 
									
										
										
										
											2021-11-09 13:29:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 11:07:20 +08:00
										 |  |  |         send_dart_notification(&token, WorkspaceNotification::UserCreateWorkspace)
 | 
					
						
							|  |  |  |             .payload(repeated_workspace)
 | 
					
						
							|  |  |  |             .send();
 | 
					
						
							| 
									
										
										
										
											2021-11-09 13:29:31 +08:00
										 |  |  |         let _ = self.init()?;
 | 
					
						
							| 
									
										
										
										
											2021-11-09 11:07:20 +08:00
										 |  |  |         Ok(())
 | 
					
						
							| 
									
										
										
										
											2021-11-08 23:15:29 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 19:19:02 +08:00
										 |  |  |     pub(crate) async fn create_workspace_from_params(
 | 
					
						
							|  |  |  |         &self,
 | 
					
						
							|  |  |  |         params: CreateWorkspaceParams,
 | 
					
						
							|  |  |  |     ) -> Result<Workspace, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |         let workspace = self.create_workspace_on_server(params.clone()).await?;
 | 
					
						
							| 
									
										
										
										
											2021-11-08 19:19:02 +08:00
										 |  |  |         self.create_workspace(workspace).await
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     pub(crate) async fn create_workspace(&self, workspace: Workspace) -> Result<Workspace, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         let user_id = self.user.user_id()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-08 18:25:32 +08:00
										 |  |  |         let token = self.user.token()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |         let workspace_table = WorkspaceTable::new(workspace.clone(), &user_id);
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |         let conn = &*self.database.db_connection()?;
 | 
					
						
							|  |  |  |         //[[immediate_transaction]]
 | 
					
						
							|  |  |  |         // https://sqlite.org/lang_transaction.html
 | 
					
						
							|  |  |  |         // IMMEDIATE cause the database connection to start a new write immediately,
 | 
					
						
							|  |  |  |         // without waiting for a write statement. The BEGIN IMMEDIATE might fail
 | 
					
						
							|  |  |  |         // with SQLITE_BUSY if another write transaction is already active on another
 | 
					
						
							|  |  |  |         // database connection.
 | 
					
						
							|  |  |  |         //
 | 
					
						
							|  |  |  |         // EXCLUSIVE is similar to IMMEDIATE in that a write transaction is started
 | 
					
						
							|  |  |  |         // immediately. EXCLUSIVE and IMMEDIATE are the same in WAL mode, but in
 | 
					
						
							|  |  |  |         // other journaling modes, EXCLUSIVE prevents other database connections from
 | 
					
						
							|  |  |  |         // reading the database while the transaction is underway.
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         conn.immediate_transaction::<_, WorkspaceError, _>(|| {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |             self.workspace_sql.create_workspace(workspace_table, conn)?;
 | 
					
						
							|  |  |  |             let repeated_workspace = self.read_local_workspaces(None, &user_id, conn)?;
 | 
					
						
							| 
									
										
										
										
											2021-10-14 14:34:22 +08:00
										 |  |  |             send_dart_notification(&token, WorkspaceNotification::UserCreateWorkspace)
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |                 .payload(repeated_workspace)
 | 
					
						
							| 
									
										
										
										
											2021-09-11 14:26:30 +08:00
										 |  |  |                 .send();
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             Ok(())
 | 
					
						
							|  |  |  |         })?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 19:19:02 +08:00
										 |  |  |         set_current_workspace(&workspace.id);
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-29 22:22:35 +08:00
										 |  |  |         Ok(workspace)
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:08:20 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 14:42:14 +08:00
										 |  |  |     #[allow(dead_code)]
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |     pub(crate) async fn update_workspace(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         let changeset = WorkspaceTableChangeset::new(params.clone());
 | 
					
						
							| 
									
										
										
										
											2021-07-21 22:41:44 +08:00
										 |  |  |         let workspace_id = changeset.id.clone();
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |         let conn = &*self.database.db_connection()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         conn.immediate_transaction::<_, WorkspaceError, _>(|| {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |             let _ = self.workspace_sql.update_workspace(changeset, conn)?;
 | 
					
						
							|  |  |  |             let user_id = self.user.user_id()?;
 | 
					
						
							|  |  |  |             let workspace = self.read_local_workspace(workspace_id.clone(), &user_id, conn)?;
 | 
					
						
							| 
									
										
										
										
											2021-10-14 14:34:22 +08:00
										 |  |  |             send_dart_notification(&workspace_id, WorkspaceNotification::WorkspaceUpdated)
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |                 .payload(workspace)
 | 
					
						
							| 
									
										
										
										
											2021-09-11 14:26:30 +08:00
										 |  |  |                 .send();
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             Ok(())
 | 
					
						
							|  |  |  |         })?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         let _ = self.update_workspace_on_server(params)?;
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |         Ok(())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-22 14:42:14 +08:00
										 |  |  |     #[allow(dead_code)]
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |     pub(crate) async fn delete_workspace(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-07-29 22:22:35 +08:00
										 |  |  |         let user_id = self.user.user_id()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-08 18:25:32 +08:00
										 |  |  |         let token = self.user.token()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |         let conn = &*self.database.db_connection()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         conn.immediate_transaction::<_, WorkspaceError, _>(|| {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |             let _ = self.workspace_sql.delete_workspace(workspace_id, conn)?;
 | 
					
						
							|  |  |  |             let repeated_workspace = self.read_local_workspaces(None, &user_id, conn)?;
 | 
					
						
							| 
									
										
										
										
											2021-10-14 14:34:22 +08:00
										 |  |  |             send_dart_notification(&token, WorkspaceNotification::UserDeleteWorkspace)
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |                 .payload(repeated_workspace)
 | 
					
						
							| 
									
										
										
										
											2021-09-11 14:26:30 +08:00
										 |  |  |                 .send();
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             Ok(())
 | 
					
						
							|  |  |  |         })?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         let _ = self.delete_workspace_on_server(workspace_id)?;
 | 
					
						
							| 
									
										
										
										
											2021-07-29 22:22:35 +08:00
										 |  |  |         Ok(())
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-08 19:19:02 +08:00
										 |  |  |     pub(crate) async fn open_workspace(&self, params: WorkspaceIdentifier) -> Result<Workspace, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-08-27 23:53:53 +08:00
										 |  |  |         let user_id = self.user.user_id()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |         let conn = self.database.db_connection()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-04 09:00:15 +08:00
										 |  |  |         if let Some(workspace_id) = params.workspace_id.clone() {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |             let workspace = self.read_local_workspace(workspace_id, &user_id, &*conn)?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |             set_current_workspace(&workspace.id);
 | 
					
						
							|  |  |  |             Ok(workspace)
 | 
					
						
							| 
									
										
										
										
											2021-09-04 09:00:15 +08:00
										 |  |  |         } else {
 | 
					
						
							| 
									
										
										
										
											2021-09-16 12:35:55 +08:00
										 |  |  |             return Err(WorkspaceError::workspace_id().context("Opened workspace id should not be empty"));
 | 
					
						
							| 
									
										
										
										
											2021-08-27 23:53:53 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-01 19:39:08 +08:00
										 |  |  |     pub(crate) async fn read_workspaces(
 | 
					
						
							|  |  |  |         &self,
 | 
					
						
							| 
									
										
										
										
											2021-11-08 19:19:02 +08:00
										 |  |  |         params: WorkspaceIdentifier,
 | 
					
						
							| 
									
										
										
										
											2021-10-01 19:39:08 +08:00
										 |  |  |     ) -> Result<RepeatedWorkspace, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-08-27 23:53:53 +08:00
										 |  |  |         let user_id = self.user.user_id()?;
 | 
					
						
							| 
									
										
										
										
											2021-10-01 19:39:08 +08:00
										 |  |  |         let workspaces =
 | 
					
						
							|  |  |  |             self.read_local_workspaces(params.workspace_id.clone(), &user_id, &*self.database.db_connection()?)?;
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         let _ = self.read_workspaces_on_server(user_id.clone(), params.clone());
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |         Ok(workspaces)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 14:47:11 +08:00
										 |  |  |     pub(crate) async fn read_current_workspace(&self) -> Result<Workspace, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |         let workspace_id = get_current_workspace()?;
 | 
					
						
							|  |  |  |         let user_id = self.user.user_id()?;
 | 
					
						
							| 
									
										
										
										
											2021-11-08 19:19:02 +08:00
										 |  |  |         let params = WorkspaceIdentifier {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |             workspace_id: Some(workspace_id.clone()),
 | 
					
						
							|  |  |  |         };
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         let workspace = self.read_local_workspace(workspace_id, &user_id, &*self.database.db_connection()?)?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |         let _ = self.read_workspaces_on_server(user_id.clone(), params)?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |         Ok(workspace)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-07 14:47:11 +08:00
										 |  |  |     pub(crate) async fn read_current_workspace_apps(&self) -> Result<RepeatedApp, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |         let workspace_id = get_current_workspace()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |         let conn = self.database.db_connection()?;
 | 
					
						
							| 
									
										
										
										
											2021-10-31 11:41:22 +08:00
										 |  |  |         let repeated_app = self.read_local_apps(&workspace_id, &*conn)?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |         // TODO: read from server
 | 
					
						
							| 
									
										
										
										
											2021-10-31 11:41:22 +08:00
										 |  |  |         Ok(repeated_app)
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |     #[tracing::instrument(level = "debug", skip(self, conn), err)]
 | 
					
						
							|  |  |  |     fn read_local_workspaces(
 | 
					
						
							|  |  |  |         &self,
 | 
					
						
							|  |  |  |         workspace_id: Option<String>,
 | 
					
						
							|  |  |  |         user_id: &str,
 | 
					
						
							|  |  |  |         conn: &SqliteConnection,
 | 
					
						
							|  |  |  |     ) -> Result<RepeatedWorkspace, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |         let workspace_id = workspace_id.to_owned();
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |         let workspace_tables = self.workspace_sql.read_workspaces(workspace_id, user_id, conn)?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-08-27 23:53:53 +08:00
										 |  |  |         let mut workspaces = vec![];
 | 
					
						
							| 
									
										
										
										
											2021-08-28 23:08:12 +08:00
										 |  |  |         for table in workspace_tables {
 | 
					
						
							| 
									
										
										
										
											2021-10-31 11:41:22 +08:00
										 |  |  |             let apps = self.read_local_apps(&table.id, conn)?.into_inner();
 | 
					
						
							| 
									
										
										
										
											2021-08-28 23:08:12 +08:00
										 |  |  |             let mut workspace: Workspace = table.into();
 | 
					
						
							|  |  |  |             workspace.apps.items = apps;
 | 
					
						
							|  |  |  |             workspaces.push(workspace);
 | 
					
						
							|  |  |  |         }
 | 
					
						
							| 
									
										
										
										
											2021-08-27 23:53:53 +08:00
										 |  |  |         Ok(RepeatedWorkspace { items: workspaces })
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-01 19:39:08 +08:00
										 |  |  |     fn read_local_workspace(
 | 
					
						
							|  |  |  |         &self,
 | 
					
						
							|  |  |  |         workspace_id: String,
 | 
					
						
							|  |  |  |         user_id: &str,
 | 
					
						
							|  |  |  |         conn: &SqliteConnection,
 | 
					
						
							|  |  |  |     ) -> Result<Workspace, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |         // Opti: fetch single workspace from local db
 | 
					
						
							| 
									
										
										
										
											2021-09-16 12:35:55 +08:00
										 |  |  |         let mut repeated_workspace = self.read_local_workspaces(Some(workspace_id.clone()), user_id, conn)?;
 | 
					
						
							| 
									
										
										
										
											2021-08-28 23:08:12 +08:00
										 |  |  |         if repeated_workspace.is_empty() {
 | 
					
						
							| 
									
										
										
										
											2021-10-16 21:38:50 +08:00
										 |  |  |             return Err(WorkspaceError::record_not_found().context(format!("{} workspace not found", workspace_id)));
 | 
					
						
							| 
									
										
										
										
											2021-08-28 23:08:12 +08:00
										 |  |  |         }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         debug_assert_eq!(repeated_workspace.len(), 1);
 | 
					
						
							| 
									
										
										
										
											2021-09-01 22:50:22 +08:00
										 |  |  |         let workspace = repeated_workspace.drain(..1).collect::<Vec<Workspace>>().pop().unwrap();
 | 
					
						
							| 
									
										
										
										
											2021-08-28 23:08:12 +08:00
										 |  |  |         Ok(workspace)
 | 
					
						
							|  |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |     #[tracing::instrument(level = "debug", skip(self, conn), err)]
 | 
					
						
							| 
									
										
										
										
											2021-10-31 11:41:22 +08:00
										 |  |  |     fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result<RepeatedApp, WorkspaceError> {
 | 
					
						
							|  |  |  |         let repeated_app = read_local_workspace_apps(workspace_id, self.trash_can.clone(), conn)?;
 | 
					
						
							|  |  |  |         Ok(repeated_app)
 | 
					
						
							| 
									
										
										
										
											2021-07-20 14:03:21 +08:00
										 |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2021-07-13 23:08:20 +08:00
										 |  |  | }
 | 
					
						
							| 
									
										
										
										
											2021-08-24 21:38:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  | impl WorkspaceController {
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |     fn token_with_server(&self) -> Result<(String, Server), WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         let token = self.user.token()?;
 | 
					
						
							|  |  |  |         let server = self.server.clone();
 | 
					
						
							|  |  |  |         Ok((token, server))
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2021-08-28 23:08:12 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |     #[tracing::instrument(level = "debug", skip(self), err)]
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |     async fn create_workspace_on_server(&self, params: CreateWorkspaceParams) -> Result<Workspace, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         let token = self.user.token()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |         let workspace = self.server.create_workspace(&token, params).await?;
 | 
					
						
							|  |  |  |         Ok(workspace)
 | 
					
						
							| 
									
										
										
										
											2021-08-28 23:08:12 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |     #[tracing::instrument(level = "debug", skip(self), err)]
 | 
					
						
							|  |  |  |     fn update_workspace_on_server(&self, params: UpdateWorkspaceParams) -> Result<(), WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |         let (token, server) = self.token_with_server()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         spawn(async move {
 | 
					
						
							|  |  |  |             match server.update_workspace(&token, params).await {
 | 
					
						
							|  |  |  |                 Ok(_) => {},
 | 
					
						
							|  |  |  |                 Err(e) => {
 | 
					
						
							|  |  |  |                     // TODO: retry?
 | 
					
						
							|  |  |  |                     log::error!("Update workspace failed: {:?}", e);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         });
 | 
					
						
							|  |  |  |         Ok(())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2021-08-24 21:38:53 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |     #[tracing::instrument(level = "debug", skip(self), err)]
 | 
					
						
							|  |  |  |     fn delete_workspace_on_server(&self, workspace_id: &str) -> Result<(), WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |         let params = DeleteWorkspaceParams {
 | 
					
						
							|  |  |  |             workspace_id: workspace_id.to_string(),
 | 
					
						
							|  |  |  |         };
 | 
					
						
							|  |  |  |         let (token, server) = self.token_with_server()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         spawn(async move {
 | 
					
						
							|  |  |  |             match server.delete_workspace(&token, params).await {
 | 
					
						
							|  |  |  |                 Ok(_) => {},
 | 
					
						
							|  |  |  |                 Err(e) => {
 | 
					
						
							|  |  |  |                     // TODO: retry?
 | 
					
						
							|  |  |  |                     log::error!("Delete workspace failed: {:?}", e);
 | 
					
						
							|  |  |  |                 },
 | 
					
						
							|  |  |  |             }
 | 
					
						
							|  |  |  |         });
 | 
					
						
							|  |  |  |         Ok(())
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2021-08-25 17:34:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |     #[tracing::instrument(level = "debug", skip(self), err)]
 | 
					
						
							| 
									
										
										
										
											2021-11-08 19:19:02 +08:00
										 |  |  |     fn read_workspaces_on_server(&self, user_id: String, params: WorkspaceIdentifier) -> Result<(), WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-02 19:57:19 +08:00
										 |  |  |         let (token, server) = self.token_with_server()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-07 23:30:43 +08:00
										 |  |  |         let workspace_sql = self.workspace_sql.clone();
 | 
					
						
							| 
									
										
										
										
											2021-09-11 20:09:46 +08:00
										 |  |  |         let app_ctrl = self.app_controller.clone();
 | 
					
						
							|  |  |  |         let view_ctrl = self.view_controller.clone();
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |         let conn = self.database.db_connection()?;
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         spawn(async move {
 | 
					
						
							| 
									
										
										
										
											2021-09-09 15:43:05 +08:00
										 |  |  |             // Opti: handle the error and retry?
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |             let workspaces = server.read_workspace(&token, params).await?;
 | 
					
						
							|  |  |  |             let _ = (&*conn).immediate_transaction::<_, WorkspaceError, _>(|| {
 | 
					
						
							| 
									
										
										
										
											2021-11-03 15:37:38 +08:00
										 |  |  |                 tracing::debug!("Save {} workspace", workspaces.len());
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |                 for workspace in &workspaces.items {
 | 
					
						
							|  |  |  |                     let mut m_workspace = workspace.clone();
 | 
					
						
							| 
									
										
										
										
											2021-10-18 16:30:20 +08:00
										 |  |  |                     let apps = m_workspace.apps.into_inner();
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |                     let workspace_table = WorkspaceTable::new(m_workspace, &user_id);
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-07 23:30:43 +08:00
										 |  |  |                     let _ = workspace_sql.create_workspace(workspace_table, &*conn)?;
 | 
					
						
							| 
									
										
										
										
											2021-11-03 15:37:38 +08:00
										 |  |  |                     tracing::debug!("Save {} apps", apps.len());
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |                     for mut app in apps {
 | 
					
						
							| 
									
										
										
										
											2021-10-18 16:30:20 +08:00
										 |  |  |                         let views = app.belongings.into_inner();
 | 
					
						
							| 
									
										
										
										
											2021-09-11 20:09:46 +08:00
										 |  |  |                         match app_ctrl.save_app(app, &*conn) {
 | 
					
						
							| 
									
										
										
										
											2021-09-08 13:50:20 +08:00
										 |  |  |                             Ok(_) => {},
 | 
					
						
							|  |  |  |                             Err(e) => log::error!("create app failed: {:?}", e),
 | 
					
						
							|  |  |  |                         }
 | 
					
						
							| 
									
										
										
										
											2021-09-07 23:30:43 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-03 15:37:38 +08:00
										 |  |  |                         tracing::debug!("Save {} views", views.len());
 | 
					
						
							| 
									
										
										
										
											2021-09-07 23:30:43 +08:00
										 |  |  |                         for view in views {
 | 
					
						
							| 
									
										
										
										
											2021-09-11 20:09:46 +08:00
										 |  |  |                             match view_ctrl.save_view(view, &*conn) {
 | 
					
						
							| 
									
										
										
										
											2021-09-08 13:50:20 +08:00
										 |  |  |                                 Ok(_) => {},
 | 
					
						
							|  |  |  |                                 Err(e) => log::error!("create view failed: {:?}", e),
 | 
					
						
							|  |  |  |                             }
 | 
					
						
							| 
									
										
										
										
											2021-09-07 21:31:04 +08:00
										 |  |  |                         }
 | 
					
						
							|  |  |  |                     }
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |                 }
 | 
					
						
							|  |  |  |                 Ok(())
 | 
					
						
							|  |  |  |             })?;
 | 
					
						
							| 
									
										
										
										
											2021-09-08 18:25:32 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-10-14 14:34:22 +08:00
										 |  |  |             send_dart_notification(&token, WorkspaceNotification::WorkspaceListUpdated)
 | 
					
						
							| 
									
										
										
										
											2021-10-01 19:39:08 +08:00
										 |  |  |                 .payload(workspaces)
 | 
					
						
							|  |  |  |                 .send();
 | 
					
						
							| 
									
										
										
										
											2021-09-07 17:12:03 +08:00
										 |  |  |             Result::<(), WorkspaceError>::Ok(())
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         });
 | 
					
						
							| 
									
										
										
										
											2021-09-06 16:18:34 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         Ok(())
 | 
					
						
							| 
									
										
										
										
											2021-08-25 17:34:20 +08:00
										 |  |  |     }
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  | const CURRENT_WORKSPACE_ID: &str = "current_workspace_id";
 | 
					
						
							| 
									
										
										
										
											2021-08-25 17:34:20 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-11-09 13:29:31 +08:00
										 |  |  | fn set_current_workspace(workspace_id: &str) { KV::set_str(CURRENT_WORKSPACE_ID, workspace_id.to_owned()); }
 | 
					
						
							| 
									
										
										
										
											2021-08-26 17:58:59 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  | fn get_current_workspace() -> Result<String, WorkspaceError> {
 | 
					
						
							| 
									
										
										
										
											2021-09-03 12:44:48 +08:00
										 |  |  |     match KV::get_str(CURRENT_WORKSPACE_ID) {
 | 
					
						
							| 
									
										
										
										
											2021-10-16 21:38:50 +08:00
										 |  |  |         None => Err(WorkspaceError::record_not_found()
 | 
					
						
							|  |  |  |             .context("Current workspace not found or should call open workspace first")),
 | 
					
						
							| 
									
										
										
										
											2021-09-02 14:47:39 +08:00
										 |  |  |         Some(workspace_id) => Ok(workspace_id),
 | 
					
						
							|  |  |  |     }
 | 
					
						
							| 
									
										
										
										
											2021-08-26 17:58:59 +08:00
										 |  |  | }
 |