From 47081f3095fec609baa10c3b04d48c48846ead6c Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 15 Mar 2022 19:00:28 +0800 Subject: [PATCH] chore: update grid test --- .../flowy-folder-data-model/view.pb.dart | 16 +- .../flowy-folder-data-model/view.pbjson.dart | 8 +- .../flowy-grid-data-model/meta.pb.dart | 73 +++++ .../flowy-grid-data-model/meta.pbjson.dart | 12 + frontend/rust-lib/Cargo.lock | 1 + frontend/rust-lib/flowy-block/src/queue.rs | 4 +- frontend/rust-lib/flowy-folder/src/manager.rs | 6 +- .../src/services/folder_editor.rs | 4 +- .../src/services/persistence/mod.rs | 2 +- .../src/services/view/controller.rs | 13 +- frontend/rust-lib/flowy-grid/src/manager.rs | 35 ++- .../src/services/block_meta_editor.rs | 4 +- .../flowy-grid/src/services/grid_editor.rs | 12 +- frontend/rust-lib/flowy-grid/src/util.rs | 9 +- .../flowy-grid/tests/grid/grid_test.rs | 49 ++- .../rust-lib/flowy-grid/tests/grid/script.rs | 110 ++++++- frontend/rust-lib/flowy-sdk/Cargo.toml | 1 + .../flowy-sdk/src/deps_resolve/folder_deps.rs | 63 ++-- .../flowy-sync/src/conflict_resolve.rs | 4 +- frontend/rust-lib/flowy-test/src/helper.rs | 8 +- .../src/client_document/document_pad.rs | 5 +- .../src/client_folder/folder_pad.rs | 2 +- .../src/client_grid/block_pad.rs | 4 +- .../src/client_grid/grid_builder.rs | 86 ++---- .../src/client_grid/grid_pad.rs | 17 +- .../src/entities/view.rs | 4 +- .../src/protobuf/model/view.rs | 76 ++--- .../src/protobuf/proto/view.proto | 4 +- .../src/entities/meta.rs | 35 ++- .../src/protobuf/model/meta.rs | 291 +++++++++++++++++- .../src/protobuf/proto/meta.proto | 5 + shared-lib/lib-ot/src/core/delta/delta.rs | 2 +- 32 files changed, 746 insertions(+), 219 deletions(-) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart index 350b5eac85..98882f444d 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pb.dart @@ -276,7 +276,7 @@ class CreateViewPayload extends $pb.GeneratedMessage { ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.TextBlock, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values) ..a<$core.int>(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3) - ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data') + ..a<$core.List<$core.int>>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) ..hasRequiredFields = false ; @@ -288,7 +288,7 @@ class CreateViewPayload extends $pb.GeneratedMessage { $core.String? thumbnail, ViewDataType? dataType, $core.int? pluginType, - $core.String? data, + $core.List<$core.int>? data, }) { final _result = create(); if (belongToId != null) { @@ -393,9 +393,9 @@ class CreateViewPayload extends $pb.GeneratedMessage { void clearPluginType() => clearField(6); @$pb.TagNumber(7) - $core.String get data => $_getSZ(6); + $core.List<$core.int> get data => $_getN(6); @$pb.TagNumber(7) - set data($core.String v) { $_setString(6, v); } + set data($core.List<$core.int> v) { $_setBytes(6, v); } @$pb.TagNumber(7) $core.bool hasData() => $_has(6); @$pb.TagNumber(7) @@ -410,7 +410,7 @@ class CreateViewParams extends $pb.GeneratedMessage { ..aOS(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'thumbnail') ..e(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'dataType', $pb.PbFieldType.OE, defaultOrMaker: ViewDataType.TextBlock, valueOf: ViewDataType.valueOf, enumValues: ViewDataType.values) ..aOS(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'viewId') - ..aOS(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data') + ..a<$core.List<$core.int>>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'data', $pb.PbFieldType.OY) ..a<$core.int>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'pluginType', $pb.PbFieldType.O3) ..hasRequiredFields = false ; @@ -423,7 +423,7 @@ class CreateViewParams extends $pb.GeneratedMessage { $core.String? thumbnail, ViewDataType? dataType, $core.String? viewId, - $core.String? data, + $core.List<$core.int>? data, $core.int? pluginType, }) { final _result = create(); @@ -529,9 +529,9 @@ class CreateViewParams extends $pb.GeneratedMessage { void clearViewId() => clearField(6); @$pb.TagNumber(7) - $core.String get data => $_getSZ(6); + $core.List<$core.int> get data => $_getN(6); @$pb.TagNumber(7) - set data($core.String v) { $_setString(6, v); } + set data($core.List<$core.int> v) { $_setBytes(6, v); } @$pb.TagNumber(7) $core.bool hasData() => $_has(6); @$pb.TagNumber(7) diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart index 358cb41100..0f1949754f 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-folder-data-model/view.pbjson.dart @@ -60,7 +60,7 @@ const CreateViewPayload$json = const { const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '9': 0, '10': 'thumbnail'}, const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'}, const {'1': 'plugin_type', '3': 6, '4': 1, '5': 5, '10': 'pluginType'}, - const {'1': 'data', '3': 7, '4': 1, '5': 9, '10': 'data'}, + const {'1': 'data', '3': 7, '4': 1, '5': 12, '10': 'data'}, ], '8': const [ const {'1': 'one_of_thumbnail'}, @@ -68,7 +68,7 @@ const CreateViewPayload$json = const { }; /// Descriptor for `CreateViewPayload`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIfCgtwbHVnaW5fdHlwZRgGIAEoBVIKcGx1Z2luVHlwZRISCgRkYXRhGAcgASgJUgRkYXRhQhIKEG9uZV9vZl90aHVtYm5haWw='); +final $typed_data.Uint8List createViewPayloadDescriptor = $convert.base64Decode('ChFDcmVhdGVWaWV3UGF5bG9hZBIgCgxiZWxvbmdfdG9faWQYASABKAlSCmJlbG9uZ1RvSWQSEgoEbmFtZRgCIAEoCVIEbmFtZRISCgRkZXNjGAMgASgJUgRkZXNjEh4KCXRodW1ibmFpbBgEIAEoCUgAUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIfCgtwbHVnaW5fdHlwZRgGIAEoBVIKcGx1Z2luVHlwZRISCgRkYXRhGAcgASgMUgRkYXRhQhIKEG9uZV9vZl90aHVtYm5haWw='); @$core.Deprecated('Use createViewParamsDescriptor instead') const CreateViewParams$json = const { '1': 'CreateViewParams', @@ -79,13 +79,13 @@ const CreateViewParams$json = const { const {'1': 'thumbnail', '3': 4, '4': 1, '5': 9, '10': 'thumbnail'}, const {'1': 'data_type', '3': 5, '4': 1, '5': 14, '6': '.ViewDataType', '10': 'dataType'}, const {'1': 'view_id', '3': 6, '4': 1, '5': 9, '10': 'viewId'}, - const {'1': 'data', '3': 7, '4': 1, '5': 9, '10': 'data'}, + const {'1': 'data', '3': 7, '4': 1, '5': 12, '10': 'data'}, const {'1': 'plugin_type', '3': 8, '4': 1, '5': 5, '10': 'pluginType'}, ], }; /// Descriptor for `CreateViewParams`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIXCgd2aWV3X2lkGAYgASgJUgZ2aWV3SWQSEgoEZGF0YRgHIAEoCVIEZGF0YRIfCgtwbHVnaW5fdHlwZRgIIAEoBVIKcGx1Z2luVHlwZQ=='); +final $typed_data.Uint8List createViewParamsDescriptor = $convert.base64Decode('ChBDcmVhdGVWaWV3UGFyYW1zEiAKDGJlbG9uZ190b19pZBgBIAEoCVIKYmVsb25nVG9JZBISCgRuYW1lGAIgASgJUgRuYW1lEhIKBGRlc2MYAyABKAlSBGRlc2MSHAoJdGh1bWJuYWlsGAQgASgJUgl0aHVtYm5haWwSKgoJZGF0YV90eXBlGAUgASgOMg0uVmlld0RhdGFUeXBlUghkYXRhVHlwZRIXCgd2aWV3X2lkGAYgASgJUgZ2aWV3SWQSEgoEZGF0YRgHIAEoDFIEZGF0YRIfCgtwbHVnaW5fdHlwZRgIIAEoBVIKcGx1Z2luVHlwZQ=='); @$core.Deprecated('Use viewIdDescriptor instead') const ViewId$json = const { '1': 'ViewId', diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart index 49168b0274..0a0837d2df 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart @@ -1003,3 +1003,76 @@ class CellMetaChangeset extends $pb.GeneratedMessage { void clearData() => clearField(3); } +class BuildGridContext extends $pb.GeneratedMessage { + static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BuildGridContext', createEmptyInstance: create) + ..pc(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldMetas', $pb.PbFieldType.PM, subBuilder: FieldMeta.create) + ..aOM(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridBlock', subBuilder: GridBlock.create) + ..aOM(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridBlockMeta', subBuilder: GridBlockMeta.create) + ..hasRequiredFields = false + ; + + BuildGridContext._() : super(); + factory BuildGridContext({ + $core.Iterable? fieldMetas, + GridBlock? gridBlock, + GridBlockMeta? gridBlockMeta, + }) { + final _result = create(); + if (fieldMetas != null) { + _result.fieldMetas.addAll(fieldMetas); + } + if (gridBlock != null) { + _result.gridBlock = gridBlock; + } + if (gridBlockMeta != null) { + _result.gridBlockMeta = gridBlockMeta; + } + return _result; + } + factory BuildGridContext.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); + factory BuildGridContext.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.deepCopy] instead. ' + 'Will be removed in next major version') + BuildGridContext clone() => BuildGridContext()..mergeFromMessage(this); + @$core.Deprecated( + 'Using this can add significant overhead to your binary. ' + 'Use [GeneratedMessageGenericExtensions.rebuild] instead. ' + 'Will be removed in next major version') + BuildGridContext copyWith(void Function(BuildGridContext) updates) => super.copyWith((message) => updates(message as BuildGridContext)) as BuildGridContext; // ignore: deprecated_member_use + $pb.BuilderInfo get info_ => _i; + @$core.pragma('dart2js:noInline') + static BuildGridContext create() => BuildGridContext._(); + BuildGridContext createEmptyInstance() => create(); + static $pb.PbList createRepeated() => $pb.PbList(); + @$core.pragma('dart2js:noInline') + static BuildGridContext getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor(create); + static BuildGridContext? _defaultInstance; + + @$pb.TagNumber(1) + $core.List get fieldMetas => $_getList(0); + + @$pb.TagNumber(2) + GridBlock get gridBlock => $_getN(1); + @$pb.TagNumber(2) + set gridBlock(GridBlock v) { setField(2, v); } + @$pb.TagNumber(2) + $core.bool hasGridBlock() => $_has(1); + @$pb.TagNumber(2) + void clearGridBlock() => clearField(2); + @$pb.TagNumber(2) + GridBlock ensureGridBlock() => $_ensure(1); + + @$pb.TagNumber(3) + GridBlockMeta get gridBlockMeta => $_getN(2); + @$pb.TagNumber(3) + set gridBlockMeta(GridBlockMeta v) { setField(3, v); } + @$pb.TagNumber(3) + $core.bool hasGridBlockMeta() => $_has(2); + @$pb.TagNumber(3) + void clearGridBlockMeta() => clearField(3); + @$pb.TagNumber(3) + GridBlockMeta ensureGridBlockMeta() => $_ensure(2); +} + diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart index 3921f443c4..4dceb2116b 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart @@ -191,3 +191,15 @@ const CellMetaChangeset$json = const { /// Descriptor for `CellMetaChangeset`. Decode as a `google.protobuf.DescriptorProto`. final $typed_data.Uint8List cellMetaChangesetDescriptor = $convert.base64Decode('ChFDZWxsTWV0YUNoYW5nZXNldBIVCgZyb3dfaWQYASABKAlSBXJvd0lkEhkKCGZpZWxkX2lkGAIgASgJUgdmaWVsZElkEhQKBGRhdGEYAyABKAlIAFIEZGF0YUINCgtvbmVfb2ZfZGF0YQ=='); +@$core.Deprecated('Use buildGridContextDescriptor instead') +const BuildGridContext$json = const { + '1': 'BuildGridContext', + '2': const [ + const {'1': 'field_metas', '3': 1, '4': 3, '5': 11, '6': '.FieldMeta', '10': 'fieldMetas'}, + const {'1': 'grid_block', '3': 2, '4': 1, '5': 11, '6': '.GridBlock', '10': 'gridBlock'}, + const {'1': 'grid_block_meta', '3': 3, '4': 1, '5': 11, '6': '.GridBlockMeta', '10': 'gridBlockMeta'}, + ], +}; + +/// Descriptor for `BuildGridContext`. Decode as a `google.protobuf.DescriptorProto`. +final $typed_data.Uint8List buildGridContextDescriptor = $convert.base64Decode('ChBCdWlsZEdyaWRDb250ZXh0EisKC2ZpZWxkX21ldGFzGAEgAygLMgouRmllbGRNZXRhUgpmaWVsZE1ldGFzEikKCmdyaWRfYmxvY2sYAiABKAsyCi5HcmlkQmxvY2tSCWdyaWRCbG9jaxI2Cg9ncmlkX2Jsb2NrX21ldGEYAyABKAsyDi5HcmlkQmxvY2tNZXRhUg1ncmlkQmxvY2tNZXRh'); diff --git a/frontend/rust-lib/Cargo.lock b/frontend/rust-lib/Cargo.lock index a4c40e1735..30aa28a798 100755 --- a/frontend/rust-lib/Cargo.lock +++ b/frontend/rust-lib/Cargo.lock @@ -1147,6 +1147,7 @@ dependencies = [ "flowy-database", "flowy-folder", "flowy-grid", + "flowy-grid-data-model", "flowy-net", "flowy-sync", "flowy-user", diff --git a/frontend/rust-lib/flowy-block/src/queue.rs b/frontend/rust-lib/flowy-block/src/queue.rs index 94955f38d8..f7932e0850 100644 --- a/frontend/rust-lib/flowy-block/src/queue.rs +++ b/frontend/rust-lib/flowy-block/src/queue.rs @@ -175,7 +175,7 @@ impl EditBlockQueue { } async fn save_local_delta(&self, delta: RichTextDelta, md5: String) -> Result { - let delta_data = delta.to_bytes(); + let delta_data = delta.to_delta_bytes(); let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); let user_id = self.user.user_id()?; let revision = Revision::new( @@ -198,7 +198,7 @@ pub(crate) struct TextBlockRevisionCompactor(); impl RevisionCompactor for TextBlockRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { let delta = make_delta_from_revisions::(revisions)?; - Ok(delta.to_bytes()) + Ok(delta.to_delta_bytes()) } } diff --git a/frontend/rust-lib/flowy-folder/src/manager.rs b/frontend/rust-lib/flowy-folder/src/manager.rs index ffa6fc26cb..8fe34a2065 100644 --- a/frontend/rust-lib/flowy-folder/src/manager.rs +++ b/frontend/rust-lib/flowy-folder/src/manager.rs @@ -245,9 +245,11 @@ pub trait ViewDataProcessor { fn close_container(&self, view_id: &str) -> FutureResult<(), FlowyError>; - fn delta_str(&self, view_id: &str) -> FutureResult; + fn delta_bytes(&self, view_id: &str) -> FutureResult; - fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult; + fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult; + + fn process_create_view_data(&self, user_id: &str, view_id: &str, data: Vec) -> FutureResult; fn data_type(&self) -> ViewDataType; } diff --git a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs index 7aaa1de7cd..48c83cc612 100644 --- a/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs +++ b/frontend/rust-lib/flowy-folder/src/services/folder_editor.rs @@ -71,7 +71,7 @@ impl ClientFolderEditor { pub(crate) fn apply_change(&self, change: FolderChange) -> FlowyResult<()> { let FolderChange { delta, md5 } = change; let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); - let delta_data = delta.to_bytes(); + let delta_data = delta.to_delta_bytes(); let revision = Revision::new( &self.rev_manager.object_id, base_rev_id, @@ -128,6 +128,6 @@ struct FolderRevisionCompactor(); impl RevisionCompactor for FolderRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { let delta = make_delta_from_revisions::(revisions)?; - Ok(delta.to_bytes()) + Ok(delta.to_delta_bytes()) } } diff --git a/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs b/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs index b05490b70a..16417934e0 100644 --- a/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs +++ b/frontend/rust-lib/flowy-folder/src/services/persistence/mod.rs @@ -115,7 +115,7 @@ impl FolderPersistence { pub async fn save_folder(&self, user_id: &str, folder_id: &FolderId, folder: FolderPad) -> FlowyResult<()> { let pool = self.database.db_pool()?; - let delta_data = initial_folder_delta(&folder)?.to_bytes(); + let delta_data = initial_folder_delta(&folder)?.to_delta_bytes(); let md5 = folder.md5(); let revision = Revision::new(folder_id.as_ref(), 0, 0, delta_data, user_id, md5); let record = RevisionRecord { diff --git a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs index 2d943df032..c9851d6652 100644 --- a/frontend/rust-lib/flowy-folder/src/services/view/controller.rs +++ b/frontend/rust-lib/flowy-folder/src/services/view/controller.rs @@ -55,13 +55,14 @@ impl ViewController { #[tracing::instrument(level = "trace", skip(self, params), fields(name = %params.name), err)] pub(crate) async fn create_view_from_params(&self, mut params: CreateViewParams) -> Result { let processor = self.get_data_processor(¶ms.data_type)?; - + let user_id = self.user.user_id()?; if params.data.is_empty() { - let user_id = self.user.user_id()?; let view_data = processor.create_default_view(&user_id, ¶ms.view_id).await?; - params.data = view_data; + params.data = view_data.to_vec(); } else { - let delta_data = Bytes::from(params.data.clone()); + let delta_data = processor + .process_create_view_data(&user_id, ¶ms.view_id, params.data.clone()) + .await?; let _ = self .create_view(¶ms.view_id, params.data_type.clone(), delta_data) .await?; @@ -162,14 +163,14 @@ impl ViewController { .await?; let processor = self.get_data_processor(&view.data_type)?; - let delta_str = processor.delta_str(view_id).await?; + let delta_bytes = processor.delta_bytes(view_id).await?; let duplicate_params = CreateViewParams { belong_to_id: view.belong_to_id.clone(), name: format!("{} (copy)", &view.name), desc: view.desc, thumbnail: view.thumbnail, data_type: view.data_type, - data: delta_str, + data: delta_bytes.to_vec(), view_id: uuid(), plugin_type: view.plugin_type, }; diff --git a/frontend/rust-lib/flowy-grid/src/manager.rs b/frontend/rust-lib/flowy-grid/src/manager.rs index fc79fcf5c0..28a246bd75 100644 --- a/frontend/rust-lib/flowy-grid/src/manager.rs +++ b/frontend/rust-lib/flowy-grid/src/manager.rs @@ -1,8 +1,11 @@ use crate::services::grid_editor::ClientGridEditor; use crate::services::kv_persistence::GridKVPersistence; +use bytes::Bytes; use dashmap::DashMap; -use flowy_collaboration::entities::revision::RepeatedRevision; +use flowy_collaboration::client_grid::{make_block_meta_delta, make_grid_delta}; +use flowy_collaboration::entities::revision::{RepeatedRevision, Revision}; use flowy_error::{FlowyError, FlowyResult}; +use flowy_grid_data_model::entities::{BuildGridContext, GridMeta}; use flowy_sync::disk::{SQLiteGridBlockMetaRevisionPersistence, SQLiteGridRevisionPersistence}; use flowy_sync::{RevisionManager, RevisionPersistence, RevisionWebSocket}; use lib_sqlite::ConnectionPool; @@ -172,3 +175,33 @@ impl GridEditorMap { self.inner.remove(grid_id); } } + +pub async fn make_grid_view_data( + user_id: &str, + view_id: &str, + grid_manager: Arc, + build_context: BuildGridContext, +) -> FlowyResult { + let block_id = build_context.grid_block.id.clone(); + let grid_meta = GridMeta { + grid_id: view_id.to_string(), + fields: build_context.field_metas, + blocks: vec![build_context.grid_block], + }; + + let grid_meta_delta = make_grid_delta(&grid_meta); + let grid_delta_data = grid_meta_delta.to_delta_bytes(); + let repeated_revision: RepeatedRevision = + Revision::initial_revision(user_id, view_id, grid_delta_data.clone()).into(); + let _ = grid_manager.create_grid(view_id, repeated_revision).await?; + + let grid_block_meta_delta = make_block_meta_delta(&build_context.grid_block_meta); + let block_meta_delta_data = grid_block_meta_delta.to_delta_bytes(); + let repeated_revision: RepeatedRevision = + Revision::initial_revision(&user_id, &block_id, block_meta_delta_data).into(); + let _ = grid_manager + .create_grid_block_meta(&block_id, repeated_revision) + .await?; + + Ok(grid_delta_data) +} diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs index c691e0b12c..fb72f8c34d 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs @@ -280,7 +280,7 @@ impl ClientGridBlockMetaEditor { let GridBlockMetaChange { delta, md5 } = change; let user_id = self.user_id.clone(); let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); - let delta_data = delta.to_bytes(); + let delta_data = delta.to_delta_bytes(); let revision = Revision::new( &self.rev_manager.object_id, base_rev_id, @@ -323,6 +323,6 @@ struct GridBlockMetaRevisionCompactor(); impl RevisionCompactor for GridBlockMetaRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { let delta = make_delta_from_revisions::(revisions)?; - Ok(delta.to_bytes()) + Ok(delta.to_delta_bytes()) } } diff --git a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs index e45dad5394..86c7a8fc0e 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -61,6 +61,10 @@ impl ClientGridEditor { Ok(()) } + pub async fn contain_field(&self, field_meta: &FieldMeta) -> bool { + self.grid_meta_pad.read().await.contain_field(&field_meta.id) + } + pub async fn update_field(&self, change: FieldChangeset) -> FlowyResult<()> { let _ = self.modify(|grid| Ok(grid.update_field(change)?)).await?; Ok(()) @@ -177,8 +181,8 @@ impl ClientGridEditor { Ok(grid_blocks) } - pub async fn delta_str(&self) -> String { - self.grid_meta_pad.read().await.delta_str() + pub async fn delta_bytes(&self) -> Bytes { + self.grid_meta_pad.read().await.delta_bytes() } async fn modify(&self, f: F) -> FlowyResult<()> @@ -199,7 +203,7 @@ impl ClientGridEditor { let GridChange { delta, md5 } = change; let user_id = self.user.user_id()?; let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair(); - let delta_data = delta.to_bytes(); + let delta_data = delta.to_delta_bytes(); let revision = Revision::new( &self.rev_manager.object_id, base_rev_id, @@ -256,6 +260,6 @@ struct GridRevisionCompactor(); impl RevisionCompactor for GridRevisionCompactor { fn bytes_from_revisions(&self, revisions: Vec) -> FlowyResult { let delta = make_delta_from_revisions::(revisions)?; - Ok(delta.to_bytes()) + Ok(delta.to_delta_bytes()) } } diff --git a/frontend/rust-lib/flowy-grid/src/util.rs b/frontend/rust-lib/flowy-grid/src/util.rs index 80f942751a..e7417b5ea7 100644 --- a/frontend/rust-lib/flowy-grid/src/util.rs +++ b/frontend/rust-lib/flowy-grid/src/util.rs @@ -1,9 +1,9 @@ use crate::services::cell::*; use crate::services::field::*; -use flowy_collaboration::client_grid::{BuildGridInfo, GridBuilder}; -use flowy_grid_data_model::entities::FieldType; +use flowy_collaboration::client_grid::GridBuilder; +use flowy_grid_data_model::entities::{BuildGridContext, FieldType}; -pub fn make_default_grid(grid_id: &str) -> BuildGridInfo { +pub fn make_default_grid() -> BuildGridContext { let text_field = FieldBuilder::new(RichTextTypeOptionsBuilder::default()) .name("Name") .visibility(true) @@ -20,12 +20,11 @@ pub fn make_default_grid(grid_id: &str) -> BuildGridInfo { .field_type(FieldType::SingleSelect) .build(); - GridBuilder::new(grid_id) + GridBuilder::default() .add_field(text_field) .add_field(single_select_field) .add_empty_row() .add_empty_row() .add_empty_row() .build() - .unwrap() } diff --git a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs index 910589eb53..30469d406f 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/grid_test.rs @@ -4,57 +4,56 @@ use flowy_grid::services::cell::*; use flowy_grid::services::row::{deserialize_cell_data, serialize_cell_data, CellDataSerde, CreateRowContextBuilder}; use flowy_grid_data_model::entities::{FieldChangeset, FieldType, GridBlock, GridBlockChangeset, RowMetaChangeset}; -#[tokio::test] -async fn default_grid_test() { - let scripts = vec![AssertFieldCount(2), AssertGridMetaPad]; - GridEditorTest::new().await.run_scripts(scripts).await; -} - #[tokio::test] async fn grid_create_field() { + let mut test = GridEditorTest::new().await; let text_field = create_text_field(); let single_select_field = create_single_select_field(); + let scripts = vec![ - AssertFieldCount(2), CreateField { field_meta: text_field.clone(), }, AssertFieldEqual { - field_index: 2, + field_index: test.field_count, field_meta: text_field, }, - AssertFieldCount(3), + ]; + test.run_scripts(scripts).await; + + let scripts = vec![ CreateField { field_meta: single_select_field.clone(), }, AssertFieldEqual { - field_index: 3, + field_index: test.field_count, field_meta: single_select_field, }, - AssertFieldCount(4), ]; - GridEditorTest::new().await.run_scripts(scripts).await; + test.run_scripts(scripts).await; } #[tokio::test] async fn grid_create_duplicate_field() { + let mut test = GridEditorTest::new().await; let text_field = create_text_field(); + let field_count = test.field_count; + let expected_field_count = field_count + 1; let scripts = vec![ - AssertFieldCount(2), CreateField { field_meta: text_field.clone(), }, - AssertFieldCount(3), CreateField { field_meta: text_field.clone(), }, - AssertFieldCount(3), + AssertFieldCount(expected_field_count), ]; - GridEditorTest::new().await.run_scripts(scripts).await; + test.run_scripts(scripts).await; } #[tokio::test] async fn grid_update_field_with_empty_change() { + let mut test = GridEditorTest::new().await; let single_select_field = create_single_select_field(); let changeset = FieldChangeset { field_id: single_select_field.id.clone(), @@ -73,21 +72,21 @@ async fn grid_update_field_with_empty_change() { }, UpdateField { changeset }, AssertFieldEqual { - field_index: 2, + field_index: test.field_count, field_meta: single_select_field, }, ]; - GridEditorTest::new().await.run_scripts(scripts).await; + test.run_scripts(scripts).await; } #[tokio::test] async fn grid_update_field() { + let mut test = GridEditorTest::new().await; let single_select_field = create_single_select_field(); let mut cloned_field = single_select_field.clone(); let mut single_select_type_options = SingleSelectDescription::from(&single_select_field); single_select_type_options.options.push(SelectOption::new("Unknown")); - let changeset = FieldChangeset { field_id: single_select_field.id.clone(), name: None, @@ -109,26 +108,26 @@ async fn grid_update_field() { }, UpdateField { changeset }, AssertFieldEqual { - field_index: 2, + field_index: test.field_count, field_meta: cloned_field, }, - AssertGridMetaPad, ]; - GridEditorTest::new().await.run_scripts(scripts).await; + test.run_scripts(scripts).await; } #[tokio::test] async fn grid_delete_field() { + let mut test = GridEditorTest::new().await; + let expected_field_count = test.field_count; let text_field = create_text_field(); let scripts = vec![ CreateField { field_meta: text_field.clone(), }, - AssertFieldCount(3), DeleteField { field_meta: text_field }, - AssertFieldCount(2), + AssertFieldCount(expected_field_count), ]; - GridEditorTest::new().await.run_scripts(scripts).await; + test.run_scripts(scripts).await; } #[tokio::test] diff --git a/frontend/rust-lib/flowy-grid/tests/grid/script.rs b/frontend/rust-lib/flowy-grid/tests/grid/script.rs index 777bad2949..c49bf82a03 100644 --- a/frontend/rust-lib/flowy-grid/tests/grid/script.rs +++ b/frontend/rust-lib/flowy-grid/tests/grid/script.rs @@ -1,15 +1,22 @@ +use bytes::Bytes; +use flowy_collaboration::client_grid::GridBuilder; +use flowy_collaboration::entities::revision::{RepeatedRevision, Revision}; +use flowy_error::FlowyResult; +use flowy_grid::manager::{make_grid_view_data, GridManager}; use flowy_grid::services::cell::*; use flowy_grid::services::field::*; use flowy_grid::services::grid_editor::{ClientGridEditor, GridPadBuilder}; use flowy_grid::services::row::CreateRowContext; use flowy_grid_data_model::entities::{ - CellMetaChangeset, FieldChangeset, FieldMeta, FieldType, GridBlock, GridBlockChangeset, RowMeta, RowMetaChangeset, + BuildGridContext, CellMetaChangeset, FieldChangeset, FieldMeta, FieldType, GridBlock, GridBlockChangeset, RowMeta, + RowMetaChangeset, }; use flowy_sync::REVISION_WRITE_INTERVAL_IN_MILLIS; use flowy_test::helper::ViewTest; use flowy_test::FlowySDKTest; use std::sync::Arc; use std::time::Duration; +use strum::{EnumCount, IntoEnumIterator}; use tokio::time::sleep; pub enum EditorScript { @@ -71,19 +78,18 @@ pub struct GridEditorTest { pub field_metas: Vec, pub grid_blocks: Vec, pub row_metas: Vec>, + pub field_count: usize, } impl GridEditorTest { pub async fn new() -> Self { - Self::with_data("".to_owned()).await - } - - pub async fn with_data(data: String) -> Self { let sdk = FlowySDKTest::default(); let _ = sdk.init_user().await; - let test = ViewTest::new_grid_view(&sdk, data).await; + let build_context = make_template_1_grid(); + let view_data: Bytes = build_context.try_into().unwrap(); + let test = ViewTest::new_grid_view(&sdk, view_data.to_vec()).await; let editor = sdk.grid_manager.open_grid(&test.view.id).await.unwrap(); - let fields = editor.get_field_metas(None).await.unwrap(); + let field_metas = editor.get_field_metas(None).await.unwrap(); let grid_blocks = editor.get_blocks().await.unwrap(); let row_metas = editor.get_row_metas(None).await.unwrap(); @@ -92,9 +98,10 @@ impl GridEditorTest { sdk, grid_id, editor, - field_metas: fields, + field_metas, grid_blocks, row_metas, + field_count: FieldType::COUNT, } } @@ -111,22 +118,30 @@ impl GridEditorTest { let _cache = rev_manager.revision_cache().await; match script { - EditorScript::CreateField { field_meta: field } => { - self.editor.create_field(field).await.unwrap(); + EditorScript::CreateField { field_meta } => { + if !self.editor.contain_field(&field_meta).await { + self.field_count += 1; + } + self.editor.create_field(field_meta).await.unwrap(); self.field_metas = self.editor.get_field_metas(None).await.unwrap(); + assert_eq!(self.field_count, self.field_metas.len()); } EditorScript::UpdateField { changeset: change } => { self.editor.update_field(change).await.unwrap(); self.field_metas = self.editor.get_field_metas(None).await.unwrap(); } - EditorScript::DeleteField { field_meta: field } => { - self.editor.delete_field(&field.id).await.unwrap(); + EditorScript::DeleteField { field_meta } => { + if self.editor.contain_field(&field_meta).await { + self.field_count -= 1; + } + + self.editor.delete_field(&field_meta.id).await.unwrap(); self.field_metas = self.editor.get_field_metas(None).await.unwrap(); + assert_eq!(self.field_count, self.field_metas.len()); } EditorScript::AssertFieldCount(count) => { assert_eq!(self.editor.get_field_metas(None).await.unwrap().len(), count); } - EditorScript::AssertFieldEqual { field_index, field_meta, @@ -220,3 +235,72 @@ pub fn create_single_select_field() -> FieldMeta { .field_type(FieldType::SingleSelect) .build() } + +fn make_template_1_grid() -> BuildGridContext { + let text_field = FieldBuilder::new(RichTextTypeOptionsBuilder::default()) + .name("Name") + .visibility(true) + .field_type(FieldType::RichText) + .build(); + + // Single Select + let single_select = SingleSelectTypeOptionsBuilder::default() + .option(SelectOption::new("Live")) + .option(SelectOption::new("Completed")) + .option(SelectOption::new("Planned")) + .option(SelectOption::new("Paused")); + let single_select_field = FieldBuilder::new(single_select) + .name("Status") + .visibility(true) + .field_type(FieldType::SingleSelect) + .build(); + + // MultiSelect + let multi_select = MultiSelectTypeOptionsBuilder::default() + .option(SelectOption::new("Google")) + .option(SelectOption::new("Facebook")) + .option(SelectOption::new("Twitter")); + let multi_select_field = FieldBuilder::new(multi_select) + .name("Platform") + .visibility(true) + .field_type(FieldType::MultiSelect) + .build(); + + // Number + let number = NumberTypeOptionsBuilder::default().set_format(NumberFormat::USD); + let number_field = FieldBuilder::new(number) + .name("Price") + .visibility(true) + .field_type(FieldType::Number) + .build(); + + // Date + let date = DateTypeOptionsBuilder::default() + .date_format(DateFormat::US) + .time_format(TimeFormat::TwentyFourHour); + let date_field = FieldBuilder::new(date) + .name("Time") + .visibility(true) + .field_type(FieldType::DateTime) + .build(); + + // Checkbox + let checkbox = CheckboxTypeOptionsBuilder::default(); + let checkbox_field = FieldBuilder::new(checkbox) + .name("is done") + .visibility(true) + .field_type(FieldType::Checkbox) + .build(); + + GridBuilder::default() + .add_field(text_field) + .add_field(single_select_field) + .add_field(multi_select_field) + .add_field(number_field) + .add_field(date_field) + .add_field(checkbox_field) + .add_empty_row() + .add_empty_row() + .add_empty_row() + .build() +} diff --git a/frontend/rust-lib/flowy-sdk/Cargo.toml b/frontend/rust-lib/flowy-sdk/Cargo.toml index 75791d0279..75ab8a3b5c 100644 --- a/frontend/rust-lib/flowy-sdk/Cargo.toml +++ b/frontend/rust-lib/flowy-sdk/Cargo.toml @@ -12,6 +12,7 @@ flowy-user = { path = "../flowy-user" } flowy-net = { path = "../flowy-net" } flowy-folder = { path = "../flowy-folder", default-features = false } flowy-grid = { path = "../flowy-grid", default-features = false } +flowy-grid-data-model = { path = "../../../shared-lib/flowy-grid-data-model" } flowy-database = { path = "../flowy-database" } flowy-block = { path = "../flowy-block", default-features = false } flowy-sync = { path = "../flowy-sync" } diff --git a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs index 0646dbcc5b..89346eaf35 100644 --- a/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs +++ b/frontend/rust-lib/flowy-sdk/src/deps_resolve/folder_deps.rs @@ -4,6 +4,7 @@ use flowy_collaboration::client_document::default::initial_quill_delta_string; use flowy_collaboration::entities::revision::{RepeatedRevision, Revision}; use flowy_collaboration::entities::ws_data::ClientRevisionWSData; use flowy_database::ConnectionPool; +use flowy_folder::errors::FlowyResult; use flowy_folder::manager::{ViewDataProcessor, ViewDataProcessorMap}; use flowy_folder::prelude::ViewDataType; use flowy_folder::{ @@ -11,8 +12,9 @@ use flowy_folder::{ event_map::{FolderCouldServiceV1, WorkspaceDatabase, WorkspaceUser}, manager::FolderManager, }; -use flowy_grid::manager::GridManager; +use flowy_grid::manager::{make_grid_view_data, GridManager}; use flowy_grid::util::make_default_grid; +use flowy_grid_data_model::entities::BuildGridContext; use flowy_net::ClientServerConfiguration; use flowy_net::{ http_server::folder::FolderHttpCloudService, local_server::LocalServer, ws::connection::FlowyWebSocketConnect, @@ -23,6 +25,7 @@ use futures_core::future::BoxFuture; use lib_infra::future::{BoxResultFuture, FutureResult}; use lib_ws::{WSChannel, WSMessageReceiver, WebSocketRawMessage}; use std::collections::HashMap; +use std::convert::TryFrom; use std::{convert::TryInto, sync::Arc}; pub struct FolderDepsResolver(); @@ -168,29 +171,39 @@ impl ViewDataProcessor for TextBlockViewDataProcessor { }) } - fn delta_str(&self, view_id: &str) -> FutureResult { + fn delta_bytes(&self, view_id: &str) -> FutureResult { let view_id = view_id.to_string(); let manager = self.0.clone(); FutureResult::new(async move { let editor = manager.open_block(view_id).await?; - let delta_str = editor.delta_str().await?; - Ok(delta_str) + let delta_bytes = Bytes::from(editor.delta_str().await?); + Ok(delta_bytes) }) } - fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult { + fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult { let user_id = user_id.to_string(); let view_id = view_id.to_string(); let manager = self.0.clone(); FutureResult::new(async move { let view_data = initial_quill_delta_string(); - let delta_data = Bytes::from(view_data.clone()); - let repeated_revision: RepeatedRevision = Revision::initial_revision(&user_id, &view_id, delta_data).into(); + let delta_data = Bytes::from(view_data); + let repeated_revision: RepeatedRevision = + Revision::initial_revision(&user_id, &view_id, delta_data.clone()).into(); let _ = manager.create_block(view_id, repeated_revision).await?; - Ok(view_data) + Ok(delta_data) }) } + fn process_create_view_data( + &self, + _user_id: &str, + _view_id: &str, + data: Vec, + ) -> FutureResult { + FutureResult::new(async move { Ok(Bytes::from(data)) }) + } + fn data_type(&self) -> ViewDataType { ViewDataType::TextBlock } @@ -230,36 +243,34 @@ impl ViewDataProcessor for GridViewDataProcessor { }) } - fn delta_str(&self, view_id: &str) -> FutureResult { + fn delta_bytes(&self, view_id: &str) -> FutureResult { let view_id = view_id.to_string(); let grid_manager = self.0.clone(); FutureResult::new(async move { let editor = grid_manager.open_grid(view_id).await?; - let delta_str = editor.delta_str().await; - Ok(delta_str) + let delta_bytes = editor.delta_bytes().await; + Ok(delta_bytes) }) } - fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult { - let info = make_default_grid(view_id); + fn create_default_view(&self, user_id: &str, view_id: &str) -> FutureResult { + let build_context = make_default_grid(); + let user_id = user_id.to_string(); + let view_id = view_id.to_string(); + let grid_manager = self.0.clone(); + + FutureResult::new(async move { make_grid_view_data(&user_id, &view_id, grid_manager, build_context).await }) + } + + fn process_create_view_data(&self, user_id: &str, view_id: &str, data: Vec) -> FutureResult { let user_id = user_id.to_string(); let view_id = view_id.to_string(); let grid_manager = self.0.clone(); FutureResult::new(async move { - let grid_delta_data = Bytes::from(info.grid_delta.to_delta_str()); - let repeated_revision: RepeatedRevision = - Revision::initial_revision(&user_id, &view_id, grid_delta_data).into(); - let _ = grid_manager.create_grid(&view_id, repeated_revision).await?; - - let block_meta_delta_data = Bytes::from(info.grid_block_meta_delta.to_delta_str()); - let repeated_revision: RepeatedRevision = - Revision::initial_revision(&user_id, &info.block_id, block_meta_delta_data).into(); - let _ = grid_manager - .create_grid_block_meta(&info.block_id, repeated_revision) - .await?; - - Ok(info.grid_delta.to_delta_str()) + let bytes = Bytes::from(data); + let build_context = BuildGridContext::try_from(bytes)?; + make_grid_view_data(&user_id, &view_id, grid_manager, build_context).await }) } diff --git a/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs b/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs index 817b77bd88..a4f4f6c818 100644 --- a/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs +++ b/frontend/rust-lib/flowy-sync/src/conflict_resolve.rs @@ -154,7 +154,7 @@ where &rev_manager.object_id, base_rev_id, rev_id, - client_delta.to_bytes(), + client_delta.to_delta_bytes(), user_id, md5.clone(), ); @@ -166,7 +166,7 @@ where &rev_manager.object_id, base_rev_id, rev_id, - server_delta.to_bytes(), + server_delta.to_delta_bytes(), user_id, md5, ); diff --git a/frontend/rust-lib/flowy-test/src/helper.rs b/frontend/rust-lib/flowy-test/src/helper.rs index 03c4077831..f83f245754 100644 --- a/frontend/rust-lib/flowy-test/src/helper.rs +++ b/frontend/rust-lib/flowy-test/src/helper.rs @@ -26,7 +26,7 @@ pub struct ViewTest { impl ViewTest { #[allow(dead_code)] - pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataType, data: String) -> Self { + pub async fn new(sdk: &FlowySDKTest, data_type: ViewDataType, data: Vec) -> Self { let workspace = create_workspace(sdk, "Workspace", "").await; open_workspace(sdk, &workspace.id).await; let app = create_app(sdk, "App", "AppFlowy GitHub Project", &workspace.id).await; @@ -39,12 +39,12 @@ impl ViewTest { } } - pub async fn new_grid_view(sdk: &FlowySDKTest, data: String) -> Self { + pub async fn new_grid_view(sdk: &FlowySDKTest, data: Vec) -> Self { Self::new(sdk, ViewDataType::Grid, data).await } pub async fn new_text_block_view(sdk: &FlowySDKTest) -> Self { - Self::new(sdk, ViewDataType::TextBlock, "".to_owned()).await + Self::new(sdk, ViewDataType::TextBlock, vec![]).await } } @@ -91,7 +91,7 @@ async fn create_app(sdk: &FlowySDKTest, name: &str, desc: &str, workspace_id: &s app } -async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataType, data: String) -> View { +async fn create_view(sdk: &FlowySDKTest, app_id: &str, data_type: ViewDataType, data: Vec) -> View { let request = CreateViewPayload { belong_to_id: app_id.to_string(), name: "View A".to_string(), diff --git a/shared-lib/flowy-collaboration/src/client_document/document_pad.rs b/shared-lib/flowy-collaboration/src/client_document/document_pad.rs index 4807d9869c..72b52f6415 100644 --- a/shared-lib/flowy-collaboration/src/client_document/document_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_document/document_pad.rs @@ -6,6 +6,7 @@ use crate::{ }, errors::CollaborateError, }; +use bytes::Bytes; use lib_ot::{ core::*, rich_text::{RichTextAttribute, RichTextDelta}, @@ -62,8 +63,8 @@ impl ClientDocument { self.delta.to_delta_str() } - pub fn to_bytes(&self) -> Vec { - self.delta.clone().to_bytes().to_vec() + pub fn to_bytes(&self) -> Bytes { + self.delta.to_delta_bytes() } pub fn to_plain_string(&self) -> String { diff --git a/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs b/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs index 4fd8a1982e..fd79fb8af0 100644 --- a/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_folder/folder_pad.rs @@ -268,7 +268,7 @@ impl FolderPad { } pub fn md5(&self) -> String { - md5(&self.delta.to_bytes()) + md5(&self.delta.to_delta_bytes()) } pub fn to_json(&self) -> CollaborateResult { diff --git a/shared-lib/flowy-collaboration/src/client_grid/block_pad.rs b/shared-lib/flowy-collaboration/src/client_grid/block_pad.rs index bd8379845a..fafa2d45ce 100644 --- a/shared-lib/flowy-collaboration/src/client_grid/block_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_grid/block_pad.rs @@ -144,7 +144,7 @@ impl GridBlockMetaPad { } pub fn md5(&self) -> String { - md5(&self.delta.to_bytes()) + md5(&self.delta.to_delta_bytes()) } pub fn delta_str(&self) -> String { @@ -165,7 +165,7 @@ pub fn make_block_meta_delta(block_meta: &GridBlockMeta) -> GridBlockMetaDelta { pub fn make_block_meta_revisions(user_id: &str, block_meta: &GridBlockMeta) -> RepeatedRevision { let delta = make_block_meta_delta(block_meta); - let bytes = delta.to_bytes(); + let bytes = delta.to_delta_bytes(); let revision = Revision::initial_revision(user_id, &block_meta.block_id, bytes); revision.into() } diff --git a/shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs b/shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs index cbf31463a4..42faa4abda 100644 --- a/shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs +++ b/shared-lib/flowy-collaboration/src/client_grid/grid_builder.rs @@ -1,66 +1,37 @@ use crate::client_grid::{make_block_meta_delta, make_grid_delta, GridBlockMetaDelta, GridMetaDelta}; use crate::errors::{CollaborateError, CollaborateResult}; -use flowy_grid_data_model::entities::{FieldMeta, GridBlock, GridBlockMeta, GridMeta, RowMeta}; +use flowy_grid_data_model::entities::{BuildGridContext, FieldMeta, GridBlock, GridBlockMeta, GridMeta, RowMeta}; pub struct GridBuilder { - grid_id: String, - fields: Vec, - grid_block: GridBlock, - grid_block_meta: GridBlockMeta, + build_context: BuildGridContext, +} + +impl std::default::Default for GridBuilder { + fn default() -> Self { + Self { + build_context: Default::default(), + } + } } impl GridBuilder { - pub fn new(grid_id: &str) -> Self { - let grid_block = GridBlock::new(); - let grid_block_meta = GridBlockMeta { - block_id: grid_block.id.clone(), - rows: vec![], - }; - - Self { - grid_id: grid_id.to_owned(), - fields: vec![], - grid_block, - grid_block_meta, - } - } - pub fn add_field(mut self, field: FieldMeta) -> Self { - self.fields.push(field); + self.build_context.field_metas.push(field); self } pub fn add_empty_row(mut self) -> Self { - let row = RowMeta::new(&self.grid_block.id); - self.grid_block_meta.rows.push(row); - self.grid_block.row_count += 1; + let row = RowMeta::new(&self.build_context.grid_block.id); + self.build_context.grid_block_meta.rows.push(row); + self.build_context.grid_block.row_count += 1; self } - pub fn build(self) -> CollaborateResult { - let block_id = self.grid_block.id.clone(); - let grid_meta = GridMeta { - grid_id: self.grid_id, - fields: self.fields, - blocks: vec![self.grid_block], - }; - // let _ = check_rows(&self.fields, &self.rows)?; - let grid_delta = make_grid_delta(&grid_meta); - let grid_block_meta_delta = make_block_meta_delta(&self.grid_block_meta); - Ok(BuildGridInfo { - grid_delta, - block_id, - grid_block_meta_delta, - }) + pub fn build(self) -> BuildGridContext { + self.build_context } } -pub struct BuildGridInfo { - pub grid_delta: GridMetaDelta, - pub block_id: String, - pub grid_block_meta_delta: GridBlockMetaDelta, -} - #[allow(dead_code)] fn check_rows(fields: &[FieldMeta], rows: &[RowMeta]) -> CollaborateResult<()> { let field_ids = fields.iter().map(|field| &field.id).collect::>(); @@ -76,28 +47,31 @@ fn check_rows(fields: &[FieldMeta], rows: &[RowMeta]) -> CollaborateResult<()> { #[cfg(test)] mod tests { - use crate::client_grid::GridBuilder; + + use crate::client_grid::{make_block_meta_delta, make_grid_delta, GridBuilder}; use flowy_grid_data_model::entities::{FieldMeta, FieldType, GridBlockMeta, GridMeta}; #[test] fn create_default_grid_test() { - let info = GridBuilder::new("1") + let grid_id = "1".to_owned(); + let build_context = GridBuilder::default() .add_field(FieldMeta::new("Name", "", FieldType::RichText)) .add_field(FieldMeta::new("Tags", "", FieldType::SingleSelect)) .add_empty_row() .add_empty_row() .add_empty_row() - .build() - .unwrap(); + .build(); - let grid_meta: GridMeta = serde_json::from_str(&info.grid_delta.to_str().unwrap()).unwrap(); - assert_eq!(grid_meta.fields.len(), 2); - assert_eq!(grid_meta.blocks.len(), 1); + let grid_meta = GridMeta { + grid_id: grid_id.clone(), + fields: build_context.field_metas, + blocks: vec![build_context.grid_block], + }; - let grid_block_meta: GridBlockMeta = - serde_json::from_str(&info.grid_block_meta_delta.to_str().unwrap()).unwrap(); - assert_eq!(grid_block_meta.rows.len(), 3); + let grid_meta_delta = make_grid_delta(&grid_meta); + let _: GridMeta = serde_json::from_str(&grid_meta_delta.to_str().unwrap()).unwrap(); - assert_eq!(grid_meta.blocks[0].id, grid_block_meta.block_id); + let grid_block_meta_delta = make_block_meta_delta(&build_context.grid_block_meta); + let _: GridBlockMeta = serde_json::from_str(&grid_block_meta_delta.to_str().unwrap()).unwrap(); } } diff --git a/shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs b/shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs index f303990546..bcae5144a8 100644 --- a/shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs +++ b/shared-lib/flowy-collaboration/src/client_grid/grid_pad.rs @@ -1,6 +1,7 @@ use crate::entities::revision::{md5, RepeatedRevision, Revision}; use crate::errors::{internal_error, CollaborateError, CollaborateResult}; use crate::util::{cal_diff, make_delta_from_revisions}; +use bytes::Bytes; use flowy_grid_data_model::entities::{ FieldChangeset, FieldMeta, FieldOrder, GridBlock, GridBlockChangeset, GridMeta, RepeatedFieldOrder, }; @@ -56,6 +57,14 @@ impl GridMetaPad { }) } + pub fn contain_field(&self, field_id: &str) -> bool { + self.grid_meta + .fields + .iter() + .find(|field| &field.id == field_id) + .is_some() + } + pub fn get_field_orders(&self) -> Vec { self.grid_meta .fields @@ -180,13 +189,17 @@ impl GridMetaPad { } pub fn md5(&self) -> String { - md5(&self.delta.to_bytes()) + md5(&self.delta.to_delta_bytes()) } pub fn delta_str(&self) -> String { self.delta.to_delta_str() } + pub fn delta_bytes(&self) -> Bytes { + self.delta.to_delta_bytes() + } + pub fn fields(&self) -> &[FieldMeta] { &self.grid_meta.fields } @@ -258,7 +271,7 @@ pub fn make_grid_delta(grid_meta: &GridMeta) -> GridMetaDelta { pub fn make_grid_revisions(user_id: &str, grid_meta: &GridMeta) -> RepeatedRevision { let delta = make_grid_delta(grid_meta); - let bytes = delta.to_bytes(); + let bytes = delta.to_delta_bytes(); let revision = Revision::initial_revision(user_id, &grid_meta.grid_id, bytes); revision.into() } diff --git a/shared-lib/flowy-folder-data-model/src/entities/view.rs b/shared-lib/flowy-folder-data-model/src/entities/view.rs index bf7b99866c..ac346188ce 100644 --- a/shared-lib/flowy-folder-data-model/src/entities/view.rs +++ b/shared-lib/flowy-folder-data-model/src/entities/view.rs @@ -127,7 +127,7 @@ pub struct CreateViewPayload { pub plugin_type: i32, #[pb(index = 7)] - pub data: String, + pub data: Vec, } #[derive(Default, ProtoBuf, Debug, Clone)] @@ -151,7 +151,7 @@ pub struct CreateViewParams { pub view_id: String, #[pb(index = 7)] - pub data: String, + pub data: Vec, #[pb(index = 8)] pub plugin_type: i32, diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs index 15d8e2feaa..9f19e18f0c 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs +++ b/shared-lib/flowy-folder-data-model/src/protobuf/model/view.rs @@ -794,7 +794,7 @@ pub struct CreateViewPayload { pub desc: ::std::string::String, pub data_type: ViewDataType, pub plugin_type: i32, - pub data: ::std::string::String, + pub data: ::std::vec::Vec, // message oneof groups pub one_of_thumbnail: ::std::option::Option, // special fields @@ -975,10 +975,10 @@ impl CreateViewPayload { self.plugin_type = v; } - // string data = 7; + // bytes data = 7; - pub fn get_data(&self) -> &str { + pub fn get_data(&self) -> &[u8] { &self.data } pub fn clear_data(&mut self) { @@ -986,19 +986,19 @@ impl CreateViewPayload { } // Param is passed by value, moved - pub fn set_data(&mut self, v: ::std::string::String) { + pub fn set_data(&mut self, v: ::std::vec::Vec) { self.data = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_data(&mut self) -> &mut ::std::string::String { + pub fn mut_data(&mut self) -> &mut ::std::vec::Vec { &mut self.data } // Take field - pub fn take_data(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.data, ::std::string::String::new()) + pub fn take_data(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.data, ::std::vec::Vec::new()) } } @@ -1037,7 +1037,7 @@ impl ::protobuf::Message for CreateViewPayload { self.plugin_type = tmp; }, 7 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?; + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -1067,7 +1067,7 @@ impl ::protobuf::Message for CreateViewPayload { my_size += ::protobuf::rt::value_size(6, self.plugin_type, ::protobuf::wire_format::WireTypeVarint); } if !self.data.is_empty() { - my_size += ::protobuf::rt::string_size(7, &self.data); + my_size += ::protobuf::rt::bytes_size(7, &self.data); } if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { match v { @@ -1098,7 +1098,7 @@ impl ::protobuf::Message for CreateViewPayload { os.write_int32(6, self.plugin_type)?; } if !self.data.is_empty() { - os.write_string(7, &self.data)?; + os.write_bytes(7, &self.data)?; } if let ::std::option::Option::Some(ref v) = self.one_of_thumbnail { match v { @@ -1175,7 +1175,7 @@ impl ::protobuf::Message for CreateViewPayload { |m: &CreateViewPayload| { &m.plugin_type }, |m: &mut CreateViewPayload| { &mut m.plugin_type }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( "data", |m: &CreateViewPayload| { &m.data }, |m: &mut CreateViewPayload| { &mut m.data }, @@ -1228,7 +1228,7 @@ pub struct CreateViewParams { pub thumbnail: ::std::string::String, pub data_type: ViewDataType, pub view_id: ::std::string::String, - pub data: ::std::string::String, + pub data: ::std::vec::Vec, pub plugin_type: i32, // special fields pub unknown_fields: ::protobuf::UnknownFields, @@ -1391,10 +1391,10 @@ impl CreateViewParams { ::std::mem::replace(&mut self.view_id, ::std::string::String::new()) } - // string data = 7; + // bytes data = 7; - pub fn get_data(&self) -> &str { + pub fn get_data(&self) -> &[u8] { &self.data } pub fn clear_data(&mut self) { @@ -1402,19 +1402,19 @@ impl CreateViewParams { } // Param is passed by value, moved - pub fn set_data(&mut self, v: ::std::string::String) { + pub fn set_data(&mut self, v: ::std::vec::Vec) { self.data = v; } // Mutable pointer to the field. // If field is not initialized, it is initialized with default value first. - pub fn mut_data(&mut self) -> &mut ::std::string::String { + pub fn mut_data(&mut self) -> &mut ::std::vec::Vec { &mut self.data } // Take field - pub fn take_data(&mut self) -> ::std::string::String { - ::std::mem::replace(&mut self.data, ::std::string::String::new()) + pub fn take_data(&mut self) -> ::std::vec::Vec { + ::std::mem::replace(&mut self.data, ::std::vec::Vec::new()) } // int32 plugin_type = 8; @@ -1461,7 +1461,7 @@ impl ::protobuf::Message for CreateViewParams { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.view_id)?; }, 7 => { - ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.data)?; + ::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?; }, 8 => { if wire_type != ::protobuf::wire_format::WireTypeVarint { @@ -1501,7 +1501,7 @@ impl ::protobuf::Message for CreateViewParams { my_size += ::protobuf::rt::string_size(6, &self.view_id); } if !self.data.is_empty() { - my_size += ::protobuf::rt::string_size(7, &self.data); + my_size += ::protobuf::rt::bytes_size(7, &self.data); } if self.plugin_type != 0 { my_size += ::protobuf::rt::value_size(8, self.plugin_type, ::protobuf::wire_format::WireTypeVarint); @@ -1531,7 +1531,7 @@ impl ::protobuf::Message for CreateViewParams { os.write_string(6, &self.view_id)?; } if !self.data.is_empty() { - os.write_string(7, &self.data)?; + os.write_bytes(7, &self.data)?; } if self.plugin_type != 0 { os.write_int32(8, self.plugin_type)?; @@ -1604,7 +1604,7 @@ impl ::protobuf::Message for CreateViewParams { |m: &CreateViewParams| { &m.view_id }, |m: &mut CreateViewParams| { &mut m.view_id }, )); - fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( + fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>( "data", |m: &CreateViewParams| { &m.data }, |m: &mut CreateViewParams| { &mut m.data }, @@ -2844,22 +2844,22 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x18\x03\x20\x01(\tR\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\0R\ \tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTypeR\x08d\ ataType\x12\x1f\n\x0bplugin_type\x18\x06\x20\x01(\x05R\npluginType\x12\ - \x12\n\x04data\x18\x07\x20\x01(\tR\x04dataB\x12\n\x10one_of_thumbnail\"\ - \xf4\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\ - \x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\x04\x20\ - \x01(\tR\tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDataTy\ - peR\x08dataType\x12\x17\n\x07view_id\x18\x06\x20\x01(\tR\x06viewId\x12\ - \x12\n\x04data\x18\x07\x20\x01(\tR\x04data\x12\x1f\n\x0bplugin_type\x18\ - \x08\x20\x01(\x05R\npluginType\"\x1e\n\x06ViewId\x12\x14\n\x05value\x18\ - \x01\x20\x01(\tR\x05value\"&\n\x0eRepeatedViewId\x12\x14\n\x05items\x18\ - \x01\x20\x03(\tR\x05items\"\xaa\x01\n\x11UpdateViewPayload\x12\x17\n\x07\ - view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\x01(\ - \tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\x12\ - \x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of_nam\ - eB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail\"\xa9\x01\n\x10UpdateVi\ - ewParams\x12\x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\ - \x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\ + \x12\n\x04data\x18\x07\x20\x01(\x0cR\x04dataB\x12\n\x10one_of_thumbnail\ + \"\xf4\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\x04desc\x18\x03\x20\x01(\tR\x04desc\x12\x1c\n\tthumbnail\x18\x04\ + \x20\x01(\tR\tthumbnail\x12*\n\tdata_type\x18\x05\x20\x01(\x0e2\r.ViewDa\ + taTypeR\x08dataType\x12\x17\n\x07view_id\x18\x06\x20\x01(\tR\x06viewId\ + \x12\x12\n\x04data\x18\x07\x20\x01(\x0cR\x04data\x12\x1f\n\x0bplugin_typ\ + e\x18\x08\x20\x01(\x05R\npluginType\"\x1e\n\x06ViewId\x12\x14\n\x05value\ + \x18\x01\x20\x01(\tR\x05value\"&\n\x0eRepeatedViewId\x12\x14\n\x05items\ + \x18\x01\x20\x03(\tR\x05items\"\xaa\x01\n\x11UpdateViewPayload\x12\x17\n\ + \x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\n\x04name\x18\x02\x20\ + \x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\tH\x01R\x04desc\ + \x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthumbnailB\r\n\x0bone_of\ + _nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnail\"\xa9\x01\n\x10Upda\ + teViewParams\x12\x17\n\x07view_id\x18\x01\x20\x01(\tR\x06viewId\x12\x14\ + \n\x04name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\ \x01(\tH\x01R\x04desc\x12\x1e\n\tthumbnail\x18\x04\x20\x01(\tH\x02R\tthu\ mbnailB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x12\n\x10one_of_thumbnai\ l*'\n\x0cViewDataType\x12\r\n\tTextBlock\x10\0\x12\x08\n\x04Grid\x10\x01\ diff --git a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto index b66f778a71..56e09c54e4 100644 --- a/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto +++ b/shared-lib/flowy-folder-data-model/src/protobuf/proto/view.proto @@ -24,7 +24,7 @@ message CreateViewPayload { oneof one_of_thumbnail { string thumbnail = 4; }; ViewDataType data_type = 5; int32 plugin_type = 6; - string data = 7; + bytes data = 7; } message CreateViewParams { string belong_to_id = 1; @@ -33,7 +33,7 @@ message CreateViewParams { string thumbnail = 4; ViewDataType data_type = 5; string view_id = 6; - string data = 7; + bytes data = 7; int32 plugin_type = 8; } message ViewId { diff --git a/shared-lib/flowy-grid-data-model/src/entities/meta.rs b/shared-lib/flowy-grid-data-model/src/entities/meta.rs index c7cd8338c8..f8c762345d 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/meta.rs @@ -1,7 +1,8 @@ use flowy_derive::{ProtoBuf, ProtoBuf_Enum}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; -use strum_macros::{Display, EnumIter, EnumString}; +use strum::{EnumCount, IntoEnumIterator}; +use strum_macros::{Display, EnumCount as EnumCountMacro, EnumIter, EnumString}; pub const DEFAULT_ROW_HEIGHT: i32 = 36; pub const DEFAULT_FIELD_WIDTH: i32 = 150; @@ -139,7 +140,9 @@ pub struct FieldChangeset { pub type_options: Option, } -#[derive(Debug, Clone, PartialEq, Eq, ProtoBuf_Enum, EnumString, EnumIter, Display, Serialize, Deserialize)] +#[derive( + Debug, Clone, PartialEq, Eq, ProtoBuf_Enum, EnumCountMacro, EnumString, EnumIter, Display, Serialize, Deserialize, +)] pub enum FieldType { RichText = 0, Number = 1, @@ -312,3 +315,31 @@ impl std::convert::From for RowMetaChangeset { } } } + +#[derive(Clone, ProtoBuf)] +pub struct BuildGridContext { + #[pb(index = 1)] + pub field_metas: Vec, + + #[pb(index = 2)] + pub grid_block: GridBlock, + + #[pb(index = 3)] + pub grid_block_meta: GridBlockMeta, +} + +impl std::default::Default for BuildGridContext { + fn default() -> Self { + let grid_block = GridBlock::new(); + let grid_block_meta = GridBlockMeta { + block_id: grid_block.id.clone(), + rows: vec![], + }; + + Self { + field_metas: vec![], + grid_block, + grid_block_meta, + } + } +} diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index bd01ee6cf6..9a90b67f81 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs @@ -3073,6 +3073,286 @@ impl ::protobuf::reflect::ProtobufValue for CellMetaChangeset { } } +#[derive(PartialEq,Clone,Default)] +pub struct BuildGridContext { + // message fields + pub field_metas: ::protobuf::RepeatedField, + pub grid_block: ::protobuf::SingularPtrField, + pub grid_block_meta: ::protobuf::SingularPtrField, + // special fields + pub unknown_fields: ::protobuf::UnknownFields, + pub cached_size: ::protobuf::CachedSize, +} + +impl<'a> ::std::default::Default for &'a BuildGridContext { + fn default() -> &'a BuildGridContext { + ::default_instance() + } +} + +impl BuildGridContext { + pub fn new() -> BuildGridContext { + ::std::default::Default::default() + } + + // repeated .FieldMeta field_metas = 1; + + + pub fn get_field_metas(&self) -> &[FieldMeta] { + &self.field_metas + } + pub fn clear_field_metas(&mut self) { + self.field_metas.clear(); + } + + // Param is passed by value, moved + pub fn set_field_metas(&mut self, v: ::protobuf::RepeatedField) { + self.field_metas = v; + } + + // Mutable pointer to the field. + pub fn mut_field_metas(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.field_metas + } + + // Take field + pub fn take_field_metas(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.field_metas, ::protobuf::RepeatedField::new()) + } + + // .GridBlock grid_block = 2; + + + pub fn get_grid_block(&self) -> &GridBlock { + self.grid_block.as_ref().unwrap_or_else(|| ::default_instance()) + } + pub fn clear_grid_block(&mut self) { + self.grid_block.clear(); + } + + pub fn has_grid_block(&self) -> bool { + self.grid_block.is_some() + } + + // Param is passed by value, moved + pub fn set_grid_block(&mut self, v: GridBlock) { + self.grid_block = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_block(&mut self) -> &mut GridBlock { + if self.grid_block.is_none() { + self.grid_block.set_default(); + } + self.grid_block.as_mut().unwrap() + } + + // Take field + pub fn take_grid_block(&mut self) -> GridBlock { + self.grid_block.take().unwrap_or_else(|| GridBlock::new()) + } + + // .GridBlockMeta grid_block_meta = 3; + + + pub fn get_grid_block_meta(&self) -> &GridBlockMeta { + self.grid_block_meta.as_ref().unwrap_or_else(|| ::default_instance()) + } + pub fn clear_grid_block_meta(&mut self) { + self.grid_block_meta.clear(); + } + + pub fn has_grid_block_meta(&self) -> bool { + self.grid_block_meta.is_some() + } + + // Param is passed by value, moved + pub fn set_grid_block_meta(&mut self, v: GridBlockMeta) { + self.grid_block_meta = ::protobuf::SingularPtrField::some(v); + } + + // Mutable pointer to the field. + // If field is not initialized, it is initialized with default value first. + pub fn mut_grid_block_meta(&mut self) -> &mut GridBlockMeta { + if self.grid_block_meta.is_none() { + self.grid_block_meta.set_default(); + } + self.grid_block_meta.as_mut().unwrap() + } + + // Take field + pub fn take_grid_block_meta(&mut self) -> GridBlockMeta { + self.grid_block_meta.take().unwrap_or_else(|| GridBlockMeta::new()) + } +} + +impl ::protobuf::Message for BuildGridContext { + fn is_initialized(&self) -> bool { + for v in &self.field_metas { + if !v.is_initialized() { + return false; + } + }; + for v in &self.grid_block { + if !v.is_initialized() { + return false; + } + }; + for v in &self.grid_block_meta { + if !v.is_initialized() { + return false; + } + }; + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { + while !is.eof()? { + let (field_number, wire_type) = is.read_tag_unpack()?; + match field_number { + 1 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.field_metas)?; + }, + 2 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.grid_block)?; + }, + 3 => { + ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.grid_block_meta)?; + }, + _ => { + ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u32 { + let mut my_size = 0; + for value in &self.field_metas { + let len = value.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + }; + if let Some(ref v) = self.grid_block.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + if let Some(ref v) = self.grid_block_meta.as_ref() { + let len = v.compute_size(); + my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; + } + my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); + self.cached_size.set(my_size); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { + for v in &self.field_metas { + os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + }; + if let Some(ref v) = self.grid_block.as_ref() { + os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + if let Some(ref v) = self.grid_block_meta.as_ref() { + os.write_tag(3, ::protobuf::wire_format::WireTypeLengthDelimited)?; + os.write_raw_varint32(v.get_cached_size())?; + v.write_to_with_cached_sizes(os)?; + } + os.write_unknown_fields(self.get_unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn get_cached_size(&self) -> u32 { + self.cached_size.get() + } + + fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { + &self.unknown_fields + } + + fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { + &mut self.unknown_fields + } + + fn as_any(&self) -> &dyn (::std::any::Any) { + self as &dyn (::std::any::Any) + } + fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { + self as &mut dyn (::std::any::Any) + } + fn into_any(self: ::std::boxed::Box) -> ::std::boxed::Box { + self + } + + fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { + Self::descriptor_static() + } + + fn new() -> BuildGridContext { + BuildGridContext::new() + } + + fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT; + descriptor.get(|| { + let mut fields = ::std::vec::Vec::new(); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "field_metas", + |m: &BuildGridContext| { &m.field_metas }, + |m: &mut BuildGridContext| { &mut m.field_metas }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "grid_block", + |m: &BuildGridContext| { &m.grid_block }, + |m: &mut BuildGridContext| { &mut m.grid_block }, + )); + fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "grid_block_meta", + |m: &BuildGridContext| { &m.grid_block_meta }, + |m: &mut BuildGridContext| { &mut m.grid_block_meta }, + )); + ::protobuf::reflect::MessageDescriptor::new_pb_name::( + "BuildGridContext", + fields, + file_descriptor_proto() + ) + }) + } + + fn default_instance() -> &'static BuildGridContext { + static instance: ::protobuf::rt::LazyV2 = ::protobuf::rt::LazyV2::INIT; + instance.get(BuildGridContext::new) + } +} + +impl ::protobuf::Clear for BuildGridContext { + fn clear(&mut self) { + self.field_metas.clear(); + self.grid_block.clear(); + self.grid_block_meta.clear(); + self.unknown_fields.clear(); + } +} + +impl ::std::fmt::Debug for BuildGridContext { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for BuildGridContext { + fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef { + ::protobuf::reflect::ReflectValueRef::Message(self) + } +} + #[derive(Clone,PartialEq,Eq,Debug,Hash)] pub enum FieldType { RichText = 0, @@ -3178,10 +3458,13 @@ static file_descriptor_proto_data: &'static [u8] = b"\ ata\x18\x02\x20\x01(\tR\x04data\"j\n\x11CellMetaChangeset\x12\x15\n\x06r\ ow_id\x18\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x02\x20\x01\ (\tR\x07fieldId\x12\x14\n\x04data\x18\x03\x20\x01(\tH\0R\x04dataB\r\n\ - \x0bone_of_data*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Nu\ - mber\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\ - \x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06\ - proto3\ + \x0bone_of_data\"\xa2\x01\n\x10BuildGridContext\x12+\n\x0bfield_metas\ + \x18\x01\x20\x03(\x0b2\n.FieldMetaR\nfieldMetas\x12)\n\ngrid_block\x18\ + \x02\x20\x01(\x0b2\n.GridBlockR\tgridBlock\x126\n\x0fgrid_block_meta\x18\ + \x03\x20\x01(\x0b2\x0e.GridBlockMetaR\rgridBlockMeta*d\n\tFieldType\x12\ + \x0c\n\x08RichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\ + \x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\ + \x04\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\ "; static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT; diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto index 32fc3896ac..12447f6e8f 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto @@ -60,6 +60,11 @@ message CellMetaChangeset { string field_id = 2; oneof one_of_data { string data = 3; }; } +message BuildGridContext { + repeated FieldMeta field_metas = 1; + GridBlock grid_block = 2; + GridBlockMeta grid_block_meta = 3; +} enum FieldType { RichText = 0; Number = 1; diff --git a/shared-lib/lib-ot/src/core/delta/delta.rs b/shared-lib/lib-ot/src/core/delta/delta.rs index ac4fcbbef5..29fd424dcb 100644 --- a/shared-lib/lib-ot/src/core/delta/delta.rs +++ b/shared-lib/lib-ot/src/core/delta/delta.rs @@ -529,7 +529,7 @@ where self.apply("") } - pub fn to_bytes(&self) -> Bytes { + pub fn to_delta_bytes(&self) -> Bytes { let json = self.to_delta_str(); Bytes::from(json.into_bytes()) }