Browse Source

chore: get cell metas

appflowy 3 years ago
parent
commit
2262dd0d7b

+ 18 - 18
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pb.dart

@@ -151,15 +151,15 @@ class GridBlockMeta extends $pb.GeneratedMessage {
   void clearRowCount() => clearField(3);
 }
 
-class GridBlockMetaSerde extends $pb.GeneratedMessage {
-  static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockMetaSerde', createEmptyInstance: create)
+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<RowMeta>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowMetas', $pb.PbFieldType.PM, subBuilder: RowMeta.create)
     ..hasRequiredFields = false
   ;
 
-  GridBlockMetaSerde._() : super();
-  factory GridBlockMetaSerde({
+  GridBlockMetaData._() : super();
+  factory GridBlockMetaData({
     $core.String? blockId,
     $core.Iterable<RowMeta>? rowMetas,
   }) {
@@ -172,26 +172,26 @@ class GridBlockMetaSerde extends $pb.GeneratedMessage {
     }
     return _result;
   }
-  factory GridBlockMetaSerde.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
-  factory GridBlockMetaSerde.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
+  factory GridBlockMetaData.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
+  factory GridBlockMetaData.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')
-  GridBlockMetaSerde clone() => GridBlockMetaSerde()..mergeFromMessage(this);
+  GridBlockMetaData clone() => GridBlockMetaData()..mergeFromMessage(this);
   @$core.Deprecated(
   'Using this can add significant overhead to your binary. '
   'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
   'Will be removed in next major version')
-  GridBlockMetaSerde copyWith(void Function(GridBlockMetaSerde) updates) => super.copyWith((message) => updates(message as GridBlockMetaSerde)) as GridBlockMetaSerde; // ignore: deprecated_member_use
+  GridBlockMetaData copyWith(void Function(GridBlockMetaData) updates) => super.copyWith((message) => updates(message as GridBlockMetaData)) as GridBlockMetaData; // ignore: deprecated_member_use
   $pb.BuilderInfo get info_ => _i;
   @$core.pragma('dart2js:noInline')
-  static GridBlockMetaSerde create() => GridBlockMetaSerde._();
-  GridBlockMetaSerde createEmptyInstance() => create();
-  static $pb.PbList<GridBlockMetaSerde> createRepeated() => $pb.PbList<GridBlockMetaSerde>();
+  static GridBlockMetaData create() => GridBlockMetaData._();
+  GridBlockMetaData createEmptyInstance() => create();
+  static $pb.PbList<GridBlockMetaData> createRepeated() => $pb.PbList<GridBlockMetaData>();
   @$core.pragma('dart2js:noInline')
-  static GridBlockMetaSerde getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GridBlockMetaSerde>(create);
-  static GridBlockMetaSerde? _defaultInstance;
+  static GridBlockMetaData getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GridBlockMetaData>(create);
+  static GridBlockMetaData? _defaultInstance;
 
   @$pb.TagNumber(1)
   $core.String get blockId => $_getSZ(0);
@@ -1078,7 +1078,7 @@ class BuildGridContext extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BuildGridContext', createEmptyInstance: create)
     ..pc<FieldMeta>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldMetas', $pb.PbFieldType.PM, subBuilder: FieldMeta.create)
     ..aOM<GridBlockMeta>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetas', subBuilder: GridBlockMeta.create)
-    ..aOM<GridBlockMetaSerde>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetaData', subBuilder: GridBlockMetaSerde.create)
+    ..aOM<GridBlockMetaData>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockMetaData', subBuilder: GridBlockMetaData.create)
     ..hasRequiredFields = false
   ;
 
@@ -1086,7 +1086,7 @@ class BuildGridContext extends $pb.GeneratedMessage {
   factory BuildGridContext({
     $core.Iterable<FieldMeta>? fieldMetas,
     GridBlockMeta? blockMetas,
-    GridBlockMetaSerde? blockMetaData,
+    GridBlockMetaData? blockMetaData,
   }) {
     final _result = create();
     if (fieldMetas != null) {
@@ -1136,14 +1136,14 @@ class BuildGridContext extends $pb.GeneratedMessage {
   GridBlockMeta ensureBlockMetas() => $_ensure(1);
 
   @$pb.TagNumber(3)
-  GridBlockMetaSerde get blockMetaData => $_getN(2);
+  GridBlockMetaData get blockMetaData => $_getN(2);
   @$pb.TagNumber(3)
-  set blockMetaData(GridBlockMetaSerde v) { setField(3, v); }
+  set blockMetaData(GridBlockMetaData v) { setField(3, v); }
   @$pb.TagNumber(3)
   $core.bool hasBlockMetaData() => $_has(2);
   @$pb.TagNumber(3)
   void clearBlockMetaData() => clearField(3);
   @$pb.TagNumber(3)
-  GridBlockMetaSerde ensureBlockMetaData() => $_ensure(2);
+  GridBlockMetaData ensureBlockMetaData() => $_ensure(2);
 }
 

+ 7 - 7
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid-data-model/meta.pbjson.dart

@@ -47,17 +47,17 @@ const GridBlockMeta$json = const {
 
 /// Descriptor for `GridBlockMeta`. Decode as a `google.protobuf.DescriptorProto`.
 final $typed_data.Uint8List gridBlockMetaDescriptor = $convert.base64Decode('Cg1HcmlkQmxvY2tNZXRhEhkKCGJsb2NrX2lkGAEgASgJUgdibG9ja0lkEiYKD3N0YXJ0X3Jvd19pbmRleBgCIAEoBVINc3RhcnRSb3dJbmRleBIbCglyb3dfY291bnQYAyABKAVSCHJvd0NvdW50');
-@$core.Deprecated('Use gridBlockMetaSerdeDescriptor instead')
-const GridBlockMetaSerde$json = const {
-  '1': 'GridBlockMetaSerde',
+@$core.Deprecated('Use gridBlockMetaDataDescriptor instead')
+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'},
   ],
 };
 
-/// Descriptor for `GridBlockMetaSerde`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List gridBlockMetaSerdeDescriptor = $convert.base64Decode('ChJHcmlkQmxvY2tNZXRhU2VyZGUSGQoIYmxvY2tfaWQYASABKAlSB2Jsb2NrSWQSJQoJcm93X21ldGFzGAIgAygLMgguUm93TWV0YVIIcm93TWV0YXM=');
+/// Descriptor for `GridBlockMetaData`. Decode as a `google.protobuf.DescriptorProto`.
+final $typed_data.Uint8List gridBlockMetaDataDescriptor = $convert.base64Decode('ChFHcmlkQmxvY2tNZXRhRGF0YRIZCghibG9ja19pZBgBIAEoCVIHYmxvY2tJZBIlCglyb3dfbWV0YXMYAiADKAsyCC5Sb3dNZXRhUghyb3dNZXRhcw==');
 @$core.Deprecated('Use fieldMetaDescriptor instead')
 const FieldMeta$json = const {
   '1': 'FieldMeta',
@@ -220,9 +220,9 @@ const BuildGridContext$json = const {
   '2': const [
     const {'1': 'field_metas', '3': 1, '4': 3, '5': 11, '6': '.FieldMeta', '10': 'fieldMetas'},
     const {'1': 'block_metas', '3': 2, '4': 1, '5': 11, '6': '.GridBlockMeta', '10': 'blockMetas'},
-    const {'1': 'block_meta_data', '3': 3, '4': 1, '5': 11, '6': '.GridBlockMetaSerde', '10': 'blockMetaData'},
+    const {'1': 'block_meta_data', '3': 3, '4': 1, '5': 11, '6': '.GridBlockMetaData', '10': 'blockMetaData'},
   ],
 };
 
 /// Descriptor for `BuildGridContext`. Decode as a `google.protobuf.DescriptorProto`.
-final $typed_data.Uint8List buildGridContextDescriptor = $convert.base64Decode('ChBCdWlsZEdyaWRDb250ZXh0EisKC2ZpZWxkX21ldGFzGAEgAygLMgouRmllbGRNZXRhUgpmaWVsZE1ldGFzEi8KC2Jsb2NrX21ldGFzGAIgASgLMg4uR3JpZEJsb2NrTWV0YVIKYmxvY2tNZXRhcxI7Cg9ibG9ja19tZXRhX2RhdGEYAyABKAsyEy5HcmlkQmxvY2tNZXRhU2VyZGVSDWJsb2NrTWV0YURhdGE=');
+final $typed_data.Uint8List buildGridContextDescriptor = $convert.base64Decode('ChBCdWlsZEdyaWRDb250ZXh0EisKC2ZpZWxkX21ldGFzGAEgAygLMgouRmllbGRNZXRhUgpmaWVsZE1ldGFzEi8KC2Jsb2NrX21ldGFzGAIgASgLMg4uR3JpZEJsb2NrTWV0YVIKYmxvY2tNZXRhcxI6Cg9ibG9ja19tZXRhX2RhdGEYAyABKAsyEi5HcmlkQmxvY2tNZXRhRGF0YVINYmxvY2tNZXRhRGF0YQ==');

+ 33 - 36
frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs

@@ -1,12 +1,12 @@
+use crate::dart_notification::{send_dart_notification, GridNotification};
 use crate::manager::GridUser;
-use crate::services::row::{make_cell, make_row_ids_per_block, GridBlockMetaData};
+use crate::services::row::{make_cell, make_row_ids_per_block, GridBlockSnapshot};
 use bytes::Bytes;
-
-use crate::dart_notification::{send_dart_notification, GridNotification};
 use dashmap::DashMap;
 use flowy_error::{FlowyError, FlowyResult};
 use flowy_grid_data_model::entities::{
-    FieldMeta, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, RowMeta, RowMetaChangeset, RowOrder,
+    CellMeta, FieldMeta, GridBlockMeta, GridBlockMetaChangeset, GridBlockOrder, RepeatedCell, RowMeta,
+    RowMetaChangeset, RowOrder,
 };
 use flowy_revision::disk::SQLiteGridBlockMetaRevisionPersistence;
 use flowy_revision::{
@@ -116,7 +116,8 @@ impl GridBlockMetaEditorManager {
 
     pub async fn get_row(&self, block_id: &str, row_id: &str) -> FlowyResult<Option<Arc<RowMeta>>> {
         let editor = self.get_editor(block_id).await?;
-        let mut row_metas = editor.get_row_metas(Some(vec![row_id.to_owned()])).await?;
+        let row_ids = vec![row_id.to_owned()];
+        let mut row_metas = editor.get_row_metas(&Some(row_ids)).await?;
         if row_metas.is_empty() {
             Ok(None)
         } else {
@@ -131,42 +132,35 @@ impl GridBlockMetaEditorManager {
         Ok(())
     }
 
-    pub(crate) async fn get_block_meta_data_from_blocks(
-        &self,
-        grid_blocks: Vec<GridBlockMeta>,
-    ) -> FlowyResult<Vec<GridBlockMetaData>> {
+    pub(crate) async fn make_block_snapshots(&self, block_ids: Vec<String>) -> FlowyResult<Vec<GridBlockSnapshot>> {
         let mut snapshots = vec![];
-        for grid_block in grid_blocks {
-            let editor = self.get_editor(&grid_block.block_id).await?;
-            let row_metas = editor.get_row_metas(None).await?;
+        for block_id in block_ids {
+            let editor = self.get_editor(&block_id).await?;
+            let row_metas = editor.get_row_metas(&None).await?;
             row_metas.iter().for_each(|row_meta| {
                 self.block_id_by_row_id
                     .insert(row_meta.id.clone(), row_meta.block_id.clone());
             });
 
-            snapshots.push(GridBlockMetaData {
-                block_id: grid_block.block_id,
-                row_metas,
-            });
+            snapshots.push(GridBlockSnapshot { block_id, row_metas });
         }
         Ok(snapshots)
     }
 
-    pub(crate) async fn get_block_meta_data(&self, block_ids: &[String]) -> FlowyResult<Vec<GridBlockMetaData>> {
-        let mut snapshots = vec![];
+    // Optimization: Using the shared memory(Arc, Cow,etc.) to reduce memory usage.
+    pub async fn get_cell_metas(
+        &self,
+        block_ids: Option<String>,
+        field_id: &str,
+        row_ids: Option<Vec<String>>,
+    ) -> FlowyResult<Vec<CellMeta>> {
+        let mut block_cell_metas = vec![];
         for block_id in block_ids {
-            let editor = self.get_editor(block_id).await?;
-            let row_metas = editor.get_row_metas(None).await?;
-            row_metas.iter().for_each(|row_meta| {
-                self.block_id_by_row_id
-                    .insert(row_meta.id.clone(), row_meta.block_id.clone());
-            });
-            snapshots.push(GridBlockMetaData {
-                block_id: block_id.clone(),
-                row_metas,
-            });
+            let editor = self.get_editor(&block_id).await?;
+            let cell_metas = editor.get_cell_metas(field_id, &row_ids).await?;
+            block_cell_metas.extend(cell_metas);
         }
-        Ok(snapshots)
+        Ok(block_cell_metas)
     }
 
     async fn get_editor_from_row_id(&self, row_id: &str) -> FlowyResult<Arc<ClientGridBlockMetaEditor>> {
@@ -178,10 +172,7 @@ impl GridBlockMetaEditorManager {
                 );
                 Err(FlowyError::internal().context(msg))
             }
-            Some(block_id) => {
-                let editor = self.get_editor(&block_id).await?;
-                Ok(editor)
-            }
+            Some(block_id) => Ok(self.get_editor(&block_id).await?),
         }
     }
 
@@ -301,7 +292,8 @@ impl ClientGridBlockMetaEditor {
     pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<RowMeta> {
         let row_id = changeset.row_id.clone();
         let _ = self.modify(|pad| Ok(pad.update_row(changeset)?)).await?;
-        let mut row_metas = self.get_row_metas(Some(vec![row_id.clone()])).await?;
+        let row_ids = vec![row_id.clone()];
+        let mut row_metas = self.get_row_metas(&Some(row_ids)).await?;
         debug_assert_eq!(row_metas.len(), 1);
 
         if row_metas.is_empty() {
@@ -312,12 +304,17 @@ impl ClientGridBlockMetaEditor {
         }
     }
 
-    pub async fn get_row_metas(&self, row_ids: Option<Vec<String>>) -> FlowyResult<Vec<Arc<RowMeta>>> {
+    pub async fn get_row_metas(&self, row_ids: &Option<Vec<String>>) -> FlowyResult<Vec<Arc<RowMeta>>> {
         let row_metas = self.pad.read().await.get_row_metas(row_ids)?;
         Ok(row_metas)
     }
 
-    pub async fn get_row_orders(&self, row_ids: Option<Vec<String>>) -> FlowyResult<Vec<RowOrder>> {
+    pub async fn get_cell_metas(&self, field_id: &str, row_ids: &Option<Vec<String>>) -> FlowyResult<Vec<CellMeta>> {
+        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<Vec<String>>) -> FlowyResult<Vec<RowOrder>> {
         let row_orders = self
             .pad
             .read()

+ 35 - 40
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -37,8 +37,9 @@ impl ClientGridEditor {
         let rev_manager = Arc::new(rev_manager);
         let pad = Arc::new(RwLock::new(grid_pad));
 
-        let block_meta_manager =
-            Arc::new(GridBlockMetaEditorManager::new(grid_id, &user, pad.read().await.get_blocks().clone()).await?);
+        let block_meta_manager = Arc::new(
+            GridBlockMetaEditorManager::new(grid_id, &user, pad.read().await.get_block_metas().clone()).await?,
+        );
 
         Ok(Arc::new(Self {
             grid_id: grid_id.to_owned(),
@@ -113,8 +114,11 @@ impl ClientGridEditor {
     }
 
     pub async fn switch_to_field_type(&self, field_id: &str, field_type: &FieldType) -> FlowyResult<()> {
-        let type_option_json_builder =
-            |field_type: &FieldType| -> String { default_type_option_builder_from_type(field_type).entry().json_str() };
+        // let cell_metas = self.block_meta_manager.get_cell_metas(None, field_id, None).await?;
+
+        let type_option_json_builder = |field_type: &FieldType| -> String {
+            return default_type_option_builder_from_type(field_type).entry().json_str();
+        };
 
         let _ = self
             .modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?))
@@ -137,12 +141,12 @@ impl ClientGridEditor {
     }
 
     pub async fn create_block(&self, grid_block: GridBlockMeta) -> FlowyResult<()> {
-        let _ = self.modify(|grid| Ok(grid.create_block(grid_block)?)).await?;
+        let _ = self.modify(|grid| Ok(grid.create_block_meta(grid_block)?)).await?;
         Ok(())
     }
 
     pub async fn update_block(&self, changeset: GridBlockMetaChangeset) -> FlowyResult<()> {
-        let _ = self.modify(|grid| Ok(grid.update_block(changeset)?)).await?;
+        let _ = self.modify(|grid| Ok(grid.update_block_meta(changeset)?)).await?;
         Ok(())
     }
 
@@ -192,12 +196,15 @@ impl ClientGridEditor {
 
     pub async fn get_rows(&self, block_id: &str) -> FlowyResult<RepeatedRow> {
         let block_ids = vec![block_id.to_owned()];
-        let mut block_meta_data_vec = self.get_block_meta_data_vec(Some(&block_ids)).await?;
-        debug_assert_eq!(block_meta_data_vec.len(), 1);
-        if block_meta_data_vec.len() == 1 {
-            let block_meta_data = block_meta_data_vec.pop().unwrap();
+        let mut grid_block_snapshot = self.grid_block_snapshots(Some(block_ids)).await?;
+
+        // For the moment, we only support one block.
+        // We can save the rows into multiple blocks and load them asynchronously in the future.
+        debug_assert_eq!(grid_block_snapshot.len(), 1);
+        if grid_block_snapshot.len() == 1 {
+            let snapshot = grid_block_snapshot.pop().unwrap();
             let field_metas = self.get_field_metas(None).await?;
-            let rows = make_rows_from_row_metas(&field_metas, &block_meta_data.row_metas);
+            let rows = make_rows_from_row_metas(&field_metas, &snapshot.row_metas);
             Ok(rows.into())
         } else {
             Ok(vec![].into())
@@ -240,15 +247,12 @@ impl ClientGridEditor {
     }
 
     pub async fn get_blocks(&self, block_ids: Option<Vec<String>>) -> FlowyResult<RepeatedGridBlock> {
-        let block_meta_data_vec = self.get_block_meta_data_vec(block_ids.as_ref()).await?;
-        match block_ids {
-            None => make_grid_blocks(block_meta_data_vec),
-            Some(block_ids) => make_grid_block_from_block_metas(&block_ids, block_meta_data_vec),
-        }
+        let block_snapshots = self.grid_block_snapshots(block_ids.clone()).await?;
+        make_grid_blocks(block_ids, block_snapshots)
     }
 
     pub async fn get_block_metas(&self) -> FlowyResult<Vec<GridBlockMeta>> {
-        let grid_blocks = self.pad.read().await.get_blocks();
+        let grid_blocks = self.pad.read().await.get_block_metas();
         Ok(grid_blocks)
     }
 
@@ -266,7 +270,7 @@ impl ClientGridEditor {
             .pad
             .read()
             .await
-            .get_blocks()
+            .get_block_metas()
             .into_iter()
             .map(|grid_block_meta| GridBlockOrder {
                 block_id: grid_block_meta.block_id,
@@ -285,27 +289,18 @@ impl ClientGridEditor {
         Ok(field_metas)
     }
 
-    pub async fn get_block_meta_data_vec(
-        &self,
-        block_ids: Option<&Vec<String>>,
-    ) -> FlowyResult<Vec<GridBlockMetaData>> {
-        match block_ids {
-            None => {
-                let grid_blocks = self.pad.read().await.get_blocks();
-                let row_metas_per_block = self
-                    .block_meta_manager
-                    .get_block_meta_data_from_blocks(grid_blocks)
-                    .await?;
-                Ok(row_metas_per_block)
-            }
-            Some(block_ids) => {
-                let row_metas_per_block = self
-                    .block_meta_manager
-                    .get_block_meta_data(block_ids.as_slice())
-                    .await?;
-                Ok(row_metas_per_block)
-            }
-        }
+    pub async fn grid_block_snapshots(&self, block_ids: Option<Vec<String>>) -> FlowyResult<Vec<GridBlockSnapshot>> {
+        let block_ids = block_ids.unwrap_or(
+            self.pad
+                .read()
+                .await
+                .get_block_metas()
+                .into_iter()
+                .map(|block_meta| block_meta.block_id)
+                .collect::<Vec<String>>(),
+        );
+        let snapshots = self.block_meta_manager.make_block_snapshots(block_ids).await?;
+        Ok(snapshots)
     }
 
     pub async fn delta_bytes(&self) -> Bytes {
@@ -347,7 +342,7 @@ impl ClientGridEditor {
     }
 
     async fn block_id(&self) -> FlowyResult<String> {
-        match self.pad.read().await.get_blocks().last() {
+        match self.pad.read().await.get_block_metas().last() {
             None => Err(FlowyError::internal().context("There is no grid block in this grid")),
             Some(grid_block) => Ok(grid_block.block_id.clone()),
         }

+ 28 - 31
frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs

@@ -22,7 +22,7 @@ impl RowIdsPerBlock {
     }
 }
 
-pub struct GridBlockMetaData {
+pub struct GridBlockSnapshot {
     pub(crate) block_id: String,
     pub row_metas: Vec<Arc<RowMeta>>,
 }
@@ -40,20 +40,6 @@ pub(crate) fn make_row_ids_per_block(row_orders: &[RowOrder]) -> Vec<RowIdsPerBl
     map.into_values().collect::<Vec<_>>()
 }
 
-pub(crate) fn make_grid_blocks(block_meta_snapshots: Vec<GridBlockMetaData>) -> FlowyResult<RepeatedGridBlock> {
-    Ok(block_meta_snapshots
-        .into_iter()
-        .map(|block_meta_data| {
-            let row_orders = make_row_orders_from_row_metas(&block_meta_data.row_metas);
-            GridBlock {
-                id: block_meta_data.block_id,
-                row_orders,
-            }
-        })
-        .collect::<Vec<GridBlock>>()
-        .into())
-}
-
 #[inline(always)]
 pub fn make_cell(
     field_map: &HashMap<&String, &FieldMeta>,
@@ -101,25 +87,36 @@ pub(crate) fn make_rows_from_row_metas(fields: &[FieldMeta], row_metas: &[Arc<Ro
     row_metas.iter().map(make_row).collect::<Vec<_>>()
 }
 
-pub(crate) fn make_grid_block_from_block_metas(
-    block_ids: &[String],
-    block_meta_data_vec: Vec<GridBlockMetaData>,
+pub(crate) fn make_grid_blocks(
+    block_ids: Option<Vec<String>>,
+    block_snapshots: Vec<GridBlockSnapshot>,
 ) -> FlowyResult<RepeatedGridBlock> {
-    let block_meta_data_map: HashMap<&String, &Vec<Arc<RowMeta>>> = block_meta_data_vec
-        .iter()
-        .map(|data| (&data.block_id, &data.row_metas))
-        .collect();
+    match block_ids {
+        None => Ok(block_snapshots
+            .into_iter()
+            .map(|snapshot| {
+                let row_orders = make_row_orders_from_row_metas(&snapshot.row_metas);
+                GridBlock::new(&snapshot.block_id, row_orders)
+            })
+            .collect::<Vec<GridBlock>>()
+            .into()),
+        Some(block_ids) => {
+            let block_meta_data_map: HashMap<&String, &Vec<Arc<RowMeta>>> = block_snapshots
+                .iter()
+                .map(|data| (&data.block_id, &data.row_metas))
+                .collect();
 
-    let mut grid_blocks = vec![];
-    for block_id in block_ids {
-        match block_meta_data_map.get(&block_id) {
-            None => {}
-            Some(row_metas) => {
-                let row_orders = make_row_orders_from_row_metas(row_metas);
-                grid_blocks.push(GridBlock::new(block_id, row_orders));
+            let mut grid_blocks = vec![];
+            for block_id in block_ids {
+                match block_meta_data_map.get(&block_id) {
+                    None => {}
+                    Some(row_metas) => {
+                        let row_orders = make_row_orders_from_row_metas(row_metas);
+                        grid_blocks.push(GridBlock::new(&block_id, row_orders));
+                    }
+                }
             }
+            Ok(grid_blocks.into())
         }
     }
-
-    Ok(grid_blocks.into())
 }

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

@@ -238,7 +238,7 @@ impl GridEditorTest {
 
 async fn get_row_metas(editor: &Arc<ClientGridEditor>) -> Vec<Arc<RowMeta>> {
     editor
-        .get_block_meta_data_vec(None)
+        .grid_block_snapshots(None)
         .await
         .unwrap()
         .pop()

+ 3 - 3
shared-lib/flowy-grid-data-model/src/entities/meta.rs

@@ -69,7 +69,7 @@ impl GridBlockMetaChangeset {
 }
 
 #[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
-pub struct GridBlockMetaSerde {
+pub struct GridBlockMetaData {
     #[pb(index = 1)]
     pub block_id: String,
 
@@ -431,13 +431,13 @@ pub struct BuildGridContext {
     pub block_metas: GridBlockMeta,
 
     #[pb(index = 3)]
-    pub block_meta_data: GridBlockMetaSerde,
+    pub block_meta_data: GridBlockMetaData,
 }
 
 impl std::default::Default for BuildGridContext {
     fn default() -> Self {
         let grid_block = GridBlockMeta::new();
-        let grid_block_meta_data = GridBlockMetaSerde {
+        let grid_block_meta_data = GridBlockMetaData {
             block_id: grid_block.block_id.clone(),
             row_metas: vec![],
         };

+ 37 - 37
shared-lib/flowy-grid-data-model/src/protobuf/model/meta.rs

@@ -510,7 +510,7 @@ impl ::protobuf::reflect::ProtobufValue for GridBlockMeta {
 }
 
 #[derive(PartialEq,Clone,Default)]
-pub struct GridBlockMetaSerde {
+pub struct GridBlockMetaData {
     // message fields
     pub block_id: ::std::string::String,
     pub row_metas: ::protobuf::RepeatedField<RowMeta>,
@@ -519,14 +519,14 @@ pub struct GridBlockMetaSerde {
     pub cached_size: ::protobuf::CachedSize,
 }
 
-impl<'a> ::std::default::Default for &'a GridBlockMetaSerde {
-    fn default() -> &'a GridBlockMetaSerde {
-        <GridBlockMetaSerde as ::protobuf::Message>::default_instance()
+impl<'a> ::std::default::Default for &'a GridBlockMetaData {
+    fn default() -> &'a GridBlockMetaData {
+        <GridBlockMetaData as ::protobuf::Message>::default_instance()
     }
 }
 
-impl GridBlockMetaSerde {
-    pub fn new() -> GridBlockMetaSerde {
+impl GridBlockMetaData {
+    pub fn new() -> GridBlockMetaData {
         ::std::default::Default::default()
     }
 
@@ -582,7 +582,7 @@ impl GridBlockMetaSerde {
     }
 }
 
-impl ::protobuf::Message for GridBlockMetaSerde {
+impl ::protobuf::Message for GridBlockMetaData {
     fn is_initialized(&self) -> bool {
         for v in &self.row_metas {
             if !v.is_initialized() {
@@ -665,8 +665,8 @@ impl ::protobuf::Message for GridBlockMetaSerde {
         Self::descriptor_static()
     }
 
-    fn new() -> GridBlockMetaSerde {
-        GridBlockMetaSerde::new()
+    fn new() -> GridBlockMetaData {
+        GridBlockMetaData::new()
     }
 
     fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
@@ -675,29 +675,29 @@ impl ::protobuf::Message for GridBlockMetaSerde {
             let mut fields = ::std::vec::Vec::new();
             fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
                 "block_id",
-                |m: &GridBlockMetaSerde| { &m.block_id },
-                |m: &mut GridBlockMetaSerde| { &mut m.block_id },
+                |m: &GridBlockMetaData| { &m.block_id },
+                |m: &mut GridBlockMetaData| { &mut m.block_id },
             ));
             fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<RowMeta>>(
                 "row_metas",
-                |m: &GridBlockMetaSerde| { &m.row_metas },
-                |m: &mut GridBlockMetaSerde| { &mut m.row_metas },
+                |m: &GridBlockMetaData| { &m.row_metas },
+                |m: &mut GridBlockMetaData| { &mut m.row_metas },
             ));
-            ::protobuf::reflect::MessageDescriptor::new_pb_name::<GridBlockMetaSerde>(
-                "GridBlockMetaSerde",
+            ::protobuf::reflect::MessageDescriptor::new_pb_name::<GridBlockMetaData>(
+                "GridBlockMetaData",
                 fields,
                 file_descriptor_proto()
             )
         })
     }
 
-    fn default_instance() -> &'static GridBlockMetaSerde {
-        static instance: ::protobuf::rt::LazyV2<GridBlockMetaSerde> = ::protobuf::rt::LazyV2::INIT;
-        instance.get(GridBlockMetaSerde::new)
+    fn default_instance() -> &'static GridBlockMetaData {
+        static instance: ::protobuf::rt::LazyV2<GridBlockMetaData> = ::protobuf::rt::LazyV2::INIT;
+        instance.get(GridBlockMetaData::new)
     }
 }
 
-impl ::protobuf::Clear for GridBlockMetaSerde {
+impl ::protobuf::Clear for GridBlockMetaData {
     fn clear(&mut self) {
         self.block_id.clear();
         self.row_metas.clear();
@@ -705,13 +705,13 @@ impl ::protobuf::Clear for GridBlockMetaSerde {
     }
 }
 
-impl ::std::fmt::Debug for GridBlockMetaSerde {
+impl ::std::fmt::Debug for GridBlockMetaData {
     fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
         ::protobuf::text_format::fmt(self, f)
     }
 }
 
-impl ::protobuf::reflect::ProtobufValue for GridBlockMetaSerde {
+impl ::protobuf::reflect::ProtobufValue for GridBlockMetaData {
     fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
         ::protobuf::reflect::ReflectValueRef::Message(self)
     }
@@ -3331,7 +3331,7 @@ pub struct BuildGridContext {
     // message fields
     pub field_metas: ::protobuf::RepeatedField<FieldMeta>,
     pub block_metas: ::protobuf::SingularPtrField<GridBlockMeta>,
-    pub block_meta_data: ::protobuf::SingularPtrField<GridBlockMetaSerde>,
+    pub block_meta_data: ::protobuf::SingularPtrField<GridBlockMetaData>,
     // special fields
     pub unknown_fields: ::protobuf::UnknownFields,
     pub cached_size: ::protobuf::CachedSize,
@@ -3406,11 +3406,11 @@ impl BuildGridContext {
         self.block_metas.take().unwrap_or_else(|| GridBlockMeta::new())
     }
 
-    // .GridBlockMetaSerde block_meta_data = 3;
+    // .GridBlockMetaData block_meta_data = 3;
 
 
-    pub fn get_block_meta_data(&self) -> &GridBlockMetaSerde {
-        self.block_meta_data.as_ref().unwrap_or_else(|| <GridBlockMetaSerde as ::protobuf::Message>::default_instance())
+    pub fn get_block_meta_data(&self) -> &GridBlockMetaData {
+        self.block_meta_data.as_ref().unwrap_or_else(|| <GridBlockMetaData as ::protobuf::Message>::default_instance())
     }
     pub fn clear_block_meta_data(&mut self) {
         self.block_meta_data.clear();
@@ -3421,13 +3421,13 @@ impl BuildGridContext {
     }
 
     // Param is passed by value, moved
-    pub fn set_block_meta_data(&mut self, v: GridBlockMetaSerde) {
+    pub fn set_block_meta_data(&mut self, v: GridBlockMetaData) {
         self.block_meta_data = ::protobuf::SingularPtrField::some(v);
     }
 
     // Mutable pointer to the field.
     // If field is not initialized, it is initialized with default value first.
-    pub fn mut_block_meta_data(&mut self) -> &mut GridBlockMetaSerde {
+    pub fn mut_block_meta_data(&mut self) -> &mut GridBlockMetaData {
         if self.block_meta_data.is_none() {
             self.block_meta_data.set_default();
         }
@@ -3435,8 +3435,8 @@ impl BuildGridContext {
     }
 
     // Take field
-    pub fn take_block_meta_data(&mut self) -> GridBlockMetaSerde {
-        self.block_meta_data.take().unwrap_or_else(|| GridBlockMetaSerde::new())
+    pub fn take_block_meta_data(&mut self) -> GridBlockMetaData {
+        self.block_meta_data.take().unwrap_or_else(|| GridBlockMetaData::new())
     }
 }
 
@@ -3566,7 +3566,7 @@ impl ::protobuf::Message for BuildGridContext {
                 |m: &BuildGridContext| { &m.block_metas },
                 |m: &mut BuildGridContext| { &mut m.block_metas },
             ));
-            fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<GridBlockMetaSerde>>(
+            fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<GridBlockMetaData>>(
                 "block_meta_data",
                 |m: &BuildGridContext| { &m.block_meta_data },
                 |m: &mut BuildGridContext| { &mut m.block_meta_data },
@@ -3674,10 +3674,10 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     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\"V\n\x12GridBlockMet\
-    aSerde\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12%\n\trow_\
-    metas\x18\x02\x20\x03(\x0b2\x08.RowMetaR\x08rowMetas\"\x99\x02\n\tFieldM\
-    eta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x12\n\x04name\x18\x02\
+    \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\"\x99\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\
@@ -3717,11 +3717,11 @@ static file_descriptor_proto_data: &'static [u8] = b"\
     (\tR\x04data\"\x83\x01\n\x11CellMetaChangeset\x12\x17\n\x07grid_id\x18\
     \x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05ro\
     wId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04da\
-    ta\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xad\x01\n\x10Bui\
+    ta\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data\"\xac\x01\n\x10Bui\
     ldGridContext\x12+\n\x0bfield_metas\x18\x01\x20\x03(\x0b2\n.FieldMetaR\n\
     fieldMetas\x12/\n\x0bblock_metas\x18\x02\x20\x01(\x0b2\x0e.GridBlockMeta\
-    R\nblockMetas\x12;\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x13.GridBl\
-    ockMetaSerdeR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\
+    R\nblockMetas\x12:\n\x0fblock_meta_data\x18\x03\x20\x01(\x0b2\x12.GridBl\
+    ockMetaDataR\rblockMetaData*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\
     \x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSi\
     ngleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbo\
     x\x10\x05b\x06proto3\

+ 2 - 2
shared-lib/flowy-grid-data-model/src/protobuf/proto/meta.proto

@@ -10,7 +10,7 @@ message GridBlockMeta {
     int32 start_row_index = 2;
     int32 row_count = 3;
 }
-message GridBlockMetaSerde {
+message GridBlockMetaData {
     string block_id = 1;
     repeated RowMeta row_metas = 2;
 }
@@ -68,7 +68,7 @@ message CellMetaChangeset {
 message BuildGridContext {
     repeated FieldMeta field_metas = 1;
     GridBlockMeta block_metas = 2;
-    GridBlockMetaSerde block_meta_data = 3;
+    GridBlockMetaData block_meta_data = 3;
 }
 enum FieldType {
     RichText = 0;

+ 21 - 8
shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs

@@ -1,10 +1,11 @@
 use crate::entities::revision::{md5, RepeatedRevision, Revision};
 use crate::errors::{CollaborateError, CollaborateResult};
 use crate::util::{cal_diff, make_delta_from_revisions};
-use flowy_grid_data_model::entities::{GridBlockMetaSerde, RowMeta, RowMetaChangeset};
+use flowy_grid_data_model::entities::{CellMeta, GridBlockMetaData, RowMeta, RowMetaChangeset};
 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;
 
@@ -25,12 +26,12 @@ impl GridBlockMetaPad {
         let s = delta.to_str()?;
         tracing::info!("delta: {}", delta);
         tracing::info!("{}", s);
-        let block_meta: GridBlockMetaSerde = serde_json::from_str(&s).map_err(|e| {
+        let meta_data: GridBlockMetaData = serde_json::from_str(&s).map_err(|e| {
             let msg = format!("Deserialize delta to block meta failed: {}", e);
             CollaborateError::internal().context(msg)
         })?;
-        let block_id = block_meta.block_id;
-        let rows = block_meta
+        let block_id = meta_data.block_id;
+        let rows = meta_data
             .row_metas
             .into_iter()
             .map(Arc::new)
@@ -78,7 +79,7 @@ impl GridBlockMetaPad {
         })
     }
 
-    pub fn get_row_metas(&self, row_ids: Option<Vec<String>>) -> CollaborateResult<Vec<Arc<RowMeta>>> {
+    pub fn get_row_metas(&self, row_ids: &Option<Vec<String>>) -> CollaborateResult<Vec<Arc<RowMeta>>> {
         match row_ids {
             None => Ok(self.row_metas.to_vec()),
             Some(row_ids) => {
@@ -102,6 +103,18 @@ impl GridBlockMetaPad {
         }
     }
 
+    pub fn get_cell_metas(&self, field_id: &str, row_ids: &Option<Vec<String>>) -> CollaborateResult<Vec<CellMeta>> {
+        let rows = self.get_row_metas(row_ids)?;
+        let cell_metas = rows
+            .iter()
+            .flat_map(|row| {
+                let cell_meta = row.cell_by_field_id.get(field_id)?;
+                Some(cell_meta.clone())
+            })
+            .collect::<Vec<CellMeta>>();
+        Ok(cell_metas)
+    }
+
     pub fn number_of_rows(&self) -> i32 {
         self.row_metas.len() as i32
     }
@@ -186,12 +199,12 @@ pub struct GridBlockMetaChange {
     pub md5: String,
 }
 
-pub fn make_block_meta_delta(grid_block_meta_data: &GridBlockMetaSerde) -> GridBlockMetaDelta {
+pub fn make_block_meta_delta(grid_block_meta_data: &GridBlockMetaData) -> GridBlockMetaDelta {
     let json = serde_json::to_string(&grid_block_meta_data).unwrap();
     PlainTextDeltaBuilder::new().insert(&json).build()
 }
 
-pub fn make_block_meta_revisions(user_id: &str, grid_block_meta_data: &GridBlockMetaSerde) -> RepeatedRevision {
+pub fn make_block_meta_revisions(user_id: &str, grid_block_meta_data: &GridBlockMetaData) -> RepeatedRevision {
     let delta = make_block_meta_delta(grid_block_meta_data);
     let bytes = delta.to_delta_bytes();
     let revision = Revision::initial_revision(user_id, &grid_block_meta_data.block_id, bytes);
@@ -200,7 +213,7 @@ pub fn make_block_meta_revisions(user_id: &str, grid_block_meta_data: &GridBlock
 
 impl std::default::Default for GridBlockMetaPad {
     fn default() -> Self {
-        let block_meta_data = GridBlockMetaSerde {
+        let block_meta_data = GridBlockMetaData {
             block_id: uuid(),
             row_metas: vec![],
         };

+ 2 - 2
shared-lib/flowy-sync/src/client_grid/grid_builder.rs

@@ -41,7 +41,7 @@ fn check_rows(fields: &[FieldMeta], rows: &[RowMeta]) -> CollaborateResult<()> {
 mod tests {
 
     use crate::client_grid::{make_block_meta_delta, make_grid_delta, GridBuilder};
-    use flowy_grid_data_model::entities::{FieldMeta, FieldType, GridBlockMetaSerde, GridMeta};
+    use flowy_grid_data_model::entities::{FieldMeta, FieldType, GridBlockMetaData, GridMeta};
 
     #[test]
     fn create_default_grid_test() {
@@ -64,6 +64,6 @@ mod tests {
         let _: GridMeta = serde_json::from_str(&grid_meta_delta.to_str().unwrap()).unwrap();
 
         let grid_block_meta_delta = make_block_meta_delta(&build_context.block_meta_data);
-        let _: GridBlockMetaSerde = serde_json::from_str(&grid_block_meta_delta.to_str().unwrap()).unwrap();
+        let _: GridBlockMetaData = serde_json::from_str(&grid_block_meta_delta.to_str().unwrap()).unwrap();
     }
 }

+ 3 - 3
shared-lib/flowy-sync/src/client_grid/grid_meta_pad.rs

@@ -212,7 +212,7 @@ impl GridMetaPad {
         }
     }
 
-    pub fn create_block(&mut self, block: GridBlockMeta) -> CollaborateResult<Option<GridChangeset>> {
+    pub fn create_block_meta(&mut self, block: GridBlockMeta) -> CollaborateResult<Option<GridChangeset>> {
         self.modify_grid(|grid| {
             if grid.block_metas.iter().any(|b| b.block_id == block.block_id) {
                 tracing::warn!("Duplicate grid block");
@@ -235,11 +235,11 @@ impl GridMetaPad {
         })
     }
 
-    pub fn get_blocks(&self) -> Vec<GridBlockMeta> {
+    pub fn get_block_metas(&self) -> Vec<GridBlockMeta> {
         self.grid_meta.block_metas.clone()
     }
 
-    pub fn update_block(&mut self, changeset: GridBlockMetaChangeset) -> CollaborateResult<Option<GridChangeset>> {
+    pub fn update_block_meta(&mut self, changeset: GridBlockMetaChangeset) -> CollaborateResult<Option<GridChangeset>> {
         let block_id = changeset.block_id.clone();
         self.modify_block(&block_id, |block| {
             let mut is_changed = None;