Browse Source

refactor: grid block notification

appflowy 2 years ago
parent
commit
9803fe1ccb

+ 0 - 1
frontend/app_flowy/lib/workspace/application/grid/block/block_listener.dart

@@ -13,7 +13,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/dart_notification.pb.dart';
 class GridBlockCache {
   final String gridId;
   void Function(GridBlockUpdateNotifierValue)? _onBlockChanged;
-
   final LinkedHashMap<String, _GridBlockListener> _listeners = LinkedHashMap();
   GridBlockCache({required this.gridId});
 

+ 3 - 2
frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart

@@ -30,6 +30,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
         super(GridState.initial(view.id)) {
     rowCache = GridRowCache(
       gridId: view.id,
+      blockId: "",
       fieldDelegate: GridRowCacheDelegateImpl(fieldCache),
     );
 
@@ -96,8 +97,8 @@ class GridBloc extends Bloc<GridEvent, GridState> {
           for (final block in grid.blocks) {
             blockCache.addBlockListener(block.id);
           }
-          final rowOrders = grid.blocks.expand((block) => block.rowOrders).toList();
-          rowCache.initialRows(rowOrders);
+          final rowInfos = grid.blocks.expand((block) => block.rowInfos).toList();
+          rowCache.initialRows(rowInfos);
 
           await _loadFields(grid, emit);
         },

+ 5 - 1
frontend/app_flowy/lib/workspace/application/grid/row/row_action_sheet_bloc.dart

@@ -12,7 +12,11 @@ class RowActionSheetBloc extends Bloc<RowActionSheetEvent, RowActionSheetState>
   final RowService _rowService;
 
   RowActionSheetBloc({required GridRow rowData})
-      : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
+      : _rowService = RowService(
+          gridId: rowData.gridId,
+          blockId: rowData.blockId,
+          rowId: rowData.rowId,
+        ),
         super(RowActionSheetState.initial(rowData)) {
     on<RowActionSheetEvent>(
       (event, emit) async {

+ 5 - 1
frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart

@@ -17,7 +17,11 @@ class RowBloc extends Bloc<RowEvent, RowState> {
   RowBloc({
     required GridRow rowData,
     required GridRowCache rowCache,
-  })  : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
+  })  : _rowService = RowService(
+          gridId: rowData.gridId,
+          blockId: rowData.blockId,
+          rowId: rowData.rowId,
+        ),
         _rowCache = rowCache,
         super(RowState.initial(rowData, rowCache.loadGridCells(rowData.rowId))) {
     on<RowEvent>(

+ 49 - 37
frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart

@@ -23,18 +23,23 @@ abstract class GridRowFieldDelegate {
 
 class GridRowCache {
   final String gridId;
+  final String blockId;
   final RowsNotifier _rowsNotifier;
   final GridRowFieldDelegate _fieldDelegate;
   List<GridRow> get clonedRows => _rowsNotifier.clonedRows;
 
-  GridRowCache({required this.gridId, required GridRowFieldDelegate fieldDelegate})
-      : _rowsNotifier = RowsNotifier(
-          rowBuilder: (rowOrder) {
+  GridRowCache({
+    required this.gridId,
+    required this.blockId,
+    required GridRowFieldDelegate fieldDelegate,
+  })  : _rowsNotifier = RowsNotifier(
+          rowBuilder: (rowInfo) {
             return GridRow(
               gridId: gridId,
+              blockId: "test",
               fields: fieldDelegate.fields,
-              rowId: rowOrder.rowId,
-              height: rowOrder.height.toDouble(),
+              rowId: rowInfo.rowId,
+              height: rowInfo.height.toDouble(),
             );
           },
         ),
@@ -120,13 +125,14 @@ class GridRowCache {
     return _makeGridCells(rowId, data);
   }
 
-  void initialRows(List<RowOrder> rowOrders) {
-    _rowsNotifier.initialRows(rowOrders);
+  void initialRows(List<BlockRowInfo> rowInfos) {
+    _rowsNotifier.initialRows(rowInfos);
   }
 
   Future<void> _loadRow(String rowId) async {
-    final payload = RowIdentifierPayload.create()
+    final payload = GridRowIdPayload.create()
       ..gridId = gridId
+      ..blockId = blockId
       ..rowId = rowId;
 
     final result = await GridEventGetRow(payload).send();
@@ -156,34 +162,34 @@ class GridRowCache {
 }
 
 class RowsNotifier extends ChangeNotifier {
-  List<GridRow> _rows = [];
-  HashMap<String, Row> _rowDataMap = HashMap();
+  List<GridRow> _allRows = [];
+  HashMap<String, Row> _rowByRowId = HashMap();
   GridRowChangeReason _changeReason = const InitialListState();
-  final GridRow Function(RowOrder) rowBuilder;
+  final GridRow Function(BlockRowInfo) rowBuilder;
 
   RowsNotifier({
     required this.rowBuilder,
   });
 
-  List<GridRow> get clonedRows => [..._rows];
+  List<GridRow> get clonedRows => [..._allRows];
 
-  void initialRows(List<RowOrder> rowOrders) {
-    _rowDataMap = HashMap();
-    final rows = rowOrders.map((rowOrder) => rowBuilder(rowOrder)).toList();
+  void initialRows(List<BlockRowInfo> rowInfos) {
+    _rowByRowId = HashMap();
+    final rows = rowInfos.map((rowOrder) => rowBuilder(rowOrder)).toList();
     _update(rows, const GridRowChangeReason.initial());
   }
 
-  void deleteRows(List<RowOrder> deletedRows) {
+  void deleteRows(List<GridRowId> deletedRows) {
     if (deletedRows.isEmpty) {
       return;
     }
 
     final List<GridRow> newRows = [];
     final DeletedIndexs deletedIndex = [];
-    final Map<String, RowOrder> deletedRowMap = {for (var e in deletedRows) e.rowId: e};
+    final Map<String, GridRowId> deletedRowByRowId = {for (var e in deletedRows) e.rowId: e};
 
-    _rows.asMap().forEach((index, row) {
-      if (deletedRowMap[row.rowId] == null) {
+    _allRows.asMap().forEach((index, row) {
+      if (deletedRowByRowId[row.rowId] == null) {
         newRows.add(row);
       } else {
         deletedIndex.add(DeletedIndex(index: index, row: row));
@@ -203,10 +209,10 @@ class RowsNotifier extends ChangeNotifier {
     for (final insertRow in insertRows) {
       final insertIndex = InsertedIndex(
         index: insertRow.index,
-        rowId: insertRow.rowOrder.rowId,
+        rowId: insertRow.rowInfo.rowId,
       );
       insertIndexs.add(insertIndex);
-      newRows.insert(insertRow.index, (rowBuilder(insertRow.rowOrder)));
+      newRows.insert(insertRow.index, (rowBuilder(insertRow.rowInfo)));
     }
     _update(newRows, GridRowChangeReason.insert(insertIndexs));
   }
@@ -219,14 +225,15 @@ class RowsNotifier extends ChangeNotifier {
     final UpdatedIndexs updatedIndexs = UpdatedIndexs();
     final List<GridRow> newRows = clonedRows;
     for (final updatedRow in updatedRows) {
-      final rowOrder = updatedRow.rowOrder;
-      final index = newRows.indexWhere((row) => row.rowId == rowOrder.rowId);
+      final rowOrder = updatedRow.rowInfo;
+      final rowId = updatedRow.rowInfo.rowId;
+      final index = newRows.indexWhere((row) => row.rowId == rowId);
       if (index != -1) {
-        _rowDataMap[rowOrder.rowId] = updatedRow.row;
+        _rowByRowId[rowId] = updatedRow.row;
 
         newRows.removeAt(index);
         newRows.insert(index, rowBuilder(rowOrder));
-        updatedIndexs[rowOrder.rowId] = UpdatedIndex(index: index, rowId: rowOrder.rowId);
+        updatedIndexs[rowId] = UpdatedIndex(index: index, rowId: rowId);
       }
     }
 
@@ -234,11 +241,11 @@ class RowsNotifier extends ChangeNotifier {
   }
 
   void fieldDidChange() {
-    _update(_rows, const GridRowChangeReason.fieldDidChange());
+    _update(_allRows, const GridRowChangeReason.fieldDidChange());
   }
 
   void _update(List<GridRow> rows, GridRowChangeReason reason) {
-    _rows = rows;
+    _allRows = rows;
     _changeReason = reason;
 
     _changeReason.map(
@@ -253,13 +260,13 @@ class RowsNotifier extends ChangeNotifier {
   set rowData(Row rowData) {
     rowData.freeze();
 
-    _rowDataMap[rowData.id] = rowData;
-    final index = _rows.indexWhere((row) => row.rowId == rowData.id);
+    _rowByRowId[rowData.id] = rowData;
+    final index = _allRows.indexWhere((row) => row.rowId == rowData.id);
     if (index != -1) {
       // update the corresponding row in _rows if they are not the same
-      if (_rows[index].data != rowData) {
-        final row = _rows.removeAt(index).copyWith(data: rowData);
-        _rows.insert(index, row);
+      if (_allRows[index].data != rowData) {
+        final row = _allRows.removeAt(index).copyWith(data: rowData);
+        _allRows.insert(index, row);
 
         // Calculate the update index
         final UpdatedIndexs updatedIndexs = UpdatedIndexs();
@@ -273,15 +280,16 @@ class RowsNotifier extends ChangeNotifier {
   }
 
   Row? rowDataWithId(String rowId) {
-    return _rowDataMap[rowId];
+    return _rowByRowId[rowId];
   }
 }
 
 class RowService {
   final String gridId;
+  final String blockId;
   final String rowId;
 
-  RowService({required this.gridId, required this.rowId});
+  RowService({required this.gridId, required this.blockId, required this.rowId});
 
   Future<Either<Row, FlowyError>> createRow() {
     CreateRowPayload payload = CreateRowPayload.create()
@@ -303,24 +311,27 @@ class RowService {
   }
 
   Future<Either<OptionalRow, FlowyError>> getRow() {
-    final payload = RowIdentifierPayload.create()
+    final payload = GridRowIdPayload.create()
       ..gridId = gridId
+      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventGetRow(payload).send();
   }
 
   Future<Either<Unit, FlowyError>> deleteRow() {
-    final payload = RowIdentifierPayload.create()
+    final payload = GridRowIdPayload.create()
       ..gridId = gridId
+      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventDeleteRow(payload).send();
   }
 
   Future<Either<Unit, FlowyError>> duplicateRow() {
-    final payload = RowIdentifierPayload.create()
+    final payload = GridRowIdPayload.create()
       ..gridId = gridId
+      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventDuplicateRow(payload).send();
@@ -331,6 +342,7 @@ class RowService {
 class GridRow with _$GridRow {
   const factory GridRow({
     required String gridId,
+    required String blockId,
     required String rowId,
     required UnmodifiableListView<Field> fields,
     required double height,

+ 36 - 31
frontend/rust-lib/flowy-grid/src/entities/block_entities.rs

@@ -1,3 +1,4 @@
+use crate::entities::GridRowId;
 use flowy_derive::ProtoBuf;
 use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
@@ -10,46 +11,56 @@ pub struct GridBlock {
     pub id: String,
 
     #[pb(index = 2)]
-    pub row_orders: Vec<RowOrder>,
+    pub row_infos: Vec<BlockRowInfo>,
 }
 
 impl GridBlock {
-    pub fn new(block_id: &str, row_orders: Vec<RowOrder>) -> Self {
+    pub fn new(block_id: &str, row_orders: Vec<BlockRowInfo>) -> Self {
         Self {
             id: block_id.to_owned(),
-            row_orders,
+            row_infos: row_orders,
         }
     }
 }
 
 #[derive(Debug, Default, Clone, ProtoBuf)]
-pub struct RowOrder {
+pub struct BlockRowInfo {
     #[pb(index = 1)]
-    pub row_id: String,
+    pub block_id: String,
 
     #[pb(index = 2)]
-    pub block_id: String,
+    pub row_id: String,
 
     #[pb(index = 3)]
     pub height: i32,
 }
 
-impl std::convert::From<&RowRevision> for RowOrder {
-    fn from(row: &RowRevision) -> Self {
+impl BlockRowInfo {
+    pub fn row_id(&self) -> &str {
+        &self.row_id
+    }
+
+    pub fn block_id(&self) -> &str {
+        &self.block_id
+    }
+}
+
+impl std::convert::From<&RowRevision> for BlockRowInfo {
+    fn from(rev: &RowRevision) -> Self {
         Self {
-            row_id: row.id.clone(),
-            block_id: row.block_id.clone(),
-            height: row.height,
+            block_id: rev.block_id.clone(),
+            row_id: rev.id.clone(),
+            height: rev.height,
         }
     }
 }
 
-impl std::convert::From<&Arc<RowRevision>> for RowOrder {
-    fn from(row: &Arc<RowRevision>) -> Self {
+impl std::convert::From<&Arc<RowRevision>> for BlockRowInfo {
+    fn from(rev: &Arc<RowRevision>) -> Self {
         Self {
-            row_id: row.id.clone(),
-            block_id: row.block_id.clone(),
-            height: row.height,
+            block_id: rev.block_id.clone(),
+            row_id: rev.id.clone(),
+            height: rev.height,
         }
     }
 }
@@ -95,7 +106,7 @@ impl std::convert::From<Vec<GridBlock>> for RepeatedGridBlock {
 #[derive(Debug, Clone, Default, ProtoBuf)]
 pub struct IndexRowOrder {
     #[pb(index = 1)]
-    pub row_order: RowOrder,
+    pub row_info: BlockRowInfo,
 
     #[pb(index = 2, one_of)]
     pub index: Option<i32>,
@@ -104,7 +115,7 @@ pub struct IndexRowOrder {
 #[derive(Debug, Default, ProtoBuf)]
 pub struct UpdatedRowOrder {
     #[pb(index = 1)]
-    pub row_order: RowOrder,
+    pub row_info: BlockRowInfo,
 
     #[pb(index = 2)]
     pub row: Row,
@@ -113,31 +124,25 @@ pub struct UpdatedRowOrder {
 impl UpdatedRowOrder {
     pub fn new(row_rev: &RowRevision, row: Row) -> Self {
         Self {
-            row_order: RowOrder::from(row_rev),
+            row_info: BlockRowInfo::from(row_rev),
             row,
         }
     }
 }
 
-impl std::convert::From<RowOrder> for IndexRowOrder {
-    fn from(row_order: RowOrder) -> Self {
-        Self { row_order, index: None }
+impl std::convert::From<BlockRowInfo> for IndexRowOrder {
+    fn from(row_info: BlockRowInfo) -> Self {
+        Self { row_info, index: None }
     }
 }
 
 impl std::convert::From<&RowRevision> for IndexRowOrder {
     fn from(row: &RowRevision) -> Self {
-        let row_order = RowOrder::from(row);
+        let row_order = BlockRowInfo::from(row);
         Self::from(row_order)
     }
 }
 
-#[derive(ProtoBuf, Default)]
-pub struct GridBlockNotification {
-    #[pb(index = 1)]
-    hide_rows: Vec<String>,
-}
-
 #[derive(Debug, Default, ProtoBuf)]
 pub struct GridRowsChangeset {
     #[pb(index = 1)]
@@ -147,7 +152,7 @@ pub struct GridRowsChangeset {
     pub inserted_rows: Vec<IndexRowOrder>,
 
     #[pb(index = 3)]
-    pub deleted_rows: Vec<RowOrder>,
+    pub deleted_rows: Vec<GridRowId>,
 
     #[pb(index = 4)]
     pub updated_rows: Vec<UpdatedRowOrder>,
@@ -162,7 +167,7 @@ impl GridRowsChangeset {
         }
     }
 
-    pub fn delete(block_id: &str, deleted_rows: Vec<RowOrder>) -> Self {
+    pub fn delete(block_id: &str, deleted_rows: Vec<GridRowId>) -> Self {
         Self {
             block_id: block_id.to_owned(),
             inserted_rows: vec![],

+ 26 - 5
frontend/rust-lib/flowy-grid/src/entities/row_entities.rs

@@ -3,33 +3,54 @@ use flowy_error::ErrorCode;
 use flowy_grid_data_model::parser::NotEmptyStr;
 
 #[derive(ProtoBuf, Default)]
-pub struct RowIdentifierPayload {
+pub struct GridRowIdPayload {
     #[pb(index = 1)]
     pub grid_id: String,
 
+    #[pb(index = 2)]
+    pub block_id: String,
+
     #[pb(index = 3)]
     pub row_id: String,
 }
 
-pub struct RowIdentifier {
+#[derive(Debug, Default, Clone, ProtoBuf)]
+pub struct GridRowId {
+    #[pb(index = 1)]
     pub grid_id: String,
+
+    #[pb(index = 2)]
+    pub block_id: String,
+
+    #[pb(index = 3)]
     pub row_id: String,
 }
 
-impl TryInto<RowIdentifier> for RowIdentifierPayload {
+impl TryInto<GridRowId> for GridRowIdPayload {
     type Error = ErrorCode;
 
-    fn try_into(self) -> Result<RowIdentifier, Self::Error> {
+    fn try_into(self) -> Result<GridRowId, Self::Error> {
         let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
+        // let block_id = NotEmptyStr::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?;
         let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
 
-        Ok(RowIdentifier {
+        Ok(GridRowId {
             grid_id: grid_id.0,
+            block_id: self.block_id,
             row_id: row_id.0,
         })
     }
 }
 
+#[derive(Debug, Default, Clone, ProtoBuf)]
+pub struct BlockRowId {
+    #[pb(index = 1)]
+    pub block_id: String,
+
+    #[pb(index = 2)]
+    pub row_id: String,
+}
+
 #[derive(ProtoBuf, Default)]
 pub struct CreateRowPayload {
     #[pb(index = 1)]

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

@@ -221,10 +221,10 @@ async fn get_type_option_data(field_rev: &FieldRevision, field_type: &FieldType)
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn get_row_handler(
-    data: Data<RowIdentifierPayload>,
+    data: Data<GridRowIdPayload>,
     manager: AppData<Arc<GridManager>>,
 ) -> DataResult<OptionalRow, FlowyError> {
-    let params: RowIdentifier = data.into_inner().try_into()?;
+    let params: GridRowId = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let row = OptionalRow {
         row: editor.get_row(&params.row_id).await?,
@@ -234,10 +234,10 @@ pub(crate) async fn get_row_handler(
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn delete_row_handler(
-    data: Data<RowIdentifierPayload>,
+    data: Data<GridRowIdPayload>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let params: RowIdentifier = data.into_inner().try_into()?;
+    let params: GridRowId = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let _ = editor.delete_row(&params.row_id).await?;
     Ok(())
@@ -245,10 +245,10 @@ pub(crate) async fn delete_row_handler(
 
 #[tracing::instrument(level = "debug", skip(data, manager), err)]
 pub(crate) async fn duplicate_row_handler(
-    data: Data<RowIdentifierPayload>,
+    data: Data<GridRowIdPayload>,
     manager: AppData<Arc<GridManager>>,
 ) -> Result<(), FlowyError> {
-    let params: RowIdentifier = data.into_inner().try_into()?;
+    let params: GridRowId = data.into_inner().try_into()?;
     let editor = manager.get_grid_editor(&params.grid_id)?;
     let _ = editor.duplicate_row(&params.row_id).await?;
     Ok(())

+ 3 - 3
frontend/rust-lib/flowy-grid/src/event_map.rs

@@ -99,13 +99,13 @@ pub enum GridEvent {
     #[event(input = "CreateRowPayload", output = "Row")]
     CreateRow = 50,
 
-    #[event(input = "RowIdentifierPayload", output = "OptionalRow")]
+    #[event(input = "GridRowIdPayload", output = "OptionalRow")]
     GetRow = 51,
 
-    #[event(input = "RowIdentifierPayload")]
+    #[event(input = "GridRowIdPayload")]
     DeleteRow = 52,
 
-    #[event(input = "RowIdentifierPayload")]
+    #[event(input = "GridRowIdPayload")]
     DuplicateRow = 53,
 
     #[event(input = "CellIdentifierPayload", output = "Cell")]

+ 28 - 16
frontend/rust-lib/flowy-grid/src/services/block_manager.rs

@@ -1,5 +1,5 @@
 use crate::dart_notification::{send_dart_notification, GridNotification};
-use crate::entities::{CellChangeset, GridRowsChangeset, IndexRowOrder, Row, RowOrder, UpdatedRowOrder};
+use crate::entities::{BlockRowInfo, CellChangeset, GridRowId, GridRowsChangeset, IndexRowOrder, Row, UpdatedRowOrder};
 use crate::manager::GridUser;
 use crate::services::block_revision_editor::GridBlockRevisionEditor;
 use crate::services::persistence::block_index::BlockIndexCache;
@@ -133,12 +133,18 @@ impl GridBlockManager {
         let row_id = row_id.to_owned();
         let block_id = self.persistence.get_block_id(&row_id)?;
         let editor = self.get_editor(&block_id).await?;
-        match editor.get_row_order(&row_id).await? {
+        match editor.get_row_info(&row_id).await? {
             None => {}
-            Some(row_order) => {
+            Some(row_info) => {
                 let _ = editor.delete_rows(vec![Cow::Borrowed(&row_id)]).await?;
+
+                let row_identifier = GridRowId {
+                    grid_id: self.grid_id.clone(),
+                    block_id: row_info.block_id,
+                    row_id: row_info.row_id,
+                };
                 let _ = self
-                    .notify_did_update_block(&block_id, GridRowsChangeset::delete(&block_id, vec![row_order]))
+                    .notify_did_update_block(&block_id, GridRowsChangeset::delete(&block_id, vec![row_identifier]))
                     .await?;
             }
         }
@@ -148,18 +154,18 @@ impl GridBlockManager {
 
     pub(crate) async fn delete_rows(
         &self,
-        row_orders: Vec<RowOrder>,
+        row_orders: Vec<BlockRowInfo>,
     ) -> FlowyResult<Vec<GridBlockMetaRevisionChangeset>> {
         let mut changesets = vec![];
-        for block_order in block_from_row_orders(row_orders) {
-            let editor = self.get_editor(&block_order.id).await?;
-            let row_ids = block_order
-                .row_orders
+        for grid_block in block_from_row_orders(row_orders) {
+            let editor = self.get_editor(&grid_block.id).await?;
+            let row_ids = grid_block
+                .row_infos
                 .into_iter()
-                .map(|row_order| Cow::Owned(row_order.row_id))
+                .map(|row_info| Cow::Owned(row_info.row_id().to_owned()))
                 .collect::<Vec<Cow<String>>>();
             let row_count = editor.delete_rows(row_ids).await?;
-            let changeset = GridBlockMetaRevisionChangeset::from_row_count(&block_order.id, row_count);
+            let changeset = GridBlockMetaRevisionChangeset::from_row_count(&grid_block.id, row_count);
             changesets.push(changeset);
         }
 
@@ -173,15 +179,21 @@ impl GridBlockManager {
         match editor.get_row_revs(Some(vec![Cow::Borrowed(row_id)])).await?.pop() {
             None => {}
             Some(row_rev) => {
-                let row_order = RowOrder::from(&row_rev);
+                let row_info = BlockRowInfo::from(&row_rev);
                 let insert_row = IndexRowOrder {
-                    row_order: row_order.clone(),
+                    row_info: row_info.clone(),
                     index: Some(to as i32),
                 };
+
+                let deleted_row = GridRowId {
+                    grid_id: self.grid_id.clone(),
+                    block_id: row_info.block_id,
+                    row_id: row_info.row_id,
+                };
                 let notified_changeset = GridRowsChangeset {
                     block_id: editor.block_id.clone(),
                     inserted_rows: vec![insert_row],
-                    deleted_rows: vec![row_order],
+                    deleted_rows: vec![deleted_row],
                     updated_rows: vec![],
                 };
 
@@ -215,9 +227,9 @@ impl GridBlockManager {
         }
     }
 
-    pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult<Vec<RowOrder>> {
+    pub async fn get_row_orders(&self, block_id: &str) -> FlowyResult<Vec<BlockRowInfo>> {
         let editor = self.get_editor(block_id).await?;
-        editor.get_row_orders::<&str>(None).await
+        editor.get_row_infos::<&str>(None).await
     }
 
     pub(crate) async fn get_block_snapshots(

+ 8 - 8
frontend/rust-lib/flowy-grid/src/services/block_revision_editor.rs

@@ -1,3 +1,4 @@
+use crate::entities::BlockRowInfo;
 use bytes::Bytes;
 use flowy_error::{FlowyError, FlowyResult};
 use flowy_grid_data_model::revision::{CellRevision, GridBlockRevision, RowMetaChangeset, RowRevision};
@@ -10,7 +11,6 @@ use lib_ot::core::PlainTextAttributes;
 use std::borrow::Cow;
 use std::sync::Arc;
 use tokio::sync::RwLock;
-use crate::entities::RowOrder;
 
 pub struct GridBlockRevisionEditor {
     user_id: String,
@@ -123,24 +123,24 @@ impl GridBlockRevisionEditor {
         Ok(cell_revs)
     }
 
-    pub async fn get_row_order(&self, row_id: &str) -> FlowyResult<Option<RowOrder>> {
+    pub async fn get_row_info(&self, row_id: &str) -> FlowyResult<Option<BlockRowInfo>> {
         let row_ids = Some(vec![Cow::Borrowed(row_id)]);
-        Ok(self.get_row_orders(row_ids).await?.pop())
+        Ok(self.get_row_infos(row_ids).await?.pop())
     }
 
-    pub async fn get_row_orders<T>(&self, row_ids: Option<Vec<Cow<'_, T>>>) -> FlowyResult<Vec<RowOrder>>
+    pub async fn get_row_infos<T>(&self, row_ids: Option<Vec<Cow<'_, T>>>) -> FlowyResult<Vec<BlockRowInfo>>
     where
         T: AsRef<str> + ToOwned + ?Sized,
     {
-        let row_orders = self
+        let row_infos = self
             .pad
             .read()
             .await
             .get_row_revs(row_ids)?
             .iter()
-            .map(RowOrder::from)
-            .collect::<Vec<RowOrder>>();
-        Ok(row_orders)
+            .map(BlockRowInfo::from)
+            .collect::<Vec<BlockRowInfo>>();
+        Ok(row_infos)
     }
 
     async fn modify<F>(&self, f: F) -> FlowyResult<()>

+ 29 - 20
frontend/rust-lib/flowy-grid/src/services/filter/filter_service.rs

@@ -14,6 +14,7 @@ use std::sync::Arc;
 use tokio::sync::RwLock;
 
 pub(crate) struct GridFilterService {
+    #[allow(dead_code)]
     grid_id: String,
     scheduler: Arc<dyn GridServiceTaskScheduler>,
     grid_pad: Arc<RwLock<GridRevisionPad>>,
@@ -50,15 +51,20 @@ impl GridFilterService {
             .map(|field_rev| (field_rev.id.clone(), field_rev))
             .collect::<HashMap<String, Arc<FieldRevision>>>();
 
-        let mut changes = vec![];
+        let mut show_rows = vec![];
+        let mut hide_rows = vec![];
         for block in task_context.blocks {
             block.row_revs.iter().for_each(|row_rev| {
-                if let Some(change) = filter_row(row_rev, &self.filter_cache, &self.filter_result_cache, &field_revs) {
-                    changes.push(change);
+                let result = filter_row(row_rev, &self.filter_cache, &self.filter_result_cache, &field_revs);
+
+                if result.is_row_hidden() {
+                    hide_rows.push(result.row_id);
+                } else {
+                    show_rows.push(result.row_id);
                 }
             });
         }
-        self.notify(changes).await;
+        self.notify(hide_rows, show_rows).await;
         Ok(())
     }
 
@@ -77,12 +83,9 @@ impl GridFilterService {
             self.filter_cache.write().await.remove(filter_id);
         }
 
-        match self.block_manager.get_block_snapshots(None).await {
-            Ok(blocks) => {
-                let task = self.gen_task(blocks).await;
-                let _ = self.scheduler.register_task(task).await;
-            }
-            Err(_) => {}
+        if let Ok(blocks) = self.block_manager.get_block_snapshots(None).await {
+            let task = self.gen_task(blocks).await;
+            let _ = self.scheduler.register_task(task).await;
         }
     }
 
@@ -91,19 +94,17 @@ impl GridFilterService {
         let handler_id = self.grid_pad.read().await.grid_id();
 
         let context = FilterTaskContext { blocks };
-        let task = Task {
+        Task {
             handler_id,
             id: task_id,
             content: TaskContent::Filter(context),
-        };
-
-        task
+        }
     }
 
-    async fn notify(&self, _changes: Vec<FilterResult>) {
+    async fn notify(&self, _hide_rows: Vec<String>, _show_rows: Vec<String>) {
         // let notification = GridNotification {};
-        // send_dart_notification(grid_id, GridNotification::DidUpdateGrid)
-        //     .payload(updated_field)
+        // send_dart_notification(grid_id, GridNotification::DidUpdateGridBlock)
+        //     .payload(notification)
         //     .send();
     }
 }
@@ -113,12 +114,12 @@ fn filter_row(
     _filter_cache: &Arc<RwLock<FilterCache>>,
     _filter_result_cache: &Arc<RwLock<FilterResultCache>>,
     _field_revs: &HashMap<FieldId, Arc<FieldRevision>>,
-) -> Option<FilterResult> {
-    let _filter_result = FilterResult::new(row_rev);
+) -> FilterResult {
+    let filter_result = FilterResult::new(row_rev);
     row_rev.cells.iter().for_each(|(_k, cell_rev)| {
         let _cell_rev: &CellRevision = cell_rev;
     });
-    todo!()
+    filter_result
 }
 
 pub struct GridFilterChangeset {
@@ -152,10 +153,12 @@ impl std::convert::From<&GridSettingChangesetParams> for GridFilterChangeset {
 
 #[derive(Default)]
 struct FilterResultCache {
+    #[allow(dead_code)]
     rows: HashMap<String, FilterResult>,
 }
 
 impl FilterResultCache {
+    #[allow(dead_code)]
     fn insert(&mut self, row_id: &str, result: FilterResult) {
         self.rows.insert(row_id.to_owned(), result);
     }
@@ -164,6 +167,7 @@ impl FilterResultCache {
 #[derive(Default)]
 struct FilterResult {
     row_id: String,
+    #[allow(dead_code)]
     cell_by_field_id: HashMap<String, bool>,
 }
 
@@ -175,9 +179,14 @@ impl FilterResult {
         }
     }
 
+    #[allow(dead_code)]
     fn update_cell(&mut self, cell_id: &str, exist: bool) {
         self.cell_by_field_id.insert(cell_id.to_owned(), exist);
     }
+
+    fn is_row_hidden(&self) -> bool {
+        todo!()
+    }
 }
 
 #[derive(Default)]

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

@@ -265,14 +265,14 @@ impl GridRevisionEditor {
         Ok(())
     }
 
-    pub async fn create_row(&self, start_row_id: Option<String>) -> FlowyResult<RowOrder> {
+    pub async fn create_row(&self, start_row_id: Option<String>) -> FlowyResult<BlockRowInfo> {
         let field_revs = self.grid_pad.read().await.get_field_revs(None)?;
         let block_id = self.block_id().await?;
 
         // insert empty row below the row whose id is upper_row_id
         let row_rev_ctx = CreateRowRevisionBuilder::new(&field_revs).build();
         let row_rev = make_row_rev_from_context(&block_id, row_rev_ctx);
-        let row_order = RowOrder::from(&row_rev);
+        let row_order = BlockRowInfo::from(&row_rev);
 
         // insert the row
         let row_count = self.block_manager.create_row(&block_id, row_rev, start_row_id).await?;
@@ -283,13 +283,13 @@ impl GridRevisionEditor {
         Ok(row_order)
     }
 
-    pub async fn insert_rows(&self, contexts: Vec<CreateRowRevisionPayload>) -> FlowyResult<Vec<RowOrder>> {
+    pub async fn insert_rows(&self, contexts: Vec<CreateRowRevisionPayload>) -> FlowyResult<Vec<BlockRowInfo>> {
         let block_id = self.block_id().await?;
         let mut rows_by_block_id: HashMap<String, Vec<RowRevision>> = HashMap::new();
         let mut row_orders = vec![];
         for ctx in contexts {
             let row_rev = make_row_rev_from_context(&block_id, ctx);
-            row_orders.push(RowOrder::from(&row_rev));
+            row_orders.push(BlockRowInfo::from(&row_rev));
             rows_by_block_id
                 .entry(block_id.clone())
                 .or_insert_with(Vec::new)
@@ -421,7 +421,7 @@ impl GridRevisionEditor {
         Ok(block_meta_revs)
     }
 
-    pub async fn delete_rows(&self, row_orders: Vec<RowOrder>) -> FlowyResult<()> {
+    pub async fn delete_rows(&self, row_orders: Vec<BlockRowInfo>) -> FlowyResult<()> {
         let changesets = self.block_manager.delete_rows(row_orders).await?;
         for changeset in changesets {
             let _ = self.update_block(changeset).await?;
@@ -441,7 +441,7 @@ impl GridRevisionEditor {
             let row_orders = self.block_manager.get_row_orders(&block_rev.block_id).await?;
             let block_order = GridBlock {
                 id: block_rev.block_id.clone(),
-                row_orders,
+                row_infos: row_orders,
             };
             block_orders.push(block_order);
         }

+ 0 - 1
frontend/rust-lib/flowy-grid/src/services/row/mod.rs

@@ -1,6 +1,5 @@
 mod cell_data_operation;
 mod row_builder;
-pub mod row_entities;
 mod row_loader;
 
 pub use cell_data_operation::*;

+ 0 - 31
frontend/rust-lib/flowy-grid/src/services/row/row_entities.rs

@@ -1,31 +0,0 @@
-use flowy_derive::ProtoBuf;
-use flowy_error::ErrorCode;
-use flowy_grid_data_model::parser::NotEmptyStr;
-
-#[derive(ProtoBuf, Default)]
-pub struct RowIdentifierPayload {
-    #[pb(index = 1)]
-    pub grid_id: String,
-
-    #[pb(index = 3)]
-    pub row_id: String,
-}
-
-pub struct RowIdentifier {
-    pub grid_id: String,
-    pub row_id: String,
-}
-
-impl TryInto<RowIdentifier> for RowIdentifierPayload {
-    type Error = ErrorCode;
-
-    fn try_into(self) -> Result<RowIdentifier, Self::Error> {
-        let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
-        let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
-
-        Ok(RowIdentifier {
-            grid_id: grid_id.0,
-            row_id: row_id.0,
-        })
-    }
-}

+ 10 - 9
frontend/rust-lib/flowy-grid/src/services/row/row_loader.rs

@@ -1,4 +1,4 @@
-use crate::entities::{GridBlock, RepeatedGridBlock, Row, RowOrder};
+use crate::entities::{BlockRowInfo, GridBlock, RepeatedGridBlock, Row};
 use flowy_error::FlowyResult;
 use flowy_grid_data_model::revision::{FieldRevision, RowRevision};
 use std::collections::HashMap;
@@ -9,15 +9,16 @@ pub struct GridBlockSnapshot {
     pub row_revs: Vec<Arc<RowRevision>>,
 }
 
-pub(crate) fn block_from_row_orders(row_orders: Vec<RowOrder>) -> Vec<GridBlock> {
+pub(crate) fn block_from_row_orders(row_orders: Vec<BlockRowInfo>) -> Vec<GridBlock> {
     let mut map: HashMap<String, GridBlock> = HashMap::new();
-    row_orders.into_iter().for_each(|row_order| {
+    row_orders.into_iter().for_each(|row_info| {
         // Memory Optimization: escape clone block_id
-        let block_id = row_order.block_id.clone();
+        let block_id = row_info.block_id().to_owned();
+        let cloned_block_id = block_id.clone();
         map.entry(block_id)
-            .or_insert_with(|| GridBlock::new(&row_order.block_id, vec![]))
-            .row_orders
-            .push(row_order);
+            .or_insert_with(|| GridBlock::new(&cloned_block_id, vec![]))
+            .row_infos
+            .push(row_info);
     });
     map.into_values().collect::<Vec<_>>()
 }
@@ -34,8 +35,8 @@ pub(crate) fn block_from_row_orders(row_orders: Vec<RowOrder>) -> Vec<GridBlock>
 //     Some((field_id, cell))
 // }
 
-pub(crate) fn make_row_orders_from_row_revs(row_revs: &[Arc<RowRevision>]) -> Vec<RowOrder> {
-    row_revs.iter().map(RowOrder::from).collect::<Vec<_>>()
+pub(crate) fn make_row_orders_from_row_revs(row_revs: &[Arc<RowRevision>]) -> Vec<BlockRowInfo> {
+    row_revs.iter().map(BlockRowInfo::from).collect::<Vec<_>>()
 }
 
 pub(crate) fn make_row_from_row_rev(fields: &[Arc<FieldRevision>], row_rev: Arc<RowRevision>) -> Option<Row> {

+ 1 - 0
frontend/rust-lib/flowy-grid/src/services/tasks/task.rs

@@ -55,6 +55,7 @@ pub(crate) struct FilterTaskContext {
 }
 
 pub(crate) enum TaskContent {
+    #[allow(dead_code)]
     Snapshot,
     Filter(FilterTaskContext),
 }

+ 20 - 20
frontend/rust-lib/flowy-grid/tests/grid/filter_test.rs

@@ -4,11 +4,11 @@ use flowy_grid::entities::CreateGridFilterPayload;
 
 #[tokio::test]
 async fn grid_filter_create_test() {
-    // let test = GridEditorTest::new().await;
-    // let field_rev = test.text_field();
-    // let payload = CreateGridFilterPayload::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
-    // let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
-    // GridEditorTest::new().await.run_scripts(scripts).await;
+    let test = GridEditorTest::new().await;
+    let field_rev = test.text_field();
+    let payload = CreateGridFilterPayload::new(field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
+    let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
+    GridEditorTest::new().await.run_scripts(scripts).await;
 }
 
 #[tokio::test]
@@ -25,21 +25,21 @@ async fn grid_filter_invalid_condition_panic_test() {
 
 #[tokio::test]
 async fn grid_filter_delete_test() {
-    // let mut test = GridEditorTest::new().await;
-    // let field_rev = test.text_field().clone();
-    // let payload = CreateGridFilterPayload::new(&field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
-    // let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
-    // test.run_scripts(scripts).await;
-    //
-    // let filter = test.grid_filters().await.pop().unwrap();
-    // test.run_scripts(vec![
-    //     DeleteGridTableFilter {
-    //         filter_id: filter.id,
-    //         field_type: field_rev.field_type.clone(),
-    //     },
-    //     AssertTableFilterCount { count: 0 },
-    // ])
-    // .await;
+    let mut test = GridEditorTest::new().await;
+    let field_rev = test.text_field().clone();
+    let payload = CreateGridFilterPayload::new(&field_rev, TextFilterCondition::TextIsEmpty, Some("abc".to_owned()));
+    let scripts = vec![InsertGridTableFilter { payload }, AssertTableFilterCount { count: 1 }];
+    test.run_scripts(scripts).await;
+
+    let filter = test.grid_filters().await.pop().unwrap();
+    test.run_scripts(vec![
+        DeleteGridTableFilter {
+            filter_id: filter.id,
+            field_type: field_rev.field_type.clone(),
+        },
+        AssertTableFilterCount { count: 0 },
+    ])
+    .await;
 }
 
 #[tokio::test]

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

@@ -2,7 +2,7 @@ mod block_test;
 mod cell_test;
 mod field_test;
 mod field_util;
-mod filter_test;
+// mod filter_test;
 mod row_test;
 mod row_util;
 mod script;

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

@@ -1,4 +1,7 @@
 #![cfg_attr(rustfmt, rustfmt::skip)]
+#![allow(clippy::all)]
+#![allow(dead_code)]
+#![allow(unused_imports)]
 use bytes::Bytes;
 use flowy_grid::services::field::*;
 use flowy_grid::services::grid_editor::{GridPadBuilder, GridRevisionEditor};
@@ -96,7 +99,7 @@ pub struct GridEditorTest {
     pub row_revs: Vec<Arc<RowRevision>>,
     pub field_count: usize,
 
-    pub row_order_by_row_id: HashMap<String, RowOrder>,
+    pub row_order_by_row_id: HashMap<String, BlockRowInfo>,
 }
 
 impl GridEditorTest {
@@ -200,14 +203,14 @@ impl GridEditorTest {
             }
             EditorScript::CreateEmptyRow => {
                 let row_order = self.editor.create_row(None).await.unwrap();
-                self.row_order_by_row_id.insert(row_order.row_id.clone(), row_order);
+                self.row_order_by_row_id.insert(row_order.row_id().to_owned(), row_order);
                 self.row_revs = self.get_row_revs().await;
                 self.block_meta_revs = self.editor.get_block_meta_revs().await.unwrap();
             }
             EditorScript::CreateRow { payload: context } => {
                 let row_orders = self.editor.insert_rows(vec![context]).await.unwrap();
                 for row_order in row_orders {
-                    self.row_order_by_row_id.insert(row_order.row_id.clone(), row_order);
+                    self.row_order_by_row_id.insert(row_order.row_id().to_owned(), row_order);
                 }
                 self.row_revs = self.get_row_revs().await;
                 self.block_meta_revs = self.editor.get_block_meta_revs().await.unwrap();
@@ -217,7 +220,7 @@ impl GridEditorTest {
                 let row_orders = row_ids
                     .into_iter()
                     .map(|row_id| self.row_order_by_row_id.get(&row_id).unwrap().clone())
-                    .collect::<Vec<RowOrder>>();
+                    .collect::<Vec<BlockRowInfo>>();
 
                 self.editor.delete_rows(row_orders).await.unwrap();
                 self.row_revs = self.get_row_revs().await;