From 152cb17701137ac461522581da9f336cd1803989 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 29 Dec 2021 00:34:00 +0800 Subject: [PATCH] fix bugs --- backend/src/services/core/view/controller.rs | 23 +- backend/src/services/core/view/persistence.rs | 15 +- backend/src/services/core/view/router.rs | 10 +- backend/src/services/document/mod.rs | 2 +- backend/src/services/document/persistence.rs | 13 +- backend/src/services/document/router.rs | 5 +- backend/src/services/document/ws_actor.rs | 24 +- backend/src/services/document/ws_receiver.rs | 6 +- backend/src/services/kv/kv.rs | 39 ++- backend/src/services/kv/mod.rs | 4 +- backend/tests/api_test/kv_test.rs | 27 ++ backend/tests/document_test/edit_script.rs | 60 +++-- backend/tests/document_test/edit_test.rs | 3 +- backend/tests/util/helper.rs | 22 +- .../flowy-core-data-model/view_create.pb.dart | 28 ++ .../view_create.pbjson.dart | 4 +- .../flowy-core/src/core/core_context.rs | 38 +-- .../flowy-core/src/services/app/controller.rs | 59 +---- .../src/services/app/event_handler.rs | 8 +- .../src/services/server/server_api_mock.rs | 8 +- .../src/services/trash/controller.rs | 2 +- .../src/services/view/controller.rs | 39 +-- .../src/services/view/event_handler.rs | 10 +- .../src/services/workspace/controller.rs | 4 +- .../rust-lib/flowy-document/src/context.rs | 24 +- .../flowy-document/src/services/controller.rs | 10 +- frontend/rust-lib/flowy-sdk/src/lib.rs | 4 +- .../rust-lib/flowy-test/src/doc_script.rs | 2 +- frontend/rust-lib/flowy-test/src/helper.rs | 4 +- frontend/rust-lib/flowy-test/src/lib.rs | 4 +- .../src/services/server/server_api_mock.rs | 6 +- .../tests/event/user_profile_test.rs | 4 +- .../flowy-virtual-net/src/mock/server.rs | 2 +- .../backend-service/src/configuration.rs | 2 +- .../flowy-collaboration/src/entities/doc.rs | 9 +- .../src/entities/revision.rs | 7 - .../flowy-collaboration/src/sync/server.rs | 52 ++-- .../src/sync/synchronizer.rs | 32 +-- .../src/entities/view/view_create.rs | 25 +- .../src/protobuf/model/view_create.rs | 247 ++++++++++++------ .../src/protobuf/proto/view_create.proto | 2 + shared-lib/lib-infra/src/lib.rs | 2 +- 42 files changed, 528 insertions(+), 363 deletions(-) diff --git a/backend/src/services/core/view/controller.rs b/backend/src/services/core/view/controller.rs index 3b6054fedb..f78862d98f 100644 --- a/backend/src/services/core/view/controller.rs +++ b/backend/src/services/core/view/controller.rs @@ -7,10 +7,11 @@ use crate::{ util::sqlx_ext::{map_sqlx_error, DBTransaction, SqlBuilder}, }; use backend_service::errors::{invalid_params, ServerError}; +use bytes::Bytes; use chrono::Utc; use flowy_collaboration::{ - entities::revision::{RevType, Revision}, - protobuf::{CreateDocParams, RepeatedRevision}, + entities::revision::{RepeatedRevision, RevType, Revision}, + protobuf::CreateDocParams, }; use flowy_core_data_model::{ parser::{ @@ -71,12 +72,13 @@ pub(crate) async fn create_view( params: CreateViewParams, user_id: &str, ) -> Result { + let view_id = check_view_id(params.view_id.clone())?; let name = ViewName::parse(params.name).map_err(invalid_params)?; let belong_to_id = AppId::parse(params.belong_to_id).map_err(invalid_params)?; let thumbnail = ViewThumbnail::parse(params.thumbnail).map_err(invalid_params)?; let desc = ViewDesc::parse(params.desc).map_err(invalid_params)?; - let (sql, args, view) = NewViewSqlBuilder::new(belong_to_id.as_ref()) + let (sql, args, view) = NewViewSqlBuilder::new(view_id, belong_to_id.as_ref()) .name(name.as_ref()) .desc(desc.as_ref()) .thumbnail(thumbnail.as_ref()) @@ -88,18 +90,13 @@ pub(crate) async fn create_view( .await .map_err(map_sqlx_error)?; - let doc_id = view.id.clone(); - let revision: flowy_collaboration::protobuf::Revision = - Revision::initial_revision(user_id, &doc_id, RevType::Remote) - .try_into() - .unwrap(); - let mut repeated_revision = RepeatedRevision::new(); - repeated_revision.set_items(vec![revision].into()); - + let delta_data = Bytes::from(params.view_data); + let md5 = format!("{:x}", md5::compute(&delta_data)); + let revision = Revision::new(&view.id, 0, 0, delta_data, RevType::Remote, user_id, md5); + let repeated_revision = RepeatedRevision::new(vec![revision]); let mut create_doc_params = CreateDocParams::new(); - create_doc_params.set_revisions(repeated_revision); + create_doc_params.set_revisions(repeated_revision.try_into().unwrap()); create_doc_params.set_id(view.id.clone()); - let _ = create_document(&kv_store, create_doc_params).await?; Ok(view) diff --git a/backend/src/services/core/view/persistence.rs b/backend/src/services/core/view/persistence.rs index fb7d830542..d6b41aec92 100644 --- a/backend/src/services/core/view/persistence.rs +++ b/backend/src/services/core/view/persistence.rs @@ -16,12 +16,11 @@ pub struct NewViewSqlBuilder { } impl NewViewSqlBuilder { - pub fn new(belong_to_id: &str) -> Self { - let uuid = uuid::Uuid::new_v4(); + pub fn new(view_id: Uuid, belong_to_id: &str) -> Self { let time = Utc::now(); let table = ViewTable { - id: uuid, + id: view_id, belong_to_id: belong_to_id.to_string(), name: "".to_string(), description: "".to_string(), @@ -94,13 +93,17 @@ impl NewViewSqlBuilder { pub(crate) fn check_view_ids(ids: Vec) -> Result, ServerError> { let mut view_ids = vec![]; for id in ids { - let view_id = ViewId::parse(id).map_err(invalid_params)?; - let view_id = Uuid::parse_str(view_id.as_ref())?; - view_ids.push(view_id); + view_ids.push(check_view_id(id)?); } Ok(view_ids) } +pub(crate) fn check_view_id(id: String) -> Result { + let view_id = ViewId::parse(id).map_err(invalid_params)?; + let view_id = Uuid::parse_str(view_id.as_ref())?; + Ok(view_id) +} + #[derive(Debug, Clone, sqlx::FromRow)] pub struct ViewTable { pub(crate) id: uuid::Uuid, diff --git a/backend/src/services/core/view/router.rs b/backend/src/services/core/view/router.rs index 8828c2efa3..b4a3af7323 100644 --- a/backend/src/services/core/view/router.rs +++ b/backend/src/services/core/view/router.rs @@ -1,7 +1,13 @@ use crate::{ context::FlowyPersistence, entities::logged_user::LoggedUser, - services::core::view::{create_view, delete_view, persistence::check_view_ids, read_view, update_view}, + services::core::view::{ + create_view, + delete_view, + persistence::{check_view_id, check_view_ids}, + read_view, + update_view, + }, util::serde_ext::parse_from_payload, }; use actix_web::{ @@ -62,7 +68,7 @@ pub async fn read_handler(payload: Payload, pool: Data, user: LoggedUser pub async fn update_handler(payload: Payload, pool: Data) -> Result { let params: UpdateViewParams = parse_from_payload(payload).await?; - let view_id = check_view_ids(vec![params.view_id.clone()])?.pop().unwrap(); + let view_id = check_view_id(params.view_id.clone())?; let name = match params.has_name() { false => None, true => Some(ViewName::parse(params.get_name().to_owned()).map_err(invalid_params)?.0), diff --git a/backend/src/services/document/mod.rs b/backend/src/services/document/mod.rs index 6c2be46dff..b9d15fe4a6 100644 --- a/backend/src/services/document/mod.rs +++ b/backend/src/services/document/mod.rs @@ -1,6 +1,6 @@ #![allow(clippy::module_inception)] -pub(crate) mod persistence; +pub mod persistence; pub(crate) mod router; pub(crate) mod ws_actor; pub(crate) mod ws_receiver; diff --git a/backend/src/services/document/persistence.rs b/backend/src/services/document/persistence.rs index da4c28bd5a..8d217a3fb6 100644 --- a/backend/src/services/document/persistence.rs +++ b/backend/src/services/document/persistence.rs @@ -1,6 +1,5 @@ use crate::{ - context::FlowyPersistence, - services::kv::{KVStore, KVTransaction, KeyValue}, + services::kv::{KVStore, KeyValue}, util::serde_ext::parse_from_bytes, }; use anyhow::Context; @@ -16,7 +15,7 @@ use flowy_collaboration::protobuf::{ }; use lib_ot::{core::OperationTransformable, rich_text::RichTextDelta}; use protobuf::Message; -use sqlx::PgPool; + use std::sync::Arc; use uuid::Uuid; @@ -30,14 +29,12 @@ pub(crate) async fn create_document( Ok(()) } -#[tracing::instrument(level = "debug", skip(persistence), err)] -pub(crate) async fn read_document( - persistence: &Arc, +#[tracing::instrument(level = "debug", skip(kv_store), err)] +pub async fn read_document( + kv_store: &Arc, params: DocIdentifier, ) -> Result { let _ = Uuid::parse_str(¶ms.doc_id).context("Parse document id to uuid failed")?; - - let kv_store = persistence.kv_store(); let revisions = kv_store.batch_get_revisions(¶ms.doc_id, None).await?; make_doc_from_revisions(¶ms.doc_id, revisions) } diff --git a/backend/src/services/document/router.rs b/backend/src/services/document/router.rs index d453e3b69f..02b039d108 100644 --- a/backend/src/services/document/router.rs +++ b/backend/src/services/document/router.rs @@ -9,7 +9,7 @@ use actix_web::{ }; use backend_service::{errors::ServerError, response::FlowyResponse}; use flowy_collaboration::protobuf::{CreateDocParams, DocIdentifier, ResetDocumentParams}; -use sqlx::PgPool; + use std::sync::Arc; pub async fn create_document_handler( @@ -28,7 +28,8 @@ pub async fn read_document_handler( persistence: Data>, ) -> Result { let params: DocIdentifier = parse_from_payload(payload).await?; - let doc = read_document(persistence.get_ref(), params).await?; + let kv_store = persistence.kv_store(); + let doc = read_document(&kv_store, params).await?; let response = FlowyResponse::success().pb(doc)?; Ok(response.into()) } diff --git a/backend/src/services/document/ws_actor.rs b/backend/src/services/document/ws_actor.rs index 9eb42e6617..922547a410 100644 --- a/backend/src/services/document/ws_actor.rs +++ b/backend/src/services/document/ws_actor.rs @@ -85,23 +85,19 @@ impl DocumentWebSocketActor { persistence, }); - match self.handle_revision(user, document_client_data).await { - Ok(_) => {}, - Err(e) => { - tracing::error!("[DocumentWebSocketActor]: process client data error {:?}", e); - }, - } - Ok(()) - } - - async fn handle_revision(&self, user: Arc, client_data: DocumentClientWSData) -> Result<()> { - match &client_data.ty { + match &document_client_data.ty { DocumentClientWSDataType::ClientPushRev => { - let _ = self + match self .doc_manager - .apply_revisions(user, client_data) + .apply_revisions(user, document_client_data) .await - .map_err(internal_error)?; + .map_err(internal_error) + { + Ok(_) => {}, + Err(e) => { + tracing::error!("[DocumentWebSocketActor]: process client data failed: {:?}", e); + }, + } }, } diff --git a/backend/src/services/document/ws_receiver.rs b/backend/src/services/document/ws_receiver.rs index a534086844..50b8512a0b 100644 --- a/backend/src/services/document/ws_receiver.rs +++ b/backend/src/services/document/ws_receiver.rs @@ -16,7 +16,7 @@ use flowy_collaboration::{ errors::CollaborateError, protobuf::DocIdentifier, }; -use lib_infra::future::{BoxResultFuture, FutureResultSend}; +use lib_infra::future::BoxResultFuture; use flowy_collaboration::sync::{DocumentPersistence, ServerDocumentManager}; use std::{ @@ -83,7 +83,7 @@ impl DocumentPersistence for DocumentPersistenceImpl { doc_id: doc_id.to_string(), ..Default::default() }; - let persistence = self.0.clone(); + let persistence = self.0.kv_store(); Box::pin(async move { let mut pb_doc = read_document(&persistence, params) .await @@ -115,11 +115,9 @@ impl DocumentPersistence for DocumentPersistenceImpl { let kv_store = self.0.kv_store(); let doc_id = doc_id.to_owned(); let f = || async move { - let expected_len = rev_ids.len(); let mut pb = kv_store.batch_get_revisions(&doc_id, rev_ids).await?; let repeated_revision: RepeatedRevision = (&mut pb).try_into()?; let revisions = repeated_revision.into_inner(); - assert_eq!(expected_len, revisions.len()); Ok(revisions) }; diff --git a/backend/src/services/kv/kv.rs b/backend/src/services/kv/kv.rs index e0a9ed1ea6..4273fe8633 100644 --- a/backend/src/services/kv/kv.rs +++ b/backend/src/services/kv/kv.rs @@ -1,13 +1,13 @@ use crate::{ - services::kv::{KVStore, KVTransaction, KeyValue}, + services::kv::{KVTransaction, KeyValue}, util::sqlx_ext::{map_sqlx_error, DBTransaction, SqlBuilder}, }; use anyhow::Context; use async_trait::async_trait; use backend_service::errors::ServerError; use bytes::Bytes; -use futures_core::future::BoxFuture; -use lib_infra::future::{BoxResultFuture, FutureResultSend}; + +use lib_infra::future::BoxResultFuture; use sql_builder::SqlBuilder as RawSqlBuilder; use sqlx::{ postgres::{PgArguments, PgRow}, @@ -17,7 +17,6 @@ use sqlx::{ Postgres, Row, }; -use std::{future::Future, pin::Pin, sync::Arc}; const KV_TABLE: &str = "kv_table"; @@ -26,6 +25,33 @@ pub struct PostgresKV { } impl PostgresKV { + pub async fn get(&self, key: &str) -> Result, ServerError> { + let key = key.to_owned(); + self.transaction(|mut transaction| Box::pin(async move { transaction.get(&key).await })) + .await + } + pub async fn set(&self, key: &str, value: Bytes) -> Result<(), ServerError> { + let key = key.to_owned(); + self.transaction(|mut transaction| Box::pin(async move { transaction.set(&key, value).await })) + .await + } + + pub async fn remove(&self, key: &str) -> Result<(), ServerError> { + let key = key.to_owned(); + self.transaction(|mut transaction| Box::pin(async move { transaction.remove(&key).await })) + .await + } + + pub async fn batch_set(&self, kvs: Vec) -> Result<(), ServerError> { + self.transaction(|mut transaction| Box::pin(async move { transaction.batch_set(kvs).await })) + .await + } + + pub async fn batch_get(&self, keys: Vec) -> Result, ServerError> { + self.transaction(|mut transaction| Box::pin(async move { transaction.batch_get(keys).await })) + .await + } + pub async fn transaction(&self, f: F) -> Result where F: for<'a> FnOnce(Box) -> BoxResultFuture, @@ -61,14 +87,13 @@ impl<'a, 'b> KVTransaction for PostgresTransaction<'a, 'b> { .fetch_one(self.0 as &mut DBTransaction<'b>) .await; - let result = match result { + match result { Ok(val) => Ok(Some(Bytes::from(val.blob))), Err(error) => match error { Error::RowNotFound => Ok(None), _ => Err(map_sqlx_error(error)), }, - }; - result + } } async fn set(&mut self, key: &str, bytes: Bytes) -> Result<(), ServerError> { diff --git a/backend/src/services/kv/mod.rs b/backend/src/services/kv/mod.rs index aeaed6b26a..540e693ea1 100644 --- a/backend/src/services/kv/mod.rs +++ b/backend/src/services/kv/mod.rs @@ -3,12 +3,10 @@ mod kv; use async_trait::async_trait; use bytes::Bytes; -use futures_core::future::BoxFuture; + pub(crate) use kv::*; -use std::sync::Arc; use backend_service::errors::ServerError; -use lib_infra::future::{BoxResultFuture, FutureResultSend}; // TODO: Generic the KVStore that enable switching KVStore to another // implementation diff --git a/backend/tests/api_test/kv_test.rs b/backend/tests/api_test/kv_test.rs index bbde912bc0..302fd5681e 100644 --- a/backend/tests/api_test/kv_test.rs +++ b/backend/tests/api_test/kv_test.rs @@ -50,3 +50,30 @@ async fn kv_batch_set_test() { assert_eq!(kvs, kvs_from_db); } + +#[actix_rt::test] +async fn kv_batch_get_start_with_test() { + let server = spawn_server().await; + let kv = server.app_ctx.persistence.kv_store(); + let kvs = vec![ + KeyValue { + key: "abc:1".to_string(), + value: "a".to_string().into(), + }, + KeyValue { + key: "abc:2".to_string(), + value: "b".to_string().into(), + }, + ]; + + kv.batch_set(kvs.clone()).await.unwrap(); + kv.transaction(|mut transaction| { + Box::pin(async move { + let kvs_from_db = transaction.batch_get_start_with("abc").await.unwrap(); + assert_eq!(kvs, kvs_from_db); + Ok(()) + }) + }) + .await + .unwrap(); +} diff --git a/backend/tests/document_test/edit_script.rs b/backend/tests/document_test/edit_script.rs index 786e6c50d6..72b0dc709a 100644 --- a/backend/tests/document_test/edit_script.rs +++ b/backend/tests/document_test/edit_script.rs @@ -6,19 +6,22 @@ use flowy_document::services::doc::edit::ClientDocEditor as ClientEditDocContext use flowy_test::{helper::ViewTest, FlowySDKTest}; use flowy_user::services::user::UserSession; use futures_util::{stream, stream::StreamExt}; -use sqlx::PgPool; + use std::sync::Arc; +use bytes::Bytes; use tokio::time::{sleep, Duration}; // use crate::helper::*; use crate::util::helper::{spawn_server, TestServer}; use flowy_collaboration::{entities::doc::DocIdentifier, protobuf::ResetDocumentParams}; use lib_ot::rich_text::{RichTextAttribute, RichTextDelta}; use parking_lot::RwLock; -use flowy_collaboration::entities::revision::RepeatedRevision; +use backend::services::document::persistence::{DocumentKVPersistence, read_document, reset_document}; + +use flowy_collaboration::entities::revision::{RepeatedRevision, Revision, RevType}; use lib_ot::core::Interval; use flowy_net::services::ws::FlowyWSConnect; -use crate::util::helper::*; + pub struct DocumentTest { server: TestServer, @@ -32,7 +35,7 @@ pub enum DocScript { ClientOpenDoc, AssertClient(&'static str), AssertServer(&'static str, i64), - ServerSaveDocument(RepeatedRevision), // delta_json, rev_id + ServerSaveDocument(String, i64), // delta_json, rev_id } impl DocumentTest { @@ -78,10 +81,8 @@ impl ScriptContext { } async fn open_doc(&mut self) { - let flowy_document = self.client_sdk.flowy_document.clone(); let doc_id = self.doc_id.clone(); - - let edit_context = flowy_document.open(DocIdentifier { doc_id }).await.unwrap(); + let edit_context = self.client_sdk.document_ctx.open(DocIdentifier { doc_id }).await.unwrap(); self.client_edit_context = Some(edit_context); } @@ -106,6 +107,7 @@ async fn run_scripts(context: Arc>, scripts: Vec { + sleep(Duration::from_millis(2000)).await; context.read().client_edit_context().insert(index, s).await.unwrap(); }, DocScript::ClientFormatText(interval, attribute) => { @@ -123,24 +125,32 @@ async fn run_scripts(context: Arc>, scripts: Vec { sleep(Duration::from_millis(100)).await; + let persistence = Data::new(context.read().server.app_ctx.persistence.kv_store()); + let doc_identifier: flowy_collaboration::protobuf::DocIdentifier = DocIdentifier { + doc_id + }.try_into().unwrap(); - // let doc_identifier = DocIdentifier { - // doc_id - // }; - // - // let doc = context.read().server.read_doc() - - - // let pg_pool = context.read().server_pg_pool.clone(); - // let doc_manager = context.read().server_doc_manager.clone(); - // let edit_doc = doc_manager.get(&doc_id).await.unwrap(); - // let json = edit_doc.document_json().await.unwrap(); - // assert_eq(s, &json); - // assert_eq!(edit_doc.rev_id().await.unwrap(), rev_id); + let document_info = read_document(persistence.get_ref(), doc_identifier).await.unwrap(); + assert_eq(s, &document_info.text); + assert_eq!(document_info.rev_id, rev_id); }, - DocScript::ServerSaveDocument(repeated_revision) => { - let pg_pool = Data::new(context.read().server.pg_pool.clone()); - reset_doc(&doc_id, repeated_revision, pg_pool).await; + DocScript::ServerSaveDocument(document_json, rev_id) => { + let delta_data = Bytes::from(document_json); + let user_id = context.read().client_user_session.user_id().unwrap(); + let md5 = format!("{:x}", md5::compute(&delta_data)); + let base_rev_id = if rev_id == 0 { rev_id } else { rev_id - 1 }; + let revision = Revision::new( + &doc_id, + base_rev_id, + rev_id, + delta_data, + RevType::Remote, + &user_id, + md5, + ); + + let kv_store = Data::new(context.read().server.app_ctx.persistence.kv_store()); + reset_doc(&doc_id, RepeatedRevision::new(vec![revision]), kv_store.get_ref()).await; }, // DocScript::Sleep(sec) => { // sleep(Duration::from_secs(sec)).await; @@ -174,10 +184,10 @@ async fn create_doc(flowy_test: &FlowySDKTest) -> String { view_test.view.id } -async fn reset_doc(doc_id: &str, repeated_revision: RepeatedRevision, pool: Data) { +async fn reset_doc(doc_id: &str, repeated_revision: RepeatedRevision, kv_store: &Arc) { let pb: flowy_collaboration::protobuf::RepeatedRevision = repeated_revision.try_into().unwrap(); let mut params = ResetDocumentParams::new(); params.set_doc_id(doc_id.to_owned()); params.set_revisions(pb); - // let _ = reset_document_handler(pool.get_ref(), params).await.unwrap(); + let _ = reset_document(kv_store, params).await.unwrap(); } diff --git a/backend/tests/document_test/edit_test.rs b/backend/tests/document_test/edit_test.rs index b6404bb9cf..61a5ee473d 100644 --- a/backend/tests/document_test/edit_test.rs +++ b/backend/tests/document_test/edit_test.rs @@ -20,7 +20,6 @@ use lib_ot::{core::Interval, rich_text::RichTextAttribute}; async fn delta_sync_while_editing() { let test = DocumentTest::new().await; test.run_scripts(vec![ - DocScript::ClientConnectWS, DocScript::ClientOpenDoc, DocScript::ClientInsertText(0, "abc"), DocScript::ClientInsertText(3, "123"), @@ -34,7 +33,6 @@ async fn delta_sync_while_editing() { async fn delta_sync_multi_revs() { let test = DocumentTest::new().await; test.run_scripts(vec![ - DocScript::ClientConnectWS, DocScript::ClientOpenDoc, DocScript::ClientInsertText(0, "abc"), DocScript::ClientInsertText(3, "123"), @@ -81,6 +79,7 @@ async fn delta_sync_with_http_request() { let mut document = Document::new::(); document.insert(0, "123").unwrap(); document.insert(3, "456").unwrap(); + let json = document.to_json(); test.run_scripts(vec![ diff --git a/backend/tests/util/helper.rs b/backend/tests/util/helper.rs index 2863b46649..90945ecf14 100644 --- a/backend/tests/util/helper.rs +++ b/backend/tests/util/helper.rs @@ -1,5 +1,5 @@ use backend::{ - application::{get_connection_pool, init_app_context, Application}, + application::{init_app_context, Application}, config::{get_configuration, DatabaseSettings}, context::AppContext, }; @@ -9,10 +9,14 @@ use backend_service::{ user_request::*, workspace_request::*, }; -use flowy_collaboration::entities::doc::{CreateDocParams, DocIdentifier, DocumentInfo}; +use flowy_collaboration::{ + document::default::initial_delta_string, + entities::doc::{CreateDocParams, DocIdentifier, DocumentInfo}, +}; use flowy_core_data_model::entities::prelude::*; use flowy_document::services::server::{create_doc_request, read_doc_request}; use flowy_user_data_model::entities::*; +use lib_infra::uuid_string; use sqlx::{Connection, Executor, PgConnection, PgPool}; use uuid::Uuid; @@ -203,7 +207,6 @@ pub async fn spawn_user_server() -> TestUserServer { #[derive(Clone)] pub struct TestServer { - pub pg_pool: PgPool, pub app_ctx: AppContext, pub client_server_config: ClientServerConfiguration, } @@ -234,9 +237,6 @@ pub async fn spawn_server() -> TestServer { client_server_config.reset_host_with_port("localhost", application_port); TestServer { - pg_pool: get_connection_pool(&configuration.database) - .await - .expect("Failed to connect to the database"), app_ctx, client_server_config, } @@ -312,7 +312,15 @@ pub async fn create_test_view(application: &TestUserServer, app_id: &str) -> Vie let desc = "This is my first view".to_string(); let thumbnail = "http://1.png".to_string(); - let params = CreateViewParams::new(app_id.to_owned(), name, desc, ViewType::Doc, thumbnail); + let params = CreateViewParams::new( + app_id.to_owned(), + name, + desc, + ViewType::Doc, + thumbnail, + initial_delta_string(), + uuid_string(), + ); let app = application.create_view(params).await; app } diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-data-model/view_create.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-data-model/view_create.pb.dart index 0b5d710a25..cb4492bb12 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-data-model/view_create.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-data-model/view_create.pb.dart @@ -137,6 +137,8 @@ class CreateViewParams extends $pb.GeneratedMessage { ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc') ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewType', $pb.PbFieldType.OE, defaultOrMaker: ViewType.Blank, valueOf: ViewType.valueOf, enumValues: ViewType.values) + ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewData') + ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId') ..hasRequiredFields = false ; @@ -147,6 +149,8 @@ class CreateViewParams extends $pb.GeneratedMessage { $core.String? desc, $core.String? thumbnail, ViewType? viewType, + $core.String? viewData, + $core.String? viewId, }) { final _result = create(); if (belongToId != null) { @@ -164,6 +168,12 @@ class CreateViewParams extends $pb.GeneratedMessage { if (viewType != null) { _result.viewType = viewType; } + if (viewData != null) { + _result.viewData = viewData; + } + if (viewId != null) { + _result.viewId = viewId; + } return _result; } factory CreateViewParams.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -231,6 +241,24 @@ class CreateViewParams extends $pb.GeneratedMessage { $core.bool hasViewType() => $_has(4); @$pb.TagNumber(5) void clearViewType() => clearField(5); + + @$pb.TagNumber(6) + $core.String get viewData => $_getSZ(5); + @$pb.TagNumber(6) + set viewData($core.String v) { $_setString(5, v); } + @$pb.TagNumber(6) + $core.bool hasViewData() => $_has(5); + @$pb.TagNumber(6) + void clearViewData() => clearField(6); + + @$pb.TagNumber(7) + $core.String get viewId => $_getSZ(6); + @$pb.TagNumber(7) + set viewId($core.String v) { $_setString(6, v); } + @$pb.TagNumber(7) + $core.bool hasViewId() => $_has(6); + @$pb.TagNumber(7) + void clearViewId() => clearField(7); } class View extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-data-model/view_create.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-data-model/view_create.pbjson.dart index 44e92472f2..c6c4bc2ea8 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-data-model/view_create.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-core-data-model/view_create.pbjson.dart @@ -45,11 +45,13 @@ const CreateViewParams$json = const { const {'1': 'desc', '3': 3, '4': 1, '5': 9, '10': 'desc'}, const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '10': 'thumbnail'}, const {'1': 'view_type', '3': 5, '4': 1, '5': 14, '6': '.ViewType', '10': 'viewType'}, + const {'1': 'view_data', '3': 6, '4': 1, '5': 9, '10': 'viewData'}, + const {'1': 'view_id', '3': 7, '4': 1, '5': 9, '10': 'viewId'}, ], }; /// Descriptor for `CreateViewParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBl'); +final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSJgoJdmlld190eXBlGAUgASgOMgkuVmlld1R5cGVSCHZpZXdUeXBlEhsKCXZpZXdfZGF0YRgGIAEoCVIIdmlld0RhdGESFwoHdmlld19pZBgHIAEoCVIGdmlld0lk'); @$core.Deprecated('Use viewDescriptor instead') const View$json = const { '1': 'View', diff --git a/frontend/rust-lib/flowy-core/src/core/core_context.rs b/frontend/rust-lib/flowy-core/src/core/core_context.rs index e38aabd963..7b283ea349 100644 --- a/frontend/rust-lib/flowy-core/src/core/core_context.rs +++ b/frontend/rust-lib/flowy-core/src/core/core_context.rs @@ -4,8 +4,8 @@ use chrono::Utc; use lazy_static::lazy_static; use parking_lot::RwLock; -use flowy_collaboration::{document::default::initial_read_me, entities::doc::DocumentDelta}; -use flowy_core_data_model::user_default; +use flowy_collaboration::document::default::{initial_delta, initial_read_me}; +use flowy_core_data_model::{entities::view::CreateViewParams, user_default}; use flowy_net::entities::NetworkType; use crate::{ @@ -85,24 +85,28 @@ impl CoreContext { let apps = workspace.take_apps().into_inner(); let cloned_workspace = workspace.clone(); - let _ = self.workspace_controller.create_workspace(workspace).await?; + let _ = self.workspace_controller.create_workspace_on_local(workspace).await?; for mut app in apps { + let app_id = app.id.clone(); let views = app.take_belongings().into_inner(); - let _ = self.app_controller.create_app(app).await?; + let _ = self.app_controller.create_app_on_local(app).await?; for (index, view) in views.into_iter().enumerate() { - if index == 0 { - let delta = initial_read_me(); - let doc_delta = DocumentDelta { - doc_id: view.id.clone(), - text: delta.to_json(), - }; - let _ = self.view_controller.apply_doc_delta(doc_delta).await?; - self.view_controller.set_latest_view(&view); - - // Close the view after initialize - self.view_controller.close_view(view.id.clone().into()).await?; - } - let _ = self.view_controller.create_view(view).await?; + let view_data = if index == 0 { + initial_read_me().to_json() + } else { + initial_delta().to_json() + }; + self.view_controller.set_latest_view(&view); + let params = CreateViewParams { + belong_to_id: app_id.clone(), + name: view.name, + desc: view.desc, + thumbnail: "".to_string(), + view_type: view.view_type, + view_data, + view_id: view.id.clone(), + }; + let _ = self.view_controller.create_view_from_params(params).await?; } } diff --git a/frontend/rust-lib/flowy-core/src/services/app/controller.rs b/frontend/rust-lib/flowy-core/src/services/app/controller.rs index 97065ba8d0..b2c11352b1 100644 --- a/frontend/rust-lib/flowy-core/src/services/app/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/controller.rs @@ -40,17 +40,17 @@ impl AppController { } pub fn init(&self) -> Result<(), FlowyError> { - self.listen_trash_can_event(); + self.listen_trash_controller_event(); Ok(()) } #[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name) err)] pub(crate) async fn create_app_from_params(&self, params: CreateAppParams) -> Result { let app = self.create_app_on_server(params).await?; - self.create_app(app).await + self.create_app_on_local(app).await } - pub(crate) async fn create_app(&self, app: App) -> Result { + pub(crate) async fn create_app_on_local(&self, app: App) -> Result { let conn = &*self.database.db_connection()?; conn.immediate_transaction::<_, FlowyError, _>(|| { let _ = self.save_app(app.clone(), &*conn)?; @@ -71,7 +71,7 @@ impl AppController { let conn = self.database.db_connection()?; let app_table = AppTableSql::read_app(¶ms.app_id, &*conn)?; - let trash_ids = self.trash_can.trash_ids(&conn)?; + let trash_ids = self.trash_can.read_trash_ids(&conn)?; if trash_ids.contains(&app_table.id) { return Err(FlowyError::record_not_found()); } @@ -165,7 +165,7 @@ impl AppController { Ok(()) } - fn listen_trash_can_event(&self) { + fn listen_trash_controller_event(&self) { let mut rx = self.trash_can.subscribe(); let database = self.database.clone(); let trash_can = self.trash_can.clone(); @@ -245,56 +245,9 @@ pub fn read_local_workspace_apps( conn: &SqliteConnection, ) -> Result { let mut app_tables = AppTableSql::read_workspace_apps(workspace_id, false, conn)?; - let trash_ids = trash_controller.trash_ids(conn)?; + let trash_ids = trash_controller.read_trash_ids(conn)?; app_tables.retain(|app_table| !trash_ids.contains(&app_table.id)); let apps = app_tables.into_iter().map(|table| table.into()).collect::>(); Ok(RepeatedApp { items: apps }) } - -// #[tracing::instrument(level = "debug", skip(self), err)] -// pub(crate) async fn delete_app(&self, app_id: &str) -> Result<(), -// FlowyError> { let conn = &*self.database.db_connection()?; -// conn.immediate_transaction::<_, FlowyError, _>(|| { -// let app = AppTableSql::delete_app(app_id, &*conn)?; -// let apps = self.read_local_apps(&app.workspace_id, &*conn)?; -// send_dart_notification(&app.workspace_id, -// WorkspaceNotification::WorkspaceDeleteApp) .payload(apps) -// .send(); -// Ok(()) -// })?; -// -// let _ = self.delete_app_on_server(app_id); -// Ok(()) -// } -// -// #[tracing::instrument(level = "debug", skip(self), err)] -// fn delete_app_on_server(&self, app_id: &str) -> Result<(), FlowyError> { -// let token = self.user.token()?; -// let server = self.server.clone(); -// let params = DeleteAppParams { -// app_id: app_id.to_string(), -// }; -// spawn(async move { -// match server.delete_app(&token, params).await { -// Ok(_) => {}, -// Err(e) => { -// // TODO: retry? -// log::error!("Delete app failed: {:?}", e); -// }, -// } -// }); -// // let action = RetryAction::new(self.server.clone(), self.user.clone(), -// move // |token, server| { let params = params.clone(); -// // async move { -// // match server.delete_app(&token, params).await { -// // Ok(_) => {}, -// // Err(e) => log::error!("Delete app failed: {:?}", e), -// // } -// // Ok::<(), FlowyError>(()) -// // } -// // }); -// // -// // spawn_retry(500, 3, action); -// Ok(()) -// } diff --git a/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs index 5c9cc6f78d..de88bc6fd0 100644 --- a/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/app/event_handler.rs @@ -29,17 +29,17 @@ pub(crate) async fn create_app_handler( pub(crate) async fn delete_app_handler( data: Data, - controller: Unit>, - trash_can: Unit>, + view_controller: Unit>, + trash_controller: Unit>, ) -> Result<(), FlowyError> { let params: AppIdentifier = data.into_inner().try_into()?; - let trash = controller + let trash = view_controller .read_app_tables(vec![params.app_id])? .into_iter() .map(|view_table| view_table.into()) .collect::>(); - let _ = trash_can.add(trash).await?; + let _ = trash_controller.add(trash).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs index dabc9dd055..791d1ae6c3 100644 --- a/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-core/src/services/server/server_api_mock.rs @@ -8,7 +8,7 @@ use crate::{ errors::FlowyError, services::server::WorkspaceServerAPI, }; -use lib_infra::{future::FutureResult, timestamp, uuid}; +use lib_infra::{future::FutureResult, timestamp, uuid_string}; pub struct WorkspaceServerMock {} @@ -18,7 +18,7 @@ impl WorkspaceServerAPI for WorkspaceServerMock { fn create_workspace(&self, _token: &str, params: CreateWorkspaceParams) -> FutureResult { let time = timestamp(); let workspace = Workspace { - id: uuid(), + id: uuid_string(), name: params.name, desc: params.desc, apps: RepeatedApp::default(), @@ -51,7 +51,7 @@ impl WorkspaceServerAPI for WorkspaceServerMock { fn create_view(&self, _token: &str, params: CreateViewParams) -> FutureResult { let time = timestamp(); let view = View { - id: uuid(), + id: uuid_string(), belong_to_id: params.belong_to_id, name: params.name, desc: params.desc, @@ -79,7 +79,7 @@ impl WorkspaceServerAPI for WorkspaceServerMock { fn create_app(&self, _token: &str, params: CreateAppParams) -> FutureResult { let time = timestamp(); let app = App { - id: uuid(), + id: uuid_string(), workspace_id: params.workspace_id, name: params.name, desc: params.desc, diff --git a/frontend/rust-lib/flowy-core/src/services/trash/controller.rs b/frontend/rust-lib/flowy-core/src/services/trash/controller.rs index b878baac59..0a1a0cab50 100644 --- a/frontend/rust-lib/flowy-core/src/services/trash/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/trash/controller.rs @@ -182,7 +182,7 @@ impl TrashController { Ok(repeated_trash) } - pub fn trash_ids(&self, conn: &SqliteConnection) -> Result, FlowyError> { + pub fn read_trash_ids(&self, conn: &SqliteConnection) -> Result, FlowyError> { let ids = TrashTableSql::read_all(&*conn)? .into_inner() .into_iter() diff --git a/frontend/rust-lib/flowy-core/src/services/view/controller.rs b/frontend/rust-lib/flowy-core/src/services/view/controller.rs index 675925d6d1..6b7172ab63 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/controller.rs @@ -21,6 +21,7 @@ use crate::{ use flowy_core_data_model::entities::share::{ExportData, ExportParams}; use flowy_database::kv::KV; use flowy_document::context::DocumentContext; +use lib_infra::uuid_string; const LATEST_VIEW_ID: &str = "latest_view_id"; @@ -57,11 +58,11 @@ impl ViewController { #[tracing::instrument(level = "debug", skip(self, params), fields(name = %params.name), err)] pub(crate) async fn create_view_from_params(&self, params: CreateViewParams) -> Result { - let view = self.create_view_on_server(params.clone()).await?; - self.create_view(view).await + let view = self.create_view_on_server(params).await?; + self.create_view_on_local(view).await } - pub(crate) async fn create_view(&self, view: View) -> Result { + pub(crate) async fn create_view_on_local(&self, view: View) -> Result { let conn = &*self.database.db_connection()?; let trash_can = self.trash_can.clone(); @@ -86,7 +87,7 @@ impl ViewController { let conn = self.database.db_connection()?; let view_table = ViewTableSql::read_view(¶ms.view_id, &*conn)?; - let trash_ids = self.trash_can.trash_ids(&conn)?; + let trash_ids = self.trash_can.read_trash_ids(&conn)?; if trash_ids.contains(&view_table.id) { return Err(FlowyError::record_not_found()); } @@ -120,7 +121,7 @@ impl ViewController { #[tracing::instrument(level = "debug", skip(self,params), fields(doc_id = %params.doc_id), err)] pub(crate) async fn close_view(&self, params: DocIdentifier) -> Result<(), FlowyError> { - let _ = self.document_ctx.close(params).await?; + let _ = self.document_ctx.doc_ctrl.close(¶ms.doc_id)?; Ok(()) } @@ -131,14 +132,14 @@ impl ViewController { let _ = KV::remove(LATEST_VIEW_ID); } } - let _ = self.document_ctx.close(params).await?; + let _ = self.document_ctx.doc_ctrl.close(¶ms.doc_id)?; Ok(()) } #[tracing::instrument(level = "debug", skip(self, params), fields(doc_id = %params.doc_id), err)] pub(crate) async fn duplicate_view(&self, params: DocIdentifier) -> Result<(), FlowyError> { let view: View = ViewTableSql::read_view(¶ms.doc_id, &*self.database.db_connection()?)?.into(); - let _delta_data = self + let delta_data = self .document_ctx .read_document_data(params, self.database.db_pool()?) .await?; @@ -149,6 +150,8 @@ impl ViewController { desc: view.desc.clone(), thumbnail: "".to_owned(), view_type: view.view_type.clone(), + view_data: delta_data.text, + view_id: uuid_string(), }; let _ = self.create_view_from_params(duplicate_params).await?; @@ -174,7 +177,7 @@ impl ViewController { pub(crate) async fn read_views_belong_to(&self, belong_to_id: &str) -> Result { // TODO: read from server let conn = self.database.db_connection()?; - let repeated_view = read_local_belonging_view(belong_to_id, self.trash_can.clone(), &conn)?; + let repeated_view = read_belonging_views_on_local(belong_to_id, self.trash_can.clone(), &conn)?; Ok(repeated_view) } @@ -195,13 +198,13 @@ impl ViewController { // let _ = notify_views_changed(&updated_view.belong_to_id, self.trash_can.clone(), conn)?; - let _ = self.update_view_on_server(params); Ok(updated_view) } pub(crate) async fn apply_doc_delta(&self, params: DocumentDelta) -> Result { - let doc = self.document_ctx.apply_doc_delta(params).await?; + let db_pool = self.document_ctx.user.db_pool()?; + let doc = self.document_ctx.doc_ctrl.apply_local_delta(params, db_pool).await?; Ok(doc) } @@ -308,7 +311,7 @@ async fn handle_trash_event( TrashEvent::NewTrash(identifiers, ret) => { let result = || { let conn = &*db_result?; - let view_tables = get_view_table_from(identifiers, conn)?; + let view_tables = read_view_tables(identifiers, conn)?; for view_table in view_tables { let _ = notify_views_changed(&view_table.belong_to_id, trash_can.clone(), conn)?; notify_dart(view_table, WorkspaceNotification::ViewDeleted); @@ -320,7 +323,7 @@ async fn handle_trash_event( TrashEvent::Putback(identifiers, ret) => { let result = || { let conn = &*db_result?; - let view_tables = get_view_table_from(identifiers, conn)?; + let view_tables = read_view_tables(identifiers, conn)?; for view_table in view_tables { let _ = notify_views_changed(&view_table.belong_to_id, trash_can.clone(), conn)?; notify_dart(view_table, WorkspaceNotification::ViewRestored); @@ -337,7 +340,7 @@ async fn handle_trash_event( for identifier in identifiers.items { let view_table = ViewTableSql::read_view(&identifier.id, conn)?; let _ = ViewTableSql::delete_view(&identifier.id, conn)?; - let _ = context.delete(identifier.id.clone().into())?; + let _ = context.doc_ctrl.delete(identifier.id.clone().into())?; notify_ids.insert(view_table.belong_to_id); } @@ -354,7 +357,7 @@ async fn handle_trash_event( } } -fn get_view_table_from(identifiers: TrashIdentifiers, conn: &SqliteConnection) -> Result, FlowyError> { +fn read_view_tables(identifiers: TrashIdentifiers, conn: &SqliteConnection) -> Result, FlowyError> { let mut view_tables = vec![]; let _ = conn.immediate_transaction::<_, FlowyError, _>(|| { for identifier in identifiers.items { @@ -377,7 +380,7 @@ fn notify_views_changed( trash_can: Arc, conn: &SqliteConnection, ) -> FlowyResult<()> { - let repeated_view = read_local_belonging_view(belong_to_id, trash_can.clone(), conn)?; + let repeated_view = read_belonging_views_on_local(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) .payload(repeated_view) @@ -385,13 +388,13 @@ fn notify_views_changed( Ok(()) } -fn read_local_belonging_view( +fn read_belonging_views_on_local( belong_to_id: &str, - trash_can: Arc, + trash_controller: Arc, conn: &SqliteConnection, ) -> FlowyResult { let mut view_tables = ViewTableSql::read_views(belong_to_id, conn)?; - let trash_ids = trash_can.trash_ids(conn)?; + let trash_ids = trash_controller.read_trash_ids(conn)?; view_tables.retain(|view_table| !trash_ids.contains(&view_table.id)); let views = view_tables diff --git a/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs index c0b27e252d..728339559d 100644 --- a/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs +++ b/frontend/rust-lib/flowy-core/src/services/view/event_handler.rs @@ -62,21 +62,21 @@ pub(crate) async fn apply_doc_delta_handler( pub(crate) async fn delete_view_handler( data: Data, - controller: Unit>, - trash_can: Unit>, + view_controller: Unit>, + trash_controller: Unit>, ) -> Result<(), FlowyError> { let params: ViewIdentifiers = data.into_inner().try_into()?; for view_id in ¶ms.view_ids { - let _ = controller.delete_view(view_id.into()).await; + let _ = view_controller.delete_view(view_id.into()).await; } - let trash = controller + let trash = view_controller .read_view_tables(params.view_ids)? .into_iter() .map(|view_table| view_table.into()) .collect::>(); - let _ = trash_can.add(trash).await?; + let _ = trash_controller.add(trash).await?; Ok(()) } diff --git a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs index aed992d7e8..f6af462033 100644 --- a/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs +++ b/frontend/rust-lib/flowy-core/src/services/workspace/controller.rs @@ -42,10 +42,10 @@ impl WorkspaceController { params: CreateWorkspaceParams, ) -> Result { let workspace = self.create_workspace_on_server(params.clone()).await?; - self.create_workspace(workspace).await + self.create_workspace_on_local(workspace).await } - pub(crate) async fn create_workspace(&self, workspace: Workspace) -> Result { + pub(crate) async fn create_workspace_on_local(&self, workspace: Workspace) -> Result { let user_id = self.user.user_id()?; let token = self.user.token()?; let workspace_table = WorkspaceTable::new(workspace.clone(), &user_id); diff --git a/frontend/rust-lib/flowy-document/src/context.rs b/frontend/rust-lib/flowy-document/src/context.rs index 07a1570958..5d5a462d72 100644 --- a/frontend/rust-lib/flowy-document/src/context.rs +++ b/frontend/rust-lib/flowy-document/src/context.rs @@ -19,8 +19,8 @@ pub trait DocumentUser: Send + Sync { } pub struct DocumentContext { - doc_ctrl: Arc, - user: Arc, + pub doc_ctrl: Arc, + pub user: Arc, } impl DocumentContext { @@ -40,21 +40,11 @@ impl DocumentContext { Ok(()) } - pub fn delete(&self, params: DocIdentifier) -> Result<(), FlowyError> { - let _ = self.doc_ctrl.delete(params)?; - Ok(()) - } - pub async fn open(&self, params: DocIdentifier) -> Result, FlowyError> { let edit_context = self.doc_ctrl.open(params, self.user.db_pool()?).await?; Ok(edit_context) } - pub async fn close(&self, params: DocIdentifier) -> Result<(), FlowyError> { - let _ = self.doc_ctrl.close(¶ms.doc_id)?; - Ok(()) - } - pub async fn read_document_data( &self, params: DocIdentifier, @@ -64,14 +54,4 @@ impl DocumentContext { let delta = edit_context.delta().await?; Ok(delta) } - - pub async fn apply_doc_delta(&self, params: DocumentDelta) -> Result { - // workaround: compare the rust's delta with flutter's delta. Will be removed - // very soon - let doc = self - .doc_ctrl - .apply_local_delta(params.clone(), self.user.db_pool()?) - .await?; - Ok(doc) - } } diff --git a/frontend/rust-lib/flowy-document/src/services/controller.rs b/frontend/rust-lib/flowy-document/src/services/controller.rs index bf60a44d7d..1f0bb704d6 100644 --- a/frontend/rust-lib/flowy-document/src/services/controller.rs +++ b/frontend/rust-lib/flowy-document/src/services/controller.rs @@ -20,7 +20,7 @@ use flowy_error::FlowyResult; use lib_infra::future::FutureResult; use std::sync::Arc; -pub(crate) struct DocController { +pub struct DocController { server: Server, ws_receivers: Arc, ws_sender: Arc, @@ -52,7 +52,7 @@ impl DocController { Ok(()) } - pub(crate) async fn open( + pub async fn open( &self, params: DocIdentifier, pool: Arc, @@ -66,7 +66,7 @@ impl DocController { Ok(edit_doc_ctx) } - pub(crate) fn close(&self, doc_id: &str) -> Result<(), FlowyError> { + pub fn close(&self, doc_id: &str) -> Result<(), FlowyError> { tracing::debug!("Close document {}", doc_id); self.open_cache.remove(doc_id); self.ws_receivers.remove_receiver(doc_id); @@ -74,7 +74,7 @@ impl DocController { } #[tracing::instrument(level = "debug", skip(self), err)] - pub(crate) fn delete(&self, params: DocIdentifier) -> Result<(), FlowyError> { + pub fn delete(&self, params: DocIdentifier) -> Result<(), FlowyError> { let doc_id = ¶ms.doc_id; self.open_cache.remove(doc_id); self.ws_receivers.remove_receiver(doc_id); @@ -86,7 +86,7 @@ impl DocController { // json : {"retain":7,"attributes":{"bold":null}} // deserialize delta: [ {retain: 7, attributes: {Bold: AttributeValue(None)}} ] #[tracing::instrument(level = "debug", skip(self, delta, db_pool), fields(doc_id = %delta.doc_id), err)] - pub(crate) async fn apply_local_delta( + pub async fn apply_local_delta( &self, delta: DocumentDelta, db_pool: Arc, diff --git a/frontend/rust-lib/flowy-sdk/src/lib.rs b/frontend/rust-lib/flowy-sdk/src/lib.rs index ab66f71612..1d0a3228a6 100644 --- a/frontend/rust-lib/flowy-sdk/src/lib.rs +++ b/frontend/rust-lib/flowy-sdk/src/lib.rs @@ -70,7 +70,7 @@ pub struct FlowySDK { #[allow(dead_code)] config: FlowySDKConfig, pub user_session: Arc, - pub flowy_document: Arc, + pub document_ctx: Arc, pub core: Arc, pub dispatcher: Arc, pub ws_manager: Arc, @@ -101,7 +101,7 @@ impl FlowySDK { Self { config, user_session, - flowy_document, + document_ctx: flowy_document, core: core_ctx, dispatcher, ws_manager, diff --git a/frontend/rust-lib/flowy-test/src/doc_script.rs b/frontend/rust-lib/flowy-test/src/doc_script.rs index c9757ff92b..681dba3dc3 100644 --- a/frontend/rust-lib/flowy-test/src/doc_script.rs +++ b/frontend/rust-lib/flowy-test/src/doc_script.rs @@ -31,7 +31,7 @@ impl EditorTest { let _ = sdk.init_user().await; let test = ViewTest::new(&sdk).await; let doc_identifier: DocIdentifier = test.view.id.clone().into(); - let editor = sdk.flowy_document.open(doc_identifier).await.unwrap(); + let editor = sdk.document_ctx.open(doc_identifier).await.unwrap(); Self { sdk, editor } } diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index 30e31280bf..0862ae49c7 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -17,7 +17,7 @@ use flowy_user::{ event::UserEvent::{InitUser, SignIn, SignOut, SignUp}, }; use lib_dispatch::prelude::{EventDispatcher, ModuleRequest, ToBytes}; -use lib_infra::uuid; +use lib_infra::uuid_string; use crate::prelude::*; @@ -293,7 +293,7 @@ pub fn root_dir() -> String { root_dir } -pub fn random_email() -> String { format!("{}@appflowy.io", uuid()) } +pub fn random_email() -> String { format!("{}@appflowy.io", uuid_string()) } pub fn login_email() -> String { "annie2@appflowy.io".to_string() } diff --git a/frontend/rust-lib/flowy-test/src/lib.rs b/frontend/rust-lib/flowy-test/src/lib.rs index 40e96d8519..44514e01ab 100644 --- a/frontend/rust-lib/flowy-test/src/lib.rs +++ b/frontend/rust-lib/flowy-test/src/lib.rs @@ -6,7 +6,7 @@ use crate::helper::*; use backend_service::configuration::{get_client_server_configuration, ClientServerConfiguration}; use flowy_sdk::{FlowySDK, FlowySDKConfig}; use flowy_user::entities::UserProfile; -use lib_infra::uuid; +use lib_infra::uuid_string; pub mod prelude { pub use crate::{event_builder::*, helper::*, *}; @@ -31,7 +31,7 @@ impl FlowySDKTest { } pub fn setup_with(server_config: ClientServerConfiguration) -> Self { - let config = FlowySDKConfig::new(&root_dir(), server_config, &uuid()).log_filter("debug"); + let config = FlowySDKConfig::new(&root_dir(), server_config, &uuid_string()).log_filter("debug"); let sdk = FlowySDK::new(config); Self(sdk) } diff --git a/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs b/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs index ae8c68da47..bace6bc616 100644 --- a/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs +++ b/frontend/rust-lib/flowy-user/src/services/server/server_api_mock.rs @@ -4,7 +4,7 @@ use crate::{ }; use crate::services::server::UserServerAPI; -use lib_infra::{future::FutureResult, uuid}; +use lib_infra::{future::FutureResult, uuid_string}; pub struct UserServerMock {} @@ -12,7 +12,7 @@ impl UserServerMock {} impl UserServerAPI for UserServerMock { fn sign_up(&self, params: SignUpParams) -> FutureResult { - let uid = uuid(); + let uid = uuid_string(); FutureResult::new(async move { Ok(SignUpResponse { user_id: uid.clone(), @@ -24,7 +24,7 @@ impl UserServerAPI for UserServerMock { } fn sign_in(&self, params: SignInParams) -> FutureResult { - let user_id = uuid(); + let user_id = uuid_string(); FutureResult::new(async { Ok(SignInResponse { user_id: user_id.clone(), diff --git a/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs b/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs index e3c2a4de09..15923b0125 100644 --- a/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs +++ b/frontend/rust-lib/flowy-user/tests/event/user_profile_test.rs @@ -1,7 +1,7 @@ use crate::helper::*; use flowy_test::{event_builder::UserModuleEventBuilder, FlowySDKTest}; use flowy_user::{errors::ErrorCode, event::UserEvent::*, prelude::*}; -use lib_infra::uuid; +use lib_infra::uuid_string; use serial_test::*; #[tokio::test] @@ -53,7 +53,7 @@ async fn user_update_with_name() { async fn user_update_with_email() { let sdk = FlowySDKTest::setup(); let user = sdk.init_user().await; - let new_email = format!("{}@gmail.com", uuid()); + let new_email = format!("{}@gmail.com", uuid_string()); let request = UpdateUserRequest::new(&user.id).email(&new_email); let _ = UserModuleEventBuilder::new(sdk.clone()) .event(UpdateUser) diff --git a/frontend/rust-lib/flowy-virtual-net/src/mock/server.rs b/frontend/rust-lib/flowy-virtual-net/src/mock/server.rs index 8c2277d832..118225ee19 100644 --- a/frontend/rust-lib/flowy-virtual-net/src/mock/server.rs +++ b/frontend/rust-lib/flowy-virtual-net/src/mock/server.rs @@ -2,7 +2,7 @@ use bytes::Bytes; use dashmap::DashMap; use flowy_collaboration::{entities::prelude::*, errors::CollaborateError, sync::*}; // use flowy_net::services::ws::*; -use lib_infra::future::{BoxResultFuture, FutureResultSend}; +use lib_infra::future::BoxResultFuture; use lib_ws::{WSModule, WebSocketRawMessage}; use std::{ convert::TryInto, diff --git a/shared-lib/backend-service/src/configuration.rs b/shared-lib/backend-service/src/configuration.rs index 0c25f86c56..0840dca19c 100644 --- a/shared-lib/backend-service/src/configuration.rs +++ b/shared-lib/backend-service/src/configuration.rs @@ -54,7 +54,7 @@ impl ClientServerConfiguration { pub fn view_url(&self) -> String { format!("{}/api/view", self.base_url()) } - pub fn doc_url(&self) -> String { format!("{}/api/document", self.base_url()) } + pub fn doc_url(&self) -> String { format!("{}/api/doc", self.base_url()) } pub fn trash_url(&self) -> String { format!("{}/api/trash", self.base_url()) } diff --git a/shared-lib/flowy-collaboration/src/entities/doc.rs b/shared-lib/flowy-collaboration/src/entities/doc.rs index 1665d04e1d..9ce484529b 100644 --- a/shared-lib/flowy-collaboration/src/entities/doc.rs +++ b/shared-lib/flowy-collaboration/src/entities/doc.rs @@ -1,6 +1,6 @@ use crate::{ entities::revision::{RepeatedRevision, Revision}, - errors::{internal_error, CollaborateError}, + errors::CollaborateError, }; use flowy_derive::ProtoBuf; use lib_ot::{core::OperationTransformable, errors::OTError, rich_text::RichTextDelta}; @@ -43,8 +43,11 @@ impl DocumentInfo { for revision in revisions { base_rev_id = revision.base_rev_id; rev_id = revision.rev_id; - let delta = RichTextDelta::from_bytes(revision.delta_data).map_err(internal_error)?; - document_delta = document_delta.compose(&delta).map_err(internal_error)?; + let delta = RichTextDelta::from_bytes(revision.delta_data) + .map_err(|e| CollaborateError::internal().context(format!("Parser revision failed. {:?}", e)))?; + document_delta = document_delta + .compose(&delta) + .map_err(|e| CollaborateError::internal().context(format!("Compose delta failed. {:?}", e)))?; } let text = document_delta.to_json(); diff --git a/shared-lib/flowy-collaboration/src/entities/revision.rs b/shared-lib/flowy-collaboration/src/entities/revision.rs index 74ba24345d..30089acd32 100644 --- a/shared-lib/flowy-collaboration/src/entities/revision.rs +++ b/shared-lib/flowy-collaboration/src/entities/revision.rs @@ -1,4 +1,3 @@ -use crate::document::default::initial_delta; use bytes::Bytes; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use lib_ot::rich_text::RichTextDelta; @@ -43,12 +42,6 @@ impl Revision { #[allow(dead_code)] pub fn is_initial(&self) -> bool { self.rev_id == 0 } - pub fn initial_revision(user_id: &str, doc_id: &str, ty: RevType) -> Self { - let delta_data = initial_delta().to_bytes(); - let md5 = format!("{:x}", md5::compute(&delta_data)); - Revision::new(doc_id, 0, 0, delta_data, ty, user_id, md5) - } - pub fn new( doc_id: &str, base_rev_id: i64, diff --git a/shared-lib/flowy-collaboration/src/sync/server.rs b/shared-lib/flowy-collaboration/src/sync/server.rs index 24d253e09e..79fc1afcf4 100644 --- a/shared-lib/flowy-collaboration/src/sync/server.rs +++ b/shared-lib/flowy-collaboration/src/sync/server.rs @@ -12,7 +12,7 @@ use crate::{ use async_stream::stream; use dashmap::DashMap; use futures::stream::StreamExt; -use lib_infra::future::{BoxResultFuture, FutureResultSend}; +use lib_infra::future::BoxResultFuture; use lib_ot::rich_text::RichTextDelta; use std::{convert::TryFrom, fmt::Debug, sync::Arc}; use tokio::{ @@ -62,14 +62,13 @@ impl ServerDocumentManager { let result = match self.get_document_handler(&doc_id).await { None => { - let _ = self.create_document(&doc_id, revisions).await.map_err(internal_error)?; + let _ = self.create_document(&doc_id, revisions).await.map_err(|e| { + CollaborateError::internal().context(format!("Server crate document failed: {}", e)) + })?; Ok(()) }, Some(handler) => { - let _ = handler - .apply_revisions(doc_id.clone(), user, revisions) - .await - .map_err(internal_error)?; + let _ = handler.apply_revisions(doc_id.clone(), user, revisions).await?; Ok(()) }, }; @@ -102,6 +101,7 @@ impl ServerDocumentManager { } } + #[tracing::instrument(level = "debug", skip(self, revisions), err)] async fn create_document( &self, doc_id: &str, @@ -117,7 +117,7 @@ impl ServerDocumentManager { let persistence = self.persistence.clone(); let handle = spawn_blocking(|| OpenDocHandle::new(doc, persistence)) .await - .map_err(internal_error)?; + .map_err(|e| CollaborateError::internal().context(format!("Create open doc handler failed: {}", e)))?; let handle = Arc::new(handle?); self.open_doc_map.insert(doc_id, handle.clone()); Ok(handle) @@ -125,6 +125,7 @@ impl ServerDocumentManager { } struct OpenDocHandle { + doc_id: String, sender: mpsc::Sender, persistence: Arc, users: DashMap>, @@ -132,17 +133,20 @@ struct OpenDocHandle { impl OpenDocHandle { fn new(doc: DocumentInfo, persistence: Arc) -> Result { + let doc_id = doc.doc_id.clone(); let (sender, receiver) = mpsc::channel(100); let users = DashMap::new(); let queue = DocumentCommandQueue::new(receiver, doc)?; tokio::task::spawn(queue.run()); Ok(Self { + doc_id, sender, persistence, users, }) } + #[tracing::instrument(level = "debug", skip(self, user, revisions), err)] async fn apply_revisions( &self, doc_id: String, @@ -159,18 +163,28 @@ impl OpenDocHandle { persistence, ret, }; + let _ = self.send(msg, rx).await?; Ok(()) } async fn send(&self, msg: DocumentCommand, rx: oneshot::Receiver) -> CollaborateResult { - let _ = self.sender.send(msg).await.map_err(internal_error)?; - let result = rx.await.map_err(internal_error)?; - Ok(result) + let _ = self + .sender + .send(msg) + .await + .map_err(|e| CollaborateError::internal().context(format!("Send document command failed: {}", e)))?; + Ok(rx.await.map_err(internal_error)?) } } -#[derive(Debug)] +impl std::ops::Drop for OpenDocHandle { + fn drop(&mut self) { + log::debug!("{} OpenDocHandle drop", self.doc_id); + } +} + +// #[derive(Debug)] enum DocumentCommand { ApplyRevisions { doc_id: String, @@ -229,12 +243,20 @@ impl DocumentCommandQueue { persistence, ret, } => { - self.synchronizer - .apply_revisions(doc_id, user, revisions, persistence) + let result = self + .synchronizer + .sync_revisions(doc_id, user, revisions, persistence) .await - .unwrap(); - let _ = ret.send(Ok(())); + .map_err(internal_error); + log::debug!("handle message {:?}", result); + let _ = ret.send(result); }, } } } + +impl std::ops::Drop for DocumentCommandQueue { + fn drop(&mut self) { + log::debug!("{} DocumentCommandQueue drop", self.doc_id); + } +} diff --git a/shared-lib/flowy-collaboration/src/sync/synchronizer.rs b/shared-lib/flowy-collaboration/src/sync/synchronizer.rs index 8199badae9..26af79d52e 100644 --- a/shared-lib/flowy-collaboration/src/sync/synchronizer.rs +++ b/shared-lib/flowy-collaboration/src/sync/synchronizer.rs @@ -4,10 +4,11 @@ use crate::{ revision::{Revision, RevisionRange}, ws::{DocumentServerWSData, DocumentServerWSDataBuilder}, }, + errors::CollaborateError, sync::DocumentPersistence, }; -use futures::TryFutureExt; -use lib_ot::{core::OperationTransformable, errors::OTError, rich_text::RichTextDelta}; + +use lib_ot::{core::OperationTransformable, rich_text::RichTextDelta}; use parking_lot::RwLock; use std::{ cmp::Ordering, @@ -48,19 +49,16 @@ impl RevisionSynchronizer { } #[tracing::instrument(level = "debug", skip(self, user, revisions, persistence), err)] - pub async fn apply_revisions( + pub async fn sync_revisions( &self, doc_id: String, user: Arc, revisions: Vec, persistence: Arc, - ) -> Result<(), OTError> { + ) -> Result<(), CollaborateError> { if revisions.is_empty() { // Return all the revisions to client - let revisions = persistence - .get_doc_revisions(&doc_id) - .map_err(|e| OTError::internal().context(e)) - .await?; + let revisions = persistence.get_doc_revisions(&doc_id).await?; let data = DocumentServerWSDataBuilder::build_push_message(&doc_id, revisions); user.receive(SyncResponse::Push(data)); return Ok(()); @@ -78,10 +76,8 @@ impl RevisionSynchronizer { let server_rev_id = next(server_base_rev_id); if server_base_rev_id == first_revision.base_rev_id || server_rev_id == first_revision.rev_id { // The rev is in the right order, just compose it. - { - for revision in &revisions { - let _ = self.compose_revision(revision)?; - } + for revision in &revisions { + let _ = self.compose_revision(revision)?; } user.receive(SyncResponse::NewRevision(revisions)); } else { @@ -108,7 +104,11 @@ impl RevisionSynchronizer { let rev_ids: Vec = (from_rev_id..=to_rev_id).collect(); let revisions = match persistence.get_revisions(&self.doc_id, rev_ids).await { Ok(revisions) => { - assert_eq!(revisions.is_empty(), false); + assert_eq!( + revisions.is_empty(), + false, + "revisions should not be empty if the doc exists" + ); revisions }, Err(e) => { @@ -126,7 +126,7 @@ impl RevisionSynchronizer { pub fn doc_json(&self) -> String { self.document.read().to_json() } - fn compose_revision(&self, revision: &Revision) -> Result<(), OTError> { + fn compose_revision(&self, revision: &Revision) -> Result<(), CollaborateError> { let delta = RichTextDelta::from_bytes(&revision.delta_data)?; let _ = self.compose_delta(delta)?; let _ = self.rev_id.fetch_update(SeqCst, SeqCst, |_e| Some(revision.rev_id)); @@ -134,13 +134,13 @@ impl RevisionSynchronizer { } #[tracing::instrument(level = "debug", skip(self, revision))] - fn transform_revision(&self, revision: &Revision) -> Result<(RichTextDelta, RichTextDelta), OTError> { + fn transform_revision(&self, revision: &Revision) -> Result<(RichTextDelta, RichTextDelta), CollaborateError> { let cli_delta = RichTextDelta::from_bytes(&revision.delta_data)?; let result = self.document.read().delta().transform(&cli_delta)?; Ok(result) } - fn compose_delta(&self, delta: RichTextDelta) -> Result<(), OTError> { + fn compose_delta(&self, delta: RichTextDelta) -> Result<(), CollaborateError> { if delta.is_empty() { log::warn!("Composed delta is empty"); } diff --git a/shared-lib/flowy-core-data-model/src/entities/view/view_create.rs b/shared-lib/flowy-core-data-model/src/entities/view/view_create.rs index 6100f8a155..bb71aabc77 100644 --- a/shared-lib/flowy-core-data-model/src/entities/view/view_create.rs +++ b/shared-lib/flowy-core-data-model/src/entities/view/view_create.rs @@ -7,7 +7,7 @@ use crate::{ view::{ViewName, ViewThumbnail}, }, }; - +use flowy_collaboration::document::default::initial_delta_string; use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use std::convert::TryInto; @@ -68,16 +68,32 @@ pub struct CreateViewParams { #[pb(index = 5)] pub view_type: ViewType, + + #[pb(index = 6)] + pub view_data: String, + + #[pb(index = 7)] + pub view_id: String, } impl CreateViewParams { - pub fn new(belong_to_id: String, name: String, desc: String, view_type: ViewType, thumbnail: String) -> Self { + pub fn new( + belong_to_id: String, + name: String, + desc: String, + view_type: ViewType, + thumbnail: String, + view_data: String, + view_id: String, + ) -> Self { Self { belong_to_id, name, desc, thumbnail, view_type, + view_data, + view_id, } } } @@ -88,7 +104,8 @@ impl TryInto for CreateViewRequest { fn try_into(self) -> Result { let name = ViewName::parse(self.name)?.0; let belong_to_id = AppId::parse(self.belong_to_id)?.0; - + let view_data = initial_delta_string(); + let view_id = uuid::Uuid::new_v4().to_string(); let thumbnail = match self.thumbnail { None => "".to_string(), Some(thumbnail) => ViewThumbnail::parse(thumbnail)?.0, @@ -100,6 +117,8 @@ impl TryInto for CreateViewRequest { self.desc, self.view_type, thumbnail, + view_data, + view_id, )) } } diff --git a/shared-lib/flowy-core-data-model/src/protobuf/model/view_create.rs b/shared-lib/flowy-core-data-model/src/protobuf/model/view_create.rs index e21f461c1b..8519e7d46b 100644 --- a/shared-lib/flowy-core-data-model/src/protobuf/model/view_create.rs +++ b/shared-lib/flowy-core-data-model/src/protobuf/model/view_create.rs @@ -387,6 +387,8 @@ pub struct CreateViewParams { pub desc: ::std::string::String, pub thumbnail: ::std::string::String, pub view_type: ViewType, + pub view_data: ::std::string::String, + pub view_id: ::std::string::String, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -521,6 +523,58 @@ impl CreateViewParams { pub fn set_view_type(&mut self, v: ViewType) { self.view_type = v; } + + // string view_data = 6; + + + pub fn get_view_data(&self) -> &str { + &self.view_data + } + pub fn clear_view_data(&mut self) { + self.view_data.clear(); + } + + // Param is passed by value, moved + pub fn set_view_data(&mut self, v: ::std::string::String) { + self.view_data = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_view_data(&mut self) -> &mut ::std::string::String { + &mut self.view_data + } + + // Take field + pub fn take_view_data(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.view_data, ::std::string::String::new()) + } + + // string view_id = 7; + + + pub fn get_view_id(&self) -> &str { + &self.view_id + } + pub fn clear_view_id(&mut self) { + self.view_id.clear(); + } + + // Param is passed by value, moved + pub fn set_view_id(&mut self, v: ::std::string::String) { + self.view_id = v; + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_view_id(&mut self) -> &mut ::std::string::String { + &mut self.view_id + } + + // Take field + pub fn take_view_id(&mut self) -> ::std::string::String { + ::std::mem::replace(&mut self.view_id, ::std::string::String::new()) + } } impl ::protobuf::Message for CreateViewParams { @@ -547,6 +601,12 @@ impl ::protobuf::Message for CreateViewParams { 5 => { ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.view_type, 5, &mut self.unknown_fields)? }, + 6 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_data)?; + }, + 7 => { + ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -574,6 +634,12 @@ impl ::protobuf::Message for CreateViewParams { if self.view_type != ViewType::Blank { my_size += ::protobuf::rt::enum_size(5, self.view_type); } + if !self.view_data.is_empty() { + my_size += ::protobuf::rt::string_size(6, &self.view_data); + } + if !self.view_id.is_empty() { + my_size += ::protobuf::rt::string_size(7, &self.view_id); + } my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); self.cached_size.set(my_size); my_size @@ -595,6 +661,12 @@ impl ::protobuf::Message for CreateViewParams { if self.view_type != ViewType::Blank { os.write_enum(5, ::protobuf::ProtobufEnum::value(&self.view_type))?; } + if !self.view_data.is_empty() { + os.write_string(6, &self.view_data)?; + } + if !self.view_id.is_empty() { + os.write_string(7, &self.view_id)?; + } os.write_unknown_fields(self.get_unknown_fields())?; ::std::result::Result::Ok(()) } @@ -658,6 +730,16 @@ impl ::protobuf::Message for CreateViewParams { |m: &CreateViewParams| { &m.view_type }, |m: &mut CreateViewParams| { &mut m.view_type }, )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "view_data", + |m: &CreateViewParams| { &m.view_data }, + |m: &mut CreateViewParams| { &mut m.view_data }, + )); + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + "view_id", + |m: &CreateViewParams| { &m.view_id }, + |m: &mut CreateViewParams| { &mut m.view_id }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "CreateViewParams", fields, @@ -679,6 +761,8 @@ impl ::protobuf::Clear for CreateViewParams { self.desc.clear(); self.thumbnail.clear(); self.view_type = ViewType::Blank; + self.view_data.clear(); + self.view_id.clear(); self.unknown_fields.clear(); } } @@ -1394,88 +1478,95 @@ static file_descriptor_proto_data: &'static [u8] = b"\ long_to_id\x18\x01\x20\x01(\tR\nbelongToId\x12\x12\n\x04name\x18\x02\x20\ \x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1e\n\ \tthumbnail\x18\x04\x20\x01(\tH\0R\tthumbnail\x12&\n\tview_type\x18\x05\ - \x20\x01(\x0e2\t.ViewTypeR\x08viewTypeB\x12\n\x10one_of_thumbnail\"\xa2\ + \x20\x01(\x0e2\t.ViewTypeR\x08viewTypeB\x12\n\x10one_of_thumbnail\"\xd8\ \x01\n\x10CreateViewParams\x12\x20\n\x0cbelong_to_id\x18\x01\x20\x01(\tR\ \nbelongToId\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04\ desc\x18\x03\x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\x04\x20\x01(\t\ R\tthumbnail\x12&\n\tview_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08view\ - Type\"\x97\x02\n\x04View\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\ - \x20\n\x0cbelong_to_id\x18\x02\x20\x01(\tR\nbelongToId\x12\x12\n\x04name\ - \x18\x03\x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x04\x20\x01(\tR\x04de\ - sc\x12&\n\tview_type\x18\x05\x20\x01(\x0e2\t.ViewTypeR\x08viewType\x12\ - \x18\n\x07version\x18\x06\x20\x01(\x03R\x07version\x12-\n\nbelongings\ - \x18\x07\x20\x01(\x0b2\r.RepeatedViewR\nbelongings\x12#\n\rmodified_time\ - \x18\x08\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\n\x0bcreate_time\x18\t\ - \x20\x01(\x03R\ncreateTime\"+\n\x0cRepeatedView\x12\x1b\n\x05items\x18\ - \x01\x20\x03(\x0b2\x05.ViewR\x05items*\x1e\n\x08ViewType\x12\t\n\x05Blan\ - k\x10\0\x12\x07\n\x03Doc\x10\x01J\xd1\n\n\x06\x12\x04\0\0!\x01\n\x08\n\ - \x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\x04\x02\0\x08\x01\n\n\n\x03\ - \x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\x04\x04\0\x02\0\x12\x03\x03\x04\ - \x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\x04\n\n\x0c\n\x05\x04\0\x02\ - \0\x01\x12\x03\x03\x0b\x17\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x03\x1a\ - \x1b\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\x14\n\x0c\n\x05\x04\0\x02\ - \x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x04\x0b\ - \x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x04\x12\x13\n\x0b\n\x04\x04\0\ - \x02\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\x04\0\x02\x02\x05\x12\x03\x05\ - \x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x05\x0b\x0f\n\x0c\n\x05\x04\ - \0\x02\x02\x03\x12\x03\x05\x12\x13\n\x0b\n\x04\x04\0\x08\0\x12\x03\x06\ - \x044\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\x06\n\x1a\n\x0b\n\x04\x04\0\ - \x02\x03\x12\x03\x06\x1d2\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\x06\x1d#\ - \n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06$-\n\x0c\n\x05\x04\0\x02\x03\ - \x03\x12\x03\x0601\n\x0b\n\x04\x04\0\x02\x04\x12\x03\x07\x04\x1b\n\x0c\n\ - \x05\x04\0\x02\x04\x06\x12\x03\x07\x04\x0c\n\x0c\n\x05\x04\0\x02\x04\x01\ - \x12\x03\x07\r\x16\n\x0c\n\x05\x04\0\x02\x04\x03\x12\x03\x07\x19\x1a\n\n\ - \n\x02\x04\x01\x12\x04\t\0\x0f\x01\n\n\n\x03\x04\x01\x01\x12\x03\t\x08\ - \x18\n\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\x1c\n\x0c\n\x05\x04\x01\x02\ - \0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\n\x0b\x17\n\ - \x0c\n\x05\x04\x01\x02\0\x03\x12\x03\n\x1a\x1b\n\x0b\n\x04\x04\x01\x02\ - \x01\x12\x03\x0b\x04\x14\n\x0c\n\x05\x04\x01\x02\x01\x05\x12\x03\x0b\x04\ - \n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\x0b\x0b\x0f\n\x0c\n\x05\x04\ - \x01\x02\x01\x03\x12\x03\x0b\x12\x13\n\x0b\n\x04\x04\x01\x02\x02\x12\x03\ - \x0c\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\x12\x03\x0c\x04\n\n\x0c\n\ - \x05\x04\x01\x02\x02\x01\x12\x03\x0c\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x02\ - \x03\x12\x03\x0c\x12\x13\n\x0b\n\x04\x04\x01\x02\x03\x12\x03\r\x04\x19\n\ - \x0c\n\x05\x04\x01\x02\x03\x05\x12\x03\r\x04\n\n\x0c\n\x05\x04\x01\x02\ - \x03\x01\x12\x03\r\x0b\x14\n\x0c\n\x05\x04\x01\x02\x03\x03\x12\x03\r\x17\ - \x18\n\x0b\n\x04\x04\x01\x02\x04\x12\x03\x0e\x04\x1b\n\x0c\n\x05\x04\x01\ - \x02\x04\x06\x12\x03\x0e\x04\x0c\n\x0c\n\x05\x04\x01\x02\x04\x01\x12\x03\ - \x0e\r\x16\n\x0c\n\x05\x04\x01\x02\x04\x03\x12\x03\x0e\x19\x1a\n\n\n\x02\ - \x04\x02\x12\x04\x10\0\x1a\x01\n\n\n\x03\x04\x02\x01\x12\x03\x10\x08\x0c\ - \n\x0b\n\x04\x04\x02\x02\0\x12\x03\x11\x04\x12\n\x0c\n\x05\x04\x02\x02\0\ - \x05\x12\x03\x11\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\x11\x0b\r\n\ - \x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x11\x10\x11\n\x0b\n\x04\x04\x02\x02\ - \x01\x12\x03\x12\x04\x1c\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\x03\x12\x04\ - \n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\x12\x0b\x17\n\x0c\n\x05\x04\ - \x02\x02\x01\x03\x12\x03\x12\x1a\x1b\n\x0b\n\x04\x04\x02\x02\x02\x12\x03\ - \x13\x04\x14\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x13\x04\n\n\x0c\n\ - \x05\x04\x02\x02\x02\x01\x12\x03\x13\x0b\x0f\n\x0c\n\x05\x04\x02\x02\x02\ - \x03\x12\x03\x13\x12\x13\n\x0b\n\x04\x04\x02\x02\x03\x12\x03\x14\x04\x14\ - \n\x0c\n\x05\x04\x02\x02\x03\x05\x12\x03\x14\x04\n\n\x0c\n\x05\x04\x02\ - \x02\x03\x01\x12\x03\x14\x0b\x0f\n\x0c\n\x05\x04\x02\x02\x03\x03\x12\x03\ - \x14\x12\x13\n\x0b\n\x04\x04\x02\x02\x04\x12\x03\x15\x04\x1b\n\x0c\n\x05\ - \x04\x02\x02\x04\x06\x12\x03\x15\x04\x0c\n\x0c\n\x05\x04\x02\x02\x04\x01\ - \x12\x03\x15\r\x16\n\x0c\n\x05\x04\x02\x02\x04\x03\x12\x03\x15\x19\x1a\n\ - \x0b\n\x04\x04\x02\x02\x05\x12\x03\x16\x04\x16\n\x0c\n\x05\x04\x02\x02\ - \x05\x05\x12\x03\x16\x04\t\n\x0c\n\x05\x04\x02\x02\x05\x01\x12\x03\x16\n\ - \x11\n\x0c\n\x05\x04\x02\x02\x05\x03\x12\x03\x16\x14\x15\n\x0b\n\x04\x04\ - \x02\x02\x06\x12\x03\x17\x04\x20\n\x0c\n\x05\x04\x02\x02\x06\x06\x12\x03\ - \x17\x04\x10\n\x0c\n\x05\x04\x02\x02\x06\x01\x12\x03\x17\x11\x1b\n\x0c\n\ - \x05\x04\x02\x02\x06\x03\x12\x03\x17\x1e\x1f\n\x0b\n\x04\x04\x02\x02\x07\ - \x12\x03\x18\x04\x1c\n\x0c\n\x05\x04\x02\x02\x07\x05\x12\x03\x18\x04\t\n\ - \x0c\n\x05\x04\x02\x02\x07\x01\x12\x03\x18\n\x17\n\x0c\n\x05\x04\x02\x02\ - \x07\x03\x12\x03\x18\x1a\x1b\n\x0b\n\x04\x04\x02\x02\x08\x12\x03\x19\x04\ - \x1a\n\x0c\n\x05\x04\x02\x02\x08\x05\x12\x03\x19\x04\t\n\x0c\n\x05\x04\ - \x02\x02\x08\x01\x12\x03\x19\n\x15\n\x0c\n\x05\x04\x02\x02\x08\x03\x12\ - \x03\x19\x18\x19\n\n\n\x02\x04\x03\x12\x04\x1b\0\x1d\x01\n\n\n\x03\x04\ - \x03\x01\x12\x03\x1b\x08\x14\n\x0b\n\x04\x04\x03\x02\0\x12\x03\x1c\x04\ - \x1c\n\x0c\n\x05\x04\x03\x02\0\x04\x12\x03\x1c\x04\x0c\n\x0c\n\x05\x04\ - \x03\x02\0\x06\x12\x03\x1c\r\x11\n\x0c\n\x05\x04\x03\x02\0\x01\x12\x03\ - \x1c\x12\x17\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x1c\x1a\x1b\n\n\n\x02\ - \x05\0\x12\x04\x1e\0!\x01\n\n\n\x03\x05\0\x01\x12\x03\x1e\x05\r\n\x0b\n\ - \x04\x05\0\x02\0\x12\x03\x1f\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\x12\x03\ - \x1f\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x1f\x0c\r\n\x0b\n\x04\x05\ - \0\x02\x01\x12\x03\x20\x04\x0c\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\x20\ - \x04\x07\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x20\n\x0bb\x06proto3\ + Type\x12\x1b\n\tview_data\x18\x06\x20\x01(\tR\x08viewData\x12\x17\n\x07v\ + iew_id\x18\x07\x20\x01(\tR\x06viewId\"\x97\x02\n\x04View\x12\x0e\n\x02id\ + \x18\x01\x20\x01(\tR\x02id\x12\x20\n\x0cbelong_to_id\x18\x02\x20\x01(\tR\ + \nbelongToId\x12\x12\n\x04name\x18\x03\x20\x01(\tR\x04name\x12\x12\n\x04\ + desc\x18\x04\x20\x01(\tR\x04desc\x12&\n\tview_type\x18\x05\x20\x01(\x0e2\ + \t.ViewTypeR\x08viewType\x12\x18\n\x07version\x18\x06\x20\x01(\x03R\x07v\ + ersion\x12-\n\nbelongings\x18\x07\x20\x01(\x0b2\r.RepeatedViewR\nbelongi\ + ngs\x12#\n\rmodified_time\x18\x08\x20\x01(\x03R\x0cmodifiedTime\x12\x1f\ + \n\x0bcreate_time\x18\t\x20\x01(\x03R\ncreateTime\"+\n\x0cRepeatedView\ + \x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.ViewR\x05items*\x1e\n\x08V\ + iewType\x12\t\n\x05Blank\x10\0\x12\x07\n\x03Doc\x10\x01J\xbf\x0b\n\x06\ + \x12\x04\0\0#\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\n\n\x02\x04\0\x12\ + \x04\x02\0\x08\x01\n\n\n\x03\x04\0\x01\x12\x03\x02\x08\x19\n\x0b\n\x04\ + \x04\0\x02\0\x12\x03\x03\x04\x1c\n\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x03\ + \x04\n\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x03\x0b\x17\n\x0c\n\x05\x04\0\ + \x02\0\x03\x12\x03\x03\x1a\x1b\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x04\x04\ + \x14\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x04\x04\n\n\x0c\n\x05\x04\0\ + \x02\x01\x01\x12\x03\x04\x0b\x0f\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\ + \x04\x12\x13\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x05\x04\x14\n\x0c\n\x05\ + \x04\0\x02\x02\x05\x12\x03\x05\x04\n\n\x0c\n\x05\x04\0\x02\x02\x01\x12\ + \x03\x05\x0b\x0f\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x05\x12\x13\n\x0b\ + \n\x04\x04\0\x08\0\x12\x03\x06\x044\n\x0c\n\x05\x04\0\x08\0\x01\x12\x03\ + \x06\n\x1a\n\x0b\n\x04\x04\0\x02\x03\x12\x03\x06\x1d2\n\x0c\n\x05\x04\0\ + \x02\x03\x05\x12\x03\x06\x1d#\n\x0c\n\x05\x04\0\x02\x03\x01\x12\x03\x06$\ + -\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\x0601\n\x0b\n\x04\x04\0\x02\x04\ + \x12\x03\x07\x04\x1b\n\x0c\n\x05\x04\0\x02\x04\x06\x12\x03\x07\x04\x0c\n\ + \x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x07\r\x16\n\x0c\n\x05\x04\0\x02\x04\ + \x03\x12\x03\x07\x19\x1a\n\n\n\x02\x04\x01\x12\x04\t\0\x11\x01\n\n\n\x03\ + \x04\x01\x01\x12\x03\t\x08\x18\n\x0b\n\x04\x04\x01\x02\0\x12\x03\n\x04\ + \x1c\n\x0c\n\x05\x04\x01\x02\0\x05\x12\x03\n\x04\n\n\x0c\n\x05\x04\x01\ + \x02\0\x01\x12\x03\n\x0b\x17\n\x0c\n\x05\x04\x01\x02\0\x03\x12\x03\n\x1a\ + \x1b\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\x0b\x04\x14\n\x0c\n\x05\x04\x01\ + \x02\x01\x05\x12\x03\x0b\x04\n\n\x0c\n\x05\x04\x01\x02\x01\x01\x12\x03\ + \x0b\x0b\x0f\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x0b\x12\x13\n\x0b\n\ + \x04\x04\x01\x02\x02\x12\x03\x0c\x04\x14\n\x0c\n\x05\x04\x01\x02\x02\x05\ + \x12\x03\x0c\x04\n\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x0c\x0b\x0f\n\ + \x0c\n\x05\x04\x01\x02\x02\x03\x12\x03\x0c\x12\x13\n\x0b\n\x04\x04\x01\ + \x02\x03\x12\x03\r\x04\x19\n\x0c\n\x05\x04\x01\x02\x03\x05\x12\x03\r\x04\ + \n\n\x0c\n\x05\x04\x01\x02\x03\x01\x12\x03\r\x0b\x14\n\x0c\n\x05\x04\x01\ + \x02\x03\x03\x12\x03\r\x17\x18\n\x0b\n\x04\x04\x01\x02\x04\x12\x03\x0e\ + \x04\x1b\n\x0c\n\x05\x04\x01\x02\x04\x06\x12\x03\x0e\x04\x0c\n\x0c\n\x05\ + \x04\x01\x02\x04\x01\x12\x03\x0e\r\x16\n\x0c\n\x05\x04\x01\x02\x04\x03\ + \x12\x03\x0e\x19\x1a\n\x0b\n\x04\x04\x01\x02\x05\x12\x03\x0f\x04\x19\n\ + \x0c\n\x05\x04\x01\x02\x05\x05\x12\x03\x0f\x04\n\n\x0c\n\x05\x04\x01\x02\ + \x05\x01\x12\x03\x0f\x0b\x14\n\x0c\n\x05\x04\x01\x02\x05\x03\x12\x03\x0f\ + \x17\x18\n\x0b\n\x04\x04\x01\x02\x06\x12\x03\x10\x04\x17\n\x0c\n\x05\x04\ + \x01\x02\x06\x05\x12\x03\x10\x04\n\n\x0c\n\x05\x04\x01\x02\x06\x01\x12\ + \x03\x10\x0b\x12\n\x0c\n\x05\x04\x01\x02\x06\x03\x12\x03\x10\x15\x16\n\n\ + \n\x02\x04\x02\x12\x04\x12\0\x1c\x01\n\n\n\x03\x04\x02\x01\x12\x03\x12\ + \x08\x0c\n\x0b\n\x04\x04\x02\x02\0\x12\x03\x13\x04\x12\n\x0c\n\x05\x04\ + \x02\x02\0\x05\x12\x03\x13\x04\n\n\x0c\n\x05\x04\x02\x02\0\x01\x12\x03\ + \x13\x0b\r\n\x0c\n\x05\x04\x02\x02\0\x03\x12\x03\x13\x10\x11\n\x0b\n\x04\ + \x04\x02\x02\x01\x12\x03\x14\x04\x1c\n\x0c\n\x05\x04\x02\x02\x01\x05\x12\ + \x03\x14\x04\n\n\x0c\n\x05\x04\x02\x02\x01\x01\x12\x03\x14\x0b\x17\n\x0c\ + \n\x05\x04\x02\x02\x01\x03\x12\x03\x14\x1a\x1b\n\x0b\n\x04\x04\x02\x02\ + \x02\x12\x03\x15\x04\x14\n\x0c\n\x05\x04\x02\x02\x02\x05\x12\x03\x15\x04\ + \n\n\x0c\n\x05\x04\x02\x02\x02\x01\x12\x03\x15\x0b\x0f\n\x0c\n\x05\x04\ + \x02\x02\x02\x03\x12\x03\x15\x12\x13\n\x0b\n\x04\x04\x02\x02\x03\x12\x03\ + \x16\x04\x14\n\x0c\n\x05\x04\x02\x02\x03\x05\x12\x03\x16\x04\n\n\x0c\n\ + \x05\x04\x02\x02\x03\x01\x12\x03\x16\x0b\x0f\n\x0c\n\x05\x04\x02\x02\x03\ + \x03\x12\x03\x16\x12\x13\n\x0b\n\x04\x04\x02\x02\x04\x12\x03\x17\x04\x1b\ + \n\x0c\n\x05\x04\x02\x02\x04\x06\x12\x03\x17\x04\x0c\n\x0c\n\x05\x04\x02\ + \x02\x04\x01\x12\x03\x17\r\x16\n\x0c\n\x05\x04\x02\x02\x04\x03\x12\x03\ + \x17\x19\x1a\n\x0b\n\x04\x04\x02\x02\x05\x12\x03\x18\x04\x16\n\x0c\n\x05\ + \x04\x02\x02\x05\x05\x12\x03\x18\x04\t\n\x0c\n\x05\x04\x02\x02\x05\x01\ + \x12\x03\x18\n\x11\n\x0c\n\x05\x04\x02\x02\x05\x03\x12\x03\x18\x14\x15\n\ + \x0b\n\x04\x04\x02\x02\x06\x12\x03\x19\x04\x20\n\x0c\n\x05\x04\x02\x02\ + \x06\x06\x12\x03\x19\x04\x10\n\x0c\n\x05\x04\x02\x02\x06\x01\x12\x03\x19\ + \x11\x1b\n\x0c\n\x05\x04\x02\x02\x06\x03\x12\x03\x19\x1e\x1f\n\x0b\n\x04\ + \x04\x02\x02\x07\x12\x03\x1a\x04\x1c\n\x0c\n\x05\x04\x02\x02\x07\x05\x12\ + \x03\x1a\x04\t\n\x0c\n\x05\x04\x02\x02\x07\x01\x12\x03\x1a\n\x17\n\x0c\n\ + \x05\x04\x02\x02\x07\x03\x12\x03\x1a\x1a\x1b\n\x0b\n\x04\x04\x02\x02\x08\ + \x12\x03\x1b\x04\x1a\n\x0c\n\x05\x04\x02\x02\x08\x05\x12\x03\x1b\x04\t\n\ + \x0c\n\x05\x04\x02\x02\x08\x01\x12\x03\x1b\n\x15\n\x0c\n\x05\x04\x02\x02\ + \x08\x03\x12\x03\x1b\x18\x19\n\n\n\x02\x04\x03\x12\x04\x1d\0\x1f\x01\n\n\ + \n\x03\x04\x03\x01\x12\x03\x1d\x08\x14\n\x0b\n\x04\x04\x03\x02\0\x12\x03\ + \x1e\x04\x1c\n\x0c\n\x05\x04\x03\x02\0\x04\x12\x03\x1e\x04\x0c\n\x0c\n\ + \x05\x04\x03\x02\0\x06\x12\x03\x1e\r\x11\n\x0c\n\x05\x04\x03\x02\0\x01\ + \x12\x03\x1e\x12\x17\n\x0c\n\x05\x04\x03\x02\0\x03\x12\x03\x1e\x1a\x1b\n\ + \n\n\x02\x05\0\x12\x04\x20\0#\x01\n\n\n\x03\x05\0\x01\x12\x03\x20\x05\r\ + \n\x0b\n\x04\x05\0\x02\0\x12\x03!\x04\x0e\n\x0c\n\x05\x05\0\x02\0\x01\ + \x12\x03!\x04\t\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03!\x0c\r\n\x0b\n\x04\ + \x05\0\x02\x01\x12\x03\"\x04\x0c\n\x0c\n\x05\x05\0\x02\x01\x01\x12\x03\"\ + \x04\x07\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\"\n\x0bb\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-core-data-model/src/protobuf/proto/view_create.proto b/shared-lib/flowy-core-data-model/src/protobuf/proto/view_create.proto index 059d1de7c7..1534ca0e81 100644 --- a/shared-lib/flowy-core-data-model/src/protobuf/proto/view_create.proto +++ b/shared-lib/flowy-core-data-model/src/protobuf/proto/view_create.proto @@ -13,6 +13,8 @@ message CreateViewParams { string desc = 3; string thumbnail = 4; ViewType view_type = 5; + string view_data = 6; + string view_id = 7; } message View { string id = 1; diff --git a/shared-lib/lib-infra/src/lib.rs b/shared-lib/lib-infra/src/lib.rs index 4e67d61c44..16e16d08a5 100644 --- a/shared-lib/lib-infra/src/lib.rs +++ b/shared-lib/lib-infra/src/lib.rs @@ -2,7 +2,7 @@ pub mod future; pub mod retry; #[allow(dead_code)] -pub fn uuid() -> String { uuid::Uuid::new_v4().to_string() } +pub fn uuid_string() -> String { uuid::Uuid::new_v4().to_string() } #[allow(dead_code)] pub fn timestamp() -> i64 { chrono::Utc::now().timestamp() }