appflowy 2 лет назад
Родитель
Сommit
a73987456e
29 измененных файлов с 161 добавлено и 144 удалено
  1. 3 3
      frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart
  2. 21 18
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cache.dart
  3. 4 22
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart
  4. 5 3
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart
  5. 5 2
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_field_notifier.dart
  6. 9 6
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart
  7. 58 36
      frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart
  8. 1 1
      frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart
  9. 1 1
      frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart
  10. 4 0
      frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart
  11. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart
  12. 2 2
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart
  13. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart
  14. 2 2
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart
  15. 5 5
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart
  16. 3 3
      frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart
  17. 2 2
      frontend/app_flowy/lib/workspace/application/grid/grid_service.dart
  18. 2 2
      frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart
  19. 10 10
      frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart
  20. 2 4
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart
  21. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart
  22. 5 5
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart
  23. 4 4
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart
  24. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart
  25. 5 5
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/builder.dart
  26. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart
  27. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart
  28. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/url.dart
  29. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart

+ 3 - 3
frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart

@@ -6,7 +6,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
 
 import 'block_listener.dart';
 
-class GridBlockCacheService {
+class GridBlockCache {
   final String gridId;
   final GridBlock block;
   late GridRowsCache _rowCache;
@@ -15,7 +15,7 @@ class GridBlockCacheService {
   List<GridRow> get rows => _rowCache.rows;
   GridRowsCache get rowCache => _rowCache;
 
-  GridBlockCacheService({
+  GridBlockCache({
     required this.gridId,
     required this.block,
     required GridFieldCache fieldCache,
@@ -23,7 +23,7 @@ class GridBlockCacheService {
     _rowCache = GridRowsCache(
       gridId: gridId,
       block: block,
-      delegate: GridRowCacheDelegateImpl(fieldCache),
+      notifier: GridRowCacheFieldNotifierImpl(fieldCache),
     );
 
     _listener = GridBlockListener(blockId: block.id);

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

@@ -1,25 +1,29 @@
 part of 'cell_service.dart';
 
-typedef GridCellMap = LinkedHashMap<String, GridCell>;
+typedef GridCellMap = LinkedHashMap<String, GridCellIdentifier>;
 
-class _GridCellCacheItem {
-  GridCellId key;
+class _GridCellCacheValue {
+  GridCellCacheKey key;
   dynamic object;
-  _GridCellCacheItem({
+  _GridCellCacheValue({
     required this.key,
     required this.object,
   });
 }
 
-class GridCellId {
+/// Use to index the cell in the grid.
+/// We use [fieldId + rowId] to identify the cell.
+class GridCellCacheKey {
   final String fieldId;
   final String rowId;
-  GridCellId({
+  GridCellCacheKey({
     required this.fieldId,
     required this.rowId,
   });
 }
 
+/// GridCellsCache is used to cache cell data of each Grid.
+/// We use GridCellCacheKey to index the cell in the cache.
 class GridCellsCache {
   final String gridId;
 
@@ -33,29 +37,28 @@ class GridCellsCache {
     _cellDataByFieldId.remove(fieldId);
   }
 
-  void insert<T extends _GridCellCacheItem>(T item) {
-    var map = _cellDataByFieldId[item.key.fieldId];
+  void insert<T extends _GridCellCacheValue>(T value) {
+    var map = _cellDataByFieldId[value.key.fieldId];
     if (map == null) {
-      _cellDataByFieldId[item.key.fieldId] = {};
-      map = _cellDataByFieldId[item.key.fieldId];
+      _cellDataByFieldId[value.key.fieldId] = {};
+      map = _cellDataByFieldId[value.key.fieldId];
     }
 
-    map![item.key.rowId] = item.object;
+    map![value.key.rowId] = value.object;
   }
 
-  T? get<T>(GridCellId key) {
+  T? get<T>(GridCellCacheKey key) {
     final map = _cellDataByFieldId[key.fieldId];
     if (map == null) {
       return null;
     } else {
-      final object = map[key.rowId];
-      if (object is T) {
-        return object;
+      final value = map[key.rowId];
+      if (value is T) {
+        return value;
       } else {
-        if (object != null) {
-          Log.error("Cache data type does not match the cache data type");
+        if (value != null) {
+          Log.error("Expected value type: $T, but receive $value");
         }
-
         return null;
       }
     }

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

@@ -5,40 +5,22 @@ abstract class IGridCellDataConfig {
   bool get reloadOnFieldChanged;
 }
 
-class GridCellDataConfig implements IGridCellDataConfig {
-  @override
-  final bool reloadOnFieldChanged;
-
-  const GridCellDataConfig({
-    this.reloadOnFieldChanged = false,
-  });
-}
-
-abstract class IGridCellDataLoader<T> {
-  Future<T?> loadData();
-
-  IGridCellDataConfig get config;
-}
-
 abstract class ICellDataParser<T> {
   T? parserData(List<int> data);
 }
 
-class GridCellDataLoader<T> extends IGridCellDataLoader<T> {
+class GridCellDataLoader<T> {
   final CellService service = CellService();
-  final GridCell gridCell;
+  final GridCellIdentifier gridCell;
   final ICellDataParser<T> parser;
-
-  @override
-  final IGridCellDataConfig config;
+  final bool reloadOnFieldChanged;
 
   GridCellDataLoader({
     required this.gridCell,
     required this.parser,
-    this.config = const GridCellDataConfig(),
+    this.reloadOnFieldChanged = false,
   });
 
-  @override
   Future<T?> loadData() {
     final fut = service.getCell(
       gridId: gridCell.gridId,

+ 5 - 3
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart

@@ -1,11 +1,13 @@
 part of 'cell_service.dart';
 
+/// Save the cell data to disk
+/// You can extend this class to do custom operations. For example, the DateCellDataPersistence.
 abstract class IGridCellDataPersistence<D> {
   Future<Option<FlowyError>> save(D data);
 }
 
 class CellDataPersistence implements IGridCellDataPersistence<String> {
-  final GridCell gridCell;
+  final GridCellIdentifier gridCell;
 
   CellDataPersistence({
     required this.gridCell,
@@ -36,7 +38,7 @@ class CalendarData with _$CalendarData {
 }
 
 class DateCellDataPersistence implements IGridCellDataPersistence<CalendarData> {
-  final GridCell gridCell;
+  final GridCellIdentifier gridCell;
   DateCellDataPersistence({
     required this.gridCell,
   });
@@ -61,7 +63,7 @@ class DateCellDataPersistence implements IGridCellDataPersistence<CalendarData>
   }
 }
 
-CellIdentifierPayload _cellIdentifier(GridCell gridCell) {
+CellIdentifierPayload _cellIdentifier(GridCellIdentifier gridCell) {
   return CellIdentifierPayload.create()
     ..gridId = gridCell.gridId
     ..fieldId = gridCell.field.id

+ 5 - 2
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_field_notifier.dart

@@ -8,6 +8,8 @@ abstract class GridFieldChangedNotifier {
   void dispose();
 }
 
+/// Grid'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 {
   /// fieldId: {objectId: callback}
   final Map<String, Map<String, List<VoidCallback>>> _fieldListenerByFieldId = {};
@@ -27,7 +29,8 @@ class GridCellFieldNotifier {
     );
   }
 
-  void addFieldListener(GridCellId cacheKey, VoidCallback onFieldChanged) {
+  ///
+  void register(GridCellCacheKey cacheKey, VoidCallback onFieldChanged) {
     var map = _fieldListenerByFieldId[cacheKey.fieldId];
     if (map == null) {
       _fieldListenerByFieldId[cacheKey.fieldId] = {};
@@ -43,7 +46,7 @@ class GridCellFieldNotifier {
     }
   }
 
-  void removeFieldListener(GridCellId cacheKey, VoidCallback fn) {
+  void unregister(GridCellCacheKey cacheKey, VoidCallback fn) {
     var callbacks = _fieldListenerByFieldId[cacheKey.fieldId]?[cacheKey.rowId];
     final index = callbacks?.indexWhere((callback) => callback == fn);
     if (index != null && index != -1) {

+ 9 - 6
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart

@@ -18,6 +18,7 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
 import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
 import 'dart:convert' show utf8;
 
+import '../../field/type_option/type_option_service.dart';
 import 'cell_field_notifier.dart';
 part 'cell_service.freezed.dart';
 part 'cell_data_loader.dart';
@@ -57,18 +58,20 @@ class CellService {
   }
 }
 
+/// Id of the cell
+/// We can locate the cell by using gridId + rowId + field.id.
 @freezed
-class GridCell with _$GridCell {
-  const factory GridCell({
+class GridCellIdentifier with _$GridCellIdentifier {
+  const factory GridCellIdentifier({
     required String gridId,
     required String rowId,
     required Field field,
-  }) = _GridCell;
+  }) = _GridCellIdentifier;
 
   // ignore: unused_element
-  const GridCell._();
+  const GridCellIdentifier._();
 
-  String cellId() {
-    return rowId + field.id + "${field.fieldType}";
+  ValueKey key() {
+    return ValueKey(rowId + field.id + "${field.fieldType}");
   }
 }

+ 58 - 36
frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart

@@ -6,12 +6,12 @@ typedef GridDateCellController = IGridCellController<DateCellData, CalendarData>
 typedef GridURLCellController = IGridCellController<URLCellData, String>;
 
 class GridCellControllerBuilder {
-  final GridCell _gridCell;
+  final GridCellIdentifier _gridCell;
   final GridCellsCache _cellCache;
   final GridFieldCache _fieldCache;
 
   GridCellControllerBuilder(
-      {required GridCell gridCell, required GridCellsCache cellCache, required GridFieldCache fieldCache})
+      {required GridCellIdentifier gridCell, required GridCellsCache cellCache, required GridFieldCache fieldCache})
       : _cellCache = cellCache,
         _fieldCache = fieldCache,
         _gridCell = gridCell;
@@ -29,34 +29,33 @@ class GridCellControllerBuilder {
           gridCell: _gridCell,
           cellCache: _cellCache,
           cellDataLoader: cellDataLoader,
-          cellFieldNotifier: cellFieldNotifier,
+          fieldNotifier: cellFieldNotifier,
           cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
         );
       case FieldType.DateTime:
         final cellDataLoader = GridCellDataLoader(
           gridCell: _gridCell,
           parser: DateCellDataParser(),
-          config: const GridCellDataConfig(reloadOnFieldChanged: true),
+          reloadOnFieldChanged: true,
         );
 
         return GridDateCellController(
           gridCell: _gridCell,
           cellCache: _cellCache,
           cellDataLoader: cellDataLoader,
-          cellFieldNotifier: cellFieldNotifier,
+          fieldNotifier: cellFieldNotifier,
           cellDataPersistence: DateCellDataPersistence(gridCell: _gridCell),
         );
       case FieldType.Number:
         final cellDataLoader = GridCellDataLoader(
           gridCell: _gridCell,
           parser: StringCellDataParser(),
-          config: const GridCellDataConfig(reloadOnFieldChanged: true),
         );
         return GridCellController(
           gridCell: _gridCell,
           cellCache: _cellCache,
           cellDataLoader: cellDataLoader,
-          cellFieldNotifier: cellFieldNotifier,
+          fieldNotifier: cellFieldNotifier,
           cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
         );
       case FieldType.RichText:
@@ -68,7 +67,7 @@ class GridCellControllerBuilder {
           gridCell: _gridCell,
           cellCache: _cellCache,
           cellDataLoader: cellDataLoader,
-          cellFieldNotifier: cellFieldNotifier,
+          fieldNotifier: cellFieldNotifier,
           cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
         );
       case FieldType.MultiSelect:
@@ -76,14 +75,14 @@ class GridCellControllerBuilder {
         final cellDataLoader = GridCellDataLoader(
           gridCell: _gridCell,
           parser: SelectOptionCellDataParser(),
-          config: const GridCellDataConfig(reloadOnFieldChanged: true),
+          reloadOnFieldChanged: true,
         );
 
         return GridSelectOptionCellController(
           gridCell: _gridCell,
           cellCache: _cellCache,
           cellDataLoader: cellDataLoader,
-          cellFieldNotifier: cellFieldNotifier,
+          fieldNotifier: cellFieldNotifier,
           cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
         );
 
@@ -96,7 +95,7 @@ class GridCellControllerBuilder {
           gridCell: _gridCell,
           cellCache: _cellCache,
           cellDataLoader: cellDataLoader,
-          cellFieldNotifier: cellFieldNotifier,
+          fieldNotifier: cellFieldNotifier,
           cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
         );
     }
@@ -104,17 +103,21 @@ class GridCellControllerBuilder {
   }
 }
 
-// T: the type of the CellData
-// D: the type of the data that will be saved to disk
+/// IGridCellController is used to manipulate the cell and receive notifications.
+/// * Read/Write cell data
+/// * Listen on field/cell notifications.
+///
+/// Generic T represents the type of the cell data.
+/// Generic D represents the type of data that will be saved to the disk
+///
 // ignore: must_be_immutable
 class IGridCellController<T, D> extends Equatable {
-  final GridCell gridCell;
+  final GridCellIdentifier gridCell;
   final GridCellsCache _cellsCache;
-  final GridCellId _cacheKey;
+  final GridCellCacheKey _cacheKey;
   final FieldService _fieldService;
-  final GridCellFieldNotifier _cellFieldNotifier;
-  // final GridCellFieldNotifier _fieldNotifier;
-  final IGridCellDataLoader<T> _cellDataLoader;
+  final GridCellFieldNotifier _fieldNotifier;
+  final GridCellDataLoader<T> _cellDataLoader;
   final IGridCellDataPersistence<D> _cellDataPersistence;
 
   late final CellListener _cellListener;
@@ -124,28 +127,27 @@ class IGridCellController<T, D> extends Equatable {
   VoidCallback? _onFieldChangedFn;
   Timer? _loadDataOperation;
   Timer? _saveDataOperation;
-  bool isDispose = false;
+  bool _isDispose = false;
 
   IGridCellController({
     required this.gridCell,
     required GridCellsCache cellCache,
-    required GridCellFieldNotifier cellFieldNotifier,
-    required IGridCellDataLoader<T> cellDataLoader,
+    required GridCellFieldNotifier fieldNotifier,
+    required GridCellDataLoader<T> cellDataLoader,
     required IGridCellDataPersistence<D> cellDataPersistence,
-    // required GridFieldChangedNotifier notifierDelegate,
   })  : _cellsCache = cellCache,
         _cellDataLoader = cellDataLoader,
         _cellDataPersistence = cellDataPersistence,
-        _cellFieldNotifier = cellFieldNotifier,
+        _fieldNotifier = fieldNotifier,
         _fieldService = FieldService(gridId: gridCell.gridId, fieldId: gridCell.field.id),
-        _cacheKey = GridCellId(rowId: gridCell.rowId, fieldId: gridCell.field.id);
+        _cacheKey = GridCellCacheKey(rowId: gridCell.rowId, fieldId: gridCell.field.id);
 
   IGridCellController<T, D> clone() {
     return IGridCellController(
         gridCell: gridCell,
         cellDataLoader: _cellDataLoader,
         cellCache: _cellsCache,
-        cellFieldNotifier: _cellFieldNotifier,
+        fieldNotifier: _fieldNotifier,
         cellDataPersistence: _cellDataPersistence);
   }
 
@@ -191,16 +193,18 @@ class IGridCellController<T, D> extends Equatable {
         onCellFieldChanged();
       }
 
-      if (_cellDataLoader.config.reloadOnFieldChanged) {
+      if (_cellDataLoader.reloadOnFieldChanged) {
         _loadData();
       }
     };
 
-    _cellFieldNotifier.addFieldListener(_cacheKey, _onFieldChangedFn!);
+    _fieldNotifier.register(_cacheKey, _onFieldChangedFn!);
 
     /// Notify the listener, the cell data was changed.
     onCellChangedFn() => onCellChanged(_cellDataNotifier?.value);
     _cellDataNotifier?.addListener(onCellChangedFn);
+
+    // Return the function pointer that can be used when calling removeListener.
     return onCellChangedFn;
   }
 
@@ -208,22 +212,38 @@ class IGridCellController<T, D> extends Equatable {
     _cellDataNotifier?.removeListener(fn);
   }
 
-  T? getCellData({bool loadIfNoCache = true}) {
+  /// Return the cell data.
+  /// The cell data will be read from the Cache first, and load from disk if it does not exist.
+  /// You can set [loadIfNotExist] to false (default is true) to disable loading the cell data.
+  T? getCellData({bool loadIfNotExist = true}) {
     final data = _cellsCache.get(_cacheKey);
-    if (data == null && loadIfNoCache) {
+    if (data == null && loadIfNotExist) {
       _loadData();
     }
     return data;
   }
 
-  Future<Either<FieldTypeOptionData, FlowyError>> getTypeOptionData() {
-    return _fieldService.getFieldTypeOptionData(fieldType: fieldType);
+  /// Return the FieldTypeOptionData that can be parsed into corresponding class using the [parser].
+  /// [PD] is the type that the parser return.
+  Future<Either<PD, FlowyError>> getFieldTypeOption<PD, P extends TypeOptionDataParser>(P parser) {
+    return _fieldService.getFieldTypeOptionData(fieldType: fieldType).then((result) {
+      return result.fold(
+        (data) => parser.fromBuffer(data.typeOptionData),
+        (err) => right(err),
+      );
+    });
   }
 
+  /// Save the cell data to disk
+  /// You can set [dedeplicate] to true (default is false) to reduce the save operation.
+  /// It's useful when you call this method when user editing the [TextField].
+  /// The default debounce interval is 300 milliseconds.
   void saveCellData(D data, {bool deduplicate = false, void Function(Option<FlowyError>)? resultCallback}) async {
     if (deduplicate) {
       _loadDataOperation?.cancel();
-      _loadDataOperation = Timer(const Duration(milliseconds: 300), () async {
+
+      _saveDataOperation?.cancel();
+      _saveDataOperation = Timer(const Duration(milliseconds: 300), () async {
         final result = await _cellDataPersistence.save(data);
         if (resultCallback != null) {
           resultCallback(result);
@@ -238,28 +258,30 @@ class IGridCellController<T, D> extends Equatable {
   }
 
   void _loadData() {
+    _saveDataOperation?.cancel();
+
     _loadDataOperation?.cancel();
     _loadDataOperation = Timer(const Duration(milliseconds: 10), () {
       _cellDataLoader.loadData().then((data) {
         _cellDataNotifier?.value = data;
-        _cellsCache.insert(_GridCellCacheItem(key: _cacheKey, object: data));
+        _cellsCache.insert(_GridCellCacheValue(key: _cacheKey, object: data));
       });
     });
   }
 
   void dispose() {
-    if (isDispose) {
+    if (_isDispose) {
       Log.error("$this should only dispose once");
       return;
     }
-    isDispose = true;
+    _isDispose = true;
     _cellListener.stop();
     _loadDataOperation?.cancel();
     _saveDataOperation?.cancel();
     _cellDataNotifier = null;
 
     if (_onFieldChangedFn != null) {
-      _cellFieldNotifier.removeFieldListener(_cacheKey, _onFieldChangedFn!);
+      _fieldNotifier.unregister(_cacheKey, _onFieldChangedFn!);
       _onFieldChangedFn = null;
     }
   }

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

@@ -184,7 +184,7 @@ class SelectOptionEditorState with _$SelectOptionEditorState {
   }) = _SelectOptionEditorState;
 
   factory SelectOptionEditorState.initial(GridSelectOptionCellController context) {
-    final data = context.getCellData(loadIfNoCache: false);
+    final data = context.getCellData(loadIfNotExist: false);
     return SelectOptionEditorState(
       options: data?.options ?? [],
       allOptions: data?.options ?? [],

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

@@ -7,7 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart';
 import 'cell_service/cell_service.dart';
 
 class SelectOptionService {
-  final GridCell gridCell;
+  final GridCellIdentifier gridCell;
   SelectOptionService({required this.gridCell});
 
   String get gridId => gridCell.gridId;

+ 4 - 0
frontend/app_flowy/lib/workspace/application/grid/field/field_service.dart

@@ -9,6 +9,10 @@ import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:protobuf/protobuf.dart';
 part 'field_service.freezed.dart';
 
+/// FieldService consists of lots of event functions. We define the events in the backend(Rust),
+/// you can find the corresponding event implementation in event_map.rs of the corresponding crate.
+///
+/// You could check out the rust-lib/flowy-grid/event_map.rs for more information.
 class FieldService {
   final String gridId;
   final String fieldId;

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/type_option/date_bloc.dart

@@ -8,7 +8,7 @@ part 'date_bloc.freezed.dart';
 
 typedef DateTypeOptionContext = TypeOptionWidgetContext<DateTypeOption>;
 
-class DateTypeOptionDataParser extends TypeOptionWidgetDataParser<DateTypeOption> {
+class DateTypeOptionDataParser extends TypeOptionDataParser<DateTypeOption> {
   @override
   DateTypeOption fromBuffer(List<int> buffer) {
     return DateTypeOption.fromBuffer(buffer);

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/field/type_option/multi_select_type_option.dart

@@ -18,7 +18,7 @@ class MultiSelectTypeOptionContext extends TypeOptionWidgetContext<MultiSelectTy
           gridId: fieldContext.gridId,
           fieldId: fieldContext.field.id,
         ),
-        super(dataBuilder: dataBuilder, fieldContext: fieldContext);
+        super(dataParser: dataBuilder, fieldContext: fieldContext);
 
   @override
   List<SelectOption> Function(SelectOption) get deleteOption {
@@ -71,7 +71,7 @@ class MultiSelectTypeOptionContext extends TypeOptionWidgetContext<MultiSelectTy
   }
 }
 
-class MultiSelectTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<MultiSelectTypeOption> {
+class MultiSelectTypeOptionWidgetDataParser extends TypeOptionDataParser<MultiSelectTypeOption> {
   @override
   MultiSelectTypeOption fromBuffer(List<int> buffer) {
     return MultiSelectTypeOption.fromBuffer(buffer);

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart

@@ -10,7 +10,7 @@ part 'number_bloc.freezed.dart';
 
 typedef NumberTypeOptionContext = TypeOptionWidgetContext<NumberTypeOption>;
 
-class NumberTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<NumberTypeOption> {
+class NumberTypeOptionWidgetDataParser extends TypeOptionDataParser<NumberTypeOption> {
   @override
   NumberTypeOption fromBuffer(List<int> buffer) {
     return NumberTypeOption.fromBuffer(buffer);

+ 2 - 2
frontend/app_flowy/lib/workspace/application/grid/field/type_option/single_select_type_option.dart

@@ -18,7 +18,7 @@ class SingleSelectTypeOptionContext extends TypeOptionWidgetContext<SingleSelect
           gridId: fieldContext.gridId,
           fieldId: fieldContext.field.id,
         ),
-        super(dataBuilder: dataBuilder, fieldContext: fieldContext);
+        super(dataParser: dataBuilder, fieldContext: fieldContext);
 
   @override
   List<SelectOption> Function(SelectOption) get deleteOption {
@@ -71,7 +71,7 @@ class SingleSelectTypeOptionContext extends TypeOptionWidgetContext<SingleSelect
   }
 }
 
-class SingleSelectTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<SingleSelectTypeOption> {
+class SingleSelectTypeOptionWidgetDataParser extends TypeOptionDataParser<SingleSelectTypeOption> {
   @override
   SingleSelectTypeOption fromBuffer(List<int> buffer) {
     return SingleSelectTypeOption.fromBuffer(buffer);

+ 5 - 5
frontend/app_flowy/lib/workspace/application/grid/field/type_option/type_option_service.dart

@@ -33,17 +33,17 @@ class TypeOptionService {
   }
 }
 
-abstract class TypeOptionWidgetDataParser<T> {
+abstract class TypeOptionDataParser<T> {
   T fromBuffer(List<int> buffer);
 }
 
 class TypeOptionWidgetContext<T extends GeneratedMessage> {
   T? _typeOptionObject;
   final GridFieldContext _fieldContext;
-  final TypeOptionWidgetDataParser<T> dataBuilder;
+  final TypeOptionDataParser<T> dataParser;
 
   TypeOptionWidgetContext({
-    required this.dataBuilder,
+    required this.dataParser,
     required GridFieldContext fieldContext,
   }) : _fieldContext = fieldContext;
 
@@ -56,7 +56,7 @@ class TypeOptionWidgetContext<T extends GeneratedMessage> {
       return _typeOptionObject!;
     }
 
-    final T object = dataBuilder.fromBuffer(_fieldContext.typeOptionData);
+    final T object = dataParser.fromBuffer(_fieldContext.typeOptionData);
     _typeOptionObject = object;
     return object;
   }
@@ -77,7 +77,7 @@ class TypeOptionContext2<T> {
   final Field field;
   final FieldService _fieldService;
   T? _data;
-  final TypeOptionWidgetDataParser dataBuilder;
+  final TypeOptionDataParser dataBuilder;
 
   TypeOptionContext2({
     required this.gridId,

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

@@ -20,7 +20,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
   final GridFieldCache fieldCache;
 
   // key: the block id
-  final LinkedHashMap<String, GridBlockCacheService> _blocks;
+  final LinkedHashMap<String, GridBlockCache> _blocks;
 
   List<GridRow> get rows {
     final List<GridRow> rows = [];
@@ -69,7 +69,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
   }
 
   GridRowsCache? getRowCache(String blockId, String rowId) {
-    final GridBlockCacheService? blockCache = _blocks[blockId];
+    final GridBlockCache? blockCache = _blocks[blockId];
     return blockCache?.rowCache;
   }
 
@@ -119,7 +119,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
         return;
       }
 
-      final cache = GridBlockCacheService(
+      final cache = GridBlockCache(
         gridId: gridId,
         block: block,
         fieldCache: fieldCache,

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

@@ -186,11 +186,11 @@ class GridFieldCache {
   }
 }
 
-class GridRowCacheDelegateImpl extends GridRowCacheDelegate {
+class GridRowCacheFieldNotifierImpl extends GridRowCacheFieldNotifier {
   final GridFieldCache _cache;
   FieldChangesetCallback? _onChangesetFn;
   FieldsCallback? _onFieldFn;
-  GridRowCacheDelegateImpl(GridFieldCache cache) : _cache = cache;
+  GridRowCacheFieldNotifierImpl(GridFieldCache cache) : _cache = cache;
 
   @override
   UnmodifiableListView<Field> get fields => _cache.unmodifiableFields;

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

@@ -58,13 +58,13 @@ class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
 @freezed
 class RowDetailEvent with _$RowDetailEvent {
   const factory RowDetailEvent.initial() = _Initial;
-  const factory RowDetailEvent.didReceiveCellDatas(List<GridCell> gridCells) = _DidReceiveCellDatas;
+  const factory RowDetailEvent.didReceiveCellDatas(List<GridCellIdentifier> gridCells) = _DidReceiveCellDatas;
 }
 
 @freezed
 class RowDetailState with _$RowDetailState {
   const factory RowDetailState({
-    required List<GridCell> gridCells,
+    required List<GridCellIdentifier> gridCells,
   }) = _RowDetailState;
 
   factory RowDetailState.initial() => RowDetailState(

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

@@ -14,7 +14,7 @@ part 'row_service.freezed.dart';
 
 typedef RowUpdateCallback = void Function();
 
-abstract class GridRowCacheDelegate {
+abstract class GridRowCacheFieldNotifier {
   UnmodifiableListView<Field> get fields;
   void onFieldsChanged(VoidCallback callback);
   void onFieldChanged(void Function(Field) callback);
@@ -27,7 +27,7 @@ class GridRowsCache {
   final _Notifier _notifier;
   List<GridRow> _rows = [];
   final HashMap<String, Row> _rowByRowId;
-  final GridRowCacheDelegate _delegate;
+  final GridRowCacheFieldNotifier _fieldNotifier;
   final GridCellsCache _cellCache;
 
   List<GridRow> get rows => _rows;
@@ -36,19 +36,19 @@ class GridRowsCache {
   GridRowsCache({
     required this.gridId,
     required this.block,
-    required GridRowCacheDelegate delegate,
+    required GridRowCacheFieldNotifier notifier,
   })  : _cellCache = GridCellsCache(gridId: gridId),
         _rowByRowId = HashMap(),
         _notifier = _Notifier(),
-        _delegate = delegate {
+        _fieldNotifier = notifier {
     //
-    delegate.onFieldsChanged(() => _notifier.receive(const GridRowChangeReason.fieldDidChange()));
-    delegate.onFieldChanged((field) => _cellCache.remove(field.id));
+    notifier.onFieldsChanged(() => _notifier.receive(const GridRowChangeReason.fieldDidChange()));
+    notifier.onFieldChanged((field) => _cellCache.remove(field.id));
     _rows = block.rowInfos.map((rowInfo) => buildGridRow(rowInfo.rowId, rowInfo.height.toDouble())).toList();
   }
 
   Future<void> dispose() async {
-    _delegate.dispose();
+    _fieldNotifier.dispose();
     _notifier.dispose();
     await _cellCache.dispose();
   }
@@ -195,9 +195,9 @@ class GridRowsCache {
 
   GridCellMap _makeGridCells(String rowId, Row? row) {
     var cellDataMap = GridCellMap.new();
-    for (final field in _delegate.fields) {
+    for (final field in _fieldNotifier.fields) {
       if (field.visibility) {
-        cellDataMap[field.id] = GridCell(
+        cellDataMap[field.id] = GridCellIdentifier(
           rowId: rowId,
           gridId: gridId,
           field: field,
@@ -236,7 +236,7 @@ class GridRowsCache {
     return GridRow(
       gridId: gridId,
       blockId: block.id,
-      fields: _delegate.fields,
+      fields: _fieldNotifier.fields,
       rowId: rowId,
       height: rowHeight,
     );

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

@@ -21,15 +21,13 @@ class GridCellBuilder {
     required this.fieldCache,
   });
 
-  GridCellWidget build(GridCell cell, {GridCellStyle? style}) {
-    final key = ValueKey(cell.cellId());
-
+  GridCellWidget build(GridCellIdentifier cell, {GridCellStyle? style}) {
     final cellControllerBuilder = GridCellControllerBuilder(
       gridCell: cell,
       cellCache: cellCache,
       fieldCache: fieldCache,
     );
-
+    final key = cell.key();
     switch (cell.field.fieldType) {
       case FieldType.Checkbox:
         return CheckboxCell(cellControllerBuilder: cellControllerBuilder, key: key);

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

@@ -80,7 +80,7 @@ class _DateCellState extends GridCellState<DateCell> {
     final calendar = DateCellEditor(onDismissed: () => widget.onCellEditing.value = false);
     calendar.show(
       context,
-      cellContext: bloc.cellContext.clone(),
+      cellController: bloc.cellContext.clone(),
     );
   }
 

+ 5 - 5
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart

@@ -31,16 +31,16 @@ class DateCellEditor with FlowyOverlayDelegate {
 
   Future<void> show(
     BuildContext context, {
-    required GridDateCellController cellContext,
+    required GridDateCellController cellController,
   }) async {
     DateCellEditor.remove(context);
 
-    final result = await cellContext.getTypeOptionData();
+    final result = await cellController.getFieldTypeOption(DateTypeOptionDataParser());
     result.fold(
-      (data) {
+      (dateTypeOption) {
         final calendar = _CellCalendarWidget(
-          cellContext: cellContext,
-          dateTypeOption: DateTypeOption.fromBuffer(data.typeOptionData),
+          cellContext: cellController,
+          dateTypeOption: dateTypeOption,
         );
 
         FlowyOverlay.of(context).insertWithAnchor(

+ 4 - 4
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart

@@ -7,9 +7,9 @@ import 'dart:async';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 class URLCellEditor extends StatefulWidget with FlowyOverlayDelegate {
-  final GridURLCellController cellContext;
+  final GridURLCellController cellController;
   final VoidCallback completed;
-  const URLCellEditor({required this.cellContext, required this.completed, Key? key}) : super(key: key);
+  const URLCellEditor({required this.cellController, required this.completed, Key? key}) : super(key: key);
 
   @override
   State<URLCellEditor> createState() => _URLCellEditorState();
@@ -21,7 +21,7 @@ class URLCellEditor extends StatefulWidget with FlowyOverlayDelegate {
   ) {
     FlowyOverlay.of(context).remove(identifier());
     final editor = URLCellEditor(
-      cellContext: cellContext,
+      cellController: cellContext,
       completed: completed,
     );
 
@@ -62,7 +62,7 @@ class _URLCellEditorState extends State<URLCellEditor> {
 
   @override
   void initState() {
-    _cellBloc = URLCellEditorBloc(cellContext: widget.cellContext);
+    _cellBloc = URLCellEditorBloc(cellContext: widget.cellController);
     _cellBloc.add(const URLCellEditorEvent.initial());
     _controller = TextEditingController(text: _cellBloc.state.content);
 

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

@@ -187,7 +187,7 @@ class _CopyURLAccessory extends StatelessWidget with GridCellAccessory {
 
   @override
   void onTap() {
-    final content = cellContext.getCellData(loadIfNoCache: false)?.content ?? "";
+    final content = cellContext.getCellData(loadIfNotExist: false)?.content ?? "";
     Clipboard.setData(ClipboardData(text: content));
     showMessageToast(LocaleKeys.grid_row_copyProperty.tr());
   }

+ 5 - 5
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/builder.dart

@@ -51,13 +51,13 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
     case FieldType.Checkbox:
       final context = CheckboxTypeOptionContext(
         fieldContext: fieldContext,
-        dataBuilder: CheckboxTypeOptionWidgetDataParser(),
+        dataParser: CheckboxTypeOptionWidgetDataParser(),
       );
       return CheckboxTypeOptionWidgetBuilder(context);
     case FieldType.DateTime:
       final context = DateTypeOptionContext(
         fieldContext: fieldContext,
-        dataBuilder: DateTypeOptionDataParser(),
+        dataParser: DateTypeOptionDataParser(),
       );
       return DateTypeOptionWidgetBuilder(
         context,
@@ -84,7 +84,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
     case FieldType.Number:
       final context = NumberTypeOptionContext(
         fieldContext: fieldContext,
-        dataBuilder: NumberTypeOptionWidgetDataParser(),
+        dataParser: NumberTypeOptionWidgetDataParser(),
       );
       return NumberTypeOptionWidgetBuilder(
         context,
@@ -93,14 +93,14 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder(
     case FieldType.RichText:
       final context = RichTextTypeOptionContext(
         fieldContext: fieldContext,
-        dataBuilder: RichTextTypeOptionWidgetDataParser(),
+        dataParser: RichTextTypeOptionWidgetDataParser(),
       );
       return RichTextTypeOptionWidgetBuilder(context);
 
     case FieldType.URL:
       final context = URLTypeOptionContext(
         fieldContext: fieldContext,
-        dataBuilder: URLTypeOptionWidgetDataParser(),
+        dataParser: URLTypeOptionWidgetDataParser(),
       );
       return URLTypeOptionWidgetBuilder(context);
   }

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/checkbox.dart

@@ -5,7 +5,7 @@ import 'builder.dart';
 
 typedef CheckboxTypeOptionContext = TypeOptionWidgetContext<CheckboxTypeOption>;
 
-class CheckboxTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<CheckboxTypeOption> {
+class CheckboxTypeOptionWidgetDataParser extends TypeOptionDataParser<CheckboxTypeOption> {
   @override
   CheckboxTypeOption fromBuffer(List<int> buffer) {
     return CheckboxTypeOption.fromBuffer(buffer);

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/rich_text.dart

@@ -5,7 +5,7 @@ import 'builder.dart';
 
 typedef RichTextTypeOptionContext = TypeOptionWidgetContext<RichTextTypeOption>;
 
-class RichTextTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<RichTextTypeOption> {
+class RichTextTypeOptionWidgetDataParser extends TypeOptionDataParser<RichTextTypeOption> {
   @override
   RichTextTypeOption fromBuffer(List<int> buffer) {
     return RichTextTypeOption.fromBuffer(buffer);

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/url.dart

@@ -5,7 +5,7 @@ import 'builder.dart';
 
 typedef URLTypeOptionContext = TypeOptionWidgetContext<URLTypeOption>;
 
-class URLTypeOptionWidgetDataParser extends TypeOptionWidgetDataParser<URLTypeOption> {
+class URLTypeOptionWidgetDataParser extends TypeOptionDataParser<URLTypeOption> {
   @override
   URLTypeOption fromBuffer(List<int> buffer) {
     return URLTypeOption.fromBuffer(buffer);

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

@@ -137,7 +137,7 @@ class _PropertyList extends StatelessWidget {
 }
 
 class _RowDetailCell extends StatelessWidget {
-  final GridCell gridCell;
+  final GridCellIdentifier gridCell;
   final GridCellBuilder cellBuilder;
   const _RowDetailCell({
     required this.gridCell,