diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 0cf248e7e4..bd9c259575 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -153,31 +153,31 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => TextCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => SelectOptionCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => NumberCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (context, _) => DateCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam( + getIt.registerFactoryParam( (cellData, _) => CheckboxCellBloc( service: CellService(), cellContext: cellData, diff --git a/frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart b/frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart index 3fb734db70..a531e65d2e 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/block/block_service.dart @@ -9,18 +9,18 @@ import 'block_listener.dart'; class GridBlockCacheService { final String gridId; final GridBlock block; - late GridRowCacheService _rowCache; + late GridRowsCache _rowCache; late GridBlockListener _listener; List get rows => _rowCache.rows; - GridRowCacheService get rowCache => _rowCache; + GridRowsCache get rowCache => _rowCache; GridBlockCacheService({ required this.gridId, required this.block, required GridFieldCache fieldCache, }) { - _rowCache = GridRowCacheService( + _rowCache = GridRowsCache( gridId: gridId, block: block, delegate: GridRowCacheDelegateImpl(fieldCache), diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cache.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cache.dart index ccf47fddb3..a6079bae6d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cache.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cache.dart @@ -2,79 +2,38 @@ part of 'cell_service.dart'; typedef GridCellMap = LinkedHashMap; -class _GridCellCacheObject { - _GridCellCacheKey key; +class _GridCellCacheItem { + GridCellId key; dynamic object; - _GridCellCacheObject({ + _GridCellCacheItem({ required this.key, required this.object, }); } -class _GridCellCacheKey { +class GridCellId { final String fieldId; final String rowId; - _GridCellCacheKey({ + GridCellId({ required this.fieldId, required this.rowId, }); } -abstract class GridCellCacheDelegate { - void onFieldUpdated(void Function(Field) callback); -} - -class GridCellCacheService { +class GridCellsCache { final String gridId; - final GridCellCacheDelegate delegate; - - /// fieldId: {objectId: callback} - final Map>> _fieldListenerByFieldId = {}; /// fieldId: {cacheKey: cacheData} final Map> _cellDataByFieldId = {}; - GridCellCacheService({ + GridCellsCache({ required this.gridId, - required this.delegate, - }) { - delegate.onFieldUpdated((field) { - _cellDataByFieldId.remove(field.id); - final map = _fieldListenerByFieldId[field.id]; - if (map != null) { - for (final callbacks in map.values) { - for (final callback in callbacks) { - callback(); - } - } - } - }); + }); + + void remove(String fieldId) { + _cellDataByFieldId.remove(fieldId); } - void addFieldListener(_GridCellCacheKey cacheKey, VoidCallback onFieldChanged) { - var map = _fieldListenerByFieldId[cacheKey.fieldId]; - if (map == null) { - _fieldListenerByFieldId[cacheKey.fieldId] = {}; - map = _fieldListenerByFieldId[cacheKey.fieldId]; - map![cacheKey.rowId] = [onFieldChanged]; - } else { - var objects = map[cacheKey.rowId]; - if (objects == null) { - map[cacheKey.rowId] = [onFieldChanged]; - } else { - objects.add(onFieldChanged); - } - } - } - - void removeFieldListener(_GridCellCacheKey cacheKey, VoidCallback fn) { - var callbacks = _fieldListenerByFieldId[cacheKey.fieldId]?[cacheKey.rowId]; - final index = callbacks?.indexWhere((callback) => callback == fn); - if (index != null && index != -1) { - callbacks?.removeAt(index); - } - } - - void insert(T item) { + void insert(T item) { var map = _cellDataByFieldId[item.key.fieldId]; if (map == null) { _cellDataByFieldId[item.key.fieldId] = {}; @@ -84,7 +43,7 @@ class GridCellCacheService { map![item.key.rowId] = item.object; } - T? get(_GridCellCacheKey key) { + T? get(GridCellId key) { final map = _cellDataByFieldId[key.fieldId]; if (map == null) { return null; @@ -103,7 +62,6 @@ class GridCellCacheService { } Future dispose() async { - _fieldListenerByFieldId.clear(); _cellDataByFieldId.clear(); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart index 676e3f66d0..95b7b77b61 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_loader.dart @@ -3,23 +3,13 @@ part of 'cell_service.dart'; abstract class IGridCellDataConfig { // The cell data will reload if it receives the field's change notification. bool get reloadOnFieldChanged; - - // When the reloadOnCellChanged is true, it will load the cell data after user input. - // For example: The number cell reload the cell data that carries the format - // user input: 12 - // cell display: $12 - bool get reloadOnCellChanged; } class GridCellDataConfig implements IGridCellDataConfig { - @override - final bool reloadOnCellChanged; - @override final bool reloadOnFieldChanged; const GridCellDataConfig({ - this.reloadOnCellChanged = false, this.reloadOnFieldChanged = false, }); } @@ -72,29 +62,6 @@ class GridCellDataLoader extends IGridCellDataLoader { } } -class SelectOptionCellDataLoader extends IGridCellDataLoader { - final SelectOptionService service; - final GridCell gridCell; - SelectOptionCellDataLoader({ - required this.gridCell, - }) : service = SelectOptionService(gridCell: gridCell); - @override - Future loadData() async { - return service.getOpitonContext().then((result) { - return result.fold( - (data) => data, - (err) { - Log.error(err); - return null; - }, - ); - }); - } - - @override - IGridCellDataConfig get config => const GridCellDataConfig(reloadOnFieldChanged: true); -} - class StringCellDataParser implements ICellDataParser { @override String? parserData(List data) { diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart index 2ad217e062..9e2f577d7c 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_data_persistence.dart @@ -1,10 +1,10 @@ part of 'cell_service.dart'; -abstract class _GridCellDataPersistence { +abstract class IGridCellDataPersistence { Future> save(D data); } -class CellDataPersistence implements _GridCellDataPersistence { +class CellDataPersistence implements IGridCellDataPersistence { final GridCell gridCell; CellDataPersistence({ @@ -35,7 +35,7 @@ class CalendarData with _$CalendarData { const factory CalendarData({required DateTime date, String? time}) = _CalendarData; } -class DateCellDataPersistence implements _GridCellDataPersistence { +class DateCellDataPersistence implements IGridCellDataPersistence { final GridCell gridCell; DateCellDataPersistence({ required this.gridCell, diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_field_notifier.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_field_notifier.dart new file mode 100644 index 0000000000..1c043e2096 --- /dev/null +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_field_notifier.dart @@ -0,0 +1,57 @@ +import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:flutter/foundation.dart'; + +import 'cell_service.dart'; + +abstract class GridFieldChangedNotifier { + void onFieldChanged(void Function(Field) callback); + void dispose(); +} + +class GridCellFieldNotifier { + /// fieldId: {objectId: callback} + final Map>> _fieldListenerByFieldId = {}; + + GridCellFieldNotifier({required GridFieldChangedNotifier notifier}) { + notifier.onFieldChanged( + (field) { + final map = _fieldListenerByFieldId[field.id]; + if (map != null) { + for (final callbacks in map.values) { + for (final callback in callbacks) { + callback(); + } + } + } + }, + ); + } + + void addFieldListener(GridCellId cacheKey, VoidCallback onFieldChanged) { + var map = _fieldListenerByFieldId[cacheKey.fieldId]; + if (map == null) { + _fieldListenerByFieldId[cacheKey.fieldId] = {}; + map = _fieldListenerByFieldId[cacheKey.fieldId]; + map![cacheKey.rowId] = [onFieldChanged]; + } else { + var objects = map[cacheKey.rowId]; + if (objects == null) { + map[cacheKey.rowId] = [onFieldChanged]; + } else { + objects.add(onFieldChanged); + } + } + } + + void removeFieldListener(GridCellId cacheKey, VoidCallback fn) { + var callbacks = _fieldListenerByFieldId[cacheKey.fieldId]?[cacheKey.rowId]; + final index = callbacks?.indexWhere((callback) => callback == fn); + if (index != null && index != -1) { + callbacks?.removeAt(index); + } + } + + Future dispose() async { + _fieldListenerByFieldId.clear(); + } +} diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart index 5e406c0c26..6c7791af92 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/cell_service.dart @@ -1,6 +1,7 @@ import 'dart:async'; import 'dart:collection'; +import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:dartz/dartz.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; @@ -14,9 +15,10 @@ import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart'; -import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart'; import 'package:app_flowy/workspace/application/grid/field/field_service.dart'; import 'dart:convert' show utf8; + +import 'cell_field_notifier.dart'; part 'cell_service.freezed.dart'; part 'cell_data_loader.dart'; part 'context_builder.dart'; diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart index 00264ad4b0..f45520c602 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service/context_builder.dart @@ -1,30 +1,35 @@ part of 'cell_service.dart'; -typedef GridCellContext = _GridCellContext; -typedef GridSelectOptionCellContext = _GridCellContext; -typedef GridDateCellContext = _GridCellContext; -typedef GridURLCellContext = _GridCellContext; +typedef GridCellController = IGridCellController; +typedef GridSelectOptionCellController = IGridCellController; +typedef GridDateCellController = IGridCellController; +typedef GridURLCellController = IGridCellController; -class GridCellContextBuilder { - final GridCellCacheService _cellCache; +class GridCellControllerBuilder { final GridCell _gridCell; - GridCellContextBuilder({ - required GridCellCacheService cellCache, - required GridCell gridCell, - }) : _cellCache = cellCache, + final GridCellsCache _cellCache; + final GridFieldCache _fieldCache; + + GridCellControllerBuilder( + {required GridCell gridCell, required GridCellsCache cellCache, required GridFieldCache fieldCache}) + : _cellCache = cellCache, + _fieldCache = fieldCache, _gridCell = gridCell; - _GridCellContext build() { + IGridCellController build() { + final cellFieldNotifier = GridCellFieldNotifier(notifier: _GridFieldChangedNotifierImpl(_fieldCache)); + switch (_gridCell.field.fieldType) { case FieldType.Checkbox: final cellDataLoader = GridCellDataLoader( gridCell: _gridCell, parser: StringCellDataParser(), ); - return GridCellContext( + return GridCellController( gridCell: _gridCell, cellCache: _cellCache, cellDataLoader: cellDataLoader, + cellFieldNotifier: cellFieldNotifier, cellDataPersistence: CellDataPersistence(gridCell: _gridCell), ); case FieldType.DateTime: @@ -34,22 +39,24 @@ class GridCellContextBuilder { config: const GridCellDataConfig(reloadOnFieldChanged: true), ); - return GridDateCellContext( + return GridDateCellController( gridCell: _gridCell, cellCache: _cellCache, cellDataLoader: cellDataLoader, + cellFieldNotifier: cellFieldNotifier, cellDataPersistence: DateCellDataPersistence(gridCell: _gridCell), ); case FieldType.Number: final cellDataLoader = GridCellDataLoader( gridCell: _gridCell, parser: StringCellDataParser(), - config: const GridCellDataConfig(reloadOnCellChanged: true, reloadOnFieldChanged: true), + config: const GridCellDataConfig(reloadOnFieldChanged: true), ); - return GridCellContext( + return GridCellController( gridCell: _gridCell, cellCache: _cellCache, cellDataLoader: cellDataLoader, + cellFieldNotifier: cellFieldNotifier, cellDataPersistence: CellDataPersistence(gridCell: _gridCell), ); case FieldType.RichText: @@ -57,10 +64,11 @@ class GridCellContextBuilder { gridCell: _gridCell, parser: StringCellDataParser(), ); - return GridCellContext( + return GridCellController( gridCell: _gridCell, cellCache: _cellCache, cellDataLoader: cellDataLoader, + cellFieldNotifier: cellFieldNotifier, cellDataPersistence: CellDataPersistence(gridCell: _gridCell), ); case FieldType.MultiSelect: @@ -71,10 +79,11 @@ class GridCellContextBuilder { config: const GridCellDataConfig(reloadOnFieldChanged: true), ); - return GridSelectOptionCellContext( + return GridSelectOptionCellController( gridCell: _gridCell, cellCache: _cellCache, cellDataLoader: cellDataLoader, + cellFieldNotifier: cellFieldNotifier, cellDataPersistence: CellDataPersistence(gridCell: _gridCell), ); @@ -83,10 +92,11 @@ class GridCellContextBuilder { gridCell: _gridCell, parser: URLCellDataParser(), ); - return GridURLCellContext( + return GridURLCellController( gridCell: _gridCell, cellCache: _cellCache, cellDataLoader: cellDataLoader, + cellFieldNotifier: cellFieldNotifier, cellDataPersistence: CellDataPersistence(gridCell: _gridCell), ); } @@ -95,37 +105,48 @@ class GridCellContextBuilder { } // T: the type of the CellData -// D: the type of the data that will be save to disk +// D: the type of the data that will be saved to disk // ignore: must_be_immutable -class _GridCellContext extends Equatable { +class IGridCellController extends Equatable { final GridCell gridCell; - final GridCellCacheService cellCache; - final _GridCellCacheKey _cacheKey; - final IGridCellDataLoader cellDataLoader; - final _GridCellDataPersistence cellDataPersistence; + final GridCellsCache _cellsCache; + final GridCellId _cacheKey; final FieldService _fieldService; + final GridCellFieldNotifier _cellFieldNotifier; + // final GridCellFieldNotifier _fieldNotifier; + final IGridCellDataLoader _cellDataLoader; + final IGridCellDataPersistence _cellDataPersistence; late final CellListener _cellListener; - late final ValueNotifier? _cellDataNotifier; + ValueNotifier? _cellDataNotifier; + bool isListening = false; VoidCallback? _onFieldChangedFn; Timer? _loadDataOperation; Timer? _saveDataOperation; + bool isDispose = false; - _GridCellContext({ + IGridCellController({ required this.gridCell, - required this.cellCache, - required this.cellDataLoader, - required this.cellDataPersistence, - }) : _fieldService = FieldService(gridId: gridCell.gridId, fieldId: gridCell.field.id), - _cacheKey = _GridCellCacheKey(rowId: gridCell.rowId, fieldId: gridCell.field.id); + required GridCellsCache cellCache, + required GridCellFieldNotifier cellFieldNotifier, + required IGridCellDataLoader cellDataLoader, + required IGridCellDataPersistence cellDataPersistence, + // required GridFieldChangedNotifier notifierDelegate, + }) : _cellsCache = cellCache, + _cellDataLoader = cellDataLoader, + _cellDataPersistence = cellDataPersistence, + _cellFieldNotifier = cellFieldNotifier, + _fieldService = FieldService(gridId: gridCell.gridId, fieldId: gridCell.field.id), + _cacheKey = GridCellId(rowId: gridCell.rowId, fieldId: gridCell.field.id); - _GridCellContext clone() { - return _GridCellContext( + IGridCellController clone() { + return IGridCellController( gridCell: gridCell, - cellDataLoader: cellDataLoader, - cellCache: cellCache, - cellDataPersistence: cellDataPersistence); + cellDataLoader: _cellDataLoader, + cellCache: _cellsCache, + cellFieldNotifier: _cellFieldNotifier, + cellDataPersistence: _cellDataPersistence); } String get gridId => gridCell.gridId; @@ -140,15 +161,23 @@ class _GridCellContext extends Equatable { FieldType get fieldType => gridCell.field.fieldType; - VoidCallback? startListening({required void Function(T?) onCellChanged}) { + VoidCallback? startListening({required void Function(T?) onCellChanged, VoidCallback? onCellFieldChanged}) { if (isListening) { Log.error("Already started. It seems like you should call clone first"); return null; } - isListening = true; - _cellDataNotifier = ValueNotifier(cellCache.get(_cacheKey)); + + /// The cell data will be changed by two reasons: + /// 1. User edit the cell + /// 2. User edit the field + /// For example: The number cell reload the cell data that carries the format + /// user input: 12 + /// cell display: $12 + _cellDataNotifier = ValueNotifier(_cellsCache.get(_cacheKey)); _cellListener = CellListener(rowId: gridCell.rowId, fieldId: gridCell.field.id); + + /// 1.Listen on user edit event and load the new cell data if needed. _cellListener.start(onCellChanged: (result) { result.fold( (_) => _loadData(), @@ -156,21 +185,21 @@ class _GridCellContext extends Equatable { ); }); - if (cellDataLoader.config.reloadOnFieldChanged) { - _onFieldChangedFn = () { - _loadData(); - }; - cellCache.addFieldListener(_cacheKey, _onFieldChangedFn!); - } + /// 2.Listen on the field event and load the cell data if needed. + _onFieldChangedFn = () { + if (onCellFieldChanged != null) { + onCellFieldChanged(); + } - onCellChangedFn() { - onCellChanged(_cellDataNotifier?.value); - - if (cellDataLoader.config.reloadOnCellChanged) { + if (_cellDataLoader.config.reloadOnFieldChanged) { _loadData(); } - } + }; + _cellFieldNotifier.addFieldListener(_cacheKey, _onFieldChangedFn!); + + /// Notify the listener, the cell data was changed. + onCellChangedFn() => onCellChanged(_cellDataNotifier?.value); _cellDataNotifier?.addListener(onCellChangedFn); return onCellChangedFn; } @@ -180,7 +209,7 @@ class _GridCellContext extends Equatable { } T? getCellData({bool loadIfNoCache = true}) { - final data = cellCache.get(_cacheKey); + final data = _cellsCache.get(_cacheKey); if (data == null && loadIfNoCache) { _loadData(); } @@ -195,13 +224,13 @@ class _GridCellContext extends Equatable { if (deduplicate) { _loadDataOperation?.cancel(); _loadDataOperation = Timer(const Duration(milliseconds: 300), () async { - final result = await cellDataPersistence.save(data); + final result = await _cellDataPersistence.save(data); if (resultCallback != null) { resultCallback(result); } }); } else { - final result = await cellDataPersistence.save(data); + final result = await _cellDataPersistence.save(data); if (resultCallback != null) { resultCallback(result); } @@ -211,24 +240,55 @@ class _GridCellContext extends Equatable { void _loadData() { _loadDataOperation?.cancel(); _loadDataOperation = Timer(const Duration(milliseconds: 10), () { - cellDataLoader.loadData().then((data) { + _cellDataLoader.loadData().then((data) { _cellDataNotifier?.value = data; - cellCache.insert(_GridCellCacheObject(key: _cacheKey, object: data)); + _cellsCache.insert(_GridCellCacheItem(key: _cacheKey, object: data)); }); }); } void dispose() { + if (isDispose) { + Log.error("$this should only dispose once"); + return; + } + isDispose = true; _cellListener.stop(); _loadDataOperation?.cancel(); _saveDataOperation?.cancel(); + _cellDataNotifier = null; if (_onFieldChangedFn != null) { - cellCache.removeFieldListener(_cacheKey, _onFieldChangedFn!); + _cellFieldNotifier.removeFieldListener(_cacheKey, _onFieldChangedFn!); _onFieldChangedFn = null; } } @override - List get props => [cellCache.get(_cacheKey) ?? "", cellId]; + List get props => [_cellsCache.get(_cacheKey) ?? "", cellId]; +} + +class _GridFieldChangedNotifierImpl extends GridFieldChangedNotifier { + final GridFieldCache _cache; + FieldChangesetCallback? _onChangesetFn; + + _GridFieldChangedNotifierImpl(GridFieldCache cache) : _cache = cache; + + @override + void dispose() { + if (_onChangesetFn != null) { + _cache.removeListener(onChangsetListener: _onChangesetFn!); + _onChangesetFn = null; + } + } + + @override + void onFieldChanged(void Function(Field p1) callback) { + _onChangesetFn = (GridFieldChangeset changeset) { + for (final updatedField in changeset.updatedFields) { + callback(updatedField); + } + }; + _cache.addListener(onChangeset: _onChangesetFn); + } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart index b8e2b13bbc..041e687c9b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/checkbox_cell_bloc.dart @@ -6,7 +6,7 @@ import 'cell_service/cell_service.dart'; part 'checkbox_cell_bloc.freezed.dart'; class CheckboxCellBloc extends Bloc { - final GridCellContext cellContext; + final GridCellController cellContext; void Function()? _onCellChangedFn; CheckboxCellBloc({ @@ -67,7 +67,7 @@ class CheckboxCellState with _$CheckboxCellState { required bool isSelected, }) = _CheckboxCellState; - factory CheckboxCellState.initial(GridCellContext context) { + factory CheckboxCellState.initial(GridCellController context) { return CheckboxCellState(isSelected: _isSelected(context.getCellData())); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart index 28f8bf1b10..84a71f7d05 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cal_bloc.dart @@ -16,7 +16,7 @@ import 'package:fixnum/fixnum.dart' as $fixnum; part 'date_cal_bloc.freezed.dart'; class DateCalBloc extends Bloc { - final GridDateCellContext cellContext; + final GridDateCellController cellContext; void Function()? _onCellChangedFn; DateCalBloc({ diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart index 00780143cc..6e98091a90 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/date_cell_bloc.dart @@ -7,7 +7,7 @@ import 'cell_service/cell_service.dart'; part 'date_cell_bloc.freezed.dart'; class DateCellBloc extends Bloc { - final GridDateCellContext cellContext; + final GridDateCellController cellContext; void Function()? _onCellChangedFn; DateCellBloc({required this.cellContext}) : super(DateCellState.initial(cellContext)) { @@ -60,7 +60,7 @@ class DateCellState with _$DateCellState { required Field field, }) = _DateCellState; - factory DateCellState.initial(GridDateCellContext context) { + factory DateCellState.initial(GridDateCellController context) { final cellData = context.getCellData(); return DateCellState( diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart index adcfee71e6..65eec13e6c 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart @@ -8,7 +8,7 @@ import 'cell_service/cell_service.dart'; part 'number_cell_bloc.freezed.dart'; class NumberCellBloc extends Bloc { - final GridCellContext cellContext; + final GridCellController cellContext; void Function()? _onCellChangedFn; NumberCellBloc({ @@ -72,7 +72,7 @@ class NumberCellState with _$NumberCellState { required Either content, }) = _NumberCellState; - factory NumberCellState.initial(GridCellContext context) { + factory NumberCellState.initial(GridCellController context) { final cellContent = context.getCellData() ?? ""; return NumberCellState( content: left(cellContent), diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart index a6e140f707..a8a9a435e8 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_cell_bloc.dart @@ -7,7 +7,7 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_serv part 'select_option_cell_bloc.freezed.dart'; class SelectOptionCellBloc extends Bloc { - final GridSelectOptionCellContext cellContext; + final GridSelectOptionCellController cellContext; void Function()? _onCellChangedFn; SelectOptionCellBloc({ @@ -66,7 +66,7 @@ class SelectOptionCellState with _$SelectOptionCellState { required List selectedOptions, }) = _SelectOptionCellState; - factory SelectOptionCellState.initial(GridSelectOptionCellContext context) { + factory SelectOptionCellState.initial(GridSelectOptionCellController context) { final data = context.getCellData(); return SelectOptionCellState( diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart index 9ce003b154..139d29141b 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_editor_bloc.dart @@ -1,5 +1,4 @@ import 'dart:async'; -import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/select_option.pb.dart'; @@ -13,16 +12,13 @@ part 'select_option_editor_bloc.freezed.dart'; class SelectOptionCellEditorBloc extends Bloc { final SelectOptionService _selectOptionService; - final GridSelectOptionCellContext cellContext; - late final GridFieldsListener _fieldListener; - void Function()? _onCellChangedFn; + final GridSelectOptionCellController cellController; Timer? _delayOperation; SelectOptionCellEditorBloc({ - required this.cellContext, - }) : _selectOptionService = SelectOptionService(gridCell: cellContext.gridCell), - _fieldListener = GridFieldsListener(gridId: cellContext.gridId), - super(SelectOptionEditorState.initial(cellContext)) { + required this.cellController, + }) : _selectOptionService = SelectOptionService(gridCell: cellController.gridCell), + super(SelectOptionEditorState.initial(cellController)) { on( (event, emit) async { await event.map( @@ -64,13 +60,8 @@ class SelectOptionCellEditorBloc extends Bloc close() async { - if (_onCellChangedFn != null) { - cellContext.removeListener(_onCellChangedFn!); - _onCellChangedFn = null; - } _delayOperation?.cancel(); - await _fieldListener.stop(); - cellContext.dispose(); + cellController.dispose(); return super.close(); } @@ -157,24 +148,16 @@ class SelectOptionCellEditorBloc extends Bloc Log.error(err), - ); - }); } } @@ -200,7 +183,7 @@ class SelectOptionEditorState with _$SelectOptionEditorState { required Option filter, }) = _SelectOptionEditorState; - factory SelectOptionEditorState.initial(GridSelectOptionCellContext context) { + factory SelectOptionEditorState.initial(GridSelectOptionCellController context) { final data = context.getCellData(loadIfNoCache: false); return SelectOptionEditorState( options: data?.options ?? [], diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart index e3b7fd2dca..783564b5fa 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/text_cell_bloc.dart @@ -6,7 +6,7 @@ import 'cell_service/cell_service.dart'; part 'text_cell_bloc.freezed.dart'; class TextCellBloc extends Bloc { - final GridCellContext cellContext; + final GridCellController cellContext; void Function()? _onCellChangedFn; TextCellBloc({ required this.cellContext, @@ -63,7 +63,7 @@ class TextCellState with _$TextCellState { required String content, }) = _TextCellState; - factory TextCellState.initial(GridCellContext context) => TextCellState( + factory TextCellState.initial(GridCellController context) => TextCellState( content: context.getCellData() ?? "", ); } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart index e1fe39c3bf..3811c90ea5 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_bloc.dart @@ -7,7 +7,7 @@ import 'cell_service/cell_service.dart'; part 'url_cell_bloc.freezed.dart'; class URLCellBloc extends Bloc { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; void Function()? _onCellChangedFn; URLCellBloc({ required this.cellContext, @@ -67,7 +67,7 @@ class URLCellState with _$URLCellState { required String url, }) = _URLCellState; - factory URLCellState.initial(GridURLCellContext context) { + factory URLCellState.initial(GridURLCellController context) { final cellData = context.getCellData(); return URLCellState( content: cellData?.content ?? "", diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_editor_bloc.dart index 6e4990943f..59435b6a38 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/url_cell_editor_bloc.dart @@ -7,7 +7,7 @@ import 'cell_service/cell_service.dart'; part 'url_cell_editor_bloc.freezed.dart'; class URLCellEditorBloc extends Bloc { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; void Function()? _onCellChangedFn; URLCellEditorBloc({ required this.cellContext, @@ -64,7 +64,7 @@ class URLCellEditorState with _$URLCellEditorState { required String content, }) = _URLCellEditorState; - factory URLCellEditorState.initial(GridURLCellContext context) { + factory URLCellEditorState.initial(GridURLCellController context) { final cellData = context.getCellData(); return URLCellEditorState( content: cellData?.content ?? "", diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart index 49e90b6a9e..e6fff41317 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_bloc.dart @@ -68,7 +68,7 @@ class GridBloc extends Bloc { return super.close(); } - GridRowCacheService? getRowCache(String blockId, String rowId) { + GridRowsCache? getRowCache(String blockId, String rowId) { final GridBlockCacheService? blockCache = _blocks[blockId]; return blockCache?.rowCache; } diff --git a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart index 391a5d13a2..3e9cbc2eee 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -202,7 +202,7 @@ class GridRowCacheDelegateImpl extends GridRowCacheDelegate { } @override - void onFieldUpdated(void Function(Field) callback) { + void onFieldChanged(void Function(Field) callback) { _onChangesetFn = (GridFieldChangeset changeset) { for (final updatedField in changeset.updatedFields) { callback(updatedField); diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart index 7f565b500a..5af7c02a5d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_bloc.dart @@ -11,12 +11,12 @@ part 'row_bloc.freezed.dart'; class RowBloc extends Bloc { final RowService _rowService; - final GridRowCacheService _rowCache; + final GridRowsCache _rowCache; void Function()? _rowListenFn; RowBloc({ required GridRow rowData, - required GridRowCacheService rowCache, + required GridRowsCache rowCache, }) : _rowService = RowService( gridId: rowData.gridId, blockId: rowData.blockId, diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart index f17f0f4cb6..0613b388a4 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_detail_bloc.dart @@ -8,12 +8,12 @@ part 'row_detail_bloc.freezed.dart'; class RowDetailBloc extends Bloc { final GridRow rowData; - final GridRowCacheService _rowCache; + final GridRowsCache _rowCache; void Function()? _rowListenFn; RowDetailBloc({ required this.rowData, - required GridRowCacheService rowCache, + required GridRowsCache rowCache, }) : _rowCache = rowCache, super(RowDetailState.initial()) { on( diff --git a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart index 78e4e6715f..27749083b4 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart @@ -1,5 +1,4 @@ import 'dart:collection'; - import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; @@ -15,34 +14,36 @@ part 'row_service.freezed.dart'; typedef RowUpdateCallback = void Function(); -abstract class GridRowCacheDelegate with GridCellCacheDelegate { +abstract class GridRowCacheDelegate { UnmodifiableListView get fields; - void onFieldsChanged(void Function() callback); + void onFieldsChanged(VoidCallback callback); + void onFieldChanged(void Function(Field) callback); void dispose(); } -class GridRowCacheService { +class GridRowsCache { final String gridId; final GridBlock block; final _Notifier _notifier; List _rows = []; final HashMap _rowByRowId; final GridRowCacheDelegate _delegate; - final GridCellCacheService _cellCache; + final GridCellsCache _cellCache; List get rows => _rows; - GridCellCacheService get cellCache => _cellCache; + GridCellsCache get cellCache => _cellCache; - GridRowCacheService({ + GridRowsCache({ required this.gridId, required this.block, required GridRowCacheDelegate delegate, - }) : _cellCache = GridCellCacheService(gridId: gridId, delegate: delegate), + }) : _cellCache = GridCellsCache(gridId: gridId), _rowByRowId = HashMap(), _notifier = _Notifier(), _delegate = delegate { // delegate.onFieldsChanged(() => _notifier.receive(const GridRowChangeReason.fieldDidChange())); + delegate.onFieldChanged((field) => _cellCache.remove(field.id)); _rows = block.rowInfos.map((rowInfo) => buildGridRow(rowInfo.rowId, rowInfo.height.toDouble())).toList(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart index 6daf2c50fa..6b980e468f 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart @@ -228,12 +228,14 @@ class _GridRowsState extends State<_GridRows> { Animation animation, ) { final rowCache = context.read().getRowCache(rowData.blockId, rowData.rowId); + final fieldCache = context.read().fieldCache; if (rowCache != null) { return SizeTransition( sizeFactor: animation, child: GridRowWidget( rowData: rowData, rowCache: rowCache, + fieldCache: fieldCache, key: ValueKey(rowData.rowId), ), ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart index 9f3c7a632e..a17384dd59 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_builder.dart @@ -1,4 +1,5 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -12,28 +13,41 @@ import 'select_option_cell/select_option_cell.dart'; import 'text_cell.dart'; import 'url_cell/url_cell.dart'; -GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCacheService cellCache, {GridCellStyle? style}) { - final key = ValueKey(gridCell.cellId()); +class GridCellBuilder { + final GridCellsCache cellCache; + final GridFieldCache fieldCache; + GridCellBuilder({ + required this.cellCache, + required this.fieldCache, + }); - final cellContextBuilder = GridCellContextBuilder(gridCell: gridCell, cellCache: cellCache); + GridCellWidget build(GridCell cell, {GridCellStyle? style}) { + final key = ValueKey(cell.cellId()); - switch (gridCell.field.fieldType) { - case FieldType.Checkbox: - return CheckboxCell(cellContextBuilder: cellContextBuilder, key: key); - case FieldType.DateTime: - return DateCell(cellContextBuilder: cellContextBuilder, key: key, style: style); - case FieldType.SingleSelect: - return SingleSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key); - case FieldType.MultiSelect: - return MultiSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key); - case FieldType.Number: - return NumberCell(cellContextBuilder: cellContextBuilder, key: key); - case FieldType.RichText: - return GridTextCell(cellContextBuilder: cellContextBuilder, style: style, key: key); - case FieldType.URL: - return GridURLCell(cellContextBuilder: cellContextBuilder, style: style, key: key); + final cellControllerBuilder = GridCellControllerBuilder( + gridCell: cell, + cellCache: cellCache, + fieldCache: fieldCache, + ); + + switch (cell.field.fieldType) { + case FieldType.Checkbox: + return CheckboxCell(cellControllerBuilder: cellControllerBuilder, key: key); + case FieldType.DateTime: + return DateCell(cellControllerBuilder: cellControllerBuilder, key: key, style: style); + case FieldType.SingleSelect: + return SingleSelectCell(cellContorllerBuilder: cellControllerBuilder, style: style, key: key); + case FieldType.MultiSelect: + return MultiSelectCell(cellContorllerBuilder: cellControllerBuilder, style: style, key: key); + case FieldType.Number: + return NumberCell(cellContorllerBuilder: cellControllerBuilder, key: key); + case FieldType.RichText: + return GridTextCell(cellContorllerBuilder: cellControllerBuilder, style: style, key: key); + case FieldType.URL: + return GridURLCell(cellContorllerBuilder: cellControllerBuilder, style: style, key: key); + } + throw UnimplementedError; } - throw UnimplementedError; } class BlankCell extends StatelessWidget { diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart index 384d85737f..ac2a2fb979 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/checkbox_cell.dart @@ -7,9 +7,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; class CheckboxCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellControllerBuilder; CheckboxCell({ - required this.cellContextBuilder, + required this.cellControllerBuilder, Key? key, }) : super(key: key); @@ -22,7 +22,7 @@ class _CheckboxCellState extends GridCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build(); + final cellContext = widget.cellControllerBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const CheckboxCellEvent.initial()); super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart index 3e7d40c796..efcb107e55 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_cell.dart @@ -19,12 +19,12 @@ abstract class GridCellDelegate { } class DateCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellControllerBuilder; late final DateCellStyle? cellStyle; DateCell({ GridCellStyle? style, - required this.cellContextBuilder, + required this.cellControllerBuilder, Key? key, }) : super(key: key) { if (style != null) { @@ -43,7 +43,7 @@ class _DateCellState extends GridCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build(); + final cellContext = widget.cellControllerBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const DateCellEvent.initial()); super.initState(); } diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart index 93d304cd1a..5dcd552fef 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/date_cell/date_editor.dart @@ -31,7 +31,7 @@ class DateCellEditor with FlowyOverlayDelegate { Future show( BuildContext context, { - required GridDateCellContext cellContext, + required GridDateCellController cellContext, }) async { DateCellEditor.remove(context); @@ -75,7 +75,7 @@ class DateCellEditor with FlowyOverlayDelegate { } class _CellCalendarWidget extends StatelessWidget { - final GridDateCellContext cellContext; + final GridDateCellController cellContext; final DateTypeOption dateTypeOption; const _CellCalendarWidget({ diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart index 7d16b16ef0..6b1cf4ceae 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart @@ -7,10 +7,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'cell_builder.dart'; class NumberCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; NumberCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, Key? key, }) : super(key: key); @@ -25,7 +25,7 @@ class _NumberCellState extends GridFocusNodeCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build(); + final cellContext = widget.cellContorllerBuilder.build(); _cellBloc = getIt(param1: cellContext)..add(const NumberCellEvent.initial()); _controller = TextEditingController(text: contentFromState(_cellBloc.state)); super.initState(); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart index 63f7e0fc28..4068507f5a 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_cell.dart @@ -21,11 +21,11 @@ class SelectOptionCellStyle extends GridCellStyle { } class SingleSelectCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; late final SelectOptionCellStyle? cellStyle; SingleSelectCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, GridCellStyle? style, Key? key, }) : super(key: key) { @@ -45,7 +45,7 @@ class _SingleSelectCellState extends State { @override void initState() { - final cellContext = widget.cellContextBuilder.build() as GridSelectOptionCellContext; + final cellContext = widget.cellContorllerBuilder.build() as GridSelectOptionCellController; _cellBloc = getIt(param1: cellContext)..add(const SelectOptionCellEvent.initial()); super.initState(); } @@ -60,7 +60,7 @@ class _SingleSelectCellState extends State { selectOptions: state.selectedOptions, cellStyle: widget.cellStyle, onFocus: (value) => widget.onCellEditing.value = value, - cellContextBuilder: widget.cellContextBuilder); + cellContorllerBuilder: widget.cellContorllerBuilder); }, ), ); @@ -75,11 +75,11 @@ class _SingleSelectCellState extends State { //---------------------------------------------------------------- class MultiSelectCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; late final SelectOptionCellStyle? cellStyle; MultiSelectCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, GridCellStyle? style, Key? key, }) : super(key: key) { @@ -99,7 +99,7 @@ class _MultiSelectCellState extends State { @override void initState() { - final cellContext = widget.cellContextBuilder.build() as GridSelectOptionCellContext; + final cellContext = widget.cellContorllerBuilder.build() as GridSelectOptionCellController; _cellBloc = getIt(param1: cellContext)..add(const SelectOptionCellEvent.initial()); super.initState(); } @@ -114,7 +114,7 @@ class _MultiSelectCellState extends State { selectOptions: state.selectedOptions, cellStyle: widget.cellStyle, onFocus: (value) => widget.onCellEditing.value = value, - cellContextBuilder: widget.cellContextBuilder); + cellContorllerBuilder: widget.cellContorllerBuilder); }, ), ); @@ -131,12 +131,12 @@ class _SelectOptionCell extends StatelessWidget { final List selectOptions; final void Function(bool) onFocus; final SelectOptionCellStyle? cellStyle; - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; const _SelectOptionCell({ required this.selectOptions, required this.onFocus, required this.cellStyle, - required this.cellContextBuilder, + required this.cellContorllerBuilder, Key? key, }) : super(key: key); @@ -172,7 +172,7 @@ class _SelectOptionCell extends StatelessWidget { InkWell( onTap: () { onFocus(true); - final cellContext = cellContextBuilder.build() as GridSelectOptionCellContext; + final cellContext = cellContorllerBuilder.build() as GridSelectOptionCellController; SelectOptionCellEditor.show(context, cellContext, () => onFocus(false)); }, ), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart index 76d9a379d7..45a641c39c 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/select_option_editor.dart @@ -24,11 +24,11 @@ import 'text_field.dart'; const double _editorPannelWidth = 300; class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { - final GridSelectOptionCellContext cellContext; + final GridSelectOptionCellController cellController; final VoidCallback onDismissed; const SelectOptionCellEditor({ - required this.cellContext, + required this.cellController, required this.onDismissed, Key? key, }) : super(key: key); @@ -37,7 +37,7 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { Widget build(BuildContext context) { return BlocProvider( create: (context) => SelectOptionCellEditorBloc( - cellContext: cellContext, + cellController: cellController, )..add(const SelectOptionEditorEvent.initial()), child: BlocBuilder( builder: (context, state) { @@ -59,12 +59,12 @@ class SelectOptionCellEditor extends StatelessWidget with FlowyOverlayDelegate { static void show( BuildContext context, - GridSelectOptionCellContext cellContext, + GridSelectOptionCellController cellContext, VoidCallback onDismissed, ) { SelectOptionCellEditor.remove(context); final editor = SelectOptionCellEditor( - cellContext: cellContext, + cellController: cellContext, onDismissed: onDismissed, ); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart index 1bece5a3d7..55bf757ba4 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/text_cell.dart @@ -14,10 +14,10 @@ class GridTextCellStyle extends GridCellStyle { } class GridTextCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; late final GridTextCellStyle? cellStyle; GridTextCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, GridCellStyle? style, Key? key, }) : super(key: key) { @@ -39,7 +39,7 @@ class _GridTextCellState extends GridFocusNodeCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build(); + final cellContext = widget.cellContorllerBuilder.build(); _cellBloc = getIt(param1: cellContext); _cellBloc.add(const TextCellEvent.initial()); _controller = TextEditingController(text: _cellBloc.state.content); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart index f4da18be86..f756bceb32 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/cell_editor.dart @@ -7,7 +7,7 @@ import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; class URLCellEditor extends StatefulWidget with FlowyOverlayDelegate { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; final VoidCallback completed; const URLCellEditor({required this.cellContext, required this.completed, Key? key}) : super(key: key); @@ -16,7 +16,7 @@ class URLCellEditor extends StatefulWidget with FlowyOverlayDelegate { static void show( BuildContext context, - GridURLCellContext cellContext, + GridURLCellController cellContext, VoidCallback completed, ) { FlowyOverlay.of(context).remove(identifier()); diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart index e37dca6632..0edb65a7dc 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/url_cell/url_cell.dart @@ -31,10 +31,10 @@ enum GridURLCellAccessoryType { } class GridURLCell extends GridCellWidget { - final GridCellContextBuilder cellContextBuilder; + final GridCellControllerBuilder cellContorllerBuilder; late final GridURLCellStyle? cellStyle; GridURLCell({ - required this.cellContextBuilder, + required this.cellContorllerBuilder, GridCellStyle? style, Key? key, }) : super(key: key) { @@ -51,11 +51,11 @@ class GridURLCell extends GridCellWidget { GridCellAccessory accessoryFromType(GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) { switch (ty) { case GridURLCellAccessoryType.edit: - final cellContext = cellContextBuilder.build() as GridURLCellContext; + final cellContext = cellContorllerBuilder.build() as GridURLCellController; return _EditURLAccessory(cellContext: cellContext, anchorContext: buildContext.anchorContext); case GridURLCellAccessoryType.copyURL: - final cellContext = cellContextBuilder.build() as GridURLCellContext; + final cellContext = cellContorllerBuilder.build() as GridURLCellController; return _CopyURLAccessory(cellContext: cellContext); } } @@ -83,7 +83,7 @@ class _GridURLCellState extends GridCellState { @override void initState() { - final cellContext = widget.cellContextBuilder.build() as GridURLCellContext; + final cellContext = widget.cellContorllerBuilder.build() as GridURLCellController; _cellBloc = URLCellBloc(cellContext: cellContext); _cellBloc.add(const URLCellEvent.initial()); super.initState(); @@ -132,7 +132,7 @@ class _GridURLCellState extends GridCellState { if (url.isNotEmpty && await canLaunchUrl(uri)) { await launchUrl(uri); } else { - final cellContext = widget.cellContextBuilder.build() as GridURLCellContext; + final cellContext = widget.cellContorllerBuilder.build() as GridURLCellController; widget.onCellEditing.value = true; URLCellEditor.show(context, cellContext, () { widget.onCellEditing.value = false; @@ -155,7 +155,7 @@ class _GridURLCellState extends GridCellState { } class _EditURLAccessory extends StatelessWidget with GridCellAccessory { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; final BuildContext anchorContext; const _EditURLAccessory({ required this.cellContext, @@ -176,7 +176,7 @@ class _EditURLAccessory extends StatelessWidget with GridCellAccessory { } class _CopyURLAccessory extends StatelessWidget with GridCellAccessory { - final GridURLCellContext cellContext; + final GridURLCellController cellContext; const _CopyURLAccessory({required this.cellContext, Key? key}) : super(key: key); @override diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart index de7f117d51..0e1c6a0041 100755 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart @@ -10,19 +10,25 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:provider/provider.dart'; -import 'row_action_sheet.dart'; +import 'row_action_sheet.dart'; import 'row_detail.dart'; class GridRowWidget extends StatefulWidget { final GridRow rowData; - final GridRowCacheService rowCache; + final GridRowsCache rowCache; + final GridCellBuilder cellBuilder; - const GridRowWidget({ + GridRowWidget({ required this.rowData, required this.rowCache, + required GridFieldCache fieldCache, Key? key, - }) : super(key: key); + }) : cellBuilder = GridCellBuilder( + cellCache: rowCache.cellCache, + fieldCache: fieldCache, + ), + super(key: key); @override State createState() => _GridRowWidgetState(); @@ -52,7 +58,11 @@ class _GridRowWidgetState extends State { return Row( children: [ const _RowLeading(), - Expanded(child: _RowCells(cellCache: widget.rowCache.cellCache, onExpand: () => _expandRow(context))), + Expanded( + child: _RowCells( + builder: widget.cellBuilder, + onExpand: () => _expandRow(context), + )), const _RowTrailing(), ], ); @@ -72,6 +82,7 @@ class _GridRowWidgetState extends State { final page = RowDetailPage( rowData: widget.rowData, rowCache: widget.rowCache, + cellBuilder: widget.cellBuilder, ); page.show(context); } @@ -146,9 +157,13 @@ class _DeleteRowButton extends StatelessWidget { } class _RowCells extends StatelessWidget { - final GridCellCacheService cellCache; final VoidCallback onExpand; - const _RowCells({required this.cellCache, required this.onExpand, Key? key}) : super(key: key); + final GridCellBuilder builder; + const _RowCells({ + required this.builder, + required this.onExpand, + Key? key, + }) : super(key: key); @override Widget build(BuildContext context) { @@ -169,8 +184,7 @@ class _RowCells extends StatelessWidget { List _makeCells(BuildContext context, GridCellMap gridCellMap) { return gridCellMap.values.map( (gridCell) { - final GridCellWidget child = buildGridCellWidget(gridCell, cellCache); - + final GridCellWidget child = builder.build(gridCell); accessoryBuilder(GridCellAccessoryBuildContext buildContext) { final builder = child.accessoryBuilder; List accessories = []; diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart index c4ccc32a1a..45dd63eb7f 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/row_detail.dart @@ -22,11 +22,13 @@ import 'package:flutter_bloc/flutter_bloc.dart'; class RowDetailPage extends StatefulWidget with FlowyOverlayDelegate { final GridRow rowData; - final GridRowCacheService rowCache; + final GridRowsCache rowCache; + final GridCellBuilder cellBuilder; const RowDetailPage({ required this.rowData, required this.rowCache, + required this.cellBuilder, Key? key, }) : super(key: key); @@ -74,7 +76,7 @@ class _RowDetailPageState extends State { children: const [Spacer(), _CloseButton()], ), ), - Expanded(child: _PropertyList(cellCache: widget.rowCache.cellCache)), + Expanded(child: _PropertyList(cellBuilder: widget.cellBuilder)), ], ), ), @@ -98,10 +100,10 @@ class _CloseButton extends StatelessWidget { } class _PropertyList extends StatelessWidget { - final GridCellCacheService cellCache; + final GridCellBuilder cellBuilder; final ScrollController _scrollController; _PropertyList({ - required this.cellCache, + required this.cellBuilder, Key? key, }) : _scrollController = ScrollController(), super(key: key); @@ -121,7 +123,7 @@ class _PropertyList extends StatelessWidget { itemBuilder: (BuildContext context, int index) { return _RowDetailCell( gridCell: state.gridCells[index], - cellCache: cellCache, + cellBuilder: cellBuilder, ); }, separatorBuilder: (BuildContext context, int index) { @@ -136,10 +138,10 @@ class _PropertyList extends StatelessWidget { class _RowDetailCell extends StatelessWidget { final GridCell gridCell; - final GridCellCacheService cellCache; + final GridCellBuilder cellBuilder; const _RowDetailCell({ required this.gridCell, - required this.cellCache, + required this.cellBuilder, Key? key, }) : super(key: key); @@ -147,7 +149,7 @@ class _RowDetailCell extends StatelessWidget { Widget build(BuildContext context) { final theme = context.watch(); final style = _customCellStyle(theme, gridCell.field.fieldType); - final cell = buildGridCellWidget(gridCell, cellCache, style: style); + final cell = cellBuilder.build(gridCell, style: style); final gesture = GestureDetector( behavior: HitTestBehavior.translucent,