mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
add core
This commit is contained in:
parent
29c14949cb
commit
6298a0d96d
@ -188,7 +188,7 @@ impl std::convert::From<TestServer> for TestUserServer {
|
|||||||
pg_pool: server.pg_pool,
|
pg_pool: server.pg_pool,
|
||||||
user_token: None,
|
user_token: None,
|
||||||
user_id: None,
|
user_id: None,
|
||||||
client_server_config: server.client_server_config.clone(),
|
client_server_config: server.client_server_config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
134
frontend/rust-lib/flowy-core/src/core/flowy_core.rs
Normal file
134
frontend/rust-lib/flowy-core/src/core/flowy_core.rs
Normal file
@ -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
frontend/rust-lib/flowy-core/src/core/mod.rs
Normal file
4
frontend/rust-lib/flowy-core/src/core/mod.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
mod flowy_core;
|
||||||
|
mod task;
|
||||||
|
|
||||||
|
pub use flowy_core::*;
|
69
frontend/rust-lib/flowy-core/src/core/task.rs
Normal file
69
frontend/rust-lib/flowy-core/src/core/task.rs
Normal file
@ -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(())
|
||||||
|
// }
|
@ -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::*;
|
|
@ -10,15 +10,14 @@ mod macros;
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate flowy_database;
|
extern crate flowy_database;
|
||||||
|
|
||||||
|
pub mod core;
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod handlers;
|
|
||||||
mod notify;
|
mod notify;
|
||||||
pub mod protobuf;
|
pub mod protobuf;
|
||||||
mod sql_tables;
|
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
pub use flowy_workspace_infra::entities::{app::*, trash::*, view::*, workspace::*};
|
pub use flowy_workspace_infra::entities::{app::*, trash::*, view::*, workspace::*};
|
||||||
|
|
||||||
pub use crate::{errors::*, module::*, services::*};
|
pub use crate::{core::*, errors::*, module::*};
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,27 @@
|
|||||||
use crate::{
|
use std::sync::Arc;
|
||||||
errors::WorkspaceError,
|
|
||||||
event::WorkspaceEvent,
|
|
||||||
handlers::*,
|
|
||||||
services::{server::construct_workspace_server, AppController, TrashCan, ViewController, WorkspaceController},
|
|
||||||
};
|
|
||||||
use backend_service::configuration::ClientServerConfiguration;
|
use backend_service::configuration::ClientServerConfiguration;
|
||||||
use flowy_database::DBConnection;
|
use flowy_database::DBConnection;
|
||||||
use flowy_document::module::FlowyDocument;
|
use flowy_document::module::FlowyDocument;
|
||||||
use lib_dispatch::prelude::*;
|
use lib_dispatch::prelude::*;
|
||||||
use lib_sqlite::ConnectionPool;
|
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 {}
|
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>,
|
user: Arc<dyn WorkspaceUser>,
|
||||||
database: Arc<dyn WorkspaceDatabase>,
|
database: Arc<dyn WorkspaceDatabase>,
|
||||||
flowy_document: Arc<FlowyDocument>,
|
flowy_document: Arc<FlowyDocument>,
|
||||||
server_config: &ClientServerConfiguration,
|
server_config: &ClientServerConfiguration,
|
||||||
) -> Arc<WorkspaceController> {
|
) -> Arc<FlowyCore> {
|
||||||
let server = construct_workspace_server(server_config);
|
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(
|
let view_controller = Arc::new(ViewController::new(
|
||||||
user.clone(),
|
user.clone(),
|
||||||
database.clone(),
|
database.clone(),
|
||||||
server.clone(),
|
server.clone(),
|
||||||
trash_can.clone(),
|
trash_controller.clone(),
|
||||||
flowy_document,
|
flowy_document,
|
||||||
));
|
));
|
||||||
|
|
||||||
let app_controller = Arc::new(AppController::new(
|
let app_controller = Arc::new(AppController::new(
|
||||||
user.clone(),
|
user.clone(),
|
||||||
database.clone(),
|
database.clone(),
|
||||||
trash_can.clone(),
|
trash_controller.clone(),
|
||||||
server.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,
|
user,
|
||||||
database,
|
server,
|
||||||
|
workspace_controller,
|
||||||
app_controller,
|
app_controller,
|
||||||
view_controller,
|
view_controller,
|
||||||
trash_can,
|
trash_controller,
|
||||||
server,
|
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(workspace: Arc<WorkspaceController>) -> Module {
|
pub fn create(core: Arc<FlowyCore>) -> Module {
|
||||||
let mut module = Module::new()
|
let mut module = Module::new()
|
||||||
.name("Flowy-Workspace")
|
.name("Flowy-Workspace")
|
||||||
.data(workspace.clone())
|
.data(core.workspace_controller.clone())
|
||||||
.data(workspace.app_controller.clone())
|
.data(core.app_controller.clone())
|
||||||
.data(workspace.view_controller.clone())
|
.data(core.view_controller.clone())
|
||||||
.data(workspace.trash_can.clone());
|
.data(core.trash_controller.clone());
|
||||||
|
|
||||||
module = module
|
module = module
|
||||||
.event(WorkspaceEvent::CreateWorkspace, create_workspace_handler)
|
.event(WorkspaceEvent::CreateWorkspace, create_workspace_handler)
|
||||||
|
@ -1,9 +1,3 @@
|
|||||||
use std::{collections::HashSet, sync::Arc};
|
|
||||||
|
|
||||||
use futures::{FutureExt, StreamExt};
|
|
||||||
|
|
||||||
use flowy_database::SqliteConnection;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entities::{
|
entities::{
|
||||||
app::{App, CreateAppParams, *},
|
app::{App, CreateAppParams, *},
|
||||||
@ -12,14 +6,21 @@ use crate::{
|
|||||||
errors::*,
|
errors::*,
|
||||||
module::{WorkspaceDatabase, WorkspaceUser},
|
module::{WorkspaceDatabase, WorkspaceUser},
|
||||||
notify::*,
|
notify::*,
|
||||||
services::{server::Server, TrashCan, TrashEvent},
|
services::{
|
||||||
sql_tables::app::{AppTable, AppTableChangeset, AppTableSql},
|
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 {
|
pub(crate) struct AppController {
|
||||||
user: Arc<dyn WorkspaceUser>,
|
user: Arc<dyn WorkspaceUser>,
|
||||||
database: Arc<dyn WorkspaceDatabase>,
|
database: Arc<dyn WorkspaceDatabase>,
|
||||||
trash_can: Arc<TrashCan>,
|
trash_can: Arc<TrashController>,
|
||||||
server: Server,
|
server: Server,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,7 +28,7 @@ impl AppController {
|
|||||||
pub(crate) fn new(
|
pub(crate) fn new(
|
||||||
user: Arc<dyn WorkspaceUser>,
|
user: Arc<dyn WorkspaceUser>,
|
||||||
database: Arc<dyn WorkspaceDatabase>,
|
database: Arc<dyn WorkspaceDatabase>,
|
||||||
trash_can: Arc<TrashCan>,
|
trash_can: Arc<TrashController>,
|
||||||
server: Server,
|
server: Server,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -185,7 +186,7 @@ impl AppController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip(database, trash_can))]
|
#[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();
|
let db_result = database.db_connection();
|
||||||
match event {
|
match event {
|
||||||
TrashEvent::NewTrash(identifiers, ret) | TrashEvent::Putback(identifiers, ret) => {
|
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)]
|
#[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)?;
|
let repeated_app = read_local_workspace_apps(workspace_id, trash_can, conn)?;
|
||||||
send_dart_notification(workspace_id, WorkspaceNotification::WorkspaceAppsChanged)
|
send_dart_notification(workspace_id, WorkspaceNotification::WorkspaceAppsChanged)
|
||||||
.payload(repeated_app)
|
.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(
|
pub fn read_local_workspace_apps(
|
||||||
workspace_id: &str,
|
workspace_id: &str,
|
||||||
trash_can: Arc<TrashCan>,
|
trash_can: Arc<TrashController>,
|
||||||
conn: &SqliteConnection,
|
conn: &SqliteConnection,
|
||||||
) -> Result<RepeatedApp, WorkspaceError> {
|
) -> Result<RepeatedApp, WorkspaceError> {
|
||||||
let mut app_tables = AppTableSql::read_workspace_apps(workspace_id, false, conn)?;
|
let mut app_tables = AppTableSql::read_workspace_apps(workspace_id, false, conn)?;
|
@ -12,7 +12,7 @@ use crate::{
|
|||||||
trash::Trash,
|
trash::Trash,
|
||||||
},
|
},
|
||||||
errors::WorkspaceError,
|
errors::WorkspaceError,
|
||||||
services::{AppController, TrashCan, ViewController},
|
services::{AppController, TrashController, ViewController},
|
||||||
};
|
};
|
||||||
use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
|
use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
|
||||||
use std::{convert::TryInto, sync::Arc};
|
use std::{convert::TryInto, sync::Arc};
|
||||||
@ -30,7 +30,7 @@ pub(crate) async fn create_app_handler(
|
|||||||
pub(crate) async fn delete_app_handler(
|
pub(crate) async fn delete_app_handler(
|
||||||
data: Data<QueryAppRequest>,
|
data: Data<QueryAppRequest>,
|
||||||
controller: Unit<Arc<AppController>>,
|
controller: Unit<Arc<AppController>>,
|
||||||
trash_can: Unit<Arc<TrashCan>>,
|
trash_can: Unit<Arc<TrashController>>,
|
||||||
) -> Result<(), WorkspaceError> {
|
) -> Result<(), WorkspaceError> {
|
||||||
let params: AppIdentifier = data.into_inner().try_into()?;
|
let params: AppIdentifier = data.into_inner().try_into()?;
|
||||||
let trash = controller
|
let trash = controller
|
3
frontend/rust-lib/flowy-core/src/services/app/mod.rs
Normal file
3
frontend/rust-lib/flowy-core/src/services/app/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod controller;
|
||||||
|
pub mod event_handler;
|
||||||
|
pub(crate) mod sql;
|
@ -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::{
|
use crate::{
|
||||||
entities::{
|
entities::{
|
||||||
app::{App, ColorStyle, UpdateAppParams},
|
app::{App, ColorStyle, UpdateAppParams},
|
||||||
trash::{Trash, TrashType},
|
trash::{Trash, TrashType},
|
||||||
view::RepeatedView,
|
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)]
|
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
|
||||||
#[belongs_to(WorkspaceTable, foreign_key = "workspace_id")]
|
#[belongs_to(WorkspaceTable, foreign_key = "workspace_id")]
|
@ -1 +0,0 @@
|
|||||||
|
|
@ -1,11 +1,10 @@
|
|||||||
pub(crate) use app_controller::*;
|
pub(crate) use app::controller::*;
|
||||||
pub(crate) use trash_can::*;
|
pub(crate) use trash::controller::*;
|
||||||
pub(crate) use view_controller::*;
|
pub(crate) use view::controller::*;
|
||||||
pub use workspace_controller::*;
|
pub(crate) use workspace::controller::*;
|
||||||
|
|
||||||
mod app_controller;
|
pub(crate) mod app;
|
||||||
mod database;
|
|
||||||
pub(crate) mod server;
|
pub(crate) mod server;
|
||||||
mod trash_can;
|
pub(crate) mod trash;
|
||||||
mod view_controller;
|
pub(crate) mod view;
|
||||||
mod workspace_controller;
|
pub(crate) mod workspace;
|
||||||
|
@ -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::{
|
use crate::{
|
||||||
entities::trash::{RepeatedTrash, Trash, TrashIdentifier, TrashIdentifiers, TrashType},
|
entities::trash::{RepeatedTrash, Trash, TrashIdentifier, TrashIdentifiers, TrashType},
|
||||||
errors::{WorkspaceError, WorkspaceResult},
|
errors::{WorkspaceError, WorkspaceResult},
|
||||||
module::{WorkspaceDatabase, WorkspaceUser},
|
module::{WorkspaceDatabase, WorkspaceUser},
|
||||||
notify::{send_anonymous_dart_notification, WorkspaceNotification},
|
notify::{send_anonymous_dart_notification, WorkspaceNotification},
|
||||||
services::server::Server,
|
services::{server::Server, trash::sql::TrashTableSql},
|
||||||
sql_tables::trash::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>,
|
pub database: Arc<dyn WorkspaceDatabase>,
|
||||||
notify: broadcast::Sender<TrashEvent>,
|
notify: broadcast::Sender<TrashEvent>,
|
||||||
server: Server,
|
server: Server,
|
||||||
user: Arc<dyn WorkspaceUser>,
|
user: Arc<dyn WorkspaceUser>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrashCan {
|
impl TrashController {
|
||||||
pub fn new(database: Arc<dyn WorkspaceDatabase>, server: Server, user: Arc<dyn WorkspaceUser>) -> Self {
|
pub fn new(database: Arc<dyn WorkspaceDatabase>, server: Server, user: Arc<dyn WorkspaceUser>) -> Self {
|
||||||
let (tx, _) = broadcast::channel(10);
|
let (tx, _) = broadcast::channel(10);
|
||||||
|
|
||||||
@ -196,7 +192,7 @@ impl TrashCan {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TrashCan {
|
impl TrashController {
|
||||||
#[tracing::instrument(level = "debug", skip(self, trash), err)]
|
#[tracing::instrument(level = "debug", skip(self, trash), err)]
|
||||||
fn create_trash_on_server<T: Into<TrashIdentifiers>>(&self, trash: T) -> WorkspaceResult<()> {
|
fn create_trash_on_server<T: Into<TrashIdentifiers>>(&self, trash: T) -> WorkspaceResult<()> {
|
||||||
let token = self.user.token()?;
|
let token = self.user.token()?;
|
@ -1,13 +1,15 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
entities::trash::{RepeatedTrash, TrashIdentifier, TrashIdentifiers},
|
entities::trash::{RepeatedTrash, TrashIdentifier, TrashIdentifiers},
|
||||||
errors::WorkspaceError,
|
errors::WorkspaceError,
|
||||||
services::TrashCan,
|
services::TrashController,
|
||||||
};
|
};
|
||||||
use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
|
use lib_dispatch::prelude::{data_result, Data, DataResult, Unit};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
#[tracing::instrument(skip(controller), err)]
|
#[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 conn = controller.database.db_connection()?;
|
||||||
let repeated_trash = controller.read_trash(&conn)?;
|
let repeated_trash = controller.read_trash(&conn)?;
|
||||||
data_result(repeated_trash)
|
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)]
|
#[tracing::instrument(skip(identifier, controller), err)]
|
||||||
pub(crate) async fn putback_trash_handler(
|
pub(crate) async fn putback_trash_handler(
|
||||||
identifier: Data<TrashIdentifier>,
|
identifier: Data<TrashIdentifier>,
|
||||||
controller: Unit<Arc<TrashCan>>,
|
controller: Unit<Arc<TrashController>>,
|
||||||
) -> Result<(), WorkspaceError> {
|
) -> Result<(), WorkspaceError> {
|
||||||
let _ = controller.putback(&identifier.id).await?;
|
let _ = controller.putback(&identifier.id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -25,20 +27,20 @@ pub(crate) async fn putback_trash_handler(
|
|||||||
#[tracing::instrument(skip(identifiers, controller), err)]
|
#[tracing::instrument(skip(identifiers, controller), err)]
|
||||||
pub(crate) async fn delete_trash_handler(
|
pub(crate) async fn delete_trash_handler(
|
||||||
identifiers: Data<TrashIdentifiers>,
|
identifiers: Data<TrashIdentifiers>,
|
||||||
controller: Unit<Arc<TrashCan>>,
|
controller: Unit<Arc<TrashController>>,
|
||||||
) -> Result<(), WorkspaceError> {
|
) -> Result<(), WorkspaceError> {
|
||||||
let _ = controller.delete(identifiers.into_inner()).await?;
|
let _ = controller.delete(identifiers.into_inner()).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(controller), err)]
|
#[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?;
|
let _ = controller.restore_all().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(skip(controller), err)]
|
#[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?;
|
let _ = controller.delete_all().await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
3
frontend/rust-lib/flowy-core/src/services/trash/mod.rs
Normal file
3
frontend/rust-lib/flowy-core/src/services/trash/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod controller;
|
||||||
|
pub mod event_handler;
|
||||||
|
mod sql;
|
@ -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 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)]
|
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
|
||||||
#[table_name = "trash_table"]
|
#[table_name = "trash_table"]
|
@ -11,8 +11,12 @@ use crate::{
|
|||||||
errors::{internal_error, WorkspaceError, WorkspaceResult},
|
errors::{internal_error, WorkspaceError, WorkspaceResult},
|
||||||
module::{WorkspaceDatabase, WorkspaceUser},
|
module::{WorkspaceDatabase, WorkspaceUser},
|
||||||
notify::{send_dart_notification, WorkspaceNotification},
|
notify::{send_dart_notification, WorkspaceNotification},
|
||||||
services::{server::Server, TrashCan, TrashEvent},
|
services::{
|
||||||
sql_tables::view::{ViewTable, ViewTableChangeset, ViewTableSql},
|
server::Server,
|
||||||
|
view::sql::{ViewTable, ViewTableChangeset, ViewTableSql},
|
||||||
|
TrashController,
|
||||||
|
TrashEvent,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use flowy_document::module::FlowyDocument;
|
use flowy_document::module::FlowyDocument;
|
||||||
use flowy_workspace_infra::entities::share::{ExportData, ExportParams};
|
use flowy_workspace_infra::entities::share::{ExportData, ExportParams};
|
||||||
@ -24,7 +28,7 @@ pub(crate) struct ViewController {
|
|||||||
user: Arc<dyn WorkspaceUser>,
|
user: Arc<dyn WorkspaceUser>,
|
||||||
server: Server,
|
server: Server,
|
||||||
database: Arc<dyn WorkspaceDatabase>,
|
database: Arc<dyn WorkspaceDatabase>,
|
||||||
trash_can: Arc<TrashCan>,
|
trash_can: Arc<TrashController>,
|
||||||
document: Arc<FlowyDocument>,
|
document: Arc<FlowyDocument>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,7 +37,7 @@ impl ViewController {
|
|||||||
user: Arc<dyn WorkspaceUser>,
|
user: Arc<dyn WorkspaceUser>,
|
||||||
database: Arc<dyn WorkspaceDatabase>,
|
database: Arc<dyn WorkspaceDatabase>,
|
||||||
server: Server,
|
server: Server,
|
||||||
trash_can: Arc<TrashCan>,
|
trash_can: Arc<TrashController>,
|
||||||
document: Arc<FlowyDocument>,
|
document: Arc<FlowyDocument>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -296,7 +300,7 @@ impl ViewController {
|
|||||||
async fn handle_trash_event(
|
async fn handle_trash_event(
|
||||||
database: Arc<dyn WorkspaceDatabase>,
|
database: Arc<dyn WorkspaceDatabase>,
|
||||||
document: Arc<FlowyDocument>,
|
document: Arc<FlowyDocument>,
|
||||||
trash_can: Arc<TrashCan>,
|
trash_can: Arc<TrashController>,
|
||||||
event: TrashEvent,
|
event: TrashEvent,
|
||||||
) {
|
) {
|
||||||
let db_result = database.db_connection();
|
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)]
|
#[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)?;
|
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());
|
tracing::Span::current().record("view_count", &format!("{}", repeated_view.len()).as_str());
|
||||||
send_dart_notification(&belong_to_id, WorkspaceNotification::AppViewsChanged)
|
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(
|
fn read_local_belonging_view(
|
||||||
belong_to_id: &str,
|
belong_to_id: &str,
|
||||||
trash_can: Arc<TrashCan>,
|
trash_can: Arc<TrashController>,
|
||||||
conn: &SqliteConnection,
|
conn: &SqliteConnection,
|
||||||
) -> WorkspaceResult<RepeatedView> {
|
) -> WorkspaceResult<RepeatedView> {
|
||||||
let mut view_tables = ViewTableSql::read_views(belong_to_id, conn)?;
|
let mut view_tables = ViewTableSql::read_views(belong_to_id, conn)?;
|
@ -13,7 +13,7 @@ use crate::{
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
errors::WorkspaceError,
|
errors::WorkspaceError,
|
||||||
services::{TrashCan, ViewController},
|
services::{TrashController, ViewController},
|
||||||
};
|
};
|
||||||
use flowy_document_infra::entities::doc::DocDelta;
|
use flowy_document_infra::entities::doc::DocDelta;
|
||||||
use flowy_workspace_infra::entities::share::{ExportData, ExportParams, ExportRequest};
|
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(
|
pub(crate) async fn delete_view_handler(
|
||||||
data: Data<QueryViewRequest>,
|
data: Data<QueryViewRequest>,
|
||||||
controller: Unit<Arc<ViewController>>,
|
controller: Unit<Arc<ViewController>>,
|
||||||
trash_can: Unit<Arc<TrashCan>>,
|
trash_can: Unit<Arc<TrashController>>,
|
||||||
) -> Result<(), WorkspaceError> {
|
) -> Result<(), WorkspaceError> {
|
||||||
let params: ViewIdentifiers = data.into_inner().try_into()?;
|
let params: ViewIdentifiers = data.into_inner().try_into()?;
|
||||||
for view_id in ¶ms.view_ids {
|
for view_id in ¶ms.view_ids {
|
3
frontend/rust-lib/flowy-core/src/services/view/mod.rs
Normal file
3
frontend/rust-lib/flowy-core/src/services/view/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod controller;
|
||||||
|
pub mod event_handler;
|
||||||
|
mod sql;
|
@ -1,15 +1,112 @@
|
|||||||
use diesel::sql_types::Integer;
|
|
||||||
|
|
||||||
use flowy_database::schema::view_table;
|
|
||||||
use lib_infra::timestamp;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
entities::{
|
entities::{
|
||||||
trash::{Trash, TrashType},
|
trash::{Trash, TrashType},
|
||||||
view::{RepeatedView, UpdateViewParams, View, ViewType},
|
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)]
|
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
|
||||||
#[belongs_to(AppTable, foreign_key = "belong_to_id")]
|
#[belongs_to(AppTable, foreign_key = "belong_to_id")]
|
@ -2,24 +2,19 @@ use crate::{
|
|||||||
errors::*,
|
errors::*,
|
||||||
module::{WorkspaceDatabase, WorkspaceUser},
|
module::{WorkspaceDatabase, WorkspaceUser},
|
||||||
notify::*,
|
notify::*,
|
||||||
services::{read_local_workspace_apps, server::Server, AppController, TrashCan, ViewController},
|
services::{
|
||||||
sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql},
|
read_local_workspace_apps,
|
||||||
|
server::Server,
|
||||||
|
workspace::sql::{WorkspaceTable, WorkspaceTableChangeset, WorkspaceTableSql},
|
||||||
|
AppController,
|
||||||
|
TrashController,
|
||||||
|
ViewController,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use chrono::Utc;
|
|
||||||
use flowy_database::SqliteConnection;
|
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::*};
|
||||||
use flowy_workspace_infra::{
|
use lib_infra::kv::KV;
|
||||||
entities::{app::RepeatedApp, view::View, workspace::*},
|
use std::sync::Arc;
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct WorkspaceController {
|
pub struct WorkspaceController {
|
||||||
pub user: Arc<dyn WorkspaceUser>,
|
pub user: Arc<dyn WorkspaceUser>,
|
||||||
@ -27,7 +22,7 @@ pub struct WorkspaceController {
|
|||||||
pub(crate) view_controller: Arc<ViewController>,
|
pub(crate) view_controller: Arc<ViewController>,
|
||||||
pub(crate) database: Arc<dyn WorkspaceDatabase>,
|
pub(crate) database: Arc<dyn WorkspaceDatabase>,
|
||||||
pub(crate) app_controller: Arc<AppController>,
|
pub(crate) app_controller: Arc<AppController>,
|
||||||
pub(crate) trash_can: Arc<TrashCan>,
|
pub(crate) trash_controller: Arc<TrashController>,
|
||||||
server: Server,
|
server: Server,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,13 +32,9 @@ impl WorkspaceController {
|
|||||||
database: Arc<dyn WorkspaceDatabase>,
|
database: Arc<dyn WorkspaceDatabase>,
|
||||||
app_controller: Arc<AppController>,
|
app_controller: Arc<AppController>,
|
||||||
view_controller: Arc<ViewController>,
|
view_controller: Arc<ViewController>,
|
||||||
trash_can: Arc<TrashCan>,
|
trash_can: Arc<TrashController>,
|
||||||
server: Server,
|
server: Server,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
if let Ok(token) = user.token() {
|
|
||||||
INIT_WORKSPACE.write().insert(token, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
let workspace_sql = Arc::new(WorkspaceTableSql {});
|
let workspace_sql = Arc::new(WorkspaceTableSql {});
|
||||||
Self {
|
Self {
|
||||||
user,
|
user,
|
||||||
@ -51,92 +42,12 @@ impl WorkspaceController {
|
|||||||
view_controller,
|
view_controller,
|
||||||
database,
|
database,
|
||||||
app_controller,
|
app_controller,
|
||||||
trash_can,
|
trash_controller: trash_can,
|
||||||
server,
|
server,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn init(&self, token: &str) -> Result<(), WorkspaceError> {
|
pub(crate) fn init(&self) -> Result<(), WorkspaceError> { Ok(()) }
|
||||||
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) async fn create_workspace_from_params(
|
pub(crate) async fn create_workspace_from_params(
|
||||||
&self,
|
&self,
|
||||||
@ -263,7 +174,7 @@ impl WorkspaceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, conn), err)]
|
#[tracing::instrument(level = "debug", skip(self, conn), err)]
|
||||||
fn read_local_workspaces(
|
pub(crate) fn read_local_workspaces(
|
||||||
&self,
|
&self,
|
||||||
workspace_id: Option<String>,
|
workspace_id: Option<String>,
|
||||||
user_id: &str,
|
user_id: &str,
|
||||||
@ -301,7 +212,7 @@ impl WorkspaceController {
|
|||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, conn), err)]
|
#[tracing::instrument(level = "debug", skip(self, conn), err)]
|
||||||
fn read_local_apps(&self, workspace_id: &str, conn: &SqliteConnection) -> Result<RepeatedApp, WorkspaceError> {
|
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)
|
Ok(repeated_app)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -354,7 +265,11 @@ impl WorkspaceController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self), err)]
|
#[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 (token, server) = self.token_with_server()?;
|
||||||
let workspace_sql = self.workspace_sql.clone();
|
let workspace_sql = self.workspace_sql.clone();
|
||||||
let app_ctrl = self.app_controller.clone();
|
let app_ctrl = self.app_controller.clone();
|
@ -0,0 +1,3 @@
|
|||||||
|
pub mod controller;
|
||||||
|
pub mod event_handler;
|
||||||
|
pub(crate) mod sql;
|
@ -1,15 +1,15 @@
|
|||||||
|
use crate::{
|
||||||
|
entities::{
|
||||||
|
app::RepeatedApp,
|
||||||
|
workspace::{UpdateWorkspaceParams, Workspace},
|
||||||
|
},
|
||||||
|
errors::WorkspaceError,
|
||||||
|
};
|
||||||
use diesel::SqliteConnection;
|
use diesel::SqliteConnection;
|
||||||
|
|
||||||
use flowy_database::{
|
use flowy_database::{
|
||||||
prelude::*,
|
prelude::*,
|
||||||
schema::{workspace_table, workspace_table::dsl},
|
schema::{workspace_table, workspace_table::dsl},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
|
||||||
errors::WorkspaceError,
|
|
||||||
sql_tables::workspace::{WorkspaceTable, WorkspaceTableChangeset},
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) struct WorkspaceTableSql {}
|
pub(crate) struct WorkspaceTableSql {}
|
||||||
|
|
||||||
impl WorkspaceTableSql {
|
impl WorkspaceTableSql {
|
||||||
@ -64,3 +64,69 @@ impl WorkspaceTableSql {
|
|||||||
Ok(())
|
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),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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)
|
|
||||||
// }
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
mod app_sql;
|
|
||||||
mod app_table;
|
|
||||||
|
|
||||||
pub(crate) use app_sql::*;
|
|
||||||
pub(crate) use app_table::*;
|
|
@ -1,4 +0,0 @@
|
|||||||
pub mod app;
|
|
||||||
pub mod trash;
|
|
||||||
pub mod view;
|
|
||||||
pub mod workspace;
|
|
@ -1,5 +0,0 @@
|
|||||||
mod trash_sql;
|
|
||||||
mod trash_table;
|
|
||||||
|
|
||||||
pub(crate) use trash_sql::*;
|
|
||||||
pub(crate) use trash_table::*;
|
|
@ -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(())
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
mod view_sql;
|
|
||||||
mod view_table;
|
|
||||||
|
|
||||||
pub use view_sql::*;
|
|
||||||
pub use view_table::*;
|
|
@ -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 })
|
|
||||||
// }
|
|
@ -1,5 +0,0 @@
|
|||||||
mod workspace_sql;
|
|
||||||
mod workspace_table;
|
|
||||||
|
|
||||||
pub(crate) use workspace_sql::*;
|
|
||||||
pub(crate) use workspace_table::*;
|
|
@ -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),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,7 +3,7 @@ mod deps_resolve;
|
|||||||
pub mod module;
|
pub mod module;
|
||||||
use crate::deps_resolve::WorkspaceDepsResolver;
|
use crate::deps_resolve::WorkspaceDepsResolver;
|
||||||
use backend_service::configuration::ClientServerConfiguration;
|
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_document::module::FlowyDocument;
|
||||||
use flowy_user::{
|
use flowy_user::{
|
||||||
prelude::UserStatus,
|
prelude::UserStatus,
|
||||||
@ -66,7 +66,7 @@ pub struct FlowySDK {
|
|||||||
config: FlowySDKConfig,
|
config: FlowySDKConfig,
|
||||||
pub user_session: Arc<UserSession>,
|
pub user_session: Arc<UserSession>,
|
||||||
pub flowy_document: Arc<FlowyDocument>,
|
pub flowy_document: Arc<FlowyDocument>,
|
||||||
pub workspace_ctrl: Arc<WorkspaceController>,
|
pub core: Arc<FlowyCore>,
|
||||||
pub dispatcher: Arc<EventDispatcher>,
|
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_config = UserSessionConfig::new(&config.root, &config.server_config, &session_cache_key);
|
||||||
let user_session = Arc::new(UserSession::new(user_config));
|
let user_session = Arc::new(UserSession::new(user_config));
|
||||||
let flowy_document = mk_document_module(user_session.clone(), &config.server_config);
|
let flowy_document = mk_document_module(user_session.clone(), &config.server_config);
|
||||||
let workspace_ctrl =
|
let core = mk_core(user_session.clone(), flowy_document.clone(), &config.server_config);
|
||||||
mk_workspace_controller(user_session.clone(), flowy_document.clone(), &config.server_config);
|
|
||||||
let modules = mk_modules(workspace_ctrl.clone(), user_session.clone());
|
let modules = mk_modules(core.clone(), user_session.clone());
|
||||||
let dispatcher = Arc::new(EventDispatcher::construct(|| modules));
|
let dispatcher = Arc::new(EventDispatcher::construct(|| modules));
|
||||||
_init(&dispatcher, user_session.clone(), workspace_ctrl.clone());
|
_init(&dispatcher, user_session.clone(), core.clone());
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
config,
|
config,
|
||||||
user_session,
|
user_session,
|
||||||
flowy_document,
|
flowy_document,
|
||||||
workspace_ctrl,
|
core,
|
||||||
dispatcher,
|
dispatcher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,38 +99,35 @@ impl FlowySDK {
|
|||||||
pub fn dispatcher(&self) -> Arc<EventDispatcher> { self.dispatcher.clone() }
|
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 user_status_subscribe = user_session.notifier.user_status_subscribe();
|
||||||
let network_status_subscribe = user_session.notifier.network_type_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 {
|
dispatch.spawn(async move {
|
||||||
user_session.init();
|
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 {
|
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(
|
async fn _listen_user_status(mut subscribe: broadcast::Receiver<UserStatus>, core: Arc<FlowyCore>) {
|
||||||
mut subscribe: broadcast::Receiver<UserStatus>,
|
|
||||||
workspace_controller: Arc<WorkspaceController>,
|
|
||||||
) {
|
|
||||||
while let Ok(status) = subscribe.recv().await {
|
while let Ok(status) = subscribe.recv().await {
|
||||||
let result = || async {
|
let result = || async {
|
||||||
match status {
|
match status {
|
||||||
UserStatus::Login { token } => {
|
UserStatus::Login { token } => {
|
||||||
let _ = workspace_controller.user_did_sign_in(&token).await?;
|
let _ = core.user_did_sign_in(&token).await?;
|
||||||
},
|
},
|
||||||
UserStatus::Logout { .. } => {
|
UserStatus::Logout { .. } => {
|
||||||
workspace_controller.user_did_logout().await;
|
core.user_did_logout().await;
|
||||||
},
|
},
|
||||||
UserStatus::Expired { .. } => {
|
UserStatus::Expired { .. } => {
|
||||||
workspace_controller.user_session_expired().await;
|
core.user_session_expired().await;
|
||||||
},
|
},
|
||||||
UserStatus::SignUp { profile, ret } => {
|
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(());
|
let _ = ret.send(());
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -144,12 +141,9 @@ async fn _listen_user_status(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn _listen_network_status(
|
async fn _listen_network_status(mut subscribe: broadcast::Receiver<NetworkType>, core: Arc<FlowyCore>) {
|
||||||
mut subscribe: broadcast::Receiver<NetworkType>,
|
|
||||||
workspace_controller: Arc<WorkspaceController>,
|
|
||||||
) {
|
|
||||||
while let Ok(new_type) = subscribe.recv().await {
|
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>,
|
user_session: Arc<UserSession>,
|
||||||
flowy_document: Arc<FlowyDocument>,
|
flowy_document: Arc<FlowyDocument>,
|
||||||
server_config: &ClientServerConfiguration,
|
server_config: &ClientServerConfiguration,
|
||||||
) -> Arc<WorkspaceController> {
|
) -> Arc<FlowyCore> {
|
||||||
let workspace_deps = WorkspaceDepsResolver::new(user_session);
|
let workspace_deps = WorkspaceDepsResolver::new(user_session);
|
||||||
let (user, database) = workspace_deps.split_into();
|
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)
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,19 @@
|
|||||||
use crate::deps_resolve::DocumentDepsResolver;
|
use crate::deps_resolve::DocumentDepsResolver;
|
||||||
use backend_service::configuration::ClientServerConfiguration;
|
use backend_service::configuration::ClientServerConfiguration;
|
||||||
use flowy_core::prelude::WorkspaceController;
|
use flowy_core::prelude::FlowyCore;
|
||||||
use flowy_document::module::FlowyDocument;
|
use flowy_document::module::FlowyDocument;
|
||||||
use flowy_user::services::user::UserSession;
|
use flowy_user::services::user::UserSession;
|
||||||
use lib_dispatch::prelude::Module;
|
use lib_dispatch::prelude::Module;
|
||||||
use std::sync::Arc;
|
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 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]
|
vec![user_module, workspace_module]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_user_module(user_session: Arc<UserSession>) -> Module { flowy_user::module::create(user_session) }
|
fn mk_user_module(user_session: Arc<UserSession>) -> Module { flowy_user::module::create(user_session) }
|
||||||
|
fn mk_core_module(core: Arc<FlowyCore>) -> Module { flowy_core::module::create(core) }
|
||||||
fn mk_workspace_module(workspace_controller: Arc<WorkspaceController>) -> Module {
|
|
||||||
flowy_core::module::create(workspace_controller)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn mk_document_module(
|
pub fn mk_document_module(
|
||||||
user_session: Arc<UserSession>,
|
user_session: Arc<UserSession>,
|
||||||
|
Loading…
Reference in New Issue
Block a user