diff --git a/app_flowy/lib/user/presentation/splash_screen.dart b/app_flowy/lib/user/presentation/splash_screen.dart index 5b9baee5bf..25cb1a6305 100644 --- a/app_flowy/lib/user/presentation/splash_screen.dart +++ b/app_flowy/lib/user/presentation/splash_screen.dart @@ -59,9 +59,9 @@ class SplashScreen extends StatelessWidget { void _handleUnauthenticated(BuildContext context, Unauthenticated result) { Log.error(result.error); - // getIt().pushSignInScreen(context); + getIt().pushSignInScreen(context); - getIt().pushSkipLoginScreen(context); + // getIt().pushSkipLoginScreen(context); } } diff --git a/backend/src/entities/workspace.rs b/backend/src/entities/workspace.rs index 6948d20758..bec2b4f8e3 100644 --- a/backend/src/entities/workspace.rs +++ b/backend/src/entities/workspace.rs @@ -1,5 +1,5 @@ use chrono::Utc; -use flowy_workspace_infra::protobuf::{App, RepeatedView, Trash, TrashType, View, ViewType}; +use flowy_workspace_infra::protobuf::{App, RepeatedView, Trash, TrashType, View, ViewType, Workspace}; use protobuf::ProtobufEnum; pub(crate) const WORKSPACE_TABLE: &'static str = "workspace_table"; @@ -17,6 +17,18 @@ pub struct WorkspaceTable { pub(crate) user_id: String, } +impl std::convert::Into for WorkspaceTable { + fn into(self) -> Workspace { + let mut workspace = Workspace::default(); + workspace.set_id(self.id.to_string()); + workspace.set_name(self.name.clone()); + workspace.set_desc(self.description.clone()); + workspace.set_modified_time(self.modified_time.timestamp()); + workspace.set_create_time(self.create_time.timestamp()); + workspace + } +} + #[derive(Debug, Clone, sqlx::FromRow)] pub struct AppTable { pub(crate) id: uuid::Uuid, @@ -28,7 +40,6 @@ pub struct AppTable { pub(crate) modified_time: chrono::DateTime, pub(crate) create_time: chrono::DateTime, pub(crate) user_id: String, - pub(crate) is_trash: bool, } impl std::convert::Into for AppTable { diff --git a/backend/src/service/app/sql_builder.rs b/backend/src/service/app/sql_builder.rs index 0b69057c99..4556dafda1 100644 --- a/backend/src/service/app/sql_builder.rs +++ b/backend/src/service/app/sql_builder.rs @@ -2,7 +2,7 @@ use crate::{ entities::workspace::{AppTable, APP_TABLE}, sqlx_ext::SqlBuilder, }; -use chrono::Utc; +use chrono::{DateTime, NaiveDateTime, Utc}; use flowy_net::errors::{invalid_params, ServerError}; use flowy_workspace_infra::{ parser::app::AppId, @@ -31,12 +31,31 @@ impl NewAppSqlBuilder { modified_time: time, create_time: time, user_id: user_id.to_string(), - is_trash: false, }; Self { table } } + pub fn from_app(user_id: &str, app: App) -> Result { + let app_id = check_app_id(app.id)?; + let create_time = DateTime::::from_utc(NaiveDateTime::from_timestamp(app.create_time, 0), Utc); + let modified_time = DateTime::::from_utc(NaiveDateTime::from_timestamp(app.modified_time, 0), Utc); + + let table = AppTable { + id: app_id, + workspace_id: app.workspace_id, + name: app.name, + description: app.desc, + color_style: default_color_style(), + last_view_id: "".to_string(), + modified_time, + create_time, + user_id: user_id.to_string(), + }; + + Ok(Self { table }) + } + pub fn name(mut self, name: &str) -> Self { self.table.name = name.to_string(); self diff --git a/backend/src/service/user/user_default.rs b/backend/src/service/user/user_default.rs index 21c87e33af..648933662a 100644 --- a/backend/src/service/user/user_default.rs +++ b/backend/src/service/user/user_default.rs @@ -7,66 +7,43 @@ use crate::{ sqlx_ext::{map_sqlx_error, DBTransaction}, }; +use crate::service::view::{create_view_with_args, sql_builder::NewViewSqlBuilder}; +use chrono::Utc; use flowy_document::services::doc::doc_initial_string; use flowy_net::errors::ServerError; use flowy_workspace_infra::protobuf::{App, CreateViewParams, View, ViewType, Workspace}; +use std::convert::TryInto; pub async fn create_default_workspace( transaction: &mut DBTransaction<'_>, user_id: &str, ) -> Result { - let workspace = create_workspace(transaction, user_id).await?; - let app = create_app(transaction, user_id, &workspace).await?; - let _ = create_default_view(transaction, &app).await?; + let time = Utc::now(); + let workspace: Workspace = flowy_workspace_infra::user_default::create_default_workspace(time) + .try_into() + .unwrap(); - Ok(workspace) -} - -async fn create_workspace(transaction: &mut DBTransaction<'_>, user_id: &str) -> Result { - let (sql, args, workspace) = WorkspaceBuilder::new(user_id.as_ref()) - .name("DefaultWorkspace") - .desc("") - .build()?; + let mut cloned_workspace = workspace.clone(); + let mut apps = cloned_workspace.take_apps(); + let (sql, args, _) = WorkspaceBuilder::from_workspace(user_id, cloned_workspace)?.build()?; let _ = sqlx::query_with(&sql, args) - .execute(transaction) + .execute(transaction as &mut DBTransaction<'_>) .await .map_err(map_sqlx_error)?; + for mut app in apps.take_items() { + let mut views = app.take_belongings(); + let (sql, args, _) = AppBuilder::from_app(user_id, app)?.build()?; + let _ = sqlx::query_with(&sql, args) + .execute(transaction as &mut DBTransaction<'_>) + .await + .map_err(map_sqlx_error)?; + + for view in views.take_items() { + let (sql, args, view) = NewViewSqlBuilder::from_view(view)?.build()?; + let _ = create_view_with_args(transaction, sql, args, view, doc_initial_string()).await?; + } + } Ok(workspace) } - -async fn create_app( - transaction: &mut DBTransaction<'_>, - user_id: &str, - workspace: &Workspace, -) -> Result { - let (sql, args, app) = AppBuilder::new(user_id, &workspace.id) - .name("Getting Started") - .desc("") - .build()?; - - let _ = sqlx::query_with(&sql, args) - .execute(transaction) - .await - .map_err(map_sqlx_error)?; - - Ok(app) -} - -async fn create_default_view(transaction: &mut DBTransaction<'_>, app: &App) -> Result { - let params = CreateViewParams { - belong_to_id: app.id.clone(), - name: "Read Me".to_string(), - desc: "".to_string(), - thumbnail: "".to_string(), - view_type: ViewType::Doc, - data: doc_initial_string(), - unknown_fields: Default::default(), - cached_size: Default::default(), - }; - - let view = create_view(transaction, params).await?; - - Ok(view) -} diff --git a/backend/src/service/view/sql_builder.rs b/backend/src/service/view/sql_builder.rs index 6c6d963e9a..954b32d239 100644 --- a/backend/src/service/view/sql_builder.rs +++ b/backend/src/service/view/sql_builder.rs @@ -2,7 +2,7 @@ use crate::{ entities::workspace::{ViewTable, VIEW_TABLE}, sqlx_ext::SqlBuilder, }; -use chrono::Utc; +use chrono::{DateTime, NaiveDateTime, Utc}; use flowy_net::errors::{invalid_params, ServerError}; use flowy_workspace_infra::{ parser::view::ViewId, @@ -35,6 +35,25 @@ impl NewViewSqlBuilder { Self { table } } + pub fn from_view(view: View) -> Result { + let view_id = ViewId::parse(view.id).map_err(invalid_params)?; + let view_id = Uuid::parse_str(view_id.as_ref())?; + let create_time = DateTime::::from_utc(NaiveDateTime::from_timestamp(view.create_time, 0), Utc); + let modified_time = DateTime::::from_utc(NaiveDateTime::from_timestamp(view.modified_time, 0), Utc); + + let table = ViewTable { + id: view_id, + belong_to_id: view.belong_to_id, + name: view.name, + description: view.desc, + modified_time, + create_time, + thumbnail: "".to_string(), + view_type: view.view_type.value(), + }; + Ok(Self { table }) + } + pub fn name(mut self, name: &str) -> Self { self.table.name = name.to_string(); self diff --git a/backend/src/service/view/view.rs b/backend/src/service/view/view.rs index 16ea717a2d..ff7f4fb9db 100644 --- a/backend/src/service/view/view.rs +++ b/backend/src/service/view/view.rs @@ -75,13 +75,24 @@ pub(crate) async fn create_view( .view_type(params.view_type) .build()?; + let view = create_view_with_args(transaction, sql, args, view, params.data).await?; + Ok(view) +} + +pub(crate) async fn create_view_with_args( + transaction: &mut DBTransaction<'_>, + sql: String, + args: PgArguments, + view: View, + view_data: String, +) -> Result { let _ = sqlx::query_with(&sql, args) .execute(transaction as &mut DBTransaction<'_>) .await .map_err(map_sqlx_error)?; let mut create_doc_params = CreateDocParams::new(); - create_doc_params.set_data(params.data); + create_doc_params.set_data(view_data); create_doc_params.set_id(view.id.clone()); let _ = create_doc(transaction, create_doc_params).await?; Ok(view) diff --git a/backend/src/service/workspace/sql_builder.rs b/backend/src/service/workspace/sql_builder.rs index e373a069bc..89b447c6ca 100644 --- a/backend/src/service/workspace/sql_builder.rs +++ b/backend/src/service/workspace/sql_builder.rs @@ -2,7 +2,7 @@ use crate::{ entities::workspace::{WorkspaceTable, WORKSPACE_TABLE}, sqlx_ext::SqlBuilder, }; -use chrono::Utc; +use chrono::{DateTime, NaiveDateTime, Utc}; use flowy_net::errors::{invalid_params, ServerError}; use flowy_workspace_infra::{ parser::workspace::WorkspaceId, @@ -31,6 +31,23 @@ impl NewWorkspaceBuilder { Self { table } } + pub fn from_workspace(user_id: &str, workspace: Workspace) -> Result { + let workspace_id = check_workspace_id(workspace.id)?; + let create_time = DateTime::::from_utc(NaiveDateTime::from_timestamp(workspace.create_time, 0), Utc); + let modified_time = DateTime::::from_utc(NaiveDateTime::from_timestamp(workspace.modified_time, 0), Utc); + + let table = WorkspaceTable { + id: workspace_id, + name: workspace.name, + description: workspace.desc, + modified_time, + create_time, + user_id: user_id.to_string(), + }; + + Ok(Self { table }) + } + pub fn name(mut self, name: &str) -> Self { self.table.name = name.to_string(); self @@ -42,8 +59,7 @@ impl NewWorkspaceBuilder { } pub fn build(self) -> Result<(String, PgArguments, Workspace), ServerError> { - let workspace = make_workspace_from_table(self.table.clone(), None); - + let workspace: Workspace = self.table.clone().into(); // TODO: use macro to fetch each field from struct let (sql, args) = SqlBuilder::create(WORKSPACE_TABLE) .add_arg("id", self.table.id) @@ -58,25 +74,6 @@ impl NewWorkspaceBuilder { } } -pub(crate) fn make_workspace_from_table(table: WorkspaceTable, apps: Option) -> Workspace { - let mut workspace = Workspace { - id: table.id.to_string(), - name: table.name, - desc: table.description, - apps: Default::default(), - modified_time: table.modified_time.timestamp(), - create_time: table.create_time.timestamp(), - unknown_fields: Default::default(), - cached_size: Default::default(), - }; - - if let Some(apps) = apps { - workspace.set_apps(apps); - } - - workspace -} - pub(crate) fn check_workspace_id(id: String) -> Result { let workspace_id = WorkspaceId::parse(id).map_err(invalid_params)?; let workspace_id = Uuid::parse_str(workspace_id.as_ref())?; diff --git a/backend/src/service/workspace/workspace.rs b/backend/src/service/workspace/workspace.rs index 6d65ac30f8..2bf801c96e 100644 --- a/backend/src/service/workspace/workspace.rs +++ b/backend/src/service/workspace/workspace.rs @@ -102,7 +102,8 @@ pub async fn read_workspaces( .context("Get workspace app") .unwrap_or(RepeatedApp::default()); - let workspace = make_workspace_from_table(table, Some(apps)); + let mut workspace: Workspace = table.into(); + workspace.set_apps(apps); workspaces.push(workspace); } diff --git a/rust-lib/flowy-workspace-infra/Cargo.toml b/rust-lib/flowy-workspace-infra/Cargo.toml index b4fa536824..19e08b1679 100644 --- a/rust-lib/flowy-workspace-infra/Cargo.toml +++ b/rust-lib/flowy-workspace-infra/Cargo.toml @@ -15,7 +15,8 @@ strum_macros = "0.21" derive_more = {version = "0.99", features = ["display"]} log = "0.4.14" flowy-document = { path = "../flowy-document" } - +uuid = { version = "0.8", features = ["serde", "v4"] } +chrono = { version = "0.4" } [features] default = [] diff --git a/rust-lib/flowy-workspace-infra/src/lib.rs b/rust-lib/flowy-workspace-infra/src/lib.rs index 74b1c03599..631fdf050b 100644 --- a/rust-lib/flowy-workspace-infra/src/lib.rs +++ b/rust-lib/flowy-workspace-infra/src/lib.rs @@ -7,3 +7,4 @@ mod macros; // #[cfg(feature = "backend")] pub mod protobuf; +pub mod user_default; diff --git a/rust-lib/flowy-workspace-infra/src/user_default.rs b/rust-lib/flowy-workspace-infra/src/user_default.rs new file mode 100644 index 0000000000..d92e11780c --- /dev/null +++ b/rust-lib/flowy-workspace-infra/src/user_default.rs @@ -0,0 +1,68 @@ +use crate::entities::{ + app::{App, RepeatedApp}, + view::{RepeatedView, View, ViewType}, + workspace::Workspace, +}; +use chrono::Utc; +use uuid::Uuid; + +pub fn create_default_workspace(time: chrono::DateTime) -> Workspace { + let workspace_id = uuid::Uuid::new_v4(); + let name = "Workspace".to_string(); + let desc = "".to_string(); + + let apps = RepeatedApp { + items: vec![create_default_app(workspace_id.to_string(), time.clone())], + }; + + let workspace = Workspace { + id: workspace_id.to_string(), + name, + desc, + apps, + modified_time: time.timestamp(), + create_time: time.timestamp(), + }; + + workspace +} + +fn create_default_app(workspace_id: String, time: chrono::DateTime) -> App { + let app_id = uuid::Uuid::new_v4(); + let name = "Getting Started".to_string(); + let desc = "".to_string(); + + let views = RepeatedView { + items: vec![create_default_view(app_id.to_string(), time.clone())], + }; + + App { + id: app_id.to_string(), + workspace_id, + name, + desc, + belongings: views, + version: 0, + modified_time: time.timestamp(), + create_time: time.timestamp(), + } +} + +fn create_default_view(app_id: String, time: chrono::DateTime) -> View { + let view_id = uuid::Uuid::new_v4(); + let name = "Read me".to_string(); + let desc = "".to_string(); + let view_type = ViewType::Doc; + + View { + id: view_id.to_string(), + belong_to_id: app_id, + name, + desc, + view_type, + version: 0, + belongings: Default::default(), + modified_time: time.timestamp(), + create_time: time.timestamp(), + } +}