diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 5f69ab1ad4..98ab00d0e4 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -148,7 +148,7 @@ void _resolveDocDeps(GetIt getIt) { void _resolveGridDeps(GetIt getIt) { // Grid getIt.registerFactoryParam( - (view, _) => GridBloc(view: view, service: GridService()), + (view, _) => GridBloc(view: view), ); getIt.registerFactoryParam( diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index 9e563e2d4e..c68cd8c726 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -9,27 +9,31 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'grid_block_service.dart'; import 'field/grid_listenr.dart'; +import 'grid_listener.dart'; import 'grid_service.dart'; part 'grid_bloc.freezed.dart'; class GridBloc extends Bloc { final View view; - final GridService service; + final GridService _gridService; + final GridListener _gridListener; final GridFieldsListener _fieldListener; - GridBlockService? _blockService; - GridBloc({required this.view, required this.service}) + GridBloc({required this.view}) : _fieldListener = GridFieldsListener(gridId: view.id), + _gridService = GridService(), + _gridListener = GridListener(gridId: view.id), super(GridState.initial()) { on( (event, emit) async { await event.map( initial: (InitialGrid value) async { await _initGrid(emit); + _startListening(); }, createRow: (_CreateRow value) { - service.createRow(gridId: view.id); + _gridService.createRow(gridId: view.id); }, delete: (_Delete value) {}, rename: (_Rename value) {}, @@ -48,7 +52,7 @@ class GridBloc extends Bloc { @override Future close() async { await _fieldListener.stop(); - await _blockService?.stop(); + await _gridListener.stop(); return super.close(); } @@ -64,22 +68,17 @@ class GridBloc extends Bloc { await _loadGrid(emit); } - Future _initGridBlock(Grid grid) async { - _blockService = GridBlockService( - gridId: grid.id, - blockOrders: grid.blockOrders, - ); - - _blockService?.blocksUpdateNotifier?.addPublishListener((result) { - result.fold( - (blockMap) => add(GridEvent.didReceiveRowUpdate(_buildRows(blockMap))), - (err) => Log.error('$err'), - ); + void _startListening() { + _gridListener.rowsUpdateNotifier.addPublishListener((result) { + result.fold((blockOrders) { + add(GridEvent.didReceiveRowUpdate(_buildRows(blockOrders))); + }, (err) => Log.error(err)); }); + _gridListener.start(); } Future _loadGrid(Emitter emit) async { - final result = await service.loadGrid(gridId: view.id); + final result = await _gridService.loadGrid(gridId: view.id); return Future( () => result.fold( (grid) async => await _loadFields(grid, emit), @@ -89,14 +88,14 @@ class GridBloc extends Bloc { } Future _loadFields(Grid grid, Emitter emit) async { - final result = await service.getFields(gridId: grid.id, fieldOrders: grid.fieldOrders); + final result = await _gridService.getFields(gridId: grid.id, fieldOrders: grid.fieldOrders); return Future( () => result.fold( (fields) { - _initGridBlock(grid); emit(state.copyWith( grid: Some(grid), fields: fields.items, + rows: _buildRows(grid.blockOrders), loadingState: GridLoadingState.finish(left(unit)), )); }, @@ -105,17 +104,17 @@ class GridBloc extends Bloc { ); } - List _buildRows(GridBlockMap blockMap) { + List _buildRows(List blockOrders) { List rows = []; - blockMap.forEach((_, GridBlock gridBlock) { - rows.addAll(gridBlock.rowOrders.map( + for (final blockOrder in blockOrders) { + rows.addAll(blockOrder.rowOrders.map( (rowOrder) => GridBlockRow( gridId: view.id, rowId: rowOrder.rowId, height: rowOrder.height.toDouble(), ), )); - }); + } return rows; } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart new file mode 100644 index 0000000000..b2917089c8 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_listener.dart @@ -0,0 +1,42 @@ +import 'package:dartz/dartz.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart'; +import 'package:flowy_infra/notifier.dart'; +import 'dart:async'; +import 'dart:typed_data'; +import 'package:app_flowy/core/notification_helper.dart'; + +class GridListener { + final String gridId; + PublishNotifier, FlowyError>> rowsUpdateNotifier = PublishNotifier(comparable: null); + GridNotificationListener? _listener; + + GridListener({required this.gridId}); + + void start() { + _listener = GridNotificationListener( + objectId: gridId, + handler: _handler, + ); + } + + void _handler(GridNotification ty, Either result) { + switch (ty) { + case GridNotification.DidUpdateBlock: + result.fold( + (payload) => rowsUpdateNotifier.value = left([GridBlockOrder.fromBuffer(payload)]), + (error) => rowsUpdateNotifier.value = right(error), + ); + break; + + default: + break; + } + } + + Future stop() async { + await _listener?.stop(); + rowsUpdateNotifier.dispose(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart index 3456007a6c..bf558cb574 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -5,7 +5,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:dartz/dartz.dart'; class GridService { - Future> loadGrid({required String gridId}) async { + Future> loadGrid({required String gridId}) async { await FolderEventSetLatestView(ViewId(value: gridId)).send(); final payload = GridId(value: gridId); diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart index e27e019be3..c5e0fb28c9 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pb.dart @@ -803,17 +803,22 @@ class RepeatedGridBlock extends $pb.GeneratedMessage { class GridBlockOrder extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockOrder', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowOrders', $pb.PbFieldType.PM, subBuilder: RowOrder.create) ..hasRequiredFields = false ; GridBlockOrder._() : super(); factory GridBlockOrder({ $core.String? blockId, + $core.Iterable? rowOrders, }) { final _result = create(); if (blockId != null) { _result.blockId = blockId; } + if (rowOrders != null) { + _result.rowOrders.addAll(rowOrders); + } return _result; } factory GridBlockOrder.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r); @@ -845,6 +850,9 @@ class GridBlockOrder extends $pb.GeneratedMessage { $core.bool hasBlockId() => $_has(0); @$pb.TagNumber(1) void clearBlockId() => clearField(1); + + @$pb.TagNumber(2) + $core.List get rowOrders => $_getList(1); } class GridBlock extends $pb.GeneratedMessage { diff --git a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart index 3cd228af79..676025d66a 100644 --- a/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart +++ b/frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/grid.pbjson.dart @@ -165,11 +165,12 @@ const GridBlockOrder$json = const { '1': 'GridBlockOrder', '2': const [ const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, + const {'1': 'row_orders', '3': 2, '4': 3, '5': 11, '6': '.RowOrder', '10': 'rowOrders'}, ], }; /// Descriptor for `GridBlockOrder`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridBlockOrderDescriptor = $convert.base64Decode('Cg5HcmlkQmxvY2tPcmRlchIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZA=='); +final $typed_data.Uint8List gridBlockOrderDescriptor = $convert.base64Decode('Cg5HcmlkQmxvY2tPcmRlchIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIoCgpyb3dfb3JkZXJzGAIgAygLMgkuUm93T3JkZXJSCXJvd09yZGVycw=='); @$core.Deprecated('Use gridBlockDescriptor instead') const GridBlock$json = const { '1': 'GridBlock', 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 d322e644c0..9e0f08d42a 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 @@ -17,7 +17,7 @@ class GridMeta extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridMeta', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId') ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fields', $pb.PbFieldType.PM, subBuilder: FieldMeta.create) - ..pc(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetas', $pb.PbFieldType.PM, subBuilder: GridBlockMeta.create) + ..pc(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blocks', $pb.PbFieldType.PM, subBuilder: GridBlockMeta.create) ..hasRequiredFields = false ; @@ -25,7 +25,7 @@ class GridMeta extends $pb.GeneratedMessage { factory GridMeta({ $core.String? gridId, $core.Iterable? fields, - $core.Iterable? blockMetas, + $core.Iterable? blocks, }) { final _result = create(); if (gridId != null) { @@ -34,8 +34,8 @@ class GridMeta extends $pb.GeneratedMessage { if (fields != null) { _result.fields.addAll(fields); } - if (blockMetas != null) { - _result.blockMetas.addAll(blockMetas); + if (blocks != null) { + _result.blocks.addAll(blocks); } return _result; } @@ -73,7 +73,7 @@ class GridMeta extends $pb.GeneratedMessage { $core.List get fields => $_getList(1); @$pb.TagNumber(3) - $core.List get blockMetas => $_getList(2); + $core.List get blocks => $_getList(2); } class GridBlockMeta extends $pb.GeneratedMessage { @@ -154,21 +154,21 @@ class GridBlockMeta extends $pb.GeneratedMessage { class GridBlockMetaData extends $pb.GeneratedMessage { static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockMetaData', createEmptyInstance: create) ..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId') - ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowMetas', $pb.PbFieldType.PM, subBuilder: RowMeta.create) + ..pc(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rows', $pb.PbFieldType.PM, subBuilder: RowMeta.create) ..hasRequiredFields = false ; GridBlockMetaData._() : super(); factory GridBlockMetaData({ $core.String? blockId, - $core.Iterable? rowMetas, + $core.Iterable? rows, }) { final _result = create(); if (blockId != null) { _result.blockId = blockId; } - if (rowMetas != null) { - _result.rowMetas.addAll(rowMetas); + if (rows != null) { + _result.rows.addAll(rows); } return _result; } @@ -203,7 +203,7 @@ class GridBlockMetaData extends $pb.GeneratedMessage { void clearBlockId() => clearField(1); @$pb.TagNumber(2) - $core.List get rowMetas => $_getList(1); + $core.List get rows => $_getList(1); } class FieldMeta extends $pb.GeneratedMessage { 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 71b0c1b8e0..70180c231d 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 @@ -29,12 +29,12 @@ const GridMeta$json = const { '2': const [ const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'}, const {'1': 'fields', '3': 2, '4': 3, '5': 11, '6': '.FieldMeta', '10': 'fields'}, - const {'1': 'block_metas', '3': 3, '4': 3, '5': 11, '6': '.GridBlockMeta', '10': 'blockMetas'}, + const {'1': 'blocks', '3': 3, '4': 3, '5': 11, '6': '.GridBlockMeta', '10': 'blocks'}, ], }; /// Descriptor for `GridMeta`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridMetaDescriptor = $convert.base64Decode('CghHcmlkTWV0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSIgoGZmllbGRzGAIgAygLMgouRmllbGRNZXRhUgZmaWVsZHMSLwoLYmxvY2tfbWV0YXMYAyADKAsyDi5HcmlkQmxvY2tNZXRhUgpibG9ja01ldGFz'); +final $typed_data.Uint8List gridMetaDescriptor = $convert.base64Decode('CghHcmlkTWV0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSIgoGZmllbGRzGAIgAygLMgouRmllbGRNZXRhUgZmaWVsZHMSJgoGYmxvY2tzGAMgAygLMg4uR3JpZEJsb2NrTWV0YVIGYmxvY2tz'); @$core.Deprecated('Use gridBlockMetaDescriptor instead') const GridBlockMeta$json = const { '1': 'GridBlockMeta', @@ -52,12 +52,12 @@ const GridBlockMetaData$json = const { '1': 'GridBlockMetaData', '2': const [ const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'}, - const {'1': 'row_metas', '3': 2, '4': 3, '5': 11, '6': '.RowMeta', '10': 'rowMetas'}, + const {'1': 'rows', '3': 2, '4': 3, '5': 11, '6': '.RowMeta', '10': 'rows'}, ], }; /// Descriptor for `GridBlockMetaData`. Decode as a `google.protobuf.DescriptorProto`. -final $typed_data.Uint8List gridBlockMetaDataDescriptor = $convert.base64Decode('ChFHcmlkQmxvY2tNZXRhRGF0YRIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIlCglyb3dfbWV0YXMYAiADKAsyCC5Sb3dNZXRhUghyb3dNZXRhcw=='); +final $typed_data.Uint8List gridBlockMetaDataDescriptor = $convert.base64Decode('ChFHcmlkQmxvY2tNZXRhRGF0YRIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIcCgRyb3dzGAIgAygLMgguUm93TWV0YVIEcm93cw=='); @$core.Deprecated('Use fieldMetaDescriptor instead') const FieldMeta$json = const { '1': 'FieldMeta', diff --git a/frontend/rust-lib/flowy-grid/src/event_handler.rs b/frontend/rust-lib/flowy-grid/src/event_handler.rs index 1ac3796059..acc1eeb5c6 100644 --- a/frontend/rust-lib/flowy-grid/src/event_handler.rs +++ b/frontend/rust-lib/flowy-grid/src/event_handler.rs @@ -186,7 +186,7 @@ pub(crate) async fn delete_row_handler( ) -> Result<(), FlowyError> { let params: RowIdentifier = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let _ = editor.delete_row(¶ms.row_id)?; + let _ = editor.delete_row(¶ms.row_id).await?; Ok(()) } @@ -197,7 +197,7 @@ pub(crate) async fn duplicate_row_handler( ) -> Result<(), FlowyError> { let params: RowIdentifier = data.into_inner().try_into()?; let editor = manager.get_grid_editor(¶ms.grid_id)?; - let _ = editor.duplicate_row(¶ms.row_id)?; + let _ = editor.duplicate_row(¶ms.row_id).await?; Ok(()) } 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 8518a70fb0..1f8e2e2006 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 @@ -7,6 +7,7 @@ use flowy_sync::entities::revision::Revision; use flowy_sync::util::make_delta_from_revisions; use lib_infra::future::FutureResult; use lib_ot::core::PlainTextAttributes; +use std::borrow::Cow; use std::sync::Arc; use tokio::sync::RwLock; @@ -54,11 +55,11 @@ impl ClientGridBlockMetaEditor { Ok(row_count) } - pub async fn delete_rows(&self, ids: Vec) -> FlowyResult { + pub async fn delete_rows(&self, ids: Vec>) -> FlowyResult { let mut row_count = 0; let _ = self .modify(|pad| { - let changeset = pad.delete_rows(&ids)?; + let changeset = pad.delete_rows(ids)?; row_count = pad.number_of_rows(); Ok(changeset) }) @@ -71,17 +72,24 @@ impl ClientGridBlockMetaEditor { Ok(()) } - pub async fn get_row_metas(&self, row_ids: Option>) -> FlowyResult>> { - let row_metas = self.pad.read().await.get_row_metas(&row_ids)?; + pub async fn get_row_metas(&self, row_ids: Option>>) -> FlowyResult>> + where + T: AsRef + ToOwned + ?Sized, + { + let row_metas = self.pad.read().await.get_row_metas(row_ids)?; Ok(row_metas) } - pub async fn get_cell_metas(&self, field_id: &str, row_ids: &Option>) -> FlowyResult> { + pub async fn get_cell_metas( + &self, + field_id: &str, + row_ids: Option>>, + ) -> FlowyResult> { let cell_metas = self.pad.read().await.get_cell_metas(field_id, row_ids)?; Ok(cell_metas) } - pub async fn get_row_orders(&self, row_ids: &Option>) -> FlowyResult> { + pub async fn get_row_orders(&self, row_ids: Option>>) -> FlowyResult> { let row_orders = self .pad .read() diff --git a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs index 54e223c242..b14f6641f3 100644 --- a/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs +++ b/frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs @@ -2,7 +2,8 @@ use crate::dart_notification::{send_dart_notification, GridNotification}; use crate::manager::GridUser; use crate::services::block_meta_editor::ClientGridBlockMetaEditor; use crate::services::persistence::block_index::BlockIndexPersistence; -use crate::services::row::{make_block_rows, make_rows_from_row_metas, GridBlockSnapshot}; +use crate::services::row::{group_row_orders, make_rows_from_row_metas, GridBlockSnapshot}; +use std::borrow::Cow; use dashmap::DashMap; use flowy_error::FlowyResult; @@ -18,6 +19,7 @@ use std::sync::Arc; pub(crate) struct GridBlockMetaEditorManager { grid_id: String, user: Arc, + // Key: block_id editor_map: DashMap>, persistence: Arc, } @@ -92,19 +94,6 @@ impl GridBlockMetaEditorManager { Ok(changesets) } - pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { - let mut changesets = vec![]; - for block_row in make_block_rows(&row_orders) { - let editor = self.get_editor(&block_row.block_id).await?; - let row_count = editor.delete_rows(block_row.row_ids).await?; - - let changeset = GridBlockMetaChangeset::from_row_count(&block_row.block_id, row_count); - changesets.push(changeset); - } - - Ok(changesets) - } - pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> { let editor = self.get_editor_from_row_id(&changeset.row_id).await?; let _ = editor.update_row(changeset.clone()).await?; @@ -112,6 +101,23 @@ impl GridBlockMetaEditorManager { Ok(()) } + pub(crate) async fn delete_rows(&self, row_orders: Vec) -> FlowyResult> { + let mut changesets = vec![]; + for block_order in group_row_orders(row_orders) { + let editor = self.get_editor(&block_order.block_id).await?; + let row_ids = block_order + .row_orders + .into_iter() + .map(|row_order| Cow::Owned(row_order.row_id)) + .collect::>>(); + let row_count = editor.delete_rows(row_ids).await?; + let changeset = GridBlockMetaChangeset::from_row_count(&block_order.block_id, row_count); + changesets.push(changeset); + } + + Ok(changesets) + } + pub async fn update_cell(&self, changeset: CellMetaChangeset) -> FlowyResult<()> { let row_id = changeset.row_id.clone(); let editor = self.get_editor_from_row_id(&row_id).await?; @@ -130,7 +136,7 @@ impl GridBlockMetaEditorManager { pub async fn get_row_meta(&self, row_id: &str) -> FlowyResult>> { let editor = self.get_editor_from_row_id(row_id).await?; - let row_ids = vec![row_id.to_owned()]; + let row_ids = vec![Cow::Borrowed(row_id)]; let mut row_metas = editor.get_row_metas(Some(row_ids)).await?; if row_metas.is_empty() { Ok(None) @@ -139,11 +145,16 @@ impl GridBlockMetaEditorManager { } } + pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult> { + let editor = self.get_editor(block_id).await?; + editor.get_row_orders(None).await + } + pub(crate) async fn make_block_snapshots(&self, block_ids: Vec) -> FlowyResult> { let mut snapshots = vec![]; for block_id in block_ids { let editor = self.get_editor(&block_id).await?; - let row_metas = editor.get_row_metas(None).await?; + let row_metas = editor.get_row_metas::<&str>(None).await?; snapshots.push(GridBlockSnapshot { block_id, row_metas }); } Ok(snapshots) @@ -155,22 +166,22 @@ impl GridBlockMetaEditorManager { &self, block_ids: Vec, field_id: &str, - row_ids: Option>, + row_ids: Option>>, ) -> FlowyResult> { let mut block_cell_metas = vec![]; for block_id in block_ids { let editor = self.get_editor(&block_id).await?; - let cell_metas = editor.get_cell_metas(field_id, &row_ids).await?; + let cell_metas = editor.get_cell_metas(field_id, row_ids.clone()).await?; block_cell_metas.extend(cell_metas); } Ok(block_cell_metas) } async fn notify_block_did_update_row(&self, block_id: &str) -> FlowyResult<()> { - let block_order: GridBlockOrder = block_id.into(); - send_dart_notification(&self.grid_id, GridNotification::DidUpdateBlock) - .payload(block_order) - .send(); + // let block_order: GridBlockOrder = block_id.into(); + // send_dart_notification(&self.grid_id, GridNotification::DidUpdateBlock) + // .payload(block_order) + // .send(); Ok(()) } @@ -196,30 +207,6 @@ impl GridBlockMetaEditorManager { } } Ok(()) - - // - // let field_meta_map = field_metas - // .iter() - // .map(|field_meta| (&field_meta.id, field_meta)) - // .collect::>(); - // - // let mut cells = vec![]; - // changeset - // .cell_by_field_id - // .into_iter() - // .for_each( - // |(field_id, cell_meta)| match make_cell_by_field_id(&field_meta_map, field_id, cell_meta) { - // None => {} - // Some((_, cell)) => cells.push(cell), - // }, - // ); - // - // if !cells.is_empty() { - // send_dart_notification(&changeset.row_id, GridNotification::DidUpdateRow) - // .payload(RepeatedCell::from(cells)) - // .send(); - // } - // Ok(()) } } 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 1753013760..44fc4c4e76 100644 --- a/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs +++ b/frontend/rust-lib/flowy-grid/src/services/grid_editor.rs @@ -337,17 +337,18 @@ impl ClientGridEditor { } pub async fn grid_data(&self) -> FlowyResult { - let field_orders = self.pad.read().await.get_field_orders(); - let block_orders = self - .pad - .read() - .await - .get_block_metas() - .into_iter() - .map(|grid_block_meta| GridBlockOrder { - block_id: grid_block_meta.block_id, - }) - .collect::>(); + let pad_read_guard = self.pad.read().await; + let field_orders = pad_read_guard.get_field_orders(); + let mut block_orders = vec![]; + for block_order in pad_read_guard.get_block_metas() { + let row_orders = self.block_meta_manager.get_row_orders(&block_order.block_id).await?; + let block_order = GridBlockOrder { + block_id: block_order.block_id, + row_orders, + }; + block_orders.push(block_order); + } + Ok(Grid { id: self.grid_id.clone(), field_orders, diff --git a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs index ac26f1d32c..26e889f1af 100644 --- a/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs +++ b/frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs @@ -1,41 +1,28 @@ use crate::services::row::decode_cell_data; use flowy_error::FlowyResult; use flowy_grid_data_model::entities::{ - Cell, CellMeta, FieldMeta, GridBlock, RepeatedGridBlock, Row, RowMeta, RowOrder, + Cell, CellMeta, FieldMeta, GridBlock, GridBlockOrder, RepeatedGridBlock, Row, RowMeta, RowOrder, }; use rayon::iter::{IntoParallelIterator, ParallelIterator}; +use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; -pub(crate) struct BlockRows { - pub(crate) block_id: String, - pub(crate) row_ids: Vec, -} - -impl BlockRows { - pub fn new(block_id: &str) -> Self { - BlockRows { - block_id: block_id.to_owned(), - row_ids: vec![], - } - } -} - pub struct GridBlockSnapshot { pub(crate) block_id: String, pub row_metas: Vec>, } -pub(crate) fn make_block_rows(row_orders: &[RowOrder]) -> Vec { - let mut map: HashMap<&String, BlockRows> = HashMap::new(); - row_orders.iter().for_each(|row_order| { - let block_id = &row_order.block_id; - let row_id = row_order.row_id.clone(); +pub(crate) fn group_row_orders(row_orders: Vec) -> Vec { + let mut map: HashMap = HashMap::new(); + row_orders.into_iter().for_each(|row_order| { + // Memory Optimization: escape clone block_id + let block_id = row_order.block_id.clone(); map.entry(block_id) - .or_insert_with(|| BlockRows::new(block_id)) - .row_ids - .push(row_id); + .or_insert_with(|| GridBlockOrder::new(&row_order.block_id)) + .row_orders + .push(row_order); }); map.into_values().collect::>() } diff --git a/shared-lib/flowy-grid-data-model/src/entities/grid.rs b/shared-lib/flowy-grid-data-model/src/entities/grid.rs index d3cb9f7f69..42b3453d20 100644 --- a/shared-lib/flowy-grid-data-model/src/entities/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/entities/grid.rs @@ -260,11 +260,17 @@ impl std::convert::From> for RepeatedGridBlock { pub struct GridBlockOrder { #[pb(index = 1)] pub block_id: String, + + #[pb(index = 2)] + pub row_orders: Vec, } -impl std::convert::From<&str> for GridBlockOrder { - fn from(s: &str) -> Self { - GridBlockOrder { block_id: s.to_owned() } +impl GridBlockOrder { + pub fn new(block_id: &str) -> Self { + GridBlockOrder { + block_id: block_id.to_owned(), + row_orders: vec![], + } } } diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs index c31a2def27..944db183f9 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs +++ b/shared-lib/flowy-grid-data-model/src/protobuf/model/grid.rs @@ -2715,6 +2715,7 @@ impl ::protobuf::reflect::ProtobufValue for RepeatedGridBlock { pub struct GridBlockOrder { // message fields pub block_id: ::std::string::String, + pub row_orders: ::protobuf::RepeatedField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -2756,10 +2757,40 @@ impl GridBlockOrder { pub fn take_block_id(&mut self) -> ::std::string::String { ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) } + + // repeated .RowOrder row_orders = 2; + + + pub fn get_row_orders(&self) -> &[RowOrder] { + &self.row_orders + } + pub fn clear_row_orders(&mut self) { + self.row_orders.clear(); + } + + // Param is passed by value, moved + pub fn set_row_orders(&mut self, v: ::protobuf::RepeatedField) { + self.row_orders = v; + } + + // Mutable pointer to the field. + pub fn mut_row_orders(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.row_orders + } + + // Take field + pub fn take_row_orders(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.row_orders, ::protobuf::RepeatedField::new()) + } } impl ::protobuf::Message for GridBlockOrder { fn is_initialized(&self) -> bool { + for v in &self.row_orders { + if !v.is_initialized() { + return false; + } + }; true } @@ -2770,6 +2801,9 @@ impl ::protobuf::Message for GridBlockOrder { 1 => { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.block_id)?; }, + 2 => { + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.row_orders)?; + }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; }, @@ -2785,6 +2819,10 @@ impl ::protobuf::Message for GridBlockOrder { if !self.block_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.block_id); } + for value in &self.row_orders { + let len = value.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 @@ -2794,6 +2832,11 @@ impl ::protobuf::Message for GridBlockOrder { if !self.block_id.is_empty() { os.write_string(1, &self.block_id)?; } + for v in &self.row_orders { + os.write_tag(2, ::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(()) } @@ -2837,6 +2880,11 @@ impl ::protobuf::Message for GridBlockOrder { |m: &GridBlockOrder| { &m.block_id }, |m: &mut GridBlockOrder| { &mut m.block_id }, )); + fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( + "row_orders", + |m: &GridBlockOrder| { &m.row_orders }, + |m: &mut GridBlockOrder| { &mut m.row_orders }, + )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "GridBlockOrder", fields, @@ -2854,6 +2902,7 @@ impl ::protobuf::Message for GridBlockOrder { impl ::protobuf::Clear for GridBlockOrder { fn clear(&mut self) { self.block_id.clear(); + self.row_orders.clear(); self.unknown_fields.clear(); } } @@ -5283,31 +5332,32 @@ static file_descriptor_proto_data: &'static [u8] = b"\ \x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\ .CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\ \x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\ - items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"+\n\x0eGridBlockOrder\ - \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\"E\n\tGridBlock\ - \x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\ - \x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\ - \x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\ - \x07content\"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07grid_id\x18\ - \x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07\ - fieldId\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07co\ - ntent\x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\"+\n\ - \x0cRepeatedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05i\ - tems\"'\n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04\ - name\"\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"\ - #\n\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\ - \x10CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ - \x12\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13on\ - e_of_start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07grid_id\ - \x18\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\ - \x06.FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\ - \x0etypeOptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cst\ - artFieldIdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\ - \x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\ - \x18\x02\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16Qu\ - eryGridBlocksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\ - \x122\n\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblo\ - ckOrdersb\x06proto3\ + items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"U\n\x0eGridBlockOrder\ + \x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_orders\ + \x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"E\n\tGridBlock\x12\x0e\n\ + \x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\ + 2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\ + \x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07content\ + \"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07grid_id\x18\x01\x20\ + \x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\ + \x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07content\ + \x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\"+\n\x0cRepe\ + atedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\ + \n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\ + \x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"#\n\ + \x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\x10\ + CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\ + \"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of\ + _start_row_id\"\xb6\x01\n\x12CreateFieldPayload\x12\x17\n\x07grid_id\x18\ + \x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.\ + FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etype\ + OptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartField\ + IdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\x17\n\ + \x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\ + \x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridB\ + locksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\ + \x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrder\ + sb\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/model/meta.rs b/shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs index f90832a447..8ca8db2765 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 @@ -28,7 +28,7 @@ pub struct GridMeta { // message fields pub grid_id: ::std::string::String, pub fields: ::protobuf::RepeatedField, - pub block_metas: ::protobuf::RepeatedField, + pub blocks: ::protobuf::RepeatedField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -96,29 +96,29 @@ impl GridMeta { ::std::mem::replace(&mut self.fields, ::protobuf::RepeatedField::new()) } - // repeated .GridBlockMeta block_metas = 3; + // repeated .GridBlockMeta blocks = 3; - pub fn get_block_metas(&self) -> &[GridBlockMeta] { - &self.block_metas + pub fn get_blocks(&self) -> &[GridBlockMeta] { + &self.blocks } - pub fn clear_block_metas(&mut self) { - self.block_metas.clear(); + pub fn clear_blocks(&mut self) { + self.blocks.clear(); } // Param is passed by value, moved - pub fn set_block_metas(&mut self, v: ::protobuf::RepeatedField) { - self.block_metas = v; + pub fn set_blocks(&mut self, v: ::protobuf::RepeatedField) { + self.blocks = v; } // Mutable pointer to the field. - pub fn mut_block_metas(&mut self) -> &mut ::protobuf::RepeatedField { - &mut self.block_metas + pub fn mut_blocks(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.blocks } // Take field - pub fn take_block_metas(&mut self) -> ::protobuf::RepeatedField { - ::std::mem::replace(&mut self.block_metas, ::protobuf::RepeatedField::new()) + pub fn take_blocks(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.blocks, ::protobuf::RepeatedField::new()) } } @@ -129,7 +129,7 @@ impl ::protobuf::Message for GridMeta { return false; } }; - for v in &self.block_metas { + for v in &self.blocks { if !v.is_initialized() { return false; } @@ -148,7 +148,7 @@ impl ::protobuf::Message for GridMeta { ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.fields)?; }, 3 => { - ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.block_metas)?; + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.blocks)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -169,7 +169,7 @@ impl ::protobuf::Message for GridMeta { let len = value.compute_size(); my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; }; - for value in &self.block_metas { + for value in &self.blocks { let len = value.compute_size(); my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; }; @@ -187,7 +187,7 @@ impl ::protobuf::Message for GridMeta { os.write_raw_varint32(v.get_cached_size())?; v.write_to_with_cached_sizes(os)?; }; - for v in &self.block_metas { + for v in &self.blocks { os.write_tag(3, ::protobuf::wire_format::WireTypeLengthDelimited)?; os.write_raw_varint32(v.get_cached_size())?; v.write_to_with_cached_sizes(os)?; @@ -241,9 +241,9 @@ impl ::protobuf::Message for GridMeta { |m: &mut GridMeta| { &mut m.fields }, )); fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "block_metas", - |m: &GridMeta| { &m.block_metas }, - |m: &mut GridMeta| { &mut m.block_metas }, + "blocks", + |m: &GridMeta| { &m.blocks }, + |m: &mut GridMeta| { &mut m.blocks }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "GridMeta", @@ -263,7 +263,7 @@ impl ::protobuf::Clear for GridMeta { fn clear(&mut self) { self.grid_id.clear(); self.fields.clear(); - self.block_metas.clear(); + self.blocks.clear(); self.unknown_fields.clear(); } } @@ -513,7 +513,7 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockMeta { pub struct GridBlockMetaData { // message fields pub block_id: ::std::string::String, - pub row_metas: ::protobuf::RepeatedField, + pub rows: ::protobuf::RepeatedField, // special fields pub unknown_fields: ::protobuf::UnknownFields, pub cached_size: ::protobuf::CachedSize, @@ -556,35 +556,35 @@ impl GridBlockMetaData { ::std::mem::replace(&mut self.block_id, ::std::string::String::new()) } - // repeated .RowMeta row_metas = 2; + // repeated .RowMeta rows = 2; - pub fn get_row_metas(&self) -> &[RowMeta] { - &self.row_metas + pub fn get_rows(&self) -> &[RowMeta] { + &self.rows } - pub fn clear_row_metas(&mut self) { - self.row_metas.clear(); + pub fn clear_rows(&mut self) { + self.rows.clear(); } // Param is passed by value, moved - pub fn set_row_metas(&mut self, v: ::protobuf::RepeatedField) { - self.row_metas = v; + pub fn set_rows(&mut self, v: ::protobuf::RepeatedField) { + self.rows = v; } // Mutable pointer to the field. - pub fn mut_row_metas(&mut self) -> &mut ::protobuf::RepeatedField { - &mut self.row_metas + pub fn mut_rows(&mut self) -> &mut ::protobuf::RepeatedField { + &mut self.rows } // Take field - pub fn take_row_metas(&mut self) -> ::protobuf::RepeatedField { - ::std::mem::replace(&mut self.row_metas, ::protobuf::RepeatedField::new()) + pub fn take_rows(&mut self) -> ::protobuf::RepeatedField { + ::std::mem::replace(&mut self.rows, ::protobuf::RepeatedField::new()) } } impl ::protobuf::Message for GridBlockMetaData { fn is_initialized(&self) -> bool { - for v in &self.row_metas { + for v in &self.rows { if !v.is_initialized() { return false; } @@ -600,7 +600,7 @@ impl ::protobuf::Message for GridBlockMetaData { ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.block_id)?; }, 2 => { - ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.row_metas)?; + ::protobuf::rt::read_repeated_message_into(wire_type, is, &mut self.rows)?; }, _ => { ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; @@ -617,7 +617,7 @@ impl ::protobuf::Message for GridBlockMetaData { if !self.block_id.is_empty() { my_size += ::protobuf::rt::string_size(1, &self.block_id); } - for value in &self.row_metas { + for value in &self.rows { let len = value.compute_size(); my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; }; @@ -630,7 +630,7 @@ impl ::protobuf::Message for GridBlockMetaData { if !self.block_id.is_empty() { os.write_string(1, &self.block_id)?; } - for v in &self.row_metas { + for v in &self.rows { os.write_tag(2, ::protobuf::wire_format::WireTypeLengthDelimited)?; os.write_raw_varint32(v.get_cached_size())?; v.write_to_with_cached_sizes(os)?; @@ -679,9 +679,9 @@ impl ::protobuf::Message for GridBlockMetaData { |m: &mut GridBlockMetaData| { &mut m.block_id }, )); fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage>( - "row_metas", - |m: &GridBlockMetaData| { &m.row_metas }, - |m: &mut GridBlockMetaData| { &mut m.row_metas }, + "rows", + |m: &GridBlockMetaData| { &m.rows }, + |m: &mut GridBlockMetaData| { &mut m.rows }, )); ::protobuf::reflect::MessageDescriptor::new_pb_name::( "GridBlockMetaData", @@ -700,7 +700,7 @@ impl ::protobuf::Message for GridBlockMetaData { impl ::protobuf::Clear for GridBlockMetaData { fn clear(&mut self) { self.block_id.clear(); - self.row_metas.clear(); + self.rows.clear(); self.unknown_fields.clear(); } } @@ -3453,26 +3453,26 @@ impl ::protobuf::reflect::ProtobufValue for FieldType { } static file_descriptor_proto_data: &'static [u8] = b"\ - \n\nmeta.proto\"x\n\x08GridMeta\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ + \n\nmeta.proto\"o\n\x08GridMeta\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\ \x06gridId\x12\"\n\x06fields\x18\x02\x20\x03(\x0b2\n.FieldMetaR\x06field\ - s\x12/\n\x0bblock_metas\x18\x03\x20\x03(\x0b2\x0e.GridBlockMetaR\nblockM\ - etas\"o\n\rGridBlockMeta\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07bl\ - ockId\x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\ - \x1b\n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"U\n\x11GridBlockMet\ - aData\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_m\ - etas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\xbc\x02\n\tFieldMe\ - ta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\ - \x20\x01(\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\ - \n\nfield_type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\ - \x06frozen\x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\ - \x20\x01(\x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05w\ - idth\x12>\n\x0ctype_options\x18\x08\x20\x03(\x0b2\x1b.FieldMeta.TypeOpti\ - onsEntryR\x0btypeOptions\x1a>\n\x10TypeOptionsEntry\x12\x10\n\x03key\x18\ - \x01\x20\x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05value:\ - \x028\x01\"\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\ - \x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06\ - gridId\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04des\ - c\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\ + s\x12&\n\x06blocks\x18\x03\x20\x03(\x0b2\x0e.GridBlockMetaR\x06blocks\"o\ + \n\rGridBlockMeta\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\ + \x12&\n\x0fstart_row_index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\x1b\ + \n\trow_count\x18\x03\x20\x01(\x05R\x08rowCount\"L\n\x11GridBlockMetaDat\ + a\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12\x1c\n\x04rows\ + \x18\x02\x20\x03(\x0b2\x08.RowMetaR\x04rows\"\xbc\x02\n\tFieldMeta\x12\ + \x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\x20\x01\ + (\tR\x04name\x12\x12\n\x04desc\x18\x03\x20\x01(\tR\x04desc\x12)\n\nfield\ + _type\x18\x04\x20\x01(\x0e2\n.FieldTypeR\tfieldType\x12\x16\n\x06frozen\ + \x18\x05\x20\x01(\x08R\x06frozen\x12\x1e\n\nvisibility\x18\x06\x20\x01(\ + \x08R\nvisibility\x12\x14\n\x05width\x18\x07\x20\x01(\x05R\x05width\x12>\ + \n\x0ctype_options\x18\x08\x20\x03(\x0b2\x1b.FieldMeta.TypeOptionsEntryR\ + \x0btypeOptions\x1a>\n\x10TypeOptionsEntry\x12\x10\n\x03key\x18\x01\x20\ + \x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\tR\x05value:\x028\ + \x01\"\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\x01\ + \x20\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06grid\ + Id\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\ + \x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\ \x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\ \x08H\x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nv\ isibility\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12*\n\ diff --git a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto index c1166a3ae1..b1bf045cd7 100644 --- a/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto +++ b/shared-lib/flowy-grid-data-model/src/protobuf/proto/grid.proto @@ -57,6 +57,7 @@ message RepeatedGridBlock { } message GridBlockOrder { string block_id = 1; + repeated RowOrder row_orders = 2; } message GridBlock { string id = 1; 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 18c05896fe..2cf0f9b2af 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 @@ -3,7 +3,7 @@ syntax = "proto3"; message GridMeta { string grid_id = 1; repeated FieldMeta fields = 2; - repeated GridBlockMeta block_metas = 3; + repeated GridBlockMeta blocks = 3; } message GridBlockMeta { string block_id = 1; @@ -12,7 +12,7 @@ message GridBlockMeta { } message GridBlockMetaData { string block_id = 1; - repeated RowMeta row_metas = 2; + repeated RowMeta rows = 2; } message FieldMeta { string id = 1; diff --git a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs index ce2802052e..bd5ea1d1a6 100644 --- a/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs +++ b/shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs @@ -5,6 +5,7 @@ use flowy_grid_data_model::entities::{CellMeta, GridBlockMetaData, RowMeta, RowM use lib_infra::uuid; use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder}; use serde::{Deserialize, Serialize}; +use std::borrow::Cow; use std::collections::HashMap; use std::sync::Arc; @@ -67,38 +68,48 @@ impl GridBlockMetaPad { }) } - pub fn delete_rows(&mut self, row_ids: &[String]) -> CollaborateResult> { + pub fn delete_rows(&mut self, row_ids: Vec>) -> CollaborateResult> { self.modify(|rows| { - rows.retain(|row| !row_ids.contains(&row.id)); + rows.retain(|row| !row_ids.contains(&Cow::Borrowed(&row.id))); Ok(Some(())) }) } - pub fn get_row_metas(&self, row_ids: &Option>) -> CollaborateResult>> { + pub fn get_row_metas(&self, row_ids: Option>>) -> CollaborateResult>> + where + T: AsRef + ToOwned + ?Sized, + { match row_ids { None => Ok(self.row_metas.to_vec()), Some(row_ids) => { let row_map = self .row_metas .iter() - .map(|row| (&row.id, row.clone())) - .collect::>>(); + .map(|row| (row.id.as_str(), row.clone())) + .collect::>>(); Ok(row_ids .iter() - .flat_map(|row_id| match row_map.get(row_id) { - None => { - tracing::error!("Can't find the row with id: {}", row_id); - None + .flat_map(|row_id| { + let row_id = row_id.as_ref().as_ref(); + match row_map.get(row_id) { + None => { + tracing::error!("Can't find the row with id: {}", row_id); + None + } + Some(row) => Some(row.clone()), } - Some(row) => Some(row.clone()), }) .collect::>()) } } } - pub fn get_cell_metas(&self, field_id: &str, row_ids: &Option>) -> CollaborateResult> { + pub fn get_cell_metas( + &self, + field_id: &str, + row_ids: Option>>, + ) -> CollaborateResult> { let rows = self.get_row_metas(row_ids)?; let cell_metas = rows .iter() @@ -227,6 +238,7 @@ impl std::default::Default for GridBlockMetaPad { mod tests { use crate::client_grid::{GridBlockMetaDelta, GridBlockMetaPad}; use flowy_grid_data_model::entities::{RowMeta, RowMetaChangeset}; + use std::borrow::Cow; #[test] fn block_meta_add_row() { @@ -331,7 +343,7 @@ mod tests { }; let _ = pad.add_row_meta(row.clone(), None).unwrap().unwrap(); - let change = pad.delete_rows(&[row.id]).unwrap().unwrap(); + let change = pad.delete_rows(vec![Cow::Borrowed(&row.id)]).unwrap().unwrap(); assert_eq!( change.delta.to_delta_str(), r#"[{"retain":29},{"delete":77},{"retain":2}]"#