appflowy 3 лет назад
Родитель
Сommit
6298a0d96d
36 измененных файлов с 676 добавлено и 578 удалено
  1. 1 1
      backend/tests/util/helper.rs
  2. 134 0
      frontend/rust-lib/flowy-core/src/core/flowy_core.rs
  3. 4 0
      frontend/rust-lib/flowy-core/src/core/mod.rs
  4. 69 0
      frontend/rust-lib/flowy-core/src/core/task.rs
  5. 0 9
      frontend/rust-lib/flowy-core/src/handlers/mod.rs
  6. 2 3
      frontend/rust-lib/flowy-core/src/lib.rs
  7. 42 21
      frontend/rust-lib/flowy-core/src/module.rs
  8. 18 13
      frontend/rust-lib/flowy-core/src/services/app/controller.rs
  9. 2 2
      frontend/rust-lib/flowy-core/src/services/app/event_handler.rs
  10. 3 0
      frontend/rust-lib/flowy-core/src/services/app/mod.rs
  11. 77 8
      frontend/rust-lib/flowy-core/src/services/app/sql.rs
  12. 0 1
      frontend/rust-lib/flowy-core/src/services/database.rs
  13. 8 9
      frontend/rust-lib/flowy-core/src/services/mod.rs
  14. 8 12
      frontend/rust-lib/flowy-core/src/services/trash/controller.rs
  15. 8 6
      frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs
  16. 3 0
      frontend/rust-lib/flowy-core/src/services/trash/mod.rs
  17. 51 2
      frontend/rust-lib/flowy-core/src/services/trash/sql.rs
  18. 15 7
      frontend/rust-lib/flowy-core/src/services/view/controller.rs
  19. 2 2
      frontend/rust-lib/flowy-core/src/services/view/event_handler.rs
  20. 3 0
      frontend/rust-lib/flowy-core/src/services/view/mod.rs
  21. 103 6
      frontend/rust-lib/flowy-core/src/services/view/sql.rs
  22. 22 107
      frontend/rust-lib/flowy-core/src/services/workspace/controller.rs
  23. 0 0
      frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs
  24. 3 0
      frontend/rust-lib/flowy-core/src/services/workspace/mod.rs
  25. 73 7
      frontend/rust-lib/flowy-core/src/services/workspace/sql.rs
  26. 0 76
      frontend/rust-lib/flowy-core/src/sql_tables/app/app_sql.rs
  27. 0 5
      frontend/rust-lib/flowy-core/src/sql_tables/app/mod.rs
  28. 0 4
      frontend/rust-lib/flowy-core/src/sql_tables/mod.rs
  29. 0 5
      frontend/rust-lib/flowy-core/src/sql_tables/trash/mod.rs
  30. 0 53
      frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_sql.rs
  31. 0 5
      frontend/rust-lib/flowy-core/src/sql_tables/view/mod.rs
  32. 0 104
      frontend/rust-lib/flowy-core/src/sql_tables/view/view_sql.rs
  33. 0 5
      frontend/rust-lib/flowy-core/src/sql_tables/workspace/mod.rs
  34. 0 71
      frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_table.rs
  35. 21 27
      frontend/rust-lib/flowy-sdk/src/lib.rs
  36. 4 7
      frontend/rust-lib/flowy-sdk/src/module.rs

+ 1 - 1
backend/tests/util/helper.rs

@@ -188,7 +188,7 @@ impl std::convert::From<TestServer> for TestUserServer {
             pg_pool: server.pg_pool,
             user_token: None,
             user_id: None,
-            client_server_config: server.client_server_config.clone(),
+            client_server_config: server.client_server_config,
         }
     }
 }

+ 134 - 0
frontend/rust-lib/flowy-core/src/core/flowy_core.rs

@@ -0,0 +1,134 @@
+use crate::{
+    entities::workspace::RepeatedWorkspace,
+    errors::{WorkspaceError, WorkspaceResult},
+    module::WorkspaceUser,
+    notify::{send_dart_notification, WorkspaceNotification},
+    services::{server::Server, AppController, TrashController, ViewController, WorkspaceController},
+};
+use chrono::Utc;
+use flowy_document_infra::{entities::doc::DocDelta, user_default::initial_read_me};
+use flowy_workspace_infra::user_default;
+use lazy_static::lazy_static;
+use lib_infra::entities::network_state::NetworkType;
+use parking_lot::RwLock;
+use std::{collections::HashMap, sync::Arc};
+
+lazy_static! {
+    static ref INIT_WORKSPACE: RwLock<HashMap<String, bool>> = RwLock::new(HashMap::new());
+}
+
+pub struct FlowyCore {
+    pub user: Arc<dyn WorkspaceUser>,
+    server: Server,
+    pub workspace_controller: Arc<WorkspaceController>,
+    pub(crate) app_controller: Arc<AppController>,
+    pub(crate) view_controller: Arc<ViewController>,
+    pub(crate) trash_controller: Arc<TrashController>,
+}
+
+impl FlowyCore {
+    pub(crate) fn new(
+        user: Arc<dyn WorkspaceUser>,
+        server: Server,
+        workspace_controller: Arc<WorkspaceController>,
+        app_controller: Arc<AppController>,
+        view_controller: Arc<ViewController>,
+        trash_controller: Arc<TrashController>,
+    ) -> Self {
+        if let Ok(token) = user.token() {
+            INIT_WORKSPACE.write().insert(token, false);
+        }
+
+        Self {
+            user,
+            server,
+            workspace_controller,
+            app_controller,
+            view_controller,
+            trash_controller,
+        }
+    }
+
+    async fn init(&self, token: &str) -> Result<(), WorkspaceError> {
+        if let Some(is_init) = INIT_WORKSPACE.read().get(token) {
+            if *is_init {
+                return Ok(());
+            }
+        }
+        log::debug!("Start initializing flowy core");
+        INIT_WORKSPACE.write().insert(token.to_owned(), true);
+        let _ = self.server.init();
+        let _ = self.workspace_controller.init()?;
+        let _ = self.app_controller.init()?;
+        let _ = self.view_controller.init()?;
+        let _ = self.trash_controller.init()?;
+        log::debug!("Finish initializing core");
+
+        Ok(())
+    }
+
+    pub fn network_state_changed(&self, new_type: NetworkType) {
+        match new_type {
+            NetworkType::UnknownNetworkType => {},
+            NetworkType::Wifi => {},
+            NetworkType::Cell => {},
+            NetworkType::Ethernet => {},
+        }
+    }
+
+    pub async fn user_did_sign_in(&self, token: &str) -> WorkspaceResult<()> {
+        // TODO: (nathan) do something here
+
+        log::debug!("workspace initialize after sign in");
+        let _ = self.init(token).await?;
+        Ok(())
+    }
+
+    pub async fn user_did_logout(&self) {
+        // TODO: (nathan) do something here
+    }
+
+    pub async fn user_session_expired(&self) {
+        // TODO: (nathan) do something here
+    }
+
+    pub async fn user_did_sign_up(&self, _token: &str) -> WorkspaceResult<()> {
+        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();
+        let cloned_workspace = workspace.clone();
+
+        let _ = self.workspace_controller.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 (index, view) in views.into_iter().enumerate() {
+                if index == 0 {
+                    let delta = initial_read_me();
+                    let doc_delta = DocDelta {
+                        doc_id: view.id.clone(),
+                        data: delta.to_json(),
+                    };
+                    let _ = self.view_controller.apply_doc_delta(doc_delta).await?;
+
+                    self.view_controller.set_latest_view(&view);
+                }
+                let _ = self.view_controller.create_view(view).await?;
+            }
+        }
+
+        let token = self.user.token()?;
+        let repeated_workspace = RepeatedWorkspace {
+            items: vec![cloned_workspace],
+        };
+
+        send_dart_notification(&token, WorkspaceNotification::UserCreateWorkspace)
+            .payload(repeated_workspace)
+            .send();
+
+        log::debug!("workspace initialize after sign up");
+        let _ = self.init(&token).await?;
+        Ok(())
+    }
+}

+ 4 - 0
frontend/rust-lib/flowy-core/src/core/mod.rs

@@ -0,0 +1,4 @@
+mod flowy_core;
+mod task;
+
+pub use flowy_core::*;

+ 69 - 0
frontend/rust-lib/flowy-core/src/core/task.rs

@@ -0,0 +1,69 @@
+use crate::{errors::WorkspaceError, services::WorkspaceController};
+use flowy_workspace_infra::entities::workspace::{QueryWorkspaceRequest, RepeatedWorkspace, WorkspaceIdentifier};
+use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
+use std::{convert::TryInto, sync::Arc};
+
+#[tracing::instrument(skip(data, controller), err)]
+pub(crate) async fn read_workspaces_handler(
+    data: Data<QueryWorkspaceRequest>,
+    controller: Unit<Arc<WorkspaceController>>,
+) -> DataResult<RepeatedWorkspace, WorkspaceError> {
+    let params: WorkspaceIdentifier = data.into_inner().try_into()?;
+    let user_id = controller.user.user_id()?;
+    let workspaces = controller.read_local_workspaces(
+        params.workspace_id.clone(),
+        &user_id,
+        &*controller.database.db_connection()?,
+    )?;
+    let _ = controller.read_workspaces_on_server(user_id, params);
+
+    data_result(workspaces)
+}
+
+// #[tracing::instrument(level = "debug", skip(self), err)]
+// fn read_workspaces_on_server(&self, user_id: String, params:
+// WorkspaceIdentifier) -> Result<(), WorkspaceError> {     let (token, server)
+// = self.token_with_server()?;     let workspace_sql =
+// self.workspace_sql.clone();     let app_ctrl = self.app_controller.clone();
+//     let view_ctrl = self.view_controller.clone();
+//     let conn = self.database.db_connection()?;
+//     tokio::spawn(async move {
+//         // Opti: handle the error and retry?
+//         let workspaces = server.read_workspace(&token, params).await?;
+//         let _ = (&*conn).immediate_transaction::<_, WorkspaceError, _>(|| {
+//             tracing::debug!("Save {} workspace", workspaces.len());
+//             for workspace in &workspaces.items {
+//                 let m_workspace = workspace.clone();
+//                 let apps = m_workspace.apps.clone().into_inner();
+//                 let workspace_table = WorkspaceTable::new(m_workspace,
+// &user_id);
+//
+//                 let _ = workspace_sql.create_workspace(workspace_table,
+// &*conn)?;                 tracing::debug!("Save {} apps", apps.len());
+//                 for app in apps {
+//                     let views = app.belongings.clone().into_inner();
+//                     match app_ctrl.save_app(app, &*conn) {
+//                         Ok(_) => {},
+//                         Err(e) => log::error!("create app failed: {:?}", e),
+//                     }
+//
+//                     tracing::debug!("Save {} views", views.len());
+//                     for view in views {
+//                         match view_ctrl.save_view(view, &*conn) {
+//                             Ok(_) => {},
+//                             Err(e) => log::error!("create view failed: {:?}",
+// e),                         }
+//                     }
+//                 }
+//             }
+//             Ok(())
+//         })?;
+//
+//         send_dart_notification(&token,
+// WorkspaceNotification::WorkspaceListUpdated)             .payload(workspaces)
+//             .send();
+//         Result::<(), WorkspaceError>::Ok(())
+//     });
+//
+//     Ok(())
+// }

+ 0 - 9
frontend/rust-lib/flowy-core/src/handlers/mod.rs

@@ -1,9 +0,0 @@
-mod app_handler;
-mod trash_handler;
-mod view_handler;
-mod workspace_handler;
-
-pub(crate) use app_handler::*;
-pub(crate) use trash_handler::*;
-pub(crate) use view_handler::*;
-pub(crate) use workspace_handler::*;

+ 2 - 3
frontend/rust-lib/flowy-core/src/lib.rs

@@ -10,15 +10,14 @@ mod macros;
 #[macro_use]
 extern crate flowy_database;
 
+pub mod core;
 pub mod errors;
-pub mod handlers;
 mod notify;
 pub mod protobuf;
-mod sql_tables;
 mod util;
 
 pub mod prelude {
     pub use flowy_workspace_infra::entities::{app::*, trash::*, view::*, workspace::*};
 
-    pub use crate::{errors::*, module::*, services::*};
+    pub use crate::{core::*, errors::*, module::*};
 }

+ 42 - 21
frontend/rust-lib/flowy-core/src/module.rs

@@ -1,15 +1,27 @@
-use crate::{
-    errors::WorkspaceError,
-    event::WorkspaceEvent,
-    handlers::*,
-    services::{server::construct_workspace_server, AppController, TrashCan, ViewController, WorkspaceController},
-};
+use std::sync::Arc;
+
 use backend_service::configuration::ClientServerConfiguration;
 use flowy_database::DBConnection;
 use flowy_document::module::FlowyDocument;
 use lib_dispatch::prelude::*;
 use lib_sqlite::ConnectionPool;
-use std::sync::Arc;
+
+use crate::{
+    core::FlowyCore,
+    errors::WorkspaceError,
+    event::WorkspaceEvent,
+    services::{
+        app::event_handler::*,
+        server::construct_workspace_server,
+        trash::event_handler::*,
+        view::event_handler::*,
+        workspace::event_handler::*,
+        AppController,
+        TrashController,
+        ViewController,
+        WorkspaceController,
+    },
+};
 
 pub trait WorkspaceDeps: WorkspaceUser + WorkspaceDatabase {}
 
@@ -28,48 +40,57 @@ pub trait WorkspaceDatabase: Send + Sync {
     }
 }
 
-pub fn init_workspace_controller(
+pub fn init_core(
     user: Arc<dyn WorkspaceUser>,
     database: Arc<dyn WorkspaceDatabase>,
     flowy_document: Arc<FlowyDocument>,
     server_config: &ClientServerConfiguration,
-) -> Arc<WorkspaceController> {
+) -> Arc<FlowyCore> {
     let server = construct_workspace_server(server_config);
 
-    let trash_can = Arc::new(TrashCan::new(database.clone(), server.clone(), user.clone()));
+    let trash_controller = Arc::new(TrashController::new(database.clone(), server.clone(), user.clone()));
 
     let view_controller = Arc::new(ViewController::new(
         user.clone(),
         database.clone(),
         server.clone(),
-        trash_can.clone(),
+        trash_controller.clone(),
         flowy_document,
     ));
 
     let app_controller = Arc::new(AppController::new(
         user.clone(),
         database.clone(),
-        trash_can.clone(),
+        trash_controller.clone(),
         server.clone(),
     ));
 
-    Arc::new(WorkspaceController::new(
+    let workspace_controller = Arc::new(WorkspaceController::new(
+        user.clone(),
+        database.clone(),
+        app_controller.clone(),
+        view_controller.clone(),
+        trash_controller.clone(),
+        server.clone(),
+    ));
+
+    Arc::new(FlowyCore::new(
         user,
-        database,
+        server,
+        workspace_controller,
         app_controller,
         view_controller,
-        trash_can,
-        server,
+        trash_controller,
     ))
 }
 
-pub fn create(workspace: Arc<WorkspaceController>) -> Module {
+pub fn create(core: Arc<FlowyCore>) -> Module {
     let mut module = Module::new()
         .name("Flowy-Workspace")
-        .data(workspace.clone())
-        .data(workspace.app_controller.clone())
-        .data(workspace.view_controller.clone())
-        .data(workspace.trash_can.clone());
+        .data(core.workspace_controller.clone())
+        .data(core.app_controller.clone())
+        .data(core.view_controller.clone())
+        .data(core.trash_controller.clone());
 
     module = module
         .event(WorkspaceEvent::CreateWorkspace, create_workspace_handler)

+ 18 - 13
frontend/rust-lib/flowy-core/src/services/app_controller.rs → frontend/rust-lib/flowy-core/src/services/app/controller.rs

@@ -1,9 +1,3 @@
-use std::{collections::HashSet, sync::Arc};
-
-use futures::{FutureExt, StreamExt};
-
-use flowy_database::SqliteConnection;
-
 use crate::{
     entities::{
         app::{App, CreateAppParams, *},
@@ -12,14 +6,21 @@ use crate::{
     errors::*,
     module::{WorkspaceDatabase, WorkspaceUser},
     notify::*,
-    services::{server::Server, TrashCan, TrashEvent},
-    sql_tables::app::{AppTable, AppTableChangeset, AppTableSql},
+    services::{
+        app::sql::{AppTable, AppTableChangeset, AppTableSql},
+        server::Server,
+        TrashController,
+        TrashEvent,
+    },
 };
+use flowy_database::SqliteConnection;
+use futures::{FutureExt, StreamExt};
+use std::{collections::HashSet, sync::Arc};
 
 pub(crate) struct AppController {
     user: Arc<dyn WorkspaceUser>,
     database: Arc<dyn WorkspaceDatabase>,
-    trash_can: Arc<TrashCan>,
+    trash_can: Arc<TrashController>,
     server: Server,
 }
 
@@ -27,7 +28,7 @@ impl AppController {
     pub(crate) fn new(
         user: Arc<dyn WorkspaceUser>,
         database: Arc<dyn WorkspaceDatabase>,
-        trash_can: Arc<TrashCan>,
+        trash_can: Arc<TrashController>,
         server: Server,
     ) -> Self {
         Self {
@@ -185,7 +186,7 @@ impl AppController {
 }
 
 #[tracing::instrument(level = "trace", skip(database, trash_can))]
-async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc<TrashCan>, event: TrashEvent) {
+async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc<TrashController>, event: TrashEvent) {
     let db_result = database.db_connection();
     match event {
         TrashEvent::NewTrash(identifiers, ret) | TrashEvent::Putback(identifiers, ret) => {
@@ -226,7 +227,11 @@ async fn handle_trash_event(database: Arc<dyn WorkspaceDatabase>, trash_can: Arc
 }
 
 #[tracing::instrument(skip(workspace_id, trash_can, conn), err)]
-fn notify_apps_changed(workspace_id: &str, trash_can: Arc<TrashCan>, conn: &SqliteConnection) -> WorkspaceResult<()> {
+fn notify_apps_changed(
+    workspace_id: &str,
+    trash_can: Arc<TrashController>,
+    conn: &SqliteConnection,
+) -> WorkspaceResult<()> {
     let repeated_app = read_local_workspace_apps(workspace_id, trash_can, conn)?;
     send_dart_notification(workspace_id, WorkspaceNotification::WorkspaceAppsChanged)
         .payload(repeated_app)
@@ -236,7 +241,7 @@ fn notify_apps_changed(workspace_id: &str, trash_can: Arc<TrashCan>, conn: &Sqli
 
 pub fn read_local_workspace_apps(
     workspace_id: &str,
-    trash_can: Arc<TrashCan>,
+    trash_can: Arc<TrashController>,
     conn: &SqliteConnection,
 ) -> Result<RepeatedApp, WorkspaceError> {
     let mut app_tables = AppTableSql::read_workspace_apps(workspace_id, false, conn)?;

+ 2 - 2
frontend/rust-lib/flowy-core/src/handlers/app_handler.rs → frontend/rust-lib/flowy-core/src/services/app/event_handler.rs

@@ -12,7 +12,7 @@ use crate::{
         trash::Trash,
     },
     errors::WorkspaceError,
-    services::{AppController, TrashCan, ViewController},
+    services::{AppController, TrashController, ViewController},
 };
 use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
 use std::{convert::TryInto, sync::Arc};
@@ -30,7 +30,7 @@ pub(crate) async fn create_app_handler(
 pub(crate) async fn delete_app_handler(
     data: Data<QueryAppRequest>,
     controller: Unit<Arc<AppController>>,
-    trash_can: Unit<Arc<TrashCan>>,
+    trash_can: Unit<Arc<TrashController>>,
 ) -> Result<(), WorkspaceError> {
     let params: AppIdentifier = data.into_inner().try_into()?;
     let trash = controller

+ 3 - 0
frontend/rust-lib/flowy-core/src/services/app/mod.rs

@@ -0,0 +1,3 @@
+pub mod controller;
+pub mod event_handler;
+pub(crate) mod sql;

+ 77 - 8
frontend/rust-lib/flowy-core/src/sql_tables/app/app_table.rs → frontend/rust-lib/flowy-core/src/services/app/sql.rs

@@ -1,18 +1,87 @@
-use std::convert::TryInto;
-
-use diesel::sql_types::Binary;
-use serde::{Deserialize, Serialize, __private::TryFrom};
-
-use flowy_database::schema::app_table;
-
 use crate::{
     entities::{
         app::{App, ColorStyle, UpdateAppParams},
         trash::{Trash, TrashType},
         view::RepeatedView,
     },
-    sql_tables::workspace::WorkspaceTable,
+    services::workspace::sql::WorkspaceTable,
 };
+use diesel::sql_types::Binary;
+use flowy_database::{
+    prelude::*,
+    schema::{app_table, app_table::dsl},
+    SqliteConnection,
+};
+use serde::{Deserialize, Serialize, __private::TryFrom};
+use std::convert::TryInto;
+
+use crate::errors::WorkspaceError;
+
+pub struct AppTableSql {}
+
+impl AppTableSql {
+    pub(crate) fn create_app(app_table: AppTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
+        match diesel_record_count!(app_table, &app_table.id, conn) {
+            0 => diesel_insert_table!(app_table, &app_table, conn),
+            _ => {
+                let changeset = AppTableChangeset::from_table(app_table);
+                diesel_update_table!(app_table, changeset, conn)
+            },
+        }
+        Ok(())
+    }
+
+    pub(crate) fn update_app(changeset: AppTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
+        diesel_update_table!(app_table, changeset, conn);
+        Ok(())
+    }
+
+    pub(crate) fn read_app(app_id: &str, conn: &SqliteConnection) -> Result<AppTable, WorkspaceError> {
+        let filter = dsl::app_table.filter(app_table::id.eq(app_id)).into_boxed();
+        let app_table = filter.first::<AppTable>(conn)?;
+        Ok(app_table)
+    }
+
+    pub(crate) fn read_workspace_apps(
+        workspace_id: &str,
+        is_trash: bool,
+        conn: &SqliteConnection,
+    ) -> Result<Vec<AppTable>, WorkspaceError> {
+        let app_table = dsl::app_table
+            .filter(app_table::workspace_id.eq(workspace_id))
+            .filter(app_table::is_trash.eq(is_trash))
+            .order(app_table::create_time.asc())
+            .load::<AppTable>(conn)?;
+
+        Ok(app_table)
+    }
+
+    pub(crate) fn delete_app(app_id: &str, conn: &SqliteConnection) -> Result<AppTable, WorkspaceError> {
+        let app_table = dsl::app_table
+            .filter(app_table::id.eq(app_id))
+            .first::<AppTable>(conn)?;
+        diesel_delete_table!(app_table, app_id, conn);
+        Ok(app_table)
+    }
+
+    // pub(crate) fn read_views_belong_to_app(
+    //     &self,
+    //     app_id: &str,
+    // ) -> Result<Vec<ViewTable>, WorkspaceError> {
+    //     let conn = self.database.db_connection()?;
+    //
+    //     let views = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
+    //         let app_table: AppTable = dsl::app_table
+    //             .filter(app_table::id.eq(app_id))
+    //             .first::<AppTable>(&*(conn))?;
+    //         let views =
+    // ViewTable::belonging_to(&app_table).load::<ViewTable>(&*conn)?;
+    //         Ok(views)
+    //     })?;
+    //
+    //     Ok(views)
+    // }
+}
 
 #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
 #[belongs_to(WorkspaceTable, foreign_key = "workspace_id")]

+ 0 - 1
frontend/rust-lib/flowy-core/src/services/database.rs

@@ -1 +0,0 @@
-

+ 8 - 9
frontend/rust-lib/flowy-core/src/services/mod.rs

@@ -1,11 +1,10 @@
-pub(crate) use app_controller::*;
-pub(crate) use trash_can::*;
-pub(crate) use view_controller::*;
-pub use workspace_controller::*;
+pub(crate) use app::controller::*;
+pub(crate) use trash::controller::*;
+pub(crate) use view::controller::*;
+pub(crate) use workspace::controller::*;
 
-mod app_controller;
-mod database;
+pub(crate) mod app;
 pub(crate) mod server;
-mod trash_can;
-mod view_controller;
-mod workspace_controller;
+pub(crate) mod trash;
+pub(crate) mod view;
+pub(crate) mod workspace;

+ 8 - 12
frontend/rust-lib/flowy-core/src/services/trash_can.rs → frontend/rust-lib/flowy-core/src/services/trash/controller.rs

@@ -1,27 +1,23 @@
-use std::{fmt::Formatter, sync::Arc};
-
-use crossbeam_utils::thread;
-use tokio::sync::{broadcast, mpsc};
-
-use flowy_database::SqliteConnection;
-
 use crate::{
     entities::trash::{RepeatedTrash, Trash, TrashIdentifier, TrashIdentifiers, TrashType},
     errors::{WorkspaceError, WorkspaceResult},
     module::{WorkspaceDatabase, WorkspaceUser},
     notify::{send_anonymous_dart_notification, WorkspaceNotification},
-    services::server::Server,
-    sql_tables::trash::TrashTableSql,
+    services::{server::Server, trash::sql::TrashTableSql},
 };
+use crossbeam_utils::thread;
+use flowy_database::SqliteConnection;
+use std::{fmt::Formatter, sync::Arc};
+use tokio::sync::{broadcast, mpsc};
 
-pub struct TrashCan {
+pub struct TrashController {
     pub database: Arc<dyn WorkspaceDatabase>,
     notify: broadcast::Sender<TrashEvent>,
     server: Server,
     user: Arc<dyn WorkspaceUser>,
 }
 
-impl TrashCan {
+impl TrashController {
     pub fn new(database: Arc<dyn WorkspaceDatabase>, server: Server, user: Arc<dyn WorkspaceUser>) -> Self {
         let (tx, _) = broadcast::channel(10);
 
@@ -196,7 +192,7 @@ impl TrashCan {
     }
 }
 
-impl TrashCan {
+impl TrashController {
     #[tracing::instrument(level = "debug", skip(self, trash), err)]
     fn create_trash_on_server<T: Into<TrashIdentifiers>>(&self, trash: T) -> WorkspaceResult<()> {
         let token = self.user.token()?;

+ 8 - 6
frontend/rust-lib/flowy-core/src/handlers/trash_handler.rs → frontend/rust-lib/flowy-core/src/services/trash/event_handler.rs

@@ -1,13 +1,15 @@
 use crate::{
     entities::trash::{RepeatedTrash, TrashIdentifier, TrashIdentifiers},
     errors::WorkspaceError,
-    services::TrashCan,
+    services::TrashController,
 };
 use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
 use std::sync::Arc;
 
 #[tracing::instrument(skip(controller), err)]
-pub(crate) async fn read_trash_handler(controller: Unit<Arc<TrashCan>>) -> DataResult<RepeatedTrash, WorkspaceError> {
+pub(crate) async fn read_trash_handler(
+    controller: Unit<Arc<TrashController>>,
+) -> DataResult<RepeatedTrash, WorkspaceError> {
     let conn = controller.database.db_connection()?;
     let repeated_trash = controller.read_trash(&conn)?;
     data_result(repeated_trash)
@@ -16,7 +18,7 @@ pub(crate) async fn read_trash_handler(controller: Unit<Arc<TrashCan>>) -> DataR
 #[tracing::instrument(skip(identifier, controller), err)]
 pub(crate) async fn putback_trash_handler(
     identifier: Data<TrashIdentifier>,
-    controller: Unit<Arc<TrashCan>>,
+    controller: Unit<Arc<TrashController>>,
 ) -> Result<(), WorkspaceError> {
     let _ = controller.putback(&identifier.id).await?;
     Ok(())
@@ -25,20 +27,20 @@ pub(crate) async fn putback_trash_handler(
 #[tracing::instrument(skip(identifiers, controller), err)]
 pub(crate) async fn delete_trash_handler(
     identifiers: Data<TrashIdentifiers>,
-    controller: Unit<Arc<TrashCan>>,
+    controller: Unit<Arc<TrashController>>,
 ) -> Result<(), WorkspaceError> {
     let _ = controller.delete(identifiers.into_inner()).await?;
     Ok(())
 }
 
 #[tracing::instrument(skip(controller), err)]
-pub(crate) async fn restore_all_handler(controller: Unit<Arc<TrashCan>>) -> Result<(), WorkspaceError> {
+pub(crate) async fn restore_all_handler(controller: Unit<Arc<TrashController>>) -> Result<(), WorkspaceError> {
     let _ = controller.restore_all().await?;
     Ok(())
 }
 
 #[tracing::instrument(skip(controller), err)]
-pub(crate) async fn delete_all_handler(controller: Unit<Arc<TrashCan>>) -> Result<(), WorkspaceError> {
+pub(crate) async fn delete_all_handler(controller: Unit<Arc<TrashController>>) -> Result<(), WorkspaceError> {
     let _ = controller.delete_all().await?;
     Ok(())
 }

+ 3 - 0
frontend/rust-lib/flowy-core/src/services/trash/mod.rs

@@ -0,0 +1,3 @@
+pub mod controller;
+pub mod event_handler;
+mod sql;

+ 51 - 2
frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_table.rs → frontend/rust-lib/flowy-core/src/services/trash/sql.rs

@@ -1,6 +1,55 @@
-use crate::entities::trash::{Trash, TrashType};
+use crate::{
+    entities::trash::{RepeatedTrash, Trash, TrashType},
+    errors::WorkspaceError,
+};
 use diesel::sql_types::Integer;
-use flowy_database::schema::trash_table;
+use flowy_database::{
+    prelude::*,
+    schema::{trash_table, trash_table::dsl},
+    SqliteConnection,
+};
+
+pub struct TrashTableSql {}
+
+impl TrashTableSql {
+    pub(crate) fn create_trash(repeated_trash: Vec<Trash>, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
+        for trash in repeated_trash {
+            let trash_table: TrashTable = trash.into();
+            match diesel_record_count!(trash_table, &trash_table.id, conn) {
+                0 => diesel_insert_table!(trash_table, &trash_table, conn),
+                _ => {
+                    let changeset = TrashTableChangeset::from(trash_table);
+                    diesel_update_table!(trash_table, changeset, conn)
+                },
+            }
+        }
+
+        Ok(())
+    }
+
+    pub(crate) fn read_all(conn: &SqliteConnection) -> Result<RepeatedTrash, WorkspaceError> {
+        let trash_tables = dsl::trash_table.load::<TrashTable>(conn)?;
+        let items = trash_tables.into_iter().map(|t| t.into()).collect::<Vec<Trash>>();
+        Ok(RepeatedTrash { items })
+    }
+
+    pub(crate) fn delete_all(conn: &SqliteConnection) -> Result<(), WorkspaceError> {
+        let _ = diesel::delete(dsl::trash_table).execute(conn)?;
+        Ok(())
+    }
+
+    pub(crate) fn read(trash_id: &str, conn: &SqliteConnection) -> Result<TrashTable, WorkspaceError> {
+        let trash_table = dsl::trash_table
+            .filter(trash_table::id.eq(trash_id))
+            .first::<TrashTable>(conn)?;
+        Ok(trash_table)
+    }
+
+    pub(crate) fn delete_trash(trash_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
+        diesel_delete_table!(trash_table, trash_id, conn);
+        Ok(())
+    }
+}
 
 #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
 #[table_name = "trash_table"]

+ 15 - 7
frontend/rust-lib/flowy-core/src/services/view_controller.rs → frontend/rust-lib/flowy-core/src/services/view/controller.rs

@@ -11,8 +11,12 @@ use crate::{
     errors::{internal_error, WorkspaceError, WorkspaceResult},
     module::{WorkspaceDatabase, WorkspaceUser},
     notify::{send_dart_notification, WorkspaceNotification},
-    services::{server::Server, TrashCan, TrashEvent},
-    sql_tables::view::{ViewTable, ViewTableChangeset, ViewTableSql},
+    services::{
+        server::Server,
+        view::sql::{ViewTable, ViewTableChangeset, ViewTableSql},
+        TrashController,
+        TrashEvent,
+    },
 };
 use flowy_document::module::FlowyDocument;
 use flowy_workspace_infra::entities::share::{ExportData, ExportParams};
@@ -24,7 +28,7 @@ pub(crate) struct ViewController {
     user: Arc<dyn WorkspaceUser>,
     server: Server,
     database: Arc<dyn WorkspaceDatabase>,
-    trash_can: Arc<TrashCan>,
+    trash_can: Arc<TrashController>,
     document: Arc<FlowyDocument>,
 }
 
@@ -33,7 +37,7 @@ impl ViewController {
         user: Arc<dyn WorkspaceUser>,
         database: Arc<dyn WorkspaceDatabase>,
         server: Server,
-        trash_can: Arc<TrashCan>,
+        trash_can: Arc<TrashController>,
         document: Arc<FlowyDocument>,
     ) -> Self {
         Self {
@@ -296,7 +300,7 @@ impl ViewController {
 async fn handle_trash_event(
     database: Arc<dyn WorkspaceDatabase>,
     document: Arc<FlowyDocument>,
-    trash_can: Arc<TrashCan>,
+    trash_can: Arc<TrashController>,
     event: TrashEvent,
 ) {
     let db_result = database.db_connection();
@@ -372,7 +376,11 @@ fn notify_dart(view_table: ViewTable, notification: WorkspaceNotification) {
 }
 
 #[tracing::instrument(skip(belong_to_id, trash_can, conn), fields(view_count), err)]
-fn notify_views_changed(belong_to_id: &str, trash_can: Arc<TrashCan>, conn: &SqliteConnection) -> WorkspaceResult<()> {
+fn notify_views_changed(
+    belong_to_id: &str,
+    trash_can: Arc<TrashController>,
+    conn: &SqliteConnection,
+) -> WorkspaceResult<()> {
     let repeated_view = read_local_belonging_view(belong_to_id, trash_can.clone(), conn)?;
     tracing::Span::current().record("view_count", &format!("{}", repeated_view.len()).as_str());
     send_dart_notification(&belong_to_id, WorkspaceNotification::AppViewsChanged)
@@ -383,7 +391,7 @@ fn notify_views_changed(belong_to_id: &str, trash_can: Arc<TrashCan>, conn: &Sql
 
 fn read_local_belonging_view(
     belong_to_id: &str,
-    trash_can: Arc<TrashCan>,
+    trash_can: Arc<TrashController>,
     conn: &SqliteConnection,
 ) -> WorkspaceResult<RepeatedView> {
     let mut view_tables = ViewTableSql::read_views(belong_to_id, conn)?;

+ 2 - 2
frontend/rust-lib/flowy-core/src/handlers/view_handler.rs → frontend/rust-lib/flowy-core/src/services/view/event_handler.rs

@@ -13,7 +13,7 @@ use crate::{
         },
     },
     errors::WorkspaceError,
-    services::{TrashCan, ViewController},
+    services::{TrashController, ViewController},
 };
 use flowy_document_infra::entities::doc::DocDelta;
 use flowy_workspace_infra::entities::share::{ExportData, ExportParams, ExportRequest};
@@ -63,7 +63,7 @@ pub(crate) async fn apply_doc_delta_handler(
 pub(crate) async fn delete_view_handler(
     data: Data<QueryViewRequest>,
     controller: Unit<Arc<ViewController>>,
-    trash_can: Unit<Arc<TrashCan>>,
+    trash_can: Unit<Arc<TrashController>>,
 ) -> Result<(), WorkspaceError> {
     let params: ViewIdentifiers = data.into_inner().try_into()?;
     for view_id in &params.view_ids {

+ 3 - 0
frontend/rust-lib/flowy-core/src/services/view/mod.rs

@@ -0,0 +1,3 @@
+pub mod controller;
+pub mod event_handler;
+mod sql;

+ 103 - 6
frontend/rust-lib/flowy-core/src/sql_tables/view/view_table.rs → frontend/rust-lib/flowy-core/src/services/view/sql.rs

@@ -1,15 +1,112 @@
-use diesel::sql_types::Integer;
-
-use flowy_database::schema::view_table;
-use lib_infra::timestamp;
-
 use crate::{
     entities::{
         trash::{Trash, TrashType},
         view::{RepeatedView, UpdateViewParams, View, ViewType},
     },
-    sql_tables::app::AppTable,
+    errors::WorkspaceError,
+    services::app::sql::AppTable,
+};
+use diesel::sql_types::Integer;
+use flowy_database::{
+    prelude::*,
+    schema::{view_table, view_table::dsl},
+    SqliteConnection,
 };
+use lib_infra::timestamp;
+
+pub struct ViewTableSql {}
+
+impl ViewTableSql {
+    pub(crate) fn create_view(view_table: ViewTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
+        match diesel_record_count!(view_table, &view_table.id, conn) {
+            0 => diesel_insert_table!(view_table, &view_table, conn),
+            _ => {
+                let changeset = ViewTableChangeset::from_table(view_table);
+                diesel_update_table!(view_table, changeset, conn)
+            },
+        }
+        Ok(())
+    }
+
+    pub(crate) fn read_view(view_id: &str, conn: &SqliteConnection) -> Result<ViewTable, WorkspaceError> {
+        // https://docs.diesel.rs/diesel/query_builder/struct.UpdateStatement.html
+        // let mut filter =
+        // dsl::view_table.filter(view_table::id.eq(view_id)).into_boxed();
+        // if let Some(is_trash) = is_trash {
+        //     filter = filter.filter(view_table::is_trash.eq(is_trash));
+        // }
+        // let repeated_view = filter.first::<ViewTable>(conn)?;
+        let view_table = dsl::view_table
+            .filter(view_table::id.eq(view_id))
+            .first::<ViewTable>(conn)?;
+
+        Ok(view_table)
+    }
+
+    // belong_to_id will be the app_id or view_id.
+    pub(crate) fn read_views(belong_to_id: &str, conn: &SqliteConnection) -> Result<Vec<ViewTable>, WorkspaceError> {
+        let view_tables = dsl::view_table
+            .filter(view_table::belong_to_id.eq(belong_to_id))
+            .order(view_table::create_time.asc())
+            .into_boxed()
+            .load::<ViewTable>(conn)?;
+
+        Ok(view_tables)
+    }
+
+    pub(crate) fn update_view(changeset: ViewTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
+        diesel_update_table!(view_table, changeset, conn);
+        Ok(())
+    }
+
+    pub(crate) fn delete_view(view_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
+        diesel_delete_table!(view_table, view_id, conn);
+        Ok(())
+    }
+}
+
+// pub(crate) fn read_views(
+//     belong_to_id: &str,
+//     is_trash: Option<bool>,
+//     conn: &SqliteConnection,
+// ) -> Result<RepeatedView, WorkspaceError> {
+//     let views = dsl::view_table
+//         .inner_join(trash_table::dsl::trash_table.on(trash_id.ne(view_table::
+// id)))         .filter(view_table::belong_to_id.eq(belong_to_id))
+//         .select((
+//             view_table::id,
+//             view_table::belong_to_id,
+//             view_table::name,
+//             view_table::desc,
+//             view_table::modified_time,
+//             view_table::create_time,
+//             view_table::thumbnail,
+//             view_table::view_type,
+//             view_table::version,
+//         ))
+//         .load(conn)?
+//         .into_iter()
+//         .map(
+//             |(id, belong_to_id, name, desc, create_time, modified_time,
+// thumbnail, view_type, version)| {                 ViewTable {
+//                     id,
+//                     belong_to_id,
+//                     name,
+//                     desc,
+//                     modified_time,
+//                     create_time,
+//                     thumbnail,
+//                     view_type,
+//                     version,
+//                     is_trash: false,
+//                 }
+//                 .into()
+//             },
+//         )
+//         .collect::<Vec<View>>();
+//
+//     Ok(RepeatedView { items: views })
+// }
 
 #[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
 #[belongs_to(AppTable, foreign_key = "belong_to_id")]

+ 22 - 107
frontend/rust-lib/flowy-core/src/services/workspace_controller.rs → frontend/rust-lib/flowy-core/src/services/workspace/controller.rs

@@ -2,24 +2,19 @@ use crate::{
     errors::*,
     module::{WorkspaceDatabase, WorkspaceUser},
     notify::*,
-    services::{read_local_workspace_apps, server::Server, AppController, TrashCan, ViewController},
-    sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql},
+    services::{
+        read_local_workspace_apps,
+        server::Server,
+        workspace::sql::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql},
+        AppController,
+        TrashController,
+        ViewController,
+    },
 };
-use chrono::Utc;
 use flowy_database::SqliteConnection;
-use flowy_document_infra::{entities::doc::DocDelta, user_default::initial_read_me};
-use flowy_workspace_infra::{
-    entities::{app::RepeatedApp, view::View, workspace::*},
-    user_default,
-};
-use lazy_static::lazy_static;
-use lib_infra::{entities::network_state::NetworkType, kv::KV};
-use parking_lot::RwLock;
-use std::{collections::HashMap, sync::Arc};
-
-lazy_static! {
-    static ref INIT_WORKSPACE: RwLock<HashMap<String, bool>> = RwLock::new(HashMap::new());
-}
+use flowy_workspace_infra::entities::{app::RepeatedApp, view::View, workspace::*};
+use lib_infra::kv::KV;
+use std::sync::Arc;
 
 pub struct WorkspaceController {
     pub user: Arc<dyn WorkspaceUser>,
@@ -27,7 +22,7 @@ pub struct WorkspaceController {
     pub(crate) view_controller: Arc<ViewController>,
     pub(crate) database: Arc<dyn WorkspaceDatabase>,
     pub(crate) app_controller: Arc<AppController>,
-    pub(crate) trash_can: Arc<TrashCan>,
+    pub(crate) trash_controller: Arc<TrashController>,
     server: Server,
 }
 
@@ -37,13 +32,9 @@ impl WorkspaceController {
         database: Arc<dyn WorkspaceDatabase>,
         app_controller: Arc<AppController>,
         view_controller: Arc<ViewController>,
-        trash_can: Arc<TrashCan>,
+        trash_can: Arc<TrashController>,
         server: Server,
     ) -> Self {
-        if let Ok(token) = user.token() {
-            INIT_WORKSPACE.write().insert(token, false);
-        }
-
         let workspace_sql = Arc::new(WorkspaceTableSql {});
         Self {
             user,
@@ -51,92 +42,12 @@ impl WorkspaceController {
             view_controller,
             database,
             app_controller,
-            trash_can,
+            trash_controller: trash_can,
             server,
         }
     }
 
-    async fn init(&self, token: &str) -> Result<(), WorkspaceError> {
-        log::debug!("Start initializing workspace");
-        if let Some(is_init) = INIT_WORKSPACE.read().get(token) {
-            if *is_init {
-                return Ok(());
-            }
-        }
-        log::debug!("Finish initializing workspace");
-        INIT_WORKSPACE.write().insert(token.to_owned(), true);
-        let _ = self.server.init();
-        let _ = self.trash_can.init()?;
-        let _ = self.view_controller.init()?;
-        let _ = self.app_controller.init()?;
-
-        Ok(())
-    }
-
-    pub fn network_state_changed(&self, new_type: NetworkType) {
-        match new_type {
-            NetworkType::UnknownNetworkType => {},
-            NetworkType::Wifi => {},
-            NetworkType::Cell => {},
-            NetworkType::Ethernet => {},
-        }
-    }
-
-    pub async fn user_did_sign_in(&self, token: &str) -> WorkspaceResult<()> {
-        // TODO: (nathan) do something here
-
-        log::debug!("workspace initialize after sign in");
-        let _ = self.init(token).await?;
-        Ok(())
-    }
-
-    pub async fn user_did_logout(&self) {
-        // TODO: (nathan) do something here
-    }
-
-    pub async fn user_session_expired(&self) {
-        // TODO: (nathan) do something here
-    }
-
-    pub async fn user_did_sign_up(&self, _token: &str) -> WorkspaceResult<()> {
-        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();
-        let cloned_workspace = workspace.clone();
-
-        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 (index, view) in views.into_iter().enumerate() {
-                if index == 0 {
-                    let delta = initial_read_me();
-                    let doc_delta = DocDelta {
-                        doc_id: view.id.clone(),
-                        data: delta.to_json(),
-                    };
-                    let _ = self.view_controller.apply_doc_delta(doc_delta).await?;
-
-                    self.view_controller.set_latest_view(&view);
-                }
-                let _ = self.view_controller.create_view(view).await?;
-            }
-        }
-
-        let token = self.user.token()?;
-        let repeated_workspace = RepeatedWorkspace {
-            items: vec![cloned_workspace],
-        };
-
-        send_dart_notification(&token, WorkspaceNotification::UserCreateWorkspace)
-            .payload(repeated_workspace)
-            .send();
-
-        log::debug!("workspace initialize after sign up");
-        let _ = self.init(&token).await?;
-        Ok(())
-    }
+    pub(crate) fn init(&self) -> Result<(), WorkspaceError> { Ok(()) }
 
     pub(crate) async fn create_workspace_from_params(
         &self,
@@ -263,7 +174,7 @@ impl WorkspaceController {
     }
 
     #[tracing::instrument(level = "debug", skip(self, conn), err)]
-    fn read_local_workspaces(
+    pub(crate) fn read_local_workspaces(
         &self,
         workspace_id: Option<String>,
         user_id: &str,
@@ -301,7 +212,7 @@ impl WorkspaceController {
 
     #[tracing::instrument(level = "debug", skip(self, conn), err)]
     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)?;
+        let repeated_app = read_local_workspace_apps(workspace_id, self.trash_controller.clone(), conn)?;
         Ok(repeated_app)
     }
 }
@@ -354,7 +265,11 @@ impl WorkspaceController {
     }
 
     #[tracing::instrument(level = "debug", skip(self), err)]
-    fn read_workspaces_on_server(&self, user_id: String, params: WorkspaceIdentifier) -> Result<(), WorkspaceError> {
+    pub(crate) fn read_workspaces_on_server(
+        &self,
+        user_id: String,
+        params: WorkspaceIdentifier,
+    ) -> Result<(), WorkspaceError> {
         let (token, server) = self.token_with_server()?;
         let workspace_sql = self.workspace_sql.clone();
         let app_ctrl = self.app_controller.clone();

+ 0 - 0
frontend/rust-lib/flowy-core/src/handlers/workspace_handler.rs → frontend/rust-lib/flowy-core/src/services/workspace/event_handler.rs


+ 3 - 0
frontend/rust-lib/flowy-core/src/services/workspace/mod.rs

@@ -0,0 +1,3 @@
+pub mod controller;
+pub mod event_handler;
+pub(crate) mod sql;

+ 73 - 7
frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_sql.rs → frontend/rust-lib/flowy-core/src/services/workspace/sql.rs

@@ -1,15 +1,15 @@
+use crate::{
+    entities::{
+        app::RepeatedApp,
+        workspace::{UpdateWorkspaceParams, Workspace},
+    },
+    errors::WorkspaceError,
+};
 use diesel::SqliteConnection;
-
 use flowy_database::{
     prelude::*,
     schema::{workspace_table, workspace_table::dsl},
 };
-
-use crate::{
-    errors::WorkspaceError,
-    sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset},
-};
-
 pub(crate) struct WorkspaceTableSql {}
 
 impl WorkspaceTableSql {
@@ -64,3 +64,69 @@ impl WorkspaceTableSql {
         Ok(())
     }
 }
+
+#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable)]
+#[table_name = "workspace_table"]
+pub struct WorkspaceTable {
+    pub id: String,
+    pub name: String,
+    pub desc: String,
+    pub modified_time: i64,
+    pub create_time: i64,
+    pub user_id: String,
+    pub version: i64,
+}
+
+impl WorkspaceTable {
+    #[allow(dead_code)]
+    pub fn new(workspace: Workspace, user_id: &str) -> Self {
+        WorkspaceTable {
+            id: workspace.id,
+            name: workspace.name,
+            desc: workspace.desc,
+            modified_time: workspace.modified_time,
+            create_time: workspace.create_time,
+            user_id: user_id.to_owned(),
+            version: 0,
+        }
+    }
+}
+
+impl std::convert::From<WorkspaceTable> for Workspace {
+    fn from(table: WorkspaceTable) -> Self {
+        Workspace {
+            id: table.id,
+            name: table.name,
+            desc: table.desc,
+            apps: RepeatedApp::default(),
+            modified_time: table.modified_time,
+            create_time: table.create_time,
+        }
+    }
+}
+
+#[derive(AsChangeset, Identifiable, Clone, Default, Debug)]
+#[table_name = "workspace_table"]
+pub struct WorkspaceTableChangeset {
+    pub id: String,
+    pub name: Option<String>,
+    pub desc: Option<String>,
+}
+
+impl WorkspaceTableChangeset {
+    pub fn new(params: UpdateWorkspaceParams) -> Self {
+        WorkspaceTableChangeset {
+            id: params.id,
+            name: params.name,
+            desc: params.desc,
+        }
+    }
+
+    pub(crate) fn from_table(table: WorkspaceTable) -> Self {
+        WorkspaceTableChangeset {
+            id: table.id,
+            name: Some(table.name),
+            desc: Some(table.desc),
+        }
+    }
+}

+ 0 - 76
frontend/rust-lib/flowy-core/src/sql_tables/app/app_sql.rs

@@ -1,76 +0,0 @@
-use flowy_database::{
-    prelude::*,
-    schema::{app_table, app_table::dsl},
-    SqliteConnection,
-};
-
-use crate::{
-    errors::WorkspaceError,
-    sql_tables::app::{AppTable, AppTableChangeset},
-};
-
-pub struct AppTableSql {}
-
-impl AppTableSql {
-    pub(crate) fn create_app(app_table: AppTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
-        match diesel_record_count!(app_table, &app_table.id, conn) {
-            0 => diesel_insert_table!(app_table, &app_table, conn),
-            _ => {
-                let changeset = AppTableChangeset::from_table(app_table);
-                diesel_update_table!(app_table, changeset, conn)
-            },
-        }
-        Ok(())
-    }
-
-    pub(crate) fn update_app(changeset: AppTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
-        diesel_update_table!(app_table, changeset, conn);
-        Ok(())
-    }
-
-    pub(crate) fn read_app(app_id: &str, conn: &SqliteConnection) -> Result<AppTable, WorkspaceError> {
-        let filter = dsl::app_table.filter(app_table::id.eq(app_id)).into_boxed();
-        let app_table = filter.first::<AppTable>(conn)?;
-        Ok(app_table)
-    }
-
-    pub(crate) fn read_workspace_apps(
-        workspace_id: &str,
-        is_trash: bool,
-        conn: &SqliteConnection,
-    ) -> Result<Vec<AppTable>, WorkspaceError> {
-        let app_table = dsl::app_table
-            .filter(app_table::workspace_id.eq(workspace_id))
-            .filter(app_table::is_trash.eq(is_trash))
-            .order(app_table::create_time.asc())
-            .load::<AppTable>(conn)?;
-
-        Ok(app_table)
-    }
-
-    pub(crate) fn delete_app(app_id: &str, conn: &SqliteConnection) -> Result<AppTable, WorkspaceError> {
-        let app_table = dsl::app_table
-            .filter(app_table::id.eq(app_id))
-            .first::<AppTable>(conn)?;
-        diesel_delete_table!(app_table, app_id, conn);
-        Ok(app_table)
-    }
-
-    // pub(crate) fn read_views_belong_to_app(
-    //     &self,
-    //     app_id: &str,
-    // ) -> Result<Vec<ViewTable>, WorkspaceError> {
-    //     let conn = self.database.db_connection()?;
-    //
-    //     let views = conn.immediate_transaction::<_, WorkspaceError, _>(|| {
-    //         let app_table: AppTable = dsl::app_table
-    //             .filter(app_table::id.eq(app_id))
-    //             .first::<AppTable>(&*(conn))?;
-    //         let views =
-    // ViewTable::belonging_to(&app_table).load::<ViewTable>(&*conn)?;
-    //         Ok(views)
-    //     })?;
-    //
-    //     Ok(views)
-    // }
-}

+ 0 - 5
frontend/rust-lib/flowy-core/src/sql_tables/app/mod.rs

@@ -1,5 +0,0 @@
-mod app_sql;
-mod app_table;
-
-pub(crate) use app_sql::*;
-pub(crate) use app_table::*;

+ 0 - 4
frontend/rust-lib/flowy-core/src/sql_tables/mod.rs

@@ -1,4 +0,0 @@
-pub mod app;
-pub mod trash;
-pub mod view;
-pub mod workspace;

+ 0 - 5
frontend/rust-lib/flowy-core/src/sql_tables/trash/mod.rs

@@ -1,5 +0,0 @@
-mod trash_sql;
-mod trash_table;
-
-pub(crate) use trash_sql::*;
-pub(crate) use trash_table::*;

+ 0 - 53
frontend/rust-lib/flowy-core/src/sql_tables/trash/trash_sql.rs

@@ -1,53 +0,0 @@
-use flowy_database::{
-    prelude::*,
-    schema::{trash_table, trash_table::dsl},
-    SqliteConnection,
-};
-
-use crate::{
-    entities::trash::{RepeatedTrash, Trash},
-    errors::WorkspaceError,
-    sql_tables::trash::{TrashTable, TrashTableChangeset},
-};
-
-pub struct TrashTableSql {}
-
-impl TrashTableSql {
-    pub(crate) fn create_trash(repeated_trash: Vec<Trash>, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
-        for trash in repeated_trash {
-            let trash_table: TrashTable = trash.into();
-            match diesel_record_count!(trash_table, &trash_table.id, conn) {
-                0 => diesel_insert_table!(trash_table, &trash_table, conn),
-                _ => {
-                    let changeset = TrashTableChangeset::from(trash_table);
-                    diesel_update_table!(trash_table, changeset, conn)
-                },
-            }
-        }
-
-        Ok(())
-    }
-
-    pub(crate) fn read_all(conn: &SqliteConnection) -> Result<RepeatedTrash, WorkspaceError> {
-        let trash_tables = dsl::trash_table.load::<TrashTable>(conn)?;
-        let items = trash_tables.into_iter().map(|t| t.into()).collect::<Vec<Trash>>();
-        Ok(RepeatedTrash { items })
-    }
-
-    pub(crate) fn delete_all(conn: &SqliteConnection) -> Result<(), WorkspaceError> {
-        let _ = diesel::delete(dsl::trash_table).execute(conn)?;
-        Ok(())
-    }
-
-    pub(crate) fn read(trash_id: &str, conn: &SqliteConnection) -> Result<TrashTable, WorkspaceError> {
-        let trash_table = dsl::trash_table
-            .filter(trash_table::id.eq(trash_id))
-            .first::<TrashTable>(conn)?;
-        Ok(trash_table)
-    }
-
-    pub(crate) fn delete_trash(trash_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
-        diesel_delete_table!(trash_table, trash_id, conn);
-        Ok(())
-    }
-}

+ 0 - 5
frontend/rust-lib/flowy-core/src/sql_tables/view/mod.rs

@@ -1,5 +0,0 @@
-mod view_sql;
-mod view_table;
-
-pub use view_sql::*;
-pub use view_table::*;

+ 0 - 104
frontend/rust-lib/flowy-core/src/sql_tables/view/view_sql.rs

@@ -1,104 +0,0 @@
-use flowy_database::{
-    prelude::*,
-    schema::{view_table, view_table::dsl},
-    SqliteConnection,
-};
-
-use crate::{
-    errors::WorkspaceError,
-    sql_tables::view::{ViewTable, ViewTableChangeset},
-};
-
-pub struct ViewTableSql {}
-
-impl ViewTableSql {
-    pub(crate) fn create_view(view_table: ViewTable, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
-        match diesel_record_count!(view_table, &view_table.id, conn) {
-            0 => diesel_insert_table!(view_table, &view_table, conn),
-            _ => {
-                let changeset = ViewTableChangeset::from_table(view_table);
-                diesel_update_table!(view_table, changeset, conn)
-            },
-        }
-        Ok(())
-    }
-
-    pub(crate) fn read_view(view_id: &str, conn: &SqliteConnection) -> Result<ViewTable, WorkspaceError> {
-        // https://docs.diesel.rs/diesel/query_builder/struct.UpdateStatement.html
-        // let mut filter =
-        // dsl::view_table.filter(view_table::id.eq(view_id)).into_boxed();
-        // if let Some(is_trash) = is_trash {
-        //     filter = filter.filter(view_table::is_trash.eq(is_trash));
-        // }
-        // let repeated_view = filter.first::<ViewTable>(conn)?;
-        let view_table = dsl::view_table
-            .filter(view_table::id.eq(view_id))
-            .first::<ViewTable>(conn)?;
-
-        Ok(view_table)
-    }
-
-    // belong_to_id will be the app_id or view_id.
-    pub(crate) fn read_views(belong_to_id: &str, conn: &SqliteConnection) -> Result<Vec<ViewTable>, WorkspaceError> {
-        let view_tables = dsl::view_table
-            .filter(view_table::belong_to_id.eq(belong_to_id))
-            .order(view_table::create_time.asc())
-            .into_boxed()
-            .load::<ViewTable>(conn)?;
-
-        Ok(view_tables)
-    }
-
-    pub(crate) fn update_view(changeset: ViewTableChangeset, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
-        diesel_update_table!(view_table, changeset, conn);
-        Ok(())
-    }
-
-    pub(crate) fn delete_view(view_id: &str, conn: &SqliteConnection) -> Result<(), WorkspaceError> {
-        diesel_delete_table!(view_table, view_id, conn);
-        Ok(())
-    }
-}
-
-// pub(crate) fn read_views(
-//     belong_to_id: &str,
-//     is_trash: Option<bool>,
-//     conn: &SqliteConnection,
-// ) -> Result<RepeatedView, WorkspaceError> {
-//     let views = dsl::view_table
-//         .inner_join(trash_table::dsl::trash_table.on(trash_id.ne(view_table::
-// id)))         .filter(view_table::belong_to_id.eq(belong_to_id))
-//         .select((
-//             view_table::id,
-//             view_table::belong_to_id,
-//             view_table::name,
-//             view_table::desc,
-//             view_table::modified_time,
-//             view_table::create_time,
-//             view_table::thumbnail,
-//             view_table::view_type,
-//             view_table::version,
-//         ))
-//         .load(conn)?
-//         .into_iter()
-//         .map(
-//             |(id, belong_to_id, name, desc, create_time, modified_time,
-// thumbnail, view_type, version)| {                 ViewTable {
-//                     id,
-//                     belong_to_id,
-//                     name,
-//                     desc,
-//                     modified_time,
-//                     create_time,
-//                     thumbnail,
-//                     view_type,
-//                     version,
-//                     is_trash: false,
-//                 }
-//                 .into()
-//             },
-//         )
-//         .collect::<Vec<View>>();
-//
-//     Ok(RepeatedView { items: views })
-// }

+ 0 - 5
frontend/rust-lib/flowy-core/src/sql_tables/workspace/mod.rs

@@ -1,5 +0,0 @@
-mod workspace_sql;
-mod workspace_table;
-
-pub(crate) use workspace_sql::*;
-pub(crate) use workspace_table::*;

+ 0 - 71
frontend/rust-lib/flowy-core/src/sql_tables/workspace/workspace_table.rs

@@ -1,71 +0,0 @@
-use crate::entities::{
-    app::RepeatedApp,
-    workspace::{UpdateWorkspaceParams, Workspace},
-};
-use flowy_database::schema::workspace_table;
-
-#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable)]
-#[table_name = "workspace_table"]
-pub struct WorkspaceTable {
-    pub id: String,
-    pub name: String,
-    pub desc: String,
-    pub modified_time: i64,
-    pub create_time: i64,
-    pub user_id: String,
-    pub version: i64,
-}
-
-impl WorkspaceTable {
-    #[allow(dead_code)]
-    pub fn new(workspace: Workspace, user_id: &str) -> Self {
-        WorkspaceTable {
-            id: workspace.id,
-            name: workspace.name,
-            desc: workspace.desc,
-            modified_time: workspace.modified_time,
-            create_time: workspace.create_time,
-            user_id: user_id.to_owned(),
-            version: 0,
-        }
-    }
-}
-
-impl std::convert::From<WorkspaceTable> for Workspace {
-    fn from(table: WorkspaceTable) -> Self {
-        Workspace {
-            id: table.id,
-            name: table.name,
-            desc: table.desc,
-            apps: RepeatedApp::default(),
-            modified_time: table.modified_time,
-            create_time: table.create_time,
-        }
-    }
-}
-
-#[derive(AsChangeset, Identifiable, Clone, Default, Debug)]
-#[table_name = "workspace_table"]
-pub struct WorkspaceTableChangeset {
-    pub id: String,
-    pub name: Option<String>,
-    pub desc: Option<String>,
-}
-
-impl WorkspaceTableChangeset {
-    pub fn new(params: UpdateWorkspaceParams) -> Self {
-        WorkspaceTableChangeset {
-            id: params.id,
-            name: params.name,
-            desc: params.desc,
-        }
-    }
-
-    pub(crate) fn from_table(table: WorkspaceTable) -> Self {
-        WorkspaceTableChangeset {
-            id: table.id,
-            name: Some(table.name),
-            desc: Some(table.desc),
-        }
-    }
-}

+ 21 - 27
frontend/rust-lib/flowy-sdk/src/lib.rs

@@ -3,7 +3,7 @@ mod deps_resolve;
 pub mod module;
 use crate::deps_resolve::WorkspaceDepsResolver;
 use backend_service::configuration::ClientServerConfiguration;
-use flowy_core::{errors::WorkspaceError, prelude::WorkspaceController};
+use flowy_core::{errors::WorkspaceError, module::init_core, prelude::FlowyCore};
 use flowy_document::module::FlowyDocument;
 use flowy_user::{
     prelude::UserStatus,
@@ -66,7 +66,7 @@ pub struct FlowySDK {
     config: FlowySDKConfig,
     pub user_session: Arc<UserSession>,
     pub flowy_document: Arc<FlowyDocument>,
-    pub workspace_ctrl: Arc<WorkspaceController>,
+    pub core: Arc<FlowyCore>,
     pub dispatcher: Arc<EventDispatcher>,
 }
 
@@ -81,17 +81,17 @@ impl FlowySDK {
         let user_config = UserSessionConfig::new(&config.root, &config.server_config, &session_cache_key);
         let user_session = Arc::new(UserSession::new(user_config));
         let flowy_document = mk_document_module(user_session.clone(), &config.server_config);
-        let workspace_ctrl =
-            mk_workspace_controller(user_session.clone(), flowy_document.clone(), &config.server_config);
-        let modules = mk_modules(workspace_ctrl.clone(), user_session.clone());
+        let core = mk_core(user_session.clone(), flowy_document.clone(), &config.server_config);
+
+        let modules = mk_modules(core.clone(), user_session.clone());
         let dispatcher = Arc::new(EventDispatcher::construct(|| modules));
-        _init(&dispatcher, user_session.clone(), workspace_ctrl.clone());
+        _init(&dispatcher, user_session.clone(), core.clone());
 
         Self {
             config,
             user_session,
             flowy_document,
-            workspace_ctrl,
+            core,
             dispatcher,
         }
     }
@@ -99,38 +99,35 @@ impl FlowySDK {
     pub fn dispatcher(&self) -> Arc<EventDispatcher> { self.dispatcher.clone() }
 }
 
-fn _init(dispatch: &EventDispatcher, user_session: Arc<UserSession>, workspace_controller: Arc<WorkspaceController>) {
+fn _init(dispatch: &EventDispatcher, user_session: Arc<UserSession>, core: Arc<FlowyCore>) {
     let user_status_subscribe = user_session.notifier.user_status_subscribe();
     let network_status_subscribe = user_session.notifier.network_type_subscribe();
-    let cloned_workspace_controller = workspace_controller.clone();
+    let cloned_core = core.clone();
 
     dispatch.spawn(async move {
         user_session.init();
-        _listen_user_status(user_status_subscribe, workspace_controller.clone()).await;
+        _listen_user_status(user_status_subscribe, core.clone()).await;
     });
     dispatch.spawn(async move {
-        _listen_network_status(network_status_subscribe, cloned_workspace_controller).await;
+        _listen_network_status(network_status_subscribe, cloned_core).await;
     });
 }
 
-async fn _listen_user_status(
-    mut subscribe: broadcast::Receiver<UserStatus>,
-    workspace_controller: Arc<WorkspaceController>,
-) {
+async fn _listen_user_status(mut subscribe: broadcast::Receiver<UserStatus>, core: Arc<FlowyCore>) {
     while let Ok(status) = subscribe.recv().await {
         let result = || async {
             match status {
                 UserStatus::Login { token } => {
-                    let _ = workspace_controller.user_did_sign_in(&token).await?;
+                    let _ = core.user_did_sign_in(&token).await?;
                 },
                 UserStatus::Logout { .. } => {
-                    workspace_controller.user_did_logout().await;
+                    core.user_did_logout().await;
                 },
                 UserStatus::Expired { .. } => {
-                    workspace_controller.user_session_expired().await;
+                    core.user_session_expired().await;
                 },
                 UserStatus::SignUp { profile, ret } => {
-                    let _ = workspace_controller.user_did_sign_up(&profile.token).await?;
+                    let _ = core.user_did_sign_up(&profile.token).await?;
                     let _ = ret.send(());
                 },
             }
@@ -144,12 +141,9 @@ async fn _listen_user_status(
     }
 }
 
-async fn _listen_network_status(
-    mut subscribe: broadcast::Receiver<NetworkType>,
-    workspace_controller: Arc<WorkspaceController>,
-) {
+async fn _listen_network_status(mut subscribe: broadcast::Receiver<NetworkType>, core: Arc<FlowyCore>) {
     while let Ok(new_type) = subscribe.recv().await {
-        workspace_controller.network_state_changed(new_type);
+        core.network_state_changed(new_type);
     }
 }
 
@@ -170,12 +164,12 @@ fn init_log(config: &FlowySDKConfig) {
     }
 }
 
-fn mk_workspace_controller(
+fn mk_core(
     user_session: Arc<UserSession>,
     flowy_document: Arc<FlowyDocument>,
     server_config: &ClientServerConfiguration,
-) -> Arc<WorkspaceController> {
+) -> Arc<FlowyCore> {
     let workspace_deps = WorkspaceDepsResolver::new(user_session);
     let (user, database) = workspace_deps.split_into();
-    flowy_core::module::init_workspace_controller(user, database, flowy_document, server_config)
+    init_core(user, database, flowy_document, server_config)
 }

+ 4 - 7
frontend/rust-lib/flowy-sdk/src/module.rs

@@ -1,22 +1,19 @@
 use crate::deps_resolve::DocumentDepsResolver;
 use backend_service::configuration::ClientServerConfiguration;
-use flowy_core::prelude::WorkspaceController;
+use flowy_core::prelude::FlowyCore;
 use flowy_document::module::FlowyDocument;
 use flowy_user::services::user::UserSession;
 use lib_dispatch::prelude::Module;
 use std::sync::Arc;
 
-pub fn mk_modules(workspace_controller: Arc<WorkspaceController>, user_session: Arc<UserSession>) -> Vec<Module> {
+pub fn mk_modules(core: Arc<FlowyCore>, user_session: Arc<UserSession>) -> Vec<Module> {
     let user_module = mk_user_module(user_session);
-    let workspace_module = mk_workspace_module(workspace_controller);
+    let workspace_module = mk_core_module(core);
     vec![user_module, workspace_module]
 }
 
 fn mk_user_module(user_session: Arc<UserSession>) -> Module { flowy_user::module::create(user_session) }
-
-fn mk_workspace_module(workspace_controller: Arc<WorkspaceController>) -> Module {
-    flowy_core::module::create(workspace_controller)
-}
+fn mk_core_module(core: Arc<FlowyCore>) -> Module { flowy_core::module::create(core) }
 
 pub fn mk_document_module(
     user_session: Arc<UserSession>,