Переглянути джерело

fix: setup GridCellContext fieldOnchanged callback

appflowy 3 роки тому
батько
коміт
cffd8fbec6

+ 21 - 22
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart

@@ -35,19 +35,6 @@ class GridCellContext<T> {
   })  : _cellListener = CellListener(rowId: gridCell.rowId, fieldId: gridCell.field.id),
         _cacheKey = GridCellCacheKey(objectId: gridCell.rowId, fieldId: gridCell.field.id) {
     _cellDataNotifier = ValueNotifier(cellCache.get(cacheKey));
-
-    _cellListener.updateCellNotifier?.addPublishListener((result) {
-      result.fold(
-        (notification) => _loadData(),
-        (err) => Log.error(err),
-      );
-    });
-
-    _cellListener.start();
-
-    if (cellDataLoader.reloadOnFieldChanged) {
-      cellCache.addListener(cacheKey, () => reloadCellData());
-    }
   }
 
   String get gridId => gridCell.gridId;
@@ -64,6 +51,27 @@ class GridCellContext<T> {
 
   GridCellCacheKey get cacheKey => _cacheKey;
 
+  void startListening({required void Function(T) onCellChanged}) {
+    _cellListener.updateCellNotifier?.addPublishListener((result) {
+      result.fold(
+        (notification) => _loadData(),
+        (err) => Log.error(err),
+      );
+    });
+    _cellListener.start();
+
+    if (cellDataLoader.reloadOnFieldChanged) {
+      cellCache.addListener(cacheKey, () => reloadCellData());
+    }
+
+    _cellDataNotifier.addListener(() {
+      final value = _cellDataNotifier.value;
+      if (value is T) {
+        onCellChanged(value);
+      }
+    });
+  }
+
   T? getCellData() {
     final data = cellCache.get(cacheKey);
     if (data == null) {
@@ -96,15 +104,6 @@ class GridCellContext<T> {
     });
   }
 
-  void onCellChanged(void Function(T) callback) {
-    _cellDataNotifier.addListener(() {
-      final value = _cellDataNotifier.value;
-      if (value is T) {
-        callback(value);
-      }
-    });
-  }
-
   void dispose() {
     _delayOperation?.cancel();
   }

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart

@@ -37,11 +37,11 @@ class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
   }
 
   void _startListening() {
-    cellContext.onCellChanged((cell) {
+    cellContext.startListening(onCellChanged: ((cell) {
       if (!isClosed) {
         add(CheckboxCellEvent.didReceiveCellUpdate(cell));
       }
-    });
+    }));
   }
 
   void _updateCellData() {

+ 7 - 5
frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart

@@ -39,11 +39,13 @@ class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
   }
 
   void _startListening() {
-    cellContext.onCellChanged((cell) {
-      if (!isClosed) {
-        add(DateCellEvent.didReceiveCellUpdate(cell));
-      }
-    });
+    cellContext.startListening(
+      onCellChanged: ((cell) {
+        if (!isClosed) {
+          add(DateCellEvent.didReceiveCellUpdate(cell));
+        }
+      }),
+    );
   }
 
   void _updateCellData(DateTime day) {

+ 7 - 5
frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart

@@ -41,11 +41,13 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
   }
 
   void _startListening() {
-    cellContext.onCellChanged((cell) {
-      if (!isClosed) {
-        add(NumberCellEvent.didReceiveCellUpdate(cell));
-      }
-    });
+    cellContext.startListening(
+      onCellChanged: ((cell) {
+        if (!isClosed) {
+          add(NumberCellEvent.didReceiveCellUpdate(cell));
+        }
+      }),
+    );
   }
 }
 

+ 10 - 8
frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart

@@ -36,14 +36,16 @@ class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
   }
 
   void _startListening() {
-    cellContext.onCellChanged((selectOptionContext) {
-      if (!isClosed) {
-        add(SelectionCellEvent.didReceiveOptions(
-          selectOptionContext.options,
-          selectOptionContext.selectOptions,
-        ));
-      }
-    });
+    cellContext.startListening(
+      onCellChanged: ((selectOptionContext) {
+        if (!isClosed) {
+          add(SelectionCellEvent.didReceiveOptions(
+            selectOptionContext.options,
+            selectOptionContext.selectOptions,
+          ));
+        }
+      }),
+    );
   }
 }
 

+ 10 - 8
frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart

@@ -82,14 +82,16 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
   }
 
   void _startListening() {
-    cellContext.onCellChanged((selectOptionContext) {
-      if (!isClosed) {
-        add(SelectOptionEditorEvent.didReceiveOptions(
-          selectOptionContext.options,
-          selectOptionContext.selectOptions,
-        ));
-      }
-    });
+    cellContext.startListening(
+      onCellChanged: ((selectOptionContext) {
+        if (!isClosed) {
+          add(SelectOptionEditorEvent.didReceiveOptions(
+            selectOptionContext.options,
+            selectOptionContext.selectOptions,
+          ));
+        }
+      }),
+    );
   }
 }
 

+ 7 - 5
frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart

@@ -41,11 +41,13 @@ class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
   }
 
   void _startListening() {
-    cellContext.onCellChanged((cell) {
-      if (!isClosed) {
-        add(TextCellEvent.didReceiveCellUpdate(cell));
-      }
-    });
+    cellContext.startListening(
+      onCellChanged: ((cell) {
+        if (!isClosed) {
+          add(TextCellEvent.didReceiveCellUpdate(cell));
+        }
+      }),
+    );
   }
 }
 

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

@@ -88,7 +88,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
       () => result.fold(
         (fields) {
           fieldCache.fields = fields.items;
-          rowCache.updateWithBlock(grid.blockOrders);
+          rowCache.resetRows(grid.blockOrders);
 
           emit(state.copyWith(
             grid: Some(grid),

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

@@ -17,7 +17,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
     required GridRowCache rowCache,
   })  : _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
         _rowCache = rowCache,
-        super(RowState.initial(rowData, rowCache.loadCellData(rowData.rowId))) {
+        super(RowState.initial(rowData, rowCache.loadGridCells(rowData.rowId))) {
     on<RowEvent>(
       (event, emit) async {
         await event.map(

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

@@ -48,7 +48,7 @@ class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
   }
 
   Future<void> _loadCellData() async {
-    final cellDataMap = _rowCache.loadCellData(rowData.rowId);
+    final cellDataMap = _rowCache.loadGridCells(rowData.rowId);
     if (!isClosed) {
       add(RowDetailEvent.didReceiveCellDatas(cellDataMap.values.toList()));
     }

+ 45 - 44
frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart

@@ -22,14 +22,13 @@ abstract class GridRowFieldDelegate {
 
 class GridRowCache {
   final String gridId;
-  final RowsNotifier _rowNotifier;
+  final RowsNotifier _rowsNotifier;
   final GridRowListener _rowsListener;
   final GridRowFieldDelegate _fieldDelegate;
-
-  List<GridRow> get clonedRows => _rowNotifier.clonedRows;
+  List<GridRow> get clonedRows => _rowsNotifier.clonedRows;
 
   GridRowCache({required this.gridId, required GridRowFieldDelegate fieldDelegate})
-      : _rowNotifier = RowsNotifier(
+      : _rowsNotifier = RowsNotifier(
           rowBuilder: (rowOrder) {
             return GridRow(
               gridId: gridId,
@@ -42,16 +41,16 @@ class GridRowCache {
         _rowsListener = GridRowListener(gridId: gridId),
         _fieldDelegate = fieldDelegate {
     //
-    fieldDelegate.onFieldChanged(() => _rowNotifier.fieldDidChange());
+    fieldDelegate.onFieldChanged(() => _rowsNotifier.fieldDidChange());
 
     // listen on the row update
     _rowsListener.rowsUpdateNotifier.addPublishListener((result) {
       result.fold(
         (changesets) {
           for (final changeset in changesets) {
-            _rowNotifier.deleteRows(changeset.deletedRows);
-            _rowNotifier.insertRows(changeset.insertedRows);
-            _rowNotifier.updateRows(changeset.updatedRows);
+            _rowsNotifier.deleteRows(changeset.deletedRows);
+            _rowsNotifier.insertRows(changeset.insertedRows);
+            _rowsNotifier.updateRows(changeset.updatedRows);
           }
         },
         (err) => Log.error(err),
@@ -62,14 +61,14 @@ class GridRowCache {
 
   Future<void> dispose() async {
     await _rowsListener.stop();
-    _rowNotifier.dispose();
+    _rowsNotifier.dispose();
   }
 
   void addListener({
     void Function(List<GridRow>, GridRowChangeReason)? onChanged,
     bool Function()? listenWhen,
   }) {
-    _rowNotifier.addListener(() {
+    _rowsNotifier.addListener(() {
       if (onChanged == null) {
         return;
       }
@@ -78,7 +77,7 @@ class GridRowCache {
         return;
       }
 
-      onChanged(clonedRows, _rowNotifier._changeReason);
+      onChanged(clonedRows, _rowsNotifier._changeReason);
     });
   }
 
@@ -87,7 +86,7 @@ class GridRowCache {
     void Function(GridCellMap)? onUpdated,
     bool Function()? listenWhen,
   }) {
-    listenrHandler() {
+    listenrHandler() async {
       if (onUpdated == null) {
         return;
       }
@@ -97,14 +96,14 @@ class GridRowCache {
       }
 
       notify() {
-        final row = _rowNotifier.rowDataWithId(rowId);
+        final row = _rowsNotifier.rowDataWithId(rowId);
         if (row != null) {
-          final GridCellMap cellDataMap = _makeCellDataMap(rowId, row);
+          final GridCellMap cellDataMap = _makeGridCells(rowId, row);
           onUpdated(cellDataMap);
         }
       }
 
-      _rowNotifier._changeReason.whenOrNull(
+      _rowsNotifier._changeReason.whenOrNull(
         update: (indexs) {
           if (indexs[rowId] != null) {
             notify();
@@ -114,11 +113,40 @@ class GridRowCache {
       );
     }
 
-    _rowNotifier.addListener(listenrHandler);
+    _rowsNotifier.addListener(listenrHandler);
     return listenrHandler;
   }
 
-  GridCellMap _makeCellDataMap(String rowId, Row? row) {
+  void removeRowListener(VoidCallback callback) {
+    _rowsNotifier.removeListener(callback);
+  }
+
+  GridCellMap loadGridCells(String rowId) {
+    final Row? data = _rowsNotifier.rowDataWithId(rowId);
+    if (data == null) {
+      _loadRow(rowId);
+    }
+    return _makeGridCells(rowId, data);
+  }
+
+  void resetRows(List<GridBlockOrder> blocks) {
+    final rowOrders = blocks.expand((block) => block.rowOrders).toList();
+    _rowsNotifier.reset(rowOrders);
+  }
+
+  Future<void> _loadRow(String rowId) async {
+    final payload = RowIdentifierPayload.create()
+      ..gridId = gridId
+      ..rowId = rowId;
+
+    final result = await GridEventGetRow(payload).send();
+    result.fold(
+      (rowData) => _rowsNotifier.rowData = rowData,
+      (err) => Log.error(err),
+    );
+  }
+
+  GridCellMap _makeGridCells(String rowId, Row? row) {
     var cellDataMap = GridCellMap.new();
     for (final field in _fieldDelegate.fields) {
       if (field.visibility) {
@@ -132,33 +160,6 @@ class GridRowCache {
     }
     return cellDataMap;
   }
-
-  void removeRowListener(VoidCallback callback) {
-    _rowNotifier.removeListener(callback);
-  }
-
-  GridCellMap loadCellData(String rowId) {
-    final Row? data = _rowNotifier.rowDataWithId(rowId);
-    if (data == null) {
-      final payload = RowIdentifierPayload.create()
-        ..gridId = gridId
-        ..rowId = rowId;
-
-      GridEventGetRow(payload).send().then((result) {
-        result.fold(
-          (rowData) => _rowNotifier.rowData = rowData,
-          (err) => Log.error(err),
-        );
-      });
-    }
-
-    return _makeCellDataMap(rowId, data);
-  }
-
-  void updateWithBlock(List<GridBlockOrder> blocks) {
-    final rowOrders = blocks.expand((block) => block.rowOrders).toList();
-    _rowNotifier.reset(rowOrders);
-  }
 }
 
 class RowsNotifier extends ChangeNotifier {

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart

@@ -2,7 +2,6 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
 import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType;
-import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
 import 'package:flutter/widgets.dart';
 import 'checkbox_cell.dart';
 import 'date_cell.dart';

+ 11 - 0
frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs

@@ -96,6 +96,12 @@ impl ClientGridBlockMetaEditor {
         Ok(())
     }
 
+    pub async fn get_row_meta(&self, row_id: &str) -> FlowyResult<Option<Arc<RowMeta>>> {
+        let row_ids = vec![Cow::Borrowed(row_id)];
+        let row_meta = self.get_row_metas(Some(row_ids)).await?.pop();
+        Ok(row_meta)
+    }
+
     pub async fn get_row_metas<T>(&self, row_ids: Option<Vec<Cow<'_, T>>>) -> FlowyResult<Vec<Arc<RowMeta>>>
     where
         T: AsRef<str> + ToOwned + ?Sized,
@@ -113,6 +119,11 @@ impl ClientGridBlockMetaEditor {
         Ok(cell_metas)
     }
 
+    pub async fn get_row_order(&self, row_id: &str) -> FlowyResult<Option<RowOrder>> {
+        let row_ids = Some(vec![Cow::Borrowed(row_id)]);
+        Ok(self.get_row_orders(row_ids).await?.pop())
+    }
+
     pub async fn get_row_orders<T>(&self, row_ids: Option<Vec<Cow<'_, T>>>) -> FlowyResult<Vec<RowOrder>>
     where
         T: AsRef<str> + ToOwned + ?Sized,

+ 10 - 7
frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs

@@ -119,11 +119,15 @@ impl GridBlockMetaEditorManager {
         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?;
-        let row_orders = editor.get_row_orders(Some(vec![Cow::Borrowed(&row_id)])).await?;
-        let _ = editor.delete_rows(vec![Cow::Borrowed(&row_id)]).await?;
-        let _ = self
-            .notify_did_update_block(GridRowsChangeset::delete(&block_id, row_orders))
-            .await?;
+        match editor.get_row_order(&row_id).await? {
+            None => {}
+            Some(row_order) => {
+                let _ = editor.delete_rows(vec![Cow::Borrowed(&row_id)]).await?;
+                let _ = self
+                    .notify_did_update_block(GridRowsChangeset::delete(&block_id, vec![row_order]))
+                    .await?;
+            }
+        }
 
         Ok(())
     }
@@ -231,8 +235,7 @@ impl GridBlockMetaEditorManager {
 
     async fn notify_did_update_block_row(&self, row_id: &str) -> FlowyResult<()> {
         let editor = self.get_editor_from_row_id(row_id).await?;
-        let row_ids = Some(vec![Cow::Borrowed(&row_id)]);
-        match editor.get_row_orders(row_ids).await?.pop() {
+        match editor.get_row_order(row_id).await? {
             None => {}
             Some(row_order) => {
                 let block_order_changeset = GridRowsChangeset::update(&editor.block_id, vec![row_order]);