瀏覽代碼

refactor: separate cache from service file

appflowy 2 年之前
父節點
當前提交
9930706d9a
共有 30 個文件被更改,包括 57 次插入560 次删除
  1. 3 3
      frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart
  2. 8 5
      frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_field_notifier.dart
  3. 1 2
      frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart
  4. 7 6
      frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart
  5. 1 1
      frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart
  6. 2 0
      frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart
  7. 2 1
      frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart
  8. 0 190
      frontend/app_flowy/lib/plugins/grid/application/grid_service.dart
  9. 2 0
      frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart
  10. 1 0
      frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart
  11. 2 2
      frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart
  12. 1 2
      frontend/app_flowy/lib/plugins/grid/application/row/row_detail_bloc.dart
  13. 0 326
      frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart
  14. 2 1
      frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart
  15. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart
  16. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart
  17. 2 2
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart
  18. 2 2
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart
  19. 2 2
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart
  20. 4 4
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart
  21. 2 2
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart
  22. 2 2
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart
  23. 1 0
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart
  24. 1 0
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart
  25. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart
  26. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart
  27. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart
  28. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart
  29. 1 1
      frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart
  30. 2 0
      frontend/app_flowy/lib/startup/deps_resolver.dart

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

@@ -1,9 +1,9 @@
 import 'dart:async';
-import 'package:app_flowy/plugins/grid/application/grid_service.dart';
-import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 
+import '../field/field_cache.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
@@ -24,7 +24,7 @@ class GridBlockCache {
     _rowCache = GridRowCache(
       gridId: gridId,
       block: block,
-      notifier: GridRowCacheFieldNotifierImpl(fieldCache),
+      notifier: GridRowFieldNotifierImpl(fieldCache),
     );
 
     _listener = GridBlockListener(blockId: block.id);

+ 8 - 5
frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_field_notifier.dart

@@ -3,20 +3,22 @@ import 'package:flutter/foundation.dart';
 
 import 'cell_service.dart';
 
-abstract class IGridFieldChangedNotifier {
-  void onFieldChanged(void Function(GridFieldPB) callback);
-  void dispose();
+abstract class IGridCellFieldNotifier {
+  void onCellFieldChanged(void Function(GridFieldPB) callback);
+  void onCellDispose();
 }
 
 /// GridPB's cell helper wrapper that enables each cell will get notified when the corresponding field was changed.
 /// You Register an onFieldChanged callback to listen to the cell changes, and unregister if you don't want to listen.
 class GridCellFieldNotifier {
+  final IGridCellFieldNotifier notifier;
+
   /// fieldId: {objectId: callback}
   final Map<String, Map<String, List<VoidCallback>>> _fieldListenerByFieldId =
       {};
 
-  GridCellFieldNotifier({required IGridFieldChangedNotifier notifier}) {
-    notifier.onFieldChanged(
+  GridCellFieldNotifier({required this.notifier}) {
+    notifier.onCellFieldChanged(
       (field) {
         final map = _fieldListenerByFieldId[field.id];
         if (map != null) {
@@ -56,6 +58,7 @@ class GridCellFieldNotifier {
   }
 
   Future<void> dispose() async {
+    notifier.onCellDispose();
     _fieldListenerByFieldId.clear();
   }
 }

+ 1 - 2
frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart

@@ -1,7 +1,5 @@
 import 'dart:async';
 import 'dart:collection';
-
-import 'package:app_flowy/plugins/grid/application/grid_service.dart';
 import 'package:dartz/dartz.dart';
 import 'package:equatable/equatable.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
@@ -18,6 +16,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_listener.dart';
 import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
 import 'dart:convert' show utf8;
 
+import '../../field/field_cache.dart';
 import '../../field/type_option/type_option_service.dart';
 import 'cell_field_notifier.dart';
 part 'cell_service.freezed.dart';

+ 7 - 6
frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart

@@ -21,8 +21,8 @@ class GridCellControllerBuilder {
         _cellId = cellId;
 
   IGridCellController build() {
-    final cellFieldNotifier = GridCellFieldNotifier(
-        notifier: _GridFieldChangedNotifierImpl(_fieldCache));
+    final cellFieldNotifier =
+        GridCellFieldNotifier(notifier: GridCellFieldNotifierImpl(_fieldCache));
 
     switch (_cellId.fieldType) {
       case FieldType.Checkbox:
@@ -295,6 +295,7 @@ class IGridCellController<T, D> extends Equatable {
 
     if (_onFieldChangedFn != null) {
       _fieldNotifier.unregister(_cacheKey, _onFieldChangedFn!);
+      _fieldNotifier.dispose();
       _onFieldChangedFn = null;
     }
   }
@@ -304,14 +305,14 @@ class IGridCellController<T, D> extends Equatable {
       [_cellsCache.get(_cacheKey) ?? "", cellId.rowId + cellId.field.id];
 }
 
-class _GridFieldChangedNotifierImpl extends IGridFieldChangedNotifier {
+class GridCellFieldNotifierImpl extends IGridCellFieldNotifier {
   final GridFieldCache _cache;
   FieldChangesetCallback? _onChangesetFn;
 
-  _GridFieldChangedNotifierImpl(GridFieldCache cache) : _cache = cache;
+  GridCellFieldNotifierImpl(GridFieldCache cache) : _cache = cache;
 
   @override
-  void dispose() {
+  void onCellDispose() {
     if (_onChangesetFn != null) {
       _cache.removeListener(onChangesetListener: _onChangesetFn!);
       _onChangesetFn = null;
@@ -319,7 +320,7 @@ class _GridFieldChangedNotifierImpl extends IGridFieldChangedNotifier {
   }
 
   @override
-  void onFieldChanged(void Function(GridFieldPB p1) callback) {
+  void onCellFieldChanged(void Function(GridFieldPB p1) callback) {
     _onChangesetFn = (GridFieldChangesetPB changeset) {
       for (final updatedField in changeset.updatedFields) {
         callback(updatedField);

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

@@ -8,7 +8,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'block/block_cache.dart';
 import 'grid_data_controller.dart';
-import 'row/row_service.dart';
+import 'row/row_cache.dart';
 import 'dart:collection';
 
 part 'grid_bloc.freezed.dart';

+ 2 - 0
frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart

@@ -9,7 +9,9 @@ import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
 import 'dart:async';
 import 'package:dartz/dartz.dart';
 import 'block/block_cache.dart';
+import 'field/field_cache.dart';
 import 'prelude.dart';
+import 'row/row_cache.dart';
 
 typedef OnFieldsChanged = void Function(UnmodifiableListView<GridFieldPB>);
 typedef OnGridChanged = void Function(GridPB);

+ 2 - 1
frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart

@@ -4,7 +4,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
-import 'grid_service.dart';
+
+import 'field/field_cache.dart';
 
 part 'grid_header_bloc.freezed.dart';
 

+ 0 - 190
frontend/app_flowy/lib/plugins/grid/application/grid_service.dart

@@ -1,17 +1,11 @@
-import 'dart:collection';
-
-import 'package:app_flowy/plugins/grid/application/field/grid_listener.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
-import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
-import 'package:flutter/foundation.dart';
-import 'row/row_service.dart';
 
 class GridService {
   final String gridId;
@@ -46,187 +40,3 @@ class GridService {
     return FolderEventCloseView(request).send();
   }
 }
-
-class FieldsNotifier extends ChangeNotifier {
-  List<GridFieldPB> _fields = [];
-
-  set fields(List<GridFieldPB> fields) {
-    _fields = fields;
-    notifyListeners();
-  }
-
-  List<GridFieldPB> get fields => _fields;
-}
-
-typedef FieldChangesetCallback = void Function(GridFieldChangesetPB);
-typedef FieldsCallback = void Function(List<GridFieldPB>);
-
-class GridFieldCache {
-  final String gridId;
-  final GridFieldsListener _fieldListener;
-  FieldsNotifier? _fieldNotifier = FieldsNotifier();
-  final Map<FieldsCallback, VoidCallback> _fieldsCallbackMap = {};
-  final Map<FieldChangesetCallback, FieldChangesetCallback>
-      _changesetCallbackMap = {};
-
-  GridFieldCache({required this.gridId})
-      : _fieldListener = GridFieldsListener(gridId: gridId) {
-    _fieldListener.start(onFieldsChanged: (result) {
-      result.fold(
-        (changeset) {
-          _deleteFields(changeset.deletedFields);
-          _insertFields(changeset.insertedFields);
-          _updateFields(changeset.updatedFields);
-          for (final listener in _changesetCallbackMap.values) {
-            listener(changeset);
-          }
-        },
-        (err) => Log.error(err),
-      );
-    });
-  }
-
-  Future<void> dispose() async {
-    await _fieldListener.stop();
-    _fieldNotifier?.dispose();
-    _fieldNotifier = null;
-  }
-
-  UnmodifiableListView<GridFieldPB> get unmodifiableFields =>
-      UnmodifiableListView(_fieldNotifier?.fields ?? []);
-
-  List<GridFieldPB> get fields => [..._fieldNotifier?.fields ?? []];
-
-  set fields(List<GridFieldPB> fields) {
-    _fieldNotifier?.fields = [...fields];
-  }
-
-  void addListener({
-    FieldsCallback? onFields,
-    FieldChangesetCallback? onChangeset,
-    bool Function()? listenWhen,
-  }) {
-    if (onChangeset != null) {
-      fn(c) {
-        if (listenWhen != null && listenWhen() == false) {
-          return;
-        }
-        onChangeset(c);
-      }
-
-      _changesetCallbackMap[onChangeset] = fn;
-    }
-
-    if (onFields != null) {
-      fn() {
-        if (listenWhen != null && listenWhen() == false) {
-          return;
-        }
-        onFields(fields);
-      }
-
-      _fieldsCallbackMap[onFields] = fn;
-      _fieldNotifier?.addListener(fn);
-    }
-  }
-
-  void removeListener({
-    FieldsCallback? onFieldsListener,
-    FieldChangesetCallback? onChangesetListener,
-  }) {
-    if (onFieldsListener != null) {
-      final fn = _fieldsCallbackMap.remove(onFieldsListener);
-      if (fn != null) {
-        _fieldNotifier?.removeListener(fn);
-      }
-    }
-
-    if (onChangesetListener != null) {
-      _changesetCallbackMap.remove(onChangesetListener);
-    }
-  }
-
-  void _deleteFields(List<GridFieldIdPB> deletedFields) {
-    if (deletedFields.isEmpty) {
-      return;
-    }
-    final List<GridFieldPB> newFields = fields;
-    final Map<String, GridFieldIdPB> deletedFieldMap = {
-      for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder
-    };
-
-    newFields.retainWhere((field) => (deletedFieldMap[field.id] == null));
-    _fieldNotifier?.fields = newFields;
-  }
-
-  void _insertFields(List<IndexFieldPB> insertedFields) {
-    if (insertedFields.isEmpty) {
-      return;
-    }
-    final List<GridFieldPB> newFields = fields;
-    for (final indexField in insertedFields) {
-      if (newFields.length > indexField.index) {
-        newFields.insert(indexField.index, indexField.field_1);
-      } else {
-        newFields.add(indexField.field_1);
-      }
-    }
-    _fieldNotifier?.fields = newFields;
-  }
-
-  void _updateFields(List<GridFieldPB> updatedFields) {
-    if (updatedFields.isEmpty) {
-      return;
-    }
-    final List<GridFieldPB> newFields = fields;
-    for (final updatedField in updatedFields) {
-      final index =
-          newFields.indexWhere((field) => field.id == updatedField.id);
-      if (index != -1) {
-        newFields.removeAt(index);
-        newFields.insert(index, updatedField);
-      }
-    }
-    _fieldNotifier?.fields = newFields;
-  }
-}
-
-class GridRowCacheFieldNotifierImpl extends GridRowCacheFieldNotifier {
-  final GridFieldCache _cache;
-  FieldChangesetCallback? _onChangesetFn;
-  FieldsCallback? _onFieldFn;
-  GridRowCacheFieldNotifierImpl(GridFieldCache cache) : _cache = cache;
-
-  @override
-  UnmodifiableListView<GridFieldPB> get fields => _cache.unmodifiableFields;
-
-  @override
-  void onFieldsChanged(VoidCallback callback) {
-    _onFieldFn = (_) => callback();
-    _cache.addListener(onFields: _onFieldFn);
-  }
-
-  @override
-  void onFieldChanged(void Function(GridFieldPB) callback) {
-    _onChangesetFn = (GridFieldChangesetPB changeset) {
-      for (final updatedField in changeset.updatedFields) {
-        callback(updatedField);
-      }
-    };
-
-    _cache.addListener(onChangeset: _onChangesetFn);
-  }
-
-  @override
-  void dispose() {
-    if (_onFieldFn != null) {
-      _cache.removeListener(onFieldsListener: _onFieldFn!);
-      _onFieldFn = null;
-    }
-
-    if (_onChangesetFn != null) {
-      _cache.removeListener(onChangesetListener: _onChangesetFn!);
-      _onChangesetFn = null;
-    }
-  }
-}

+ 2 - 0
frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart

@@ -6,6 +6,8 @@ import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
 import 'package:dartz/dartz.dart';
 
+import 'row_cache.dart';
+
 part 'row_action_sheet_bloc.freezed.dart';
 
 class RowActionSheetBloc

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

@@ -5,6 +5,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
+import 'row_cache.dart';
 import 'row_data_controller.dart';
 import 'row_service.dart';
 

+ 2 - 2
frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart

@@ -1,7 +1,7 @@
 import 'package:flutter/material.dart';
 import '../cell/cell_service/cell_service.dart';
-import '../grid_service.dart';
-import 'row_service.dart';
+import '../field/field_cache.dart';
+import 'row_cache.dart';
 
 typedef OnRowChanged = void Function(GridCellMap, GridRowChangeReason);
 

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

@@ -2,8 +2,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_servic
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
-import 'row_service.dart';
-
+import 'row_cache.dart';
 part 'row_detail_bloc.freezed.dart';
 
 class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {

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

@@ -1,283 +1,9 @@
-import 'dart:collection';
-import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_sdk/dispatch/dispatch.dart';
-import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart';
-import 'package:flutter/foundation.dart';
-import 'package:freezed_annotation/freezed_annotation.dart';
-part 'row_service.freezed.dart';
-
-typedef RowUpdateCallback = void Function();
-
-abstract class GridRowCacheFieldNotifier {
-  UnmodifiableListView<GridFieldPB> get fields;
-  void onFieldsChanged(VoidCallback callback);
-  void onFieldChanged(void Function(GridFieldPB) callback);
-  void dispose();
-}
-
-/// Cache the rows in memory
-/// Insert / delete / update row
-///
-/// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid for more information.
-
-class GridRowCache {
-  final String gridId;
-  final GridBlockPB block;
-
-  /// _rows containers the current block's rows
-  /// Use List to reverse the order of the GridRow.
-  List<GridRowInfo> _rowInfos = [];
-
-  /// Use Map for faster access the raw row data.
-  final HashMap<String, GridRowPB> _rowByRowId;
-
-  final GridCellCache _cellCache;
-  final GridRowCacheFieldNotifier _fieldNotifier;
-  final _GridRowChangesetNotifier _rowChangeReasonNotifier;
-
-  UnmodifiableListView<GridRowInfo> get rows => UnmodifiableListView(_rowInfos);
-  GridCellCache get cellCache => _cellCache;
-
-  GridRowCache({
-    required this.gridId,
-    required this.block,
-    required GridRowCacheFieldNotifier notifier,
-  })  : _cellCache = GridCellCache(gridId: gridId),
-        _rowByRowId = HashMap(),
-        _rowChangeReasonNotifier = _GridRowChangesetNotifier(),
-        _fieldNotifier = notifier {
-    //
-    notifier.onFieldsChanged(() => _rowChangeReasonNotifier
-        .receive(const GridRowChangeReason.fieldDidChange()));
-    notifier.onFieldChanged((field) => _cellCache.remove(field.id));
-    _rowInfos = block.rows
-        .map((rowInfo) => buildGridRow(rowInfo.id, rowInfo.height.toDouble()))
-        .toList();
-  }
-
-  Future<void> dispose() async {
-    _fieldNotifier.dispose();
-    _rowChangeReasonNotifier.dispose();
-    await _cellCache.dispose();
-  }
-
-  void applyChangesets(List<GridBlockChangesetPB> changesets) {
-    for (final changeset in changesets) {
-      _deleteRows(changeset.deletedRows);
-      _insertRows(changeset.insertedRows);
-      _updateRows(changeset.updatedRows);
-      _hideRows(changeset.hideRows);
-      _showRows(changeset.visibleRows);
-    }
-  }
-
-  void _deleteRows(List<String> deletedRows) {
-    if (deletedRows.isEmpty) {
-      return;
-    }
-
-    final List<GridRowInfo> newRows = [];
-    final DeletedIndexs deletedIndex = [];
-    final Map<String, String> deletedRowByRowId = {
-      for (var rowId in deletedRows) rowId: rowId
-    };
-
-    _rowInfos.asMap().forEach((index, row) {
-      if (deletedRowByRowId[row.id] == null) {
-        newRows.add(row);
-      } else {
-        _rowByRowId.remove(row.id);
-        deletedIndex.add(DeletedIndex(index: index, row: row));
-      }
-    });
-    _rowInfos = newRows;
-    _rowChangeReasonNotifier.receive(GridRowChangeReason.delete(deletedIndex));
-  }
-
-  void _insertRows(List<InsertedRowPB> insertRows) {
-    if (insertRows.isEmpty) {
-      return;
-    }
-
-    InsertedIndexs insertIndexs = [];
-    for (final insertRow in insertRows) {
-      final insertIndex = InsertedIndex(
-        index: insertRow.index,
-        rowId: insertRow.rowId,
-      );
-      insertIndexs.add(insertIndex);
-      _rowInfos.insert(insertRow.index,
-          (buildGridRow(insertRow.rowId, insertRow.height.toDouble())));
-    }
-
-    _rowChangeReasonNotifier.receive(GridRowChangeReason.insert(insertIndexs));
-  }
-
-  void _updateRows(List<UpdatedRowPB> updatedRows) {
-    if (updatedRows.isEmpty) {
-      return;
-    }
-
-    final UpdatedIndexs updatedIndexs = UpdatedIndexs();
-    for (final updatedRow in updatedRows) {
-      final rowId = updatedRow.rowId;
-      final index = _rowInfos.indexWhere((row) => row.id == rowId);
-      if (index != -1) {
-        _rowByRowId[rowId] = updatedRow.row;
-
-        _rowInfos.removeAt(index);
-        _rowInfos.insert(
-            index, buildGridRow(rowId, updatedRow.row.height.toDouble()));
-        updatedIndexs[rowId] = UpdatedIndex(index: index, rowId: rowId);
-      }
-    }
-
-    _rowChangeReasonNotifier.receive(GridRowChangeReason.update(updatedIndexs));
-  }
-
-  void _hideRows(List<String> hideRows) {}
-
-  void _showRows(List<String> visibleRows) {}
-
-  void onRowsChanged(
-    void Function(GridRowChangeReason) onRowChanged,
-  ) {
-    _rowChangeReasonNotifier.addListener(() {
-      onRowChanged(_rowChangeReasonNotifier.reason);
-    });
-  }
-
-  RowUpdateCallback addListener({
-    required String rowId,
-    void Function(GridCellMap, GridRowChangeReason)? onCellUpdated,
-    bool Function()? listenWhen,
-  }) {
-    listenerHandler() async {
-      if (listenWhen != null && listenWhen() == false) {
-        return;
-      }
-
-      notifyUpdate() {
-        if (onCellUpdated != null) {
-          final row = _rowByRowId[rowId];
-          if (row != null) {
-            final GridCellMap cellDataMap = _makeGridCells(rowId, row);
-            onCellUpdated(cellDataMap, _rowChangeReasonNotifier.reason);
-          }
-        }
-      }
-
-      _rowChangeReasonNotifier.reason.whenOrNull(
-        update: (indexs) {
-          if (indexs[rowId] != null) notifyUpdate();
-        },
-        fieldDidChange: () => notifyUpdate(),
-      );
-    }
-
-    _rowChangeReasonNotifier.addListener(listenerHandler);
-    return listenerHandler;
-  }
-
-  void removeRowListener(VoidCallback callback) {
-    _rowChangeReasonNotifier.removeListener(callback);
-  }
-
-  GridCellMap loadGridCells(String rowId) {
-    final GridRowPB? data = _rowByRowId[rowId];
-    if (data == null) {
-      _loadRow(rowId);
-    }
-    return _makeGridCells(rowId, data);
-  }
-
-  Future<void> _loadRow(String rowId) async {
-    final payload = GridRowIdPB.create()
-      ..gridId = gridId
-      ..blockId = block.id
-      ..rowId = rowId;
-
-    final result = await GridEventGetRow(payload).send();
-    result.fold(
-      (optionRow) => _refreshRow(optionRow),
-      (err) => Log.error(err),
-    );
-  }
-
-  GridCellMap _makeGridCells(String rowId, GridRowPB? row) {
-    var cellDataMap = GridCellMap.new();
-    for (final field in _fieldNotifier.fields) {
-      if (field.visibility) {
-        cellDataMap[field.id] = GridCellIdentifier(
-          rowId: rowId,
-          gridId: gridId,
-          field: field,
-        );
-      }
-    }
-    return cellDataMap;
-  }
-
-  void _refreshRow(OptionalRowPB optionRow) {
-    if (!optionRow.hasRow()) {
-      return;
-    }
-    final updatedRow = optionRow.row;
-    updatedRow.freeze();
-
-    _rowByRowId[updatedRow.id] = updatedRow;
-    final index =
-        _rowInfos.indexWhere((gridRow) => gridRow.id == updatedRow.id);
-    if (index != -1) {
-      // update the corresponding row in _rows if they are not the same
-      if (_rowInfos[index].rawRow != updatedRow) {
-        final row = _rowInfos.removeAt(index).copyWith(rawRow: updatedRow);
-        _rowInfos.insert(index, row);
-
-        // Calculate the update index
-        final UpdatedIndexs updatedIndexs = UpdatedIndexs();
-        updatedIndexs[row.id] = UpdatedIndex(index: index, rowId: row.id);
-
-        //
-        _rowChangeReasonNotifier
-            .receive(GridRowChangeReason.update(updatedIndexs));
-      }
-    }
-  }
-
-  GridRowInfo buildGridRow(String rowId, double rowHeight) {
-    return GridRowInfo(
-      gridId: gridId,
-      blockId: block.id,
-      fields: _fieldNotifier.fields,
-      id: rowId,
-      height: rowHeight,
-    );
-  }
-}
-
-class _GridRowChangesetNotifier extends ChangeNotifier {
-  GridRowChangeReason reason = const InitialListState();
-
-  _GridRowChangesetNotifier();
-
-  void receive(GridRowChangeReason newReason) {
-    reason = newReason;
-    reason.map(
-      insert: (_) => notifyListeners(),
-      delete: (_) => notifyListeners(),
-      update: (_) => notifyListeners(),
-      fieldDidChange: (_) => notifyListeners(),
-      initial: (_) {},
-    );
-  }
-}
 
 class RowService {
   final String gridId;
@@ -334,55 +60,3 @@ class RowService {
     return GridEventDuplicateRow(payload).send();
   }
 }
-
-@freezed
-class GridRowInfo with _$GridRowInfo {
-  const factory GridRowInfo({
-    required String gridId,
-    required String blockId,
-    required String id,
-    required UnmodifiableListView<GridFieldPB> fields,
-    required double height,
-    GridRowPB? rawRow,
-  }) = _GridRowInfo;
-}
-
-typedef InsertedIndexs = List<InsertedIndex>;
-typedef DeletedIndexs = List<DeletedIndex>;
-typedef UpdatedIndexs = LinkedHashMap<String, UpdatedIndex>;
-
-@freezed
-class GridRowChangeReason with _$GridRowChangeReason {
-  const factory GridRowChangeReason.insert(InsertedIndexs items) = _Insert;
-  const factory GridRowChangeReason.delete(DeletedIndexs items) = _Delete;
-  const factory GridRowChangeReason.update(UpdatedIndexs indexs) = _Update;
-  const factory GridRowChangeReason.fieldDidChange() = _FieldDidChange;
-  const factory GridRowChangeReason.initial() = InitialListState;
-}
-
-class InsertedIndex {
-  final int index;
-  final String rowId;
-  InsertedIndex({
-    required this.index,
-    required this.rowId,
-  });
-}
-
-class DeletedIndex {
-  final int index;
-  final GridRowInfo row;
-  DeletedIndex({
-    required this.index,
-    required this.row,
-  });
-}
-
-class UpdatedIndex {
-  final int index;
-  final String rowId;
-  UpdatedIndex({
-    required this.index,
-    required this.rowId,
-  });
-}

+ 2 - 1
frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart

@@ -1,11 +1,12 @@
 import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
-import 'package:app_flowy/plugins/grid/application/grid_service.dart';
 import 'package:flowy_sdk/log.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
 
+import '../field/field_cache.dart';
+
 part 'property_bloc.freezed.dart';
 
 class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> {

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/grid/application/grid_bloc.dart';
-import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
 import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
@@ -12,6 +11,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:flutter/material.dart';
 import 'package:linked_scroll_controller/linked_scroll_controller.dart';
+import '../application/row/row_cache.dart';
 import 'controller/grid_scroll.dart';
 import 'layout/layout.dart';
 import 'layout/sizes.dart';

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

@@ -1,5 +1,5 @@
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
-import 'package:app_flowy/plugins/grid/application/grid_service.dart';
+import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/services.dart';
 import 'package:flutter/widgets.dart';

+ 2 - 2
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart

@@ -22,8 +22,8 @@ class _CheckboxCellState extends GridCellState<GridCheckboxCell> {
 
   @override
   void initState() {
-    final cellContext = widget.cellControllerBuilder.build();
-    _cellBloc = getIt<CheckboxCellBloc>(param1: cellContext)
+    final cellController = widget.cellControllerBuilder.build();
+    _cellBloc = getIt<CheckboxCellBloc>(param1: cellController)
       ..add(const CheckboxCellEvent.initial());
     super.initState();
   }

+ 2 - 2
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart

@@ -43,8 +43,8 @@ class _DateCellState extends GridCellState<GridDateCell> {
 
   @override
   void initState() {
-    final cellContext = widget.cellControllerBuilder.build();
-    _cellBloc = getIt<DateCellBloc>(param1: cellContext)
+    final cellController = widget.cellControllerBuilder.build();
+    _cellBloc = getIt<DateCellBloc>(param1: cellController)
       ..add(const DateCellEvent.initial());
     super.initState();
   }

+ 2 - 2
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart

@@ -25,8 +25,8 @@ class _NumberCellState extends GridFocusNodeCellState<GridNumberCell> {
 
   @override
   void initState() {
-    final cellContext = widget.cellControllerBuilder.build();
-    _cellBloc = getIt<NumberCellBloc>(param1: cellContext)
+    final cellController = widget.cellControllerBuilder.build();
+    _cellBloc = getIt<NumberCellBloc>(param1: cellController)
       ..add(const NumberCellEvent.initial());
     _controller =
         TextEditingController(text: contentFromState(_cellBloc.state));

+ 4 - 4
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart

@@ -46,9 +46,9 @@ class _SingleSelectCellState extends State<GridSingleSelectCell> {
 
   @override
   void initState() {
-    final cellContext =
+    final cellController =
         widget.cellControllerBuilder.build() as GridSelectOptionCellController;
-    _cellBloc = getIt<SelectOptionCellBloc>(param1: cellContext)
+    _cellBloc = getIt<SelectOptionCellBloc>(param1: cellController)
       ..add(const SelectOptionCellEvent.initial());
     super.initState();
   }
@@ -102,9 +102,9 @@ class _MultiSelectCellState extends State<GridMultiSelectCell> {
 
   @override
   void initState() {
-    final cellContext =
+    final cellController =
         widget.cellControllerBuilder.build() as GridSelectOptionCellController;
-    _cellBloc = getIt<SelectOptionCellBloc>(param1: cellContext)
+    _cellBloc = getIt<SelectOptionCellBloc>(param1: cellController)
       ..add(const SelectOptionCellEvent.initial());
     super.initState();
   }

+ 2 - 2
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart

@@ -39,8 +39,8 @@ class _GridTextCellState extends GridFocusNodeCellState<GridTextCell> {
 
   @override
   void initState() {
-    final cellContext = widget.cellControllerBuilder.build();
-    _cellBloc = getIt<TextCellBloc>(param1: cellContext);
+    final cellController = widget.cellControllerBuilder.build();
+    _cellBloc = getIt<TextCellBloc>(param1: cellController);
     _cellBloc.add(const TextCellEvent.initial());
     _controller = TextEditingController(text: _cellBloc.state.content);
     super.initState();

+ 2 - 2
frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart

@@ -52,10 +52,10 @@ class GridURLCell extends GridCellWidget {
       GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) {
     switch (ty) {
       case GridURLCellAccessoryType.edit:
-        final cellContext =
+        final cellController =
             cellControllerBuilder.build() as GridURLCellController;
         return _EditURLAccessory(
-            cellContext: cellContext,
+            cellContext: cellController,
             anchorContext: buildContext.anchorContext);
 
       case GridURLCellAccessoryType.copyURL:

+ 1 - 0
frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart

@@ -1,3 +1,4 @@
+import 'package:app_flowy/plugins/grid/application/field/field_cache.dart';
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/grid/application/prelude.dart';
 import 'package:flowy_infra/image.dart';

+ 1 - 0
frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart

@@ -1,4 +1,5 @@
 import 'package:app_flowy/plugins/grid/application/prelude.dart';
+import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
 import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart

@@ -1,5 +1,4 @@
 import 'package:app_flowy/plugins/grid/application/row/row_action_sheet_bloc.dart';
-import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:app_flowy/generated/locale_keys.g.dart';
 import 'package:flowy_infra/image.dart';
@@ -12,6 +11,7 @@ import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
+import '../../../application/row/row_cache.dart';
 import '../../layout/sizes.dart';
 
 class GridRowActionSheet extends StatelessWidget {

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart

@@ -1,7 +1,6 @@
 import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
 import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
 import 'package:app_flowy/plugins/grid/application/row/row_detail_bloc.dart';
-import 'package:app_flowy/plugins/grid/application/row/row_service.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@@ -14,6 +13,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
+import '../../../application/row/row_cache.dart';
 import '../../layout/sizes.dart';
 import '../cell/cell_accessory.dart';
 import '../cell/prelude.dart';

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart

@@ -1,6 +1,5 @@
 import 'package:app_flowy/startup/startup.dart';
 import 'package:app_flowy/plugins/grid/application/field/field_service.dart';
-import 'package:app_flowy/plugins/grid/application/grid_service.dart';
 import 'package:app_flowy/plugins/grid/application/setting/property_bloc.dart';
 import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart';
 import 'package:flowy_infra/image.dart';
@@ -15,6 +14,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:styled_widget/styled_widget.dart';
 
+import '../../../application/field/field_cache.dart';
 import '../../layout/sizes.dart';
 import '../header/field_editor.dart';
 

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart

@@ -1,4 +1,3 @@
-import 'package:app_flowy/plugins/grid/application/grid_service.dart';
 import 'package:app_flowy/plugins/grid/application/setting/setting_bloc.dart';
 import 'package:easy_localization/easy_localization.dart';
 import 'package:flowy_infra/image.dart';
@@ -12,6 +11,7 @@ import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:app_flowy/generated/locale_keys.g.dart';
+import '../../../application/field/field_cache.dart';
 import '../../layout/sizes.dart';
 import 'grid_property.dart';
 

+ 1 - 1
frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart

@@ -1,4 +1,3 @@
-import 'package:app_flowy/plugins/grid/application/grid_service.dart';
 import 'package:flowy_infra/image.dart';
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/extension.dart';
@@ -6,6 +5,7 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
+import '../../../application/field/field_cache.dart';
 import '../../layout/sizes.dart';
 import 'grid_setting.dart';
 

+ 2 - 0
frontend/app_flowy/lib/startup/deps_resolver.dart

@@ -21,6 +21,8 @@ import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart';
 import 'package:fluttertoast/fluttertoast.dart';
 import 'package:get_it/get_it.dart';
 
+import '../plugins/grid/application/field/field_cache.dart';
+
 class DependencyResolver {
   static Future<void> resolve(GetIt getIt) async {
     _resolveUserDeps(getIt);