diff --git a/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart b/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart index ea2a4ec916..ff528adcbf 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/rust_sdk.dart @@ -54,11 +54,11 @@ AppFlowyEnv getAppFlowyEnv() { Future appFlowyDocumentDirectory() async { switch (integrationEnv()) { case IntegrationMode.develop: - Directory documentsDir = await getApplicationDocumentsDirectory() + Directory documentsDir = await getApplicationSupportDirectory() ..create(); return Directory(path.join(documentsDir.path, 'data_dev')).create(); case IntegrationMode.release: - Directory documentsDir = await getApplicationDocumentsDirectory(); + Directory documentsDir = await getApplicationSupportDirectory(); return Directory(path.join(documentsDir.path, 'data')).create(); case IntegrationMode.test: return Directory(path.join(Directory.current.path, '.sandbox')); diff --git a/frontend/rust-lib/flowy-core/assets/read_me.json b/frontend/rust-lib/flowy-core/assets/read_me.json index 2e47a80467..f9b4ca1612 100644 --- a/frontend/rust-lib/flowy-core/assets/read_me.json +++ b/frontend/rust-lib/flowy-core/assets/read_me.json @@ -1,5 +1,10 @@ { "type": "page", + "data": { + "delta": [ + {"insert": ""} + ] + }, "children": [ { "type": "heading", diff --git a/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs b/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs index a69c9135d5..c8eea5077b 100644 --- a/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs +++ b/frontend/rust-lib/flowy-core/src/deps_resolve/folder2_deps.rs @@ -10,7 +10,6 @@ use flowy_database2::entities::DatabaseLayoutPB; use flowy_database2::services::share::csv::CSVFormat; use flowy_database2::template::{make_default_board, make_default_calendar, make_default_grid}; use flowy_database2::DatabaseManager2; -use flowy_document2::document_data::default_document_data; use flowy_document2::entities::DocumentDataPB; use flowy_document2::manager::DocumentManager; use flowy_document2::parser::json::parser::JsonToDocumentParser; @@ -105,7 +104,7 @@ impl FolderOperationHandler for DocumentFolderOperation { let json_str = include_str!("../../assets/read_me.json"); let document_pb = JsonToDocumentParser::json_str_to_document(json_str).unwrap(); manager - .create_document(view.parent_view.id.clone(), document_pb.into()) + .create_document(view.parent_view.id.clone(), Some(document_pb.into())) .unwrap(); view }) @@ -152,7 +151,7 @@ impl FolderOperationHandler for DocumentFolderOperation { let manager = self.0.clone(); FutureResult::new(async move { let data = DocumentDataPB::try_from(Bytes::from(data))?; - manager.create_document(view_id, data.into())?; + manager.create_document(view_id, Some(data.into()))?; Ok(()) }) } @@ -169,7 +168,7 @@ impl FolderOperationHandler for DocumentFolderOperation { let view_id = view_id.to_string(); let manager = self.0.clone(); FutureResult::new(async move { - manager.create_document(view_id, default_document_data())?; + manager.create_document(view_id, None)?; Ok(()) }) } @@ -184,7 +183,7 @@ impl FolderOperationHandler for DocumentFolderOperation { let manager = self.0.clone(); FutureResult::new(async move { let data = DocumentDataPB::try_from(Bytes::from(bytes))?; - manager.create_document(view_id, data.into())?; + manager.create_document(view_id, Some(data.into()))?; Ok(()) }) } diff --git a/frontend/rust-lib/flowy-document2/src/document_block_keys.rs b/frontend/rust-lib/flowy-document2/src/document_block_keys.rs new file mode 100644 index 0000000000..92ff17e91a --- /dev/null +++ b/frontend/rust-lib/flowy-document2/src/document_block_keys.rs @@ -0,0 +1,2 @@ +pub const PAGE: &str = "page"; +pub const PARAGRAPH_BLOCK_TYPE: &str = "paragraph"; diff --git a/frontend/rust-lib/flowy-document2/src/document_data.rs b/frontend/rust-lib/flowy-document2/src/document_data.rs index dfe169912d..242139c8ad 100644 --- a/frontend/rust-lib/flowy-document2/src/document_data.rs +++ b/frontend/rust-lib/flowy-document2/src/document_data.rs @@ -3,7 +3,10 @@ use std::{collections::HashMap, vec}; use collab_document::blocks::{Block, DocumentData, DocumentMeta}; use nanoid::nanoid; -use crate::entities::{BlockPB, ChildrenPB, DocumentDataPB, MetaPB}; +use crate::{ + document_block_keys::{PAGE, PARAGRAPH_BLOCK_TYPE}, + entities::{BlockPB, ChildrenPB, DocumentDataPB, MetaPB}, +}; impl From for DocumentDataPB { fn from(data: DocumentData) -> Self { @@ -58,8 +61,8 @@ impl From for DocumentData { /// The default document data. /// The default document data is a document with a page block and a text block. pub fn default_document_data() -> DocumentData { - let page_type = "page".to_string(); - let text_type = "text".to_string(); + let page_type = PAGE.to_string(); + let text_type = PARAGRAPH_BLOCK_TYPE.to_string(); let mut blocks: HashMap = HashMap::new(); let mut meta: HashMap> = HashMap::new(); diff --git a/frontend/rust-lib/flowy-document2/src/entities.rs b/frontend/rust-lib/flowy-document2/src/entities.rs index ae86d04bab..e0195d8f2d 100644 --- a/frontend/rust-lib/flowy-document2/src/entities.rs +++ b/frontend/rust-lib/flowy-document2/src/entities.rs @@ -203,3 +203,36 @@ pub struct ExportDataPB { #[pb(index = 2)] pub export_type: ExportType, } +#[derive(PartialEq, Eq, Debug, ProtoBuf_Enum, Clone)] +pub enum ConvertType { + Json = 0, +} + +impl Default for ConvertType { + fn default() -> Self { + ConvertType::Json + } +} + +impl From for ConvertType { + fn from(val: i32) -> Self { + match val { + 0 => ConvertType::Json, + _ => { + tracing::error!("Invalid export type: {}", val); + ConvertType::Json + }, + } + } +} + +/// for the json type +/// the data is the json string +#[derive(Default, ProtoBuf, Debug)] +pub struct ConvertDataPayloadPB { + #[pb(index = 1)] + pub convert_type: ConvertType, + + #[pb(index = 2)] + pub data: Vec, +} diff --git a/frontend/rust-lib/flowy-document2/src/event_handler.rs b/frontend/rust-lib/flowy-document2/src/event_handler.rs index 7317907101..7dea2c7bf5 100644 --- a/frontend/rust-lib/flowy-document2/src/event_handler.rs +++ b/frontend/rust-lib/flowy-document2/src/event_handler.rs @@ -8,20 +8,20 @@ use std::sync::Arc; use collab_document::blocks::{ json_str_to_hashmap, Block, BlockAction, BlockActionPayload, BlockActionType, BlockEvent, - BlockEventPayload, DeltaType, DocumentData, + BlockEventPayload, DeltaType, }; use flowy_error::{FlowyError, FlowyResult}; use lib_dispatch::prelude::{data_result_ok, AFPluginData, AFPluginState, DataResult}; -use crate::document_data::default_document_data; use crate::{ entities::{ ApplyActionPayloadPB, BlockActionPB, BlockActionPayloadPB, BlockActionTypePB, BlockEventPB, - BlockEventPayloadPB, BlockPB, CloseDocumentPayloadPB, CreateDocumentPayloadPB, DeltaTypePB, - DocEventPB, DocumentDataPB, OpenDocumentPayloadPB, + BlockEventPayloadPB, BlockPB, CloseDocumentPayloadPB, ConvertDataPayloadPB, ConvertType, + CreateDocumentPayloadPB, DeltaTypePB, DocEventPB, DocumentDataPB, OpenDocumentPayloadPB, }, manager::DocumentManager, + parser::json::parser::JsonToDocumentParser, }; // Handler for creating a new document @@ -30,10 +30,7 @@ pub(crate) async fn create_document_handler( manager: AFPluginState>, ) -> FlowyResult<()> { let data = data.into_inner(); - let initial_data = data - .initial_data - .map(|data| DocumentData::from(data)) - .unwrap_or_else(default_document_data); + let initial_data = data.initial_data.map(|data| data.into()); manager.create_document(data.document_id, initial_data)?; Ok(()) } @@ -83,6 +80,29 @@ pub(crate) async fn apply_action_handler( Ok(()) } +pub(crate) async fn convert_data_to_document( + data: AFPluginData, + _manager: AFPluginState>, +) -> DataResult { + let payload = data.into_inner(); + let document = convert_data_to_document_internal(payload)?; + data_result_ok(document) +} + +pub fn convert_data_to_document_internal( + payload: ConvertDataPayloadPB, +) -> Result { + let convert_type = payload.convert_type; + let data = payload.data; + match convert_type { + ConvertType::Json => { + let json_str = String::from_utf8(data).map_err(|_| FlowyError::invalid_data())?; + let document = JsonToDocumentParser::json_str_to_document(&json_str)?; + Ok(document) + }, + } +} + impl From for BlockAction { fn from(pb: BlockActionPB) -> Self { Self { diff --git a/frontend/rust-lib/flowy-document2/src/event_map.rs b/frontend/rust-lib/flowy-document2/src/event_map.rs index ca1e127d87..f5af77503f 100644 --- a/frontend/rust-lib/flowy-document2/src/event_map.rs +++ b/frontend/rust-lib/flowy-document2/src/event_map.rs @@ -6,8 +6,8 @@ use lib_dispatch::prelude::AFPlugin; use crate::{ event_handler::{ - apply_action_handler, close_document_handler, create_document_handler, - get_document_data_handler, open_document_handler, + apply_action_handler, close_document_handler, convert_data_to_document, + create_document_handler, get_document_data_handler, open_document_handler, }, manager::DocumentManager, }; @@ -22,6 +22,10 @@ pub fn init(document_manager: Arc) -> AFPlugin { plugin = plugin.event(DocumentEvent::CloseDocument, close_document_handler); plugin = plugin.event(DocumentEvent::ApplyAction, apply_action_handler); plugin = plugin.event(DocumentEvent::GetDocumentData, get_document_data_handler); + plugin = plugin.event( + DocumentEvent::ConvertDataToDocument, + convert_data_to_document, + ); plugin } @@ -43,4 +47,7 @@ pub enum DocumentEvent { #[event(input = "GetDocumentDataPayloadPB")] GetDocumentData = 4, + + #[event(input = "ConvertDataPayloadPB", output = "DocumentDataPB")] + ConvertDataToDocument = 5, } diff --git a/frontend/rust-lib/flowy-document2/src/lib.rs b/frontend/rust-lib/flowy-document2/src/lib.rs index 0b6ec6b5fd..a79379801e 100644 --- a/frontend/rust-lib/flowy-document2/src/lib.rs +++ b/frontend/rust-lib/flowy-document2/src/lib.rs @@ -1,10 +1,11 @@ pub mod document; +pub mod document_block_keys; pub mod document_data; pub mod entities; +pub mod event_handler; pub mod event_map; pub mod manager; pub mod parser; pub mod protobuf; -mod event_handler; mod notification; diff --git a/frontend/rust-lib/flowy-document2/src/manager.rs b/frontend/rust-lib/flowy-document2/src/manager.rs index 9cd3e1274e..220c131d49 100644 --- a/frontend/rust-lib/flowy-document2/src/manager.rs +++ b/frontend/rust-lib/flowy-document2/src/manager.rs @@ -9,6 +9,7 @@ use flowy_error::{FlowyError, FlowyResult}; use crate::{ document::Document, + document_data::default_document_data, entities::DocEventPB, notification::{send_notification, DocumentNotification}, }; @@ -34,11 +35,20 @@ impl DocumentManager { } } - pub fn create_document(&self, doc_id: String, data: DocumentData) -> FlowyResult> { + /// Create a new document. + /// + /// if the document already exists, return the existing document. + /// if the data is None, will create a document with default data. + pub fn create_document( + &self, + doc_id: String, + data: Option, + ) -> FlowyResult> { tracing::debug!("create a document: {:?}", &doc_id); let uid = self.user.user_id()?; let db = self.user.collab_db()?; let collab = self.collab_builder.build(uid, &doc_id, "document", db); + let data = data.unwrap_or_else(|| default_document_data()); let document = Arc::new(Document::create_with_data(collab, data)?); Ok(document) } diff --git a/frontend/rust-lib/flowy-document2/tests/document/document_insert_test.rs b/frontend/rust-lib/flowy-document2/tests/document/document_insert_test.rs index e47ebd8439..4b7da9efbe 100644 --- a/frontend/rust-lib/flowy-document2/tests/document/document_insert_test.rs +++ b/frontend/rust-lib/flowy-document2/tests/document/document_insert_test.rs @@ -2,6 +2,7 @@ use std::{collections::HashMap, sync::Arc, vec}; use crate::document::util::default_collab_builder; use collab_document::blocks::{Block, BlockAction, BlockActionPayload, BlockActionType}; +use flowy_document2::document_block_keys::PARAGRAPH_BLOCK_TYPE; use flowy_document2::document_data::default_document_data; use flowy_document2::{document::Document, manager::DocumentManager}; use nanoid::nanoid; @@ -16,7 +17,7 @@ fn document_apply_insert_block_with_empty_parent_id() { let text_block_id = nanoid!(10); let text_block = Block { id: text_block_id.clone(), - ty: "text".to_string(), + ty: PARAGRAPH_BLOCK_TYPE.to_string(), parent: "".to_string(), children: nanoid!(10), external_id: None, @@ -47,7 +48,7 @@ fn create_and_open_empty_document() -> (DocumentManager, Arc, String) // create a document _ = manager - .create_document(doc_id.clone(), data.clone()) + .create_document(doc_id.clone(), Some(data.clone())) .unwrap(); let document = manager.open_document(doc_id).unwrap(); diff --git a/frontend/rust-lib/flowy-document2/tests/document/document_test.rs b/frontend/rust-lib/flowy-document2/tests/document/document_test.rs index 55e50d88f5..c2392ac536 100644 --- a/frontend/rust-lib/flowy-document2/tests/document/document_test.rs +++ b/frontend/rust-lib/flowy-document2/tests/document/document_test.rs @@ -1,6 +1,7 @@ use std::{collections::HashMap, sync::Arc, vec}; use collab_document::blocks::{Block, BlockAction, BlockActionPayload, BlockActionType}; +use flowy_document2::document_block_keys::PARAGRAPH_BLOCK_TYPE; use nanoid::nanoid; use serde_json::{json, to_value, Value}; @@ -19,7 +20,7 @@ fn restore_document() { let doc_id: String = nanoid!(10); let data = default_document_data(); let document_a = manager - .create_document(doc_id.clone(), data.clone()) + .create_document(doc_id.clone(), Some(data.clone())) .unwrap(); let data_a = document_a.lock().get_document().unwrap(); assert_eq!(data_a, data); @@ -36,7 +37,7 @@ fn restore_document() { assert_eq!(data_b, data); // restore - _ = manager.create_document(doc_id.clone(), data.clone()); + _ = manager.create_document(doc_id.clone(), Some(data.clone())); // open a document let data_b = manager .open_document(doc_id.clone()) @@ -59,7 +60,7 @@ fn document_apply_insert_action() { let data = default_document_data(); // create a document - _ = manager.create_document(doc_id.clone(), data.clone()); + _ = manager.create_document(doc_id.clone(), Some(data.clone())); // open a document let document = manager.open_document(doc_id.clone()).unwrap(); @@ -68,7 +69,7 @@ fn document_apply_insert_action() { // insert a text block let text_block = Block { id: nanoid!(10), - ty: "text".to_string(), + ty: PARAGRAPH_BLOCK_TYPE.to_string(), parent: page_block.id, children: nanoid!(10), external_id: None, @@ -110,7 +111,7 @@ fn document_apply_update_page_action() { let data = default_document_data(); // create a document - _ = manager.create_document(doc_id.clone(), data.clone()); + _ = manager.create_document(doc_id.clone(), Some(data.clone())); // open a document let document = manager.open_document(doc_id.clone()).unwrap(); @@ -152,7 +153,7 @@ fn document_apply_update_action() { let data = default_document_data(); // create a document - _ = manager.create_document(doc_id.clone(), data.clone()); + _ = manager.create_document(doc_id.clone(), Some(data.clone())); // open a document let document = manager.open_document(doc_id.clone()).unwrap(); @@ -162,7 +163,7 @@ fn document_apply_update_action() { let text_block_id = nanoid!(10); let text_block = Block { id: text_block_id.clone(), - ty: "text".to_string(), + ty: PARAGRAPH_BLOCK_TYPE.to_string(), parent: page_block.id, children: nanoid!(10), external_id: None, diff --git a/frontend/rust-lib/flowy-document2/tests/document/event_handler_test.rs b/frontend/rust-lib/flowy-document2/tests/document/event_handler_test.rs new file mode 100644 index 0000000000..aa737c8889 --- /dev/null +++ b/frontend/rust-lib/flowy-document2/tests/document/event_handler_test.rs @@ -0,0 +1,32 @@ +use flowy_document2::{ + entities::{ConvertDataPayloadPB, ConvertType}, + event_handler::convert_data_to_document_internal, +}; + +#[test] +fn convert_json_to_document() { + let json_str = r#" + { + "type": "page", + "children": [ + { + "type": "paragraph1" + } + ] + }"#; + let payload = ConvertDataPayloadPB { + convert_type: ConvertType::Json, + data: json_str.as_bytes().to_vec(), + }; + let document_data = convert_data_to_document_internal(payload).unwrap(); + + let page_id = document_data.page_id; + let blocks = document_data.blocks; + let children_map = document_data.meta.children_map; + let page_block = blocks.get(&page_id).unwrap(); + let page_children = children_map.get(&page_block.children_id).unwrap(); + assert_eq!(page_children.children.len(), 1); + let paragraph1 = blocks.get(page_children.children.get(0).unwrap()).unwrap(); + assert_eq!(paragraph1.ty, "paragraph1"); + assert_eq!(paragraph1.parent_id, page_block.id); +} diff --git a/frontend/rust-lib/flowy-document2/tests/document/mod.rs b/frontend/rust-lib/flowy-document2/tests/document/mod.rs index a59fbc5ef1..5cf915fa51 100644 --- a/frontend/rust-lib/flowy-document2/tests/document/mod.rs +++ b/frontend/rust-lib/flowy-document2/tests/document/mod.rs @@ -1,3 +1,4 @@ mod document_insert_test; mod document_test; +mod event_handler_test; mod util;