Browse Source

refactor: refresh rows

nathan 2 years ago
parent
commit
07ebb0cb95
24 changed files with 248 additions and 76 deletions
  1. 0 1
      frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart
  2. 18 11
      frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart
  3. 1 1
      frontend/app_flowy/lib/plugins/grid/application/block/block_listener.dart
  4. 1 1
      frontend/app_flowy/lib/plugins/grid/application/field/grid_listener.dart
  5. 0 1
      frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart
  6. 1 4
      frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart
  7. 1 4
      frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart
  8. 12 1
      frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart
  9. 0 5
      frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart
  10. 72 0
      frontend/app_flowy/lib/plugins/grid/application/view/grid_view_listener.dart
  11. 4 2
      frontend/rust-lib/flowy-grid/src/dart_notification.rs
  12. 5 5
      frontend/rust-lib/flowy-grid/src/entities/block_entities.rs
  13. 2 0
      frontend/rust-lib/flowy-grid/src/entities/mod.rs
  14. 0 6
      frontend/rust-lib/flowy-grid/src/entities/row_entities.rs
  15. 55 0
      frontend/rust-lib/flowy-grid/src/entities/view_entities.rs
  16. 0 21
      frontend/rust-lib/flowy-grid/src/services/block_editor.rs
  17. 20 3
      frontend/rust-lib/flowy-grid/src/services/block_manager.rs
  18. 6 3
      frontend/rust-lib/flowy-grid/src/services/grid_editor.rs
  19. 1 0
      frontend/rust-lib/flowy-grid/src/services/mod.rs
  20. 9 0
      frontend/rust-lib/flowy-grid/src/services/sort/controller.rs
  21. 3 0
      frontend/rust-lib/flowy-grid/src/services/sort/mod.rs
  22. 9 7
      frontend/rust-lib/flowy-grid/src/services/view_editor/changed_notifier.rs
  23. 20 0
      frontend/rust-lib/flowy-grid/src/services/view_editor/editor.rs
  24. 8 0
      frontend/rust-lib/flowy-grid/src/services/view_editor/editor_manager.rs

+ 0 - 1
frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart

@@ -23,7 +23,6 @@ class BoardCardBloc extends Bloc<BoardCardEvent, BoardCardState> {
     required bool isEditing,
   })  : _rowService = RowFFIService(
           gridId: gridId,
-          blockId: dataController.rowPB.blockId,
         ),
         _dataController = dataController,
         super(

+ 18 - 11
frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart

@@ -1,17 +1,17 @@
 import 'dart:async';
+import 'package:app_flowy/plugins/grid/application/view/grid_view_listener.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 
 import '../field/field_controller.dart';
 import '../row/row_cache.dart';
-import 'block_listener.dart';
 
 /// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid for more information
 class GridBlockCache {
   final String gridId;
   final BlockPB block;
   late GridRowCache _rowCache;
-  late GridBlockListener _listener;
+  final GridViewListener _gridViewListener;
 
   List<RowInfo> get rows => _rowCache.visibleRows;
   GridRowCache get rowCache => _rowCache;
@@ -20,24 +20,31 @@ class GridBlockCache {
     required this.gridId,
     required this.block,
     required GridFieldController fieldController,
-  }) {
+  }) : _gridViewListener = GridViewListener(viewId: gridId) {
     _rowCache = GridRowCache(
       gridId: gridId,
       block: block,
       notifier: GridRowFieldNotifierImpl(fieldController),
     );
 
-    _listener = GridBlockListener(blockId: block.id);
-    _listener.start((result) {
-      result.fold(
-        (changeset) => _rowCache.applyChangesets(changeset),
-        (err) => Log.error(err),
-      );
-    });
+    _gridViewListener.start(
+      onRowsChanged: (result) {
+        result.fold(
+          (changeset) => _rowCache.applyRowsChanged(changeset),
+          (err) => Log.error(err),
+        );
+      },
+      onRowsVisibilityChanged: (result) {
+        result.fold(
+          (changeset) => _rowCache.applyRowsVisibility(changeset),
+          (err) => Log.error(err),
+        );
+      },
+    );
   }
 
   Future<void> dispose() async {
-    await _listener.stop();
+    await _gridViewListener.stop();
     await _rowCache.dispose();
   }
 

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

@@ -32,7 +32,7 @@ class GridBlockListener {
 
   void _handler(GridDartNotification ty, Either<Uint8List, FlowyError> result) {
     switch (ty) {
-      case GridDartNotification.DidUpdateGridBlock:
+      case GridDartNotification.DidUpdateGridRows:
         result.fold(
           (payload) => _rowsUpdateNotifier?.value =
               left(GridBlockChangesetPB.fromBuffer(payload)),

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/application/field/grid_listener.dart

@@ -27,7 +27,7 @@ class GridFieldsListener {
 
   void _handler(GridDartNotification ty, Either<Uint8List, FlowyError> result) {
     switch (ty) {
-      case GridDartNotification.DidUpdateGridField:
+      case GridDartNotification.DidUpdateGridFields:
         result.fold(
           (payload) => updateFieldsNotifier?.value =
               left(GridFieldChangesetPB.fromBuffer(payload)),

+ 0 - 1
frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart

@@ -38,7 +38,6 @@ class GridBloc extends Bloc<GridEvent, GridState> {
           },
           deleteRow: (rowInfo) async {
             final rowService = RowFFIService(
-              blockId: rowInfo.rowPB.blockId,
               gridId: rowInfo.gridId,
             );
             await rowService.deleteRow(rowInfo.rowPB.id);

+ 1 - 4
frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart

@@ -15,10 +15,7 @@ class RowActionSheetBloc
   final RowFFIService _rowService;
 
   RowActionSheetBloc({required RowInfo rowInfo})
-      : _rowService = RowFFIService(
-          gridId: rowInfo.gridId,
-          blockId: rowInfo.rowPB.blockId,
-        ),
+      : _rowService = RowFFIService(gridId: rowInfo.gridId),
         super(RowActionSheetState.initial(rowInfo)) {
     on<RowActionSheetEvent>(
       (event, emit) async {

+ 1 - 4
frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart

@@ -18,10 +18,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
   RowBloc({
     required RowInfo rowInfo,
     required GridRowDataController dataController,
-  })  : _rowService = RowFFIService(
-          gridId: rowInfo.gridId,
-          blockId: rowInfo.rowPB.blockId,
-        ),
+  })  : _rowService = RowFFIService(gridId: rowInfo.gridId),
         _dataController = dataController,
         super(RowState.initial(rowInfo, dataController.loadData())) {
     on<RowEvent>(

+ 12 - 1
frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart

@@ -4,6 +4,7 @@ import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
 import 'package:flutter/foundation.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
@@ -77,6 +78,17 @@ class GridRowCache {
     _showRows(changeset.visibleRows);
   }
 
+  void applyRowsChanged(GridViewRowsChangesetPB changeset) {
+    _deleteRows(changeset.deletedRows);
+    _insertRows(changeset.insertedRows);
+    _updateRows(changeset.updatedRows);
+  }
+
+  void applyRowsVisibility(GridRowsVisibilityChangesetPB changeset) {
+    _hideRows(changeset.invisibleRows);
+    _showRows(changeset.visibleRows);
+  }
+
   void _deleteRows(List<String> deletedRowIds) {
     for (final rowId in deletedRowIds) {
       final deletedRow = _rowList.remove(rowId);
@@ -192,7 +204,6 @@ class GridRowCache {
   Future<void> _loadRow(String rowId) async {
     final payload = RowIdPB.create()
       ..gridId = gridId
-      ..blockId = block.id
       ..rowId = rowId;
 
     final result = await GridEventGetRow(payload).send();

+ 0 - 5
frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart

@@ -8,11 +8,9 @@ import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
 
 class RowFFIService {
   final String gridId;
-  final String blockId;
 
   RowFFIService({
     required this.gridId,
-    required this.blockId,
   });
 
   Future<Either<RowPB, FlowyError>> createRow(String rowId) {
@@ -26,7 +24,6 @@ class RowFFIService {
   Future<Either<OptionalRowPB, FlowyError>> getRow(String rowId) {
     final payload = RowIdPB.create()
       ..gridId = gridId
-      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventGetRow(payload).send();
@@ -35,7 +32,6 @@ class RowFFIService {
   Future<Either<Unit, FlowyError>> deleteRow(String rowId) {
     final payload = RowIdPB.create()
       ..gridId = gridId
-      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventDeleteRow(payload).send();
@@ -44,7 +40,6 @@ class RowFFIService {
   Future<Either<Unit, FlowyError>> duplicateRow(String rowId) {
     final payload = RowIdPB.create()
       ..gridId = gridId
-      ..blockId = blockId
       ..rowId = rowId;
 
     return GridEventDuplicateRow(payload).send();

+ 72 - 0
frontend/app_flowy/lib/plugins/grid/application/view/grid_view_listener.dart

@@ -0,0 +1,72 @@
+import 'dart:async';
+import 'dart:typed_data';
+import 'package:app_flowy/core/grid_notification.dart';
+import 'package:dartz/dartz.dart';
+import 'package:flowy_infra/notifier.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_sdk/protobuf/flowy-grid/view_entities.pb.dart';
+
+typedef GridRowsVisibilityNotifierValue
+    = Either<GridRowsVisibilityChangesetPB, FlowyError>;
+
+typedef GridViewRowsNotifierValue = Either<GridViewRowsChangesetPB, FlowyError>;
+
+class GridViewListener {
+  final String viewId;
+  PublishNotifier<GridViewRowsNotifierValue>? _rowsNotifier = PublishNotifier();
+  PublishNotifier<GridRowsVisibilityNotifierValue>? _rowsVisibilityNotifier =
+      PublishNotifier();
+
+  GridNotificationListener? _listener;
+  GridViewListener({required this.viewId});
+
+  void start({
+    required void Function(GridViewRowsNotifierValue) onRowsChanged,
+    required void Function(GridRowsVisibilityNotifierValue)
+        onRowsVisibilityChanged,
+  }) {
+    if (_listener != null) {
+      _listener?.stop();
+    }
+
+    _listener = GridNotificationListener(
+      objectId: viewId,
+      handler: _handler,
+    );
+
+    _rowsNotifier?.addPublishListener(onRowsChanged);
+    _rowsVisibilityNotifier?.addPublishListener(onRowsVisibilityChanged);
+  }
+
+  void _handler(GridDartNotification ty, Either<Uint8List, FlowyError> result) {
+    switch (ty) {
+      case GridDartNotification.DidUpdateGridViewRowsVisibility:
+        result.fold(
+          (payload) => _rowsVisibilityNotifier?.value =
+              left(GridRowsVisibilityChangesetPB.fromBuffer(payload)),
+          (error) => _rowsVisibilityNotifier?.value = right(error),
+        );
+        break;
+      case GridDartNotification.DidUpdateGridViewRows:
+        result.fold(
+          (payload) => _rowsNotifier?.value =
+              left(GridViewRowsChangesetPB.fromBuffer(payload)),
+          (error) => _rowsNotifier?.value = right(error),
+        );
+        break;
+
+      default:
+        break;
+    }
+  }
+
+  Future<void> stop() async {
+    await _listener?.stop();
+    _rowsVisibilityNotifier?.dispose();
+    _rowsVisibilityNotifier = null;
+
+    _rowsNotifier?.dispose();
+    _rowsNotifier = null;
+  }
+}

+ 4 - 2
frontend/rust-lib/flowy-grid/src/dart_notification.rs

@@ -6,8 +6,10 @@ const OBSERVABLE_CATEGORY: &str = "Grid";
 pub enum GridDartNotification {
     Unknown = 0,
     DidCreateBlock = 11,
-    DidUpdateGridBlock = 20,
-    DidUpdateGridField = 21,
+    DidUpdateGridRows = 19,
+    DidUpdateGridViewRows = 20,
+    DidUpdateGridViewRowsVisibility = 21,
+    DidUpdateGridFields = 22,
     DidUpdateRow = 30,
     DidUpdateCell = 40,
     DidUpdateField = 50,

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

@@ -173,7 +173,7 @@ pub struct UpdatedRowPB {
 #[derive(Debug, Default, Clone, ProtoBuf)]
 pub struct GridBlockChangesetPB {
     #[pb(index = 1)]
-    pub block_id: String,
+    pub view_id: String,
 
     #[pb(index = 2)]
     pub inserted_rows: Vec<InsertedRowPB>,
@@ -191,9 +191,9 @@ pub struct GridBlockChangesetPB {
     pub invisible_rows: Vec<String>,
 }
 impl GridBlockChangesetPB {
-    pub fn insert(block_id: String, inserted_rows: Vec<InsertedRowPB>) -> Self {
+    pub fn insert(view_id: String, inserted_rows: Vec<InsertedRowPB>) -> Self {
         Self {
-            block_id,
+            view_id,
             inserted_rows,
             ..Default::default()
         }
@@ -201,7 +201,7 @@ impl GridBlockChangesetPB {
 
     pub fn delete(block_id: &str, deleted_rows: Vec<String>) -> Self {
         Self {
-            block_id: block_id.to_owned(),
+            view_id: block_id.to_owned(),
             deleted_rows,
             ..Default::default()
         }
@@ -209,7 +209,7 @@ impl GridBlockChangesetPB {
 
     pub fn update(block_id: &str, updated_rows: Vec<UpdatedRowPB>) -> Self {
         Self {
-            block_id: block_id.to_owned(),
+            view_id: block_id.to_owned(),
             updated_rows,
             ..Default::default()
         }

+ 2 - 0
frontend/rust-lib/flowy-grid/src/entities/mod.rs

@@ -7,6 +7,7 @@ mod group_entities;
 pub mod parser;
 mod row_entities;
 pub mod setting_entities;
+mod view_entities;
 
 pub use block_entities::*;
 pub use cell_entities::*;
@@ -16,3 +17,4 @@ pub use grid_entities::*;
 pub use group_entities::*;
 pub use row_entities::*;
 pub use setting_entities::*;
+pub use view_entities::*;

+ 0 - 6
frontend/rust-lib/flowy-grid/src/entities/row_entities.rs

@@ -9,15 +9,11 @@ pub struct RowIdPB {
     pub grid_id: String,
 
     #[pb(index = 2)]
-    pub block_id: String,
-
-    #[pb(index = 3)]
     pub row_id: String,
 }
 
 pub struct RowIdParams {
     pub grid_id: String,
-    pub block_id: String,
     pub row_id: String,
 }
 
@@ -26,12 +22,10 @@ impl TryInto<RowIdParams> for RowIdPB {
 
     fn try_into(self) -> Result<RowIdParams, 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(RowIdParams {
             grid_id: grid_id.0,
-            block_id: block_id.0,
             row_id: row_id.0,
         })
     }

+ 55 - 0
frontend/rust-lib/flowy-grid/src/entities/view_entities.rs

@@ -0,0 +1,55 @@
+use crate::entities::{GridLayout, InsertedRowPB, UpdatedRowPB};
+use flowy_derive::ProtoBuf;
+
+#[derive(Debug, Default, Clone, ProtoBuf)]
+pub struct GridRowsVisibilityChangesetPB {
+    #[pb(index = 1)]
+    pub view_id: String,
+
+    #[pb(index = 5)]
+    pub visible_rows: Vec<InsertedRowPB>,
+
+    #[pb(index = 6)]
+    pub invisible_rows: Vec<String>,
+}
+
+#[derive(Debug, Default, Clone, ProtoBuf)]
+pub struct GridViewRowsChangesetPB {
+    #[pb(index = 1)]
+    pub view_id: String,
+
+    #[pb(index = 2)]
+    pub inserted_rows: Vec<InsertedRowPB>,
+
+    #[pb(index = 3)]
+    pub deleted_rows: Vec<String>,
+
+    #[pb(index = 4)]
+    pub updated_rows: Vec<UpdatedRowPB>,
+}
+
+impl GridViewRowsChangesetPB {
+    pub fn insert(view_id: String, inserted_rows: Vec<InsertedRowPB>) -> Self {
+        Self {
+            view_id,
+            inserted_rows,
+            ..Default::default()
+        }
+    }
+
+    pub fn delete(block_id: &str, deleted_rows: Vec<String>) -> Self {
+        Self {
+            view_id: block_id.to_owned(),
+            deleted_rows,
+            ..Default::default()
+        }
+    }
+
+    pub fn update(block_id: &str, updated_rows: Vec<UpdatedRowPB>) -> Self {
+        Self {
+            view_id: block_id.to_owned(),
+            updated_rows,
+            ..Default::default()
+        }
+    }
+}

+ 0 - 21
frontend/rust-lib/flowy-grid/src/services/block_editor.rs

@@ -1,4 +1,3 @@
-use crate::entities::RowPB;
 use bytes::Bytes;
 use flowy_error::{FlowyError, FlowyResult};
 use flowy_http_model::revision::Revision;
@@ -136,26 +135,6 @@ impl GridBlockRevisionEditor {
         Ok(cell_revs)
     }
 
-    pub async fn get_row_pb(&self, row_id: &str) -> FlowyResult<Option<RowPB>> {
-        let row_ids = Some(vec![Cow::Borrowed(row_id)]);
-        Ok(self.get_row_pbs(row_ids).await?.pop())
-    }
-
-    pub async fn get_row_pbs<T>(&self, row_ids: Option<Vec<Cow<'_, T>>>) -> FlowyResult<Vec<RowPB>>
-    where
-        T: AsRef<str> + ToOwned + ?Sized,
-    {
-        let row_infos = self
-            .pad
-            .read()
-            .await
-            .get_row_revs(row_ids)?
-            .iter()
-            .map(RowPB::from)
-            .collect::<Vec<RowPB>>();
-        Ok(row_infos)
-    }
-
     async fn modify<F>(&self, f: F) -> FlowyResult<()>
     where
         F: for<'a> FnOnce(&'a mut GridBlockRevisionPad) -> FlowyResult<Option<GridBlockRevisionChangeset>>,

+ 20 - 3
frontend/rust-lib/flowy-grid/src/services/block_manager.rs

@@ -14,13 +14,28 @@ use flowy_revision::{RevisionManager, RevisionPersistence, RevisionPersistenceCo
 use grid_rev_model::{GridBlockMetaRevision, GridBlockMetaRevisionChangeset, RowChangeset, RowRevision};
 use std::borrow::Cow;
 use std::collections::HashMap;
-use std::sync::Arc;
+use std::sync::{Arc, Weak};
+use tokio::sync::{broadcast, RwLock};
+
+pub trait GridBlockDelegate: Send + Sync + 'static {
+    fn notify_did_insert_row(&self, row: InsertedRowPB);
+    fn notify_did_update_row(&self, row: UpdatedRowPB);
+    fn notify_did_delete_row(&self, row_id: String);
+}
+
+#[derive(Debug, Clone)]
+pub enum GridBlockEvent {
+    DidInsertRow { row: InsertedRowPB },
+    UpdateRow { row: UpdatedRowPB },
+    DeleteRow { row_id: String },
+}
 
 type BlockId = String;
 pub(crate) struct GridBlockManager {
     user: Arc<dyn GridUser>,
     persistence: Arc<BlockIndexCache>,
     block_editors: DashMap<BlockId, Arc<GridBlockRevisionEditor>>,
+    notifier: broadcast::Sender<GridBlockEvent>,
 }
 
 impl GridBlockManager {
@@ -28,6 +43,7 @@ impl GridBlockManager {
         user: &Arc<dyn GridUser>,
         block_meta_revs: Vec<Arc<GridBlockMetaRevision>>,
         persistence: Arc<BlockIndexCache>,
+        block_event_tx: broadcast::Sender<GridBlockEvent>,
     ) -> FlowyResult<Self> {
         let block_editors = make_block_editors(user, block_meta_revs).await?;
         let user = user.clone();
@@ -35,6 +51,7 @@ impl GridBlockManager {
             user,
             block_editors,
             persistence,
+            notifier: block_event_tx,
         };
         Ok(manager)
     }
@@ -180,7 +197,7 @@ impl GridBlockManager {
         };
 
         let notified_changeset = GridBlockChangesetPB {
-            block_id: editor.block_id.clone(),
+            view_id: editor.block_id.clone(),
             inserted_rows: vec![insert_row],
             deleted_rows: vec![delete_row_id],
             ..Default::default()
@@ -241,7 +258,7 @@ impl GridBlockManager {
     }
 
     async fn notify_did_update_block(&self, block_id: &str, changeset: GridBlockChangesetPB) -> FlowyResult<()> {
-        send_dart_notification(block_id, GridDartNotification::DidUpdateGridBlock)
+        send_dart_notification(block_id, GridDartNotification::DidUpdateGridRows)
             .payload(changeset)
             .send();
         Ok(())

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

@@ -63,8 +63,9 @@ impl GridRevisionEditor {
         let grid_pad = Arc::new(RwLock::new(grid_pad));
 
         // Block manager
+        let (block_event_tx, block_event_rx) = broadcast::channel(100);
         let block_meta_revs = grid_pad.read().await.get_block_meta_revs();
-        let block_manager = Arc::new(GridBlockManager::new(&user, block_meta_revs, persistence).await?);
+        let block_manager = Arc::new(GridBlockManager::new(&user, block_meta_revs, persistence, block_event_tx).await?);
         let delegate = Arc::new(GridViewEditorDelegateImpl {
             pad: grid_pad.clone(),
             block_manager: block_manager.clone(),
@@ -72,7 +73,8 @@ impl GridRevisionEditor {
         });
 
         // View manager
-        let view_manager = Arc::new(GridViewManager::new(grid_id.to_owned(), user.clone(), delegate).await?);
+        let view_manager =
+            Arc::new(GridViewManager::new(grid_id.to_owned(), user.clone(), delegate, block_event_rx).await?);
 
         let editor = Arc::new(Self {
             grid_id: grid_id.to_owned(),
@@ -391,6 +393,7 @@ impl GridRevisionEditor {
         Ok(())
     }
 
+    /// Returns all the rows in this block.
     pub async fn get_row_pbs(&self, block_id: &str) -> FlowyResult<Vec<RowPB>> {
         let rows = self.block_manager.get_row_revs(block_id).await?;
         let rows = self
@@ -801,7 +804,7 @@ impl GridRevisionEditor {
     }
 
     async fn notify_did_update_grid(&self, changeset: GridFieldChangesetPB) -> FlowyResult<()> {
-        send_dart_notification(&self.grid_id, GridDartNotification::DidUpdateGridField)
+        send_dart_notification(&self.grid_id, GridDartNotification::DidUpdateGridFields)
             .payload(changeset)
             .send();
         Ok(())

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

@@ -11,4 +11,5 @@ pub mod group;
 pub mod persistence;
 pub mod row;
 pub mod setting;
+pub mod sort;
 pub mod view_editor;

+ 9 - 0
frontend/rust-lib/flowy-grid/src/services/sort/controller.rs

@@ -0,0 +1,9 @@
+use crate::services::block_manager::GridBlockManager;
+use std::sync::Arc;
+
+pub struct SortController {}
+impl SortController {
+    pub fn new() -> Self {
+        Self {}
+    }
+}

+ 3 - 0
frontend/rust-lib/flowy-grid/src/services/sort/mod.rs

@@ -0,0 +1,3 @@
+mod controller;
+
+pub use controller::*;

+ 9 - 7
frontend/rust-lib/flowy-grid/src/services/view_editor/changed_notifier.rs

@@ -1,5 +1,5 @@
 use crate::dart_notification::{send_dart_notification, GridDartNotification};
-use crate::entities::GridBlockChangesetPB;
+use crate::entities::{GridBlockChangesetPB, GridRowsVisibilityChangesetPB};
 use crate::services::filter::FilterResultNotification;
 use async_stream::stream;
 use futures::stream::StreamExt;
@@ -28,16 +28,18 @@ impl GridViewChangedReceiverRunner {
             .for_each(|changed| async {
                 match changed {
                     GridViewChanged::DidReceiveFilterResult(notification) => {
-                        let changeset = GridBlockChangesetPB {
-                            block_id: notification.block_id,
+                        let changeset = GridRowsVisibilityChangesetPB {
+                            view_id: notification.view_id,
                             visible_rows: notification.visible_rows,
                             invisible_rows: notification.invisible_rows,
-                            ..Default::default()
                         };
 
-                        send_dart_notification(&changeset.block_id, GridDartNotification::DidUpdateGridBlock)
-                            .payload(changeset)
-                            .send()
+                        send_dart_notification(
+                            &changeset.view_id,
+                            GridDartNotification::DidUpdateGridViewRowsVisibility,
+                        )
+                        .payload(changeset)
+                        .send()
                     }
                 }
             })

+ 20 - 0
frontend/rust-lib/flowy-grid/src/services/view_editor/editor.rs

@@ -6,6 +6,7 @@ use crate::services::group::{
     GroupController, MoveGroupRowContext,
 };
 use crate::services::row::GridBlock;
+use crate::services::sort::SortController;
 use crate::services::view_editor::changed_notifier::GridViewChangedNotifier;
 use crate::services::view_editor::trait_impl::*;
 use crate::services::view_editor::GridViewChangedReceiverRunner;
@@ -29,11 +30,22 @@ use tokio::sync::{broadcast, RwLock};
 pub trait GridViewEditorDelegate: Send + Sync + 'static {
     /// If the field_ids is None, then it will return all the field revisions
     fn get_field_revs(&self, field_ids: Option<Vec<String>>) -> Fut<Vec<Arc<FieldRevision>>>;
+
+    /// Returns the field with the field_id
     fn get_field_rev(&self, field_id: &str) -> Fut<Option<Arc<FieldRevision>>>;
 
+    /// Returns the index of the row with row_id
     fn index_of_row(&self, row_id: &str) -> Fut<Option<usize>>;
+
+    /// Get the row with row_id
     fn get_row_rev(&self, row_id: &str) -> Fut<Option<(usize, Arc<RowRevision>)>>;
+
+    /// Get all the rows that the current Grid has
+    /// One block has a list of rows
     fn get_row_revs(&self) -> Fut<Vec<Arc<RowRevision>>>;
+
+    /// Get all the blocks that the current Grid has.
+    /// One grid has a list of blocks
     fn get_blocks(&self) -> Fut<Vec<GridBlock>>;
 
     fn get_task_scheduler(&self) -> Arc<RwLock<TaskDispatcher>>;
@@ -47,6 +59,7 @@ pub struct GridViewRevisionEditor {
     delegate: Arc<dyn GridViewEditorDelegate>,
     group_controller: Arc<RwLock<Box<dyn GroupController>>>,
     filter_controller: Arc<RwLock<FilterController>>,
+    sort_controller: Arc<RwLock<SortController>>,
     pub notifier: GridViewChangedNotifier,
 }
 
@@ -89,6 +102,8 @@ impl GridViewRevisionEditor {
         )
         .await?;
 
+        let sort_controller = Arc::new(RwLock::new(SortController::new()));
+
         let user_id = user_id.to_owned();
         let group_controller = Arc::new(RwLock::new(group_controller));
         let filter_controller =
@@ -101,6 +116,7 @@ impl GridViewRevisionEditor {
             delegate,
             group_controller,
             filter_controller,
+            sort_controller,
             notifier,
         })
     }
@@ -112,6 +128,10 @@ impl GridViewRevisionEditor {
         self.filter_controller.read().await.close().await;
     }
 
+    pub async fn notify_rows_did_changed(&self) {
+        //
+    }
+
     pub async fn filter_rows(&self, _block_id: &str, mut rows: Vec<Arc<RowRevision>>) -> Vec<Arc<RowRevision>> {
         self.filter_controller.write().await.filter_row_revs(&mut rows).await;
         rows

+ 8 - 0
frontend/rust-lib/flowy-grid/src/services/view_editor/editor_manager.rs

@@ -3,6 +3,7 @@ use crate::entities::{
     MoveGroupParams, RepeatedGroupPB, RowPB,
 };
 use crate::manager::GridUser;
+use crate::services::block_manager::GridBlockEvent;
 use crate::services::filter::FilterType;
 use crate::services::persistence::rev_sqlite::{
     SQLiteGridRevisionSnapshotPersistence, SQLiteGridViewRevisionPersistence,
@@ -24,6 +25,7 @@ pub struct GridViewManager {
     user: Arc<dyn GridUser>,
     delegate: Arc<dyn GridViewEditorDelegate>,
     view_editors: RwLock<RefCountHashMap<Arc<GridViewRevisionEditor>>>,
+    block_event_rx: broadcast::Receiver<GridBlockEvent>,
 }
 
 impl GridViewManager {
@@ -31,6 +33,7 @@ impl GridViewManager {
         grid_id: String,
         user: Arc<dyn GridUser>,
         delegate: Arc<dyn GridViewEditorDelegate>,
+        block_event_rx: broadcast::Receiver<GridBlockEvent>,
     ) -> FlowyResult<Self> {
         let view_editors = RwLock::new(RefCountHashMap::default());
         Ok(Self {
@@ -38,6 +41,7 @@ impl GridViewManager {
             user,
             delegate,
             view_editors,
+            block_event_rx,
         })
     }
 
@@ -49,6 +53,10 @@ impl GridViewManager {
         Ok(self.get_view_editor(view_id).await?.notifier.subscribe())
     }
 
+    pub async fn get_rows(&self) -> FlowyResult<Vec<Arc<RowRevision>>> {
+        todo!()
+    }
+
     pub async fn filter_rows(&self, block_id: &str, rows: Vec<Arc<RowRevision>>) -> FlowyResult<Vec<Arc<RowRevision>>> {
         let editor = self.get_default_view_editor().await?;
         let rows = editor.filter_rows(block_id, rows).await;