Explorar o código

feat: support create document with initial data (#1841)

Nathan.fooo %!s(int64=2) %!d(string=hai) anos
pai
achega
8588afcda6

+ 2 - 2
frontend/app_flowy/lib/plugins/document/application/doc_bloc.dart

@@ -75,8 +75,8 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
   Future<void> _initial(Initial value, Emitter<DocumentState> emit) async {
     final result = await _documentService.openDocument(view: view);
     result.fold(
-      (block) {
-        final document = Document.fromJson(jsonDecode(block.snapshot));
+      (documentData) {
+        final document = Document.fromJson(jsonDecode(documentData.content));
         editorState = EditorState(document: document);
         _listenOnDocumentChange();
         emit(

+ 3 - 3
frontend/app_flowy/lib/plugins/document/application/doc_service.dart

@@ -6,14 +6,14 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
 import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart';
 
 class DocumentService {
-  Future<Either<DocumentSnapshotPB, FlowyError>> openDocument({
+  Future<Either<DocumentDataPB, FlowyError>> openDocument({
     required ViewPB view,
   }) async {
     await FolderEventSetLatestView(ViewIdPB(value: view.id)).send();
 
-    final payload = OpenDocumentContextPB()
+    final payload = OpenDocumentPayloadPB()
       ..documentId = view.id
-      ..documentVersion = DocumentVersionPB.V1;
+      ..version = DocumentVersionPB.V1;
     // switch (view.dataFormat) {
     //   case ViewDataFormatPB.DeltaFormat:
     //     payload.documentVersion = DocumentVersionPB.V0;

+ 0 - 46
frontend/app_flowy/lib/plugins/grid/application/row/row_listener.dart

@@ -1,46 +0,0 @@
-import 'package:app_flowy/core/grid_notification.dart';
-import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/notification.pb.dart';
-import 'package:flowy_infra/notifier.dart';
-import 'dart:async';
-import 'dart:typed_data';
-import 'package:dartz/dartz.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
-import 'package:appflowy_backend/protobuf/flowy-database/row_entities.pb.dart';
-
-typedef UpdateRowNotifiedValue = Either<RowPB, FlowyError>;
-typedef UpdateFieldNotifiedValue = Either<List<FieldPB>, FlowyError>;
-
-class RowListener {
-  final String rowId;
-  PublishNotifier<UpdateRowNotifiedValue>? updateRowNotifier =
-      PublishNotifier();
-  DatabaseNotificationListener? _listener;
-
-  RowListener({required this.rowId});
-
-  void start() {
-    _listener =
-        DatabaseNotificationListener(objectId: rowId, handler: _handler);
-  }
-
-  void _handler(DatabaseNotification ty, Either<Uint8List, FlowyError> result) {
-    switch (ty) {
-      case DatabaseNotification.DidUpdateRow:
-        result.fold(
-          (payload) =>
-              updateRowNotifier?.value = left(RowPB.fromBuffer(payload)),
-          (error) => updateRowNotifier?.value = right(error),
-        );
-        break;
-      default:
-        break;
-    }
-  }
-
-  Future<void> stop() async {
-    await _listener?.stop();
-    updateRowNotifier?.dispose();
-    updateRowNotifier = null;
-  }
-}

+ 8 - 50
frontend/app_flowy/lib/workspace/application/app/app_service.dart

@@ -1,4 +1,5 @@
 import 'dart:async';
+import 'dart:convert';
 
 import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart';
 import 'package:dartz/dartz.dart';
@@ -23,13 +24,18 @@ class AppService {
     required ViewDataFormatPB dataFormatType,
     required PluginType pluginType,
     required ViewLayoutTypePB layoutType,
+
+    /// The initial data should be the JSON of the doucment
+    /// For example: {"document":{"type":"editor","children":[]}}
+    String? initialData,
   }) {
-    var payload = CreateViewPayloadPB.create()
+    final payload = CreateViewPayloadPB.create()
       ..belongToId = appId
       ..name = name
       ..desc = desc ?? ""
       ..dataFormat = dataFormatType
-      ..layout = layoutType;
+      ..layout = layoutType
+      ..initialData = utf8.encode(initialData ?? "");
 
     return FolderEventCreateView(payload).send();
   }
@@ -118,54 +124,6 @@ class AppService {
   }
 }
 
-extension AppFlowy on Either {
-  T? getLeftOrNull<T>() {
-    if (isLeft()) {
-      final result = fold<T?>((l) => l, (r) => null);
-      return result;
-    }
-    return null;
-  }
-
-  Future<List<Tuple2<AppPB, List<ViewPB>>>> fetchViews(
-      ViewLayoutTypePB layoutType) async {
-    final result = <Tuple2<AppPB, List<ViewPB>>>[];
-    return FolderEventReadCurrentWorkspace().send().then((value) async {
-      final workspaces = value.getLeftOrNull<WorkspaceSettingPB>();
-      if (workspaces != null) {
-        final apps = workspaces.workspace.apps.items;
-        for (var app in apps) {
-          final views = await getViews(appId: app.id).then(
-            (value) => value
-                .getLeftOrNull<List<ViewPB>>()
-                ?.where((e) => e.layout == layoutType)
-                .toList(),
-          );
-          if (views != null && views.isNotEmpty) {
-            result.add(Tuple2(app, views));
-          }
-        }
-      }
-      return result;
-    });
-  }
-
-  Future<Either<ViewPB, FlowyError>> getView(
-    String appID,
-    String viewID,
-  ) async {
-    final payload = AppIdPB.create()..value = appID;
-    return FolderEventReadApp(payload).send().then((result) {
-      return result.fold(
-        (app) => left(
-          app.belongings.items.firstWhere((e) => e.id == viewID),
-        ),
-        (error) => right(error),
-      );
-    });
-  }
-}
-
 extension AppFlowy on Either {
   T? getLeftOrNull<T>() {
     if (isLeft()) {

+ 12 - 3
frontend/rust-lib/flowy-core/src/deps_resolve/folder_deps.rs

@@ -5,6 +5,7 @@ use flowy_client_ws::FlowyWebSocketConnect;
 use flowy_database::entities::LayoutTypePB;
 use flowy_database::manager::{make_database_view_data, DatabaseManager};
 use flowy_database::util::{make_default_board, make_default_calendar, make_default_grid};
+use flowy_document::editor::make_transaction_from_document_content;
 use flowy_document::DocumentManager;
 use flowy_folder::entities::{ViewDataFormatPB, ViewLayoutTypePB, ViewPB};
 use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap};
@@ -150,7 +151,15 @@ impl ViewDataProcessor for DocumentViewDataProcessor {
     ) -> FutureResult<(), FlowyError> {
         // Only accept Document type
         debug_assert_eq!(layout, ViewLayoutTypePB::Document);
-        let revision = Revision::initial_revision(view_id, view_data);
+        let view_data = match String::from_utf8(view_data.to_vec()) {
+            Ok(content) => match make_transaction_from_document_content(&content) {
+                Ok(transaction) => transaction.to_bytes().unwrap_or(vec![]),
+                Err(_) => vec![],
+            },
+            Err(_) => vec![],
+        };
+
+        let revision = Revision::initial_revision(view_id, Bytes::from(view_data));
         let view_id = view_id.to_string();
         let manager = self.0.clone();
 
@@ -199,7 +208,7 @@ impl ViewDataProcessor for DocumentViewDataProcessor {
         })
     }
 
-    fn create_view_from_delta_data(
+    fn create_view_with_data(
         &self,
         _user_id: &str,
         _view_id: &str,
@@ -279,7 +288,7 @@ impl ViewDataProcessor for GridViewDataProcessor {
         })
     }
 
-    fn create_view_from_delta_data(
+    fn create_view_with_data(
         &self,
         user_id: &str,
         view_id: &str,

+ 4 - 4
frontend/rust-lib/flowy-document/src/entities.rs

@@ -58,13 +58,13 @@ impl TryInto<EditParams> for EditPayloadPB {
 }
 
 #[derive(Default, ProtoBuf)]
-pub struct DocumentSnapshotPB {
+pub struct DocumentDataPB {
     #[pb(index = 1)]
     pub doc_id: String,
 
     /// Encode in JSON format
     #[pb(index = 2)]
-    pub snapshot: String,
+    pub content: String,
 }
 
 #[derive(Default, ProtoBuf)]
@@ -96,12 +96,12 @@ impl std::default::Default for DocumentVersionPB {
 }
 
 #[derive(Default, ProtoBuf)]
-pub struct OpenDocumentContextPB {
+pub struct OpenDocumentPayloadPB {
     #[pb(index = 1)]
     pub document_id: String,
 
     #[pb(index = 2)]
-    pub document_version: DocumentVersionPB,
+    pub version: DocumentVersionPB,
 }
 
 #[derive(Default, Debug)]

+ 6 - 6
frontend/rust-lib/flowy-document/src/event_handler.rs

@@ -1,5 +1,5 @@
 use crate::entities::{
-    DocumentSnapshotPB, EditParams, EditPayloadPB, ExportDataPB, ExportParams, ExportPayloadPB, OpenDocumentContextPB,
+    DocumentDataPB, EditParams, EditPayloadPB, ExportDataPB, ExportParams, ExportPayloadPB, OpenDocumentPayloadPB,
 };
 use crate::DocumentManager;
 use flowy_error::FlowyError;
@@ -9,15 +9,15 @@ use std::convert::TryInto;
 use std::sync::Arc;
 
 pub(crate) async fn get_document_handler(
-    data: AFPluginData<OpenDocumentContextPB>,
+    data: AFPluginData<OpenDocumentPayloadPB>,
     manager: AFPluginState<Arc<DocumentManager>>,
-) -> DataResult<DocumentSnapshotPB, FlowyError> {
-    let context: OpenDocumentContextPB = data.into_inner();
+) -> DataResult<DocumentDataPB, FlowyError> {
+    let context: OpenDocumentPayloadPB = data.into_inner();
     let editor = manager.open_document_editor(&context.document_id).await?;
     let document_data = editor.export().await?;
-    data_result(DocumentSnapshotPB {
+    data_result(DocumentDataPB {
         doc_id: context.document_id,
-        snapshot: document_data,
+        content: document_data,
     })
 }
 

+ 1 - 1
frontend/rust-lib/flowy-document/src/event_map.rs

@@ -19,7 +19,7 @@ pub fn init(document_manager: Arc<DocumentManager>) -> AFPlugin {
 #[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
 #[event_err = "FlowyError"]
 pub enum DocumentEvent {
-    #[event(input = "OpenDocumentContextPB", output = "DocumentSnapshotPB")]
+    #[event(input = "OpenDocumentPayloadPB", output = "DocumentDataPB")]
     GetDocument = 0,
 
     #[event(input = "EditPayloadPB")]

+ 3 - 3
frontend/rust-lib/flowy-folder/src/entities/view.rs

@@ -162,7 +162,7 @@ pub struct CreateViewPayloadPB {
     pub layout: ViewLayoutTypePB,
 
     #[pb(index = 7)]
-    pub view_content_data: Vec<u8>,
+    pub initial_data: Vec<u8>,
 }
 
 #[derive(Debug, Clone)]
@@ -174,7 +174,7 @@ pub struct CreateViewParams {
     pub data_format: ViewDataFormatPB,
     pub layout: ViewLayoutTypePB,
     pub view_id: String,
-    pub view_content_data: Vec<u8>,
+    pub initial_data: Vec<u8>,
 }
 
 impl TryInto<CreateViewParams> for CreateViewPayloadPB {
@@ -197,7 +197,7 @@ impl TryInto<CreateViewParams> for CreateViewPayloadPB {
             layout: self.layout,
             thumbnail,
             view_id,
-            view_content_data: self.view_content_data,
+            initial_data: self.initial_data,
         })
     }
 }

+ 1 - 1
frontend/rust-lib/flowy-folder/src/manager.rs

@@ -282,7 +282,7 @@ pub trait ViewDataProcessor {
         data_format: ViewDataFormatPB,
     ) -> FutureResult<Bytes, FlowyError>;
 
-    fn create_view_from_delta_data(
+    fn create_view_with_data(
         &self,
         user_id: &str,
         view_id: &str,

+ 7 - 7
frontend/rust-lib/flowy-folder/src/services/view/controller.rs

@@ -59,7 +59,7 @@ impl ViewController {
     ) -> Result<ViewRevision, FlowyError> {
         let processor = self.get_data_processor(params.data_format.clone())?;
         let user_id = self.user.user_id()?;
-        if params.view_content_data.is_empty() {
+        if params.initial_data.is_empty() {
             tracing::trace!("Create view with build-in data");
             let view_data = processor
                 .create_default_view(
@@ -69,14 +69,14 @@ impl ViewController {
                     params.data_format.clone(),
                 )
                 .await?;
-            params.view_content_data = view_data.to_vec();
+            params.initial_data = view_data.to_vec();
         } else {
             tracing::trace!("Create view with view data");
-            let delta_data = processor
-                .create_view_from_delta_data(
+            let view_data = processor
+                .create_view_with_data(
                     &user_id,
                     &params.view_id,
-                    params.view_content_data.clone(),
+                    params.initial_data.clone(),
                     params.layout.clone(),
                 )
                 .await?;
@@ -84,7 +84,7 @@ impl ViewController {
                 &params.view_id,
                 params.data_format.clone(),
                 params.layout.clone(),
-                delta_data,
+                view_data,
             )
             .await?;
         };
@@ -232,7 +232,7 @@ impl ViewController {
             thumbnail: view_rev.thumbnail,
             data_format: view_rev.data_format.into(),
             layout: view_rev.layout.into(),
-            view_content_data: view_data.to_vec(),
+            initial_data: view_data.to_vec(),
             view_id: gen_view_id(),
         };
 

+ 1 - 1
frontend/rust-lib/flowy-folder/tests/workspace/script.rs

@@ -363,7 +363,7 @@ pub async fn create_view(
         thumbnail: None,
         data_format: data_type,
         layout,
-        view_content_data: vec![],
+        initial_data: vec![],
     };
     FolderEventBuilder::new(sdk.clone())
         .event(CreateView)

+ 1 - 1
frontend/rust-lib/flowy-test/src/helper.rs

@@ -119,7 +119,7 @@ async fn create_view(
         thumbnail: Some("http://1.png".to_string()),
         data_format,
         layout,
-        view_content_data: data,
+        initial_data: data,
     };
 
     FolderEventBuilder::new(sdk.clone())