diff --git a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart index d4ffebd117..b78bc86661 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_bloc.dart @@ -25,7 +25,8 @@ class BoardBloc extends Bloc { final MoveRowFFIService _rowService; LinkedHashMap groupControllers = LinkedHashMap(); - GridFieldCache get fieldCache => _gridDataController.fieldCache; + GridFieldController get fieldController => + _gridDataController.fieldController; String get gridId => _gridDataController.gridId; BoardBloc({required ViewPB view}) diff --git a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart index c78621b0a3..5435db2c3a 100644 --- a/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/board_data_controller.dart @@ -12,7 +12,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'board_listener.dart'; -typedef OnFieldsChanged = void Function(UnmodifiableListView); +typedef OnFieldsChanged = void Function(UnmodifiableListView); typedef OnGridChanged = void Function(GridPB); typedef DidLoadGroups = void Function(List); typedef OnUpdatedGroup = void Function(List); @@ -29,7 +29,7 @@ typedef OnError = void Function(FlowyError); class BoardDataController { final String gridId; final GridFFIService _gridFFIService; - final GridFieldCache fieldCache; + final GridFieldController fieldController; final BoardListener _listener; // key: the block id @@ -56,7 +56,7 @@ class BoardDataController { // ignore: prefer_collection_literals _blocks = LinkedHashMap(), _gridFFIService = GridFFIService(gridId: view.id), - fieldCache = GridFieldCache(gridId: view.id); + fieldController = GridFieldController(gridId: view.id); void addListener({ required OnGridChanged onGridChanged, @@ -75,7 +75,7 @@ class BoardDataController { _onRowsChanged = onRowsChanged; _onError = onError; - fieldCache.addListener(onFields: (fields) { + fieldController.addListener(onFields: (fields) { _onFieldsChanged?.call(UnmodifiableListView(fields)); }); @@ -113,16 +113,15 @@ class BoardDataController { () => result.fold( (grid) async { _onGridChanged?.call(grid); - - return await _loadFields(grid).then((result) { - return result.fold( - (l) { - _loadGroups(grid.blocks); - return left(l); - }, - (err) => right(err), - ); - }); + return await fieldController.loadFields(fieldIds: grid.fields).then( + (result) => result.fold( + (l) { + _loadGroups(grid.blocks); + return left(l); + }, + (err) => right(err), + ), + ); }, (err) => right(err), ), @@ -136,33 +135,19 @@ class BoardDataController { Future dispose() async { await _gridFFIService.closeGrid(); - await fieldCache.dispose(); + await fieldController.dispose(); for (final blockCache in _blocks.values) { blockCache.dispose(); } } - Future> _loadFields(GridPB grid) async { - final result = await _gridFFIService.getFields(fieldIds: grid.fields); - return Future( - () => result.fold( - (fields) { - fieldCache.fields = fields.items; - _onFieldsChanged?.call(UnmodifiableListView(fieldCache.fields)); - return left(unit); - }, - (err) => right(err), - ), - ); - } - Future _loadGroups(List blocks) async { for (final block in blocks) { final cache = GridBlockCache( gridId: gridId, block: block, - fieldCache: fieldCache, + fieldController: fieldController, ); cache.addListener(onRowsChanged: (reason) { diff --git a/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart index b1110f45cc..dd1f77a9d1 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/board_date_cell_bloc.dart @@ -1,6 +1,6 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -20,8 +20,6 @@ class BoardDateCellBloc extends Bloc { emit(state.copyWith( data: cellData, dateStr: _dateStrFromCellData(cellData))); }, - didReceiveFieldUpdate: (FieldPB value) => - emit(state.copyWith(field: value)), ); }, ); @@ -53,8 +51,6 @@ class BoardDateCellEvent with _$BoardDateCellEvent { const factory BoardDateCellEvent.initial() = _InitialCell; const factory BoardDateCellEvent.didReceiveCellUpdate(DateCellDataPB? data) = _DidReceiveCellUpdate; - const factory BoardDateCellEvent.didReceiveFieldUpdate(FieldPB field) = - _DidReceiveFieldUpdate; } @freezed @@ -62,14 +58,14 @@ class BoardDateCellState with _$BoardDateCellState { const factory BoardDateCellState({ required DateCellDataPB? data, required String dateStr, - required FieldPB field, + required GridFieldContext fieldContext, }) = _BoardDateCellState; factory BoardDateCellState.initial(GridDateCellController context) { final cellData = context.getCellData(); return BoardDateCellState( - field: context.field, + fieldContext: context.fieldContext, data: cellData, dateStr: _dateStrFromCellData(cellData), ); diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart index ad30d2b250..e4dccbf0df 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_bloc.dart @@ -59,7 +59,7 @@ class BoardCardBloc extends Bloc { return RowInfo( gridId: _rowService.gridId, fields: UnmodifiableListView( - state.cells.map((cell) => cell.identifier.field).toList(), + state.cells.map((cell) => cell.identifier.fieldContext).toList(), ), rowPB: state.rowPB, ); @@ -120,9 +120,9 @@ class BoardCellEquatable extends Equatable { @override List get props => [ - identifier.field.id, - identifier.field.fieldType, - identifier.field.visibility, - identifier.field.width, + identifier.fieldContext.id, + identifier.fieldContext.fieldType, + identifier.fieldContext.visibility, + identifier.fieldContext.width, ]; } diff --git a/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart b/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart index f362fdf0e6..377b0dae50 100644 --- a/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/board/application/card/card_data_controller.dart @@ -10,15 +10,15 @@ typedef OnCardChanged = void Function(GridCellMap, RowsChangedReason); class CardDataController extends BoardCellBuilderDelegate { final RowPB rowPB; - final GridFieldCache _fieldCache; + final GridFieldController _fieldController; final GridRowCache _rowCache; final List _onCardChangedListeners = []; CardDataController({ required this.rowPB, - required GridFieldCache fieldCache, + required GridFieldController fieldController, required GridRowCache rowCache, - }) : _fieldCache = fieldCache, + }) : _fieldController = fieldController, _rowCache = rowCache; GridCellMap loadData() { @@ -41,7 +41,7 @@ class CardDataController extends BoardCellBuilderDelegate { @override GridCellFieldNotifier buildFieldNotifier() { return GridCellFieldNotifier( - notifier: GridCellFieldNotifierImpl(_fieldCache)); + notifier: GridCellFieldNotifierImpl(_fieldController)); } @override diff --git a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart index 0b043a2ba7..f52237ad49 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/board_page.dart @@ -222,10 +222,10 @@ class _BoardContentState extends State { /// Return placeholder widget if the rowCache is null. if (rowCache == null) return SizedBox(key: ObjectKey(columnItem)); - final fieldCache = context.read().fieldCache; + final fieldController = context.read().fieldController; final gridId = context.read().gridId; final cardController = CardDataController( - fieldCache: fieldCache, + fieldController: fieldController, rowCache: rowCache, rowPB: rowPB, ); @@ -252,7 +252,7 @@ class _BoardContentState extends State { dataController: cardController, openCard: (context) => _openCard( gridId, - fieldCache, + fieldController, rowPB, rowCache, context, @@ -271,17 +271,17 @@ class _BoardContentState extends State { ); } - void _openCard(String gridId, GridFieldCache fieldCache, RowPB rowPB, - GridRowCache rowCache, BuildContext context) { + void _openCard(String gridId, GridFieldController fieldController, + RowPB rowPB, GridRowCache rowCache, BuildContext context) { final rowInfo = RowInfo( gridId: gridId, - fields: UnmodifiableListView(fieldCache.fields), + fields: UnmodifiableListView(fieldController.fieldContexts), rowPB: rowPB, ); final dataController = GridRowDataController( rowInfo: rowInfo, - fieldCache: fieldCache, + fieldController: fieldController, rowCache: rowCache, ); @@ -302,7 +302,7 @@ class _ToolbarBlocAdaptor extends StatelessWidget { final bloc = context.read(); final toolbarContext = BoardToolbarContext( viewId: bloc.gridId, - fieldCache: bloc.fieldCache, + fieldController: bloc.fieldController, ); return BoardToolbar(toolbarContext: toolbarContext); diff --git a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart index d981bd6006..a270f50951 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_setting.dart @@ -19,16 +19,16 @@ import 'board_toolbar.dart'; class BoardSettingContext { final String viewId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; BoardSettingContext({ required this.viewId, - required this.fieldCache, + required this.fieldController, }); factory BoardSettingContext.from(BoardToolbarContext toolbarContext) => BoardSettingContext( viewId: toolbarContext.viewId, - fieldCache: toolbarContext.fieldCache, + fieldController: toolbarContext.fieldController, ); } @@ -93,13 +93,13 @@ class BoardSettingList extends StatelessWidget { case BoardSettingAction.properties: GridPropertyList( gridId: settingContext.viewId, - fieldCache: settingContext.fieldCache) + fieldController: settingContext.fieldController) .show(context); break; case BoardSettingAction.groups: GridGroupList( viewId: settingContext.viewId, - fieldCache: settingContext.fieldCache) + fieldController: settingContext.fieldController) .show(context); break; } diff --git a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart index fae27851a9..bf8d2e3443 100644 --- a/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart +++ b/frontend/app_flowy/lib/plugins/board/presentation/toolbar/board_toolbar.dart @@ -9,11 +9,11 @@ import 'board_setting.dart'; class BoardToolbarContext { final String viewId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; BoardToolbarContext({ required this.viewId, - required this.fieldCache, + required this.fieldController, }); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart index b639700b5f..35ed334cee 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/block/block_cache.dart @@ -19,12 +19,12 @@ class GridBlockCache { GridBlockCache({ required this.gridId, required this.block, - required GridFieldCache fieldCache, + required GridFieldController fieldController, }) { _rowCache = GridRowCache( gridId: gridId, block: block, - notifier: GridRowFieldNotifierImpl(fieldCache), + notifier: GridRowFieldNotifierImpl(fieldController), ); _listener = GridBlockListener(blockId: block.id); diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart index d716133d05..29fb521976 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_controller.dart @@ -148,10 +148,10 @@ class IGridCellController extends Equatable { _cellDataLoader = cellDataLoader, _cellDataPersistence = cellDataPersistence, _fieldNotifier = fieldNotifier, - _fieldService = - FieldService(gridId: cellId.gridId, fieldId: cellId.field.id), - _cacheKey = - GridCellCacheKey(rowId: cellId.rowId, fieldId: cellId.field.id); + _fieldService = FieldService( + gridId: cellId.gridId, fieldId: cellId.fieldContext.id), + _cacheKey = GridCellCacheKey( + rowId: cellId.rowId, fieldId: cellId.fieldContext.id); IGridCellController clone() { return IGridCellController( @@ -166,11 +166,11 @@ class IGridCellController extends Equatable { String get rowId => cellId.rowId; - String get fieldId => cellId.field.id; + String get fieldId => cellId.fieldContext.id; - FieldPB get field => cellId.field; + GridFieldContext get fieldContext => cellId.fieldContext; - FieldType get fieldType => cellId.field.fieldType; + FieldType get fieldType => cellId.fieldContext.fieldType; VoidCallback? startListening( {required void Function(T?) onCellChanged, @@ -182,7 +182,8 @@ class IGridCellController extends Equatable { isListening = true; _cellDataNotifier = ValueNotifier(_cellsCache.get(_cacheKey)); - _cellListener = CellListener(rowId: cellId.rowId, fieldId: cellId.field.id); + _cellListener = + CellListener(rowId: cellId.rowId, fieldId: cellId.fieldContext.id); /// 1.Listen on user edit event and load the new cell data if needed. /// For example: @@ -308,14 +309,14 @@ class IGridCellController extends Equatable { @override List get props => - [_cellsCache.get(_cacheKey) ?? "", cellId.rowId + cellId.field.id]; + [_cellsCache.get(_cacheKey) ?? "", cellId.rowId + cellId.fieldContext.id]; } class GridCellFieldNotifierImpl extends IGridCellFieldNotifier { - final GridFieldCache _cache; - FieldChangesetCallback? _onChangesetFn; + final GridFieldController _cache; + OnChangeset? _onChangesetFn; - GridCellFieldNotifierImpl(GridFieldCache cache) : _cache = cache; + GridCellFieldNotifierImpl(GridFieldController cache) : _cache = cache; @override void onCellDispose() { diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart index eb64543167..360df60b4e 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_service.dart @@ -60,17 +60,17 @@ class GridCellIdentifier with _$GridCellIdentifier { const factory GridCellIdentifier({ required String gridId, required String rowId, - required FieldPB field, + required GridFieldContext fieldContext, }) = _GridCellIdentifier; // ignore: unused_element const GridCellIdentifier._(); - String get fieldId => field.id; + String get fieldId => fieldContext.id; - FieldType get fieldType => field.fieldType; + FieldType get fieldType => fieldContext.fieldType; ValueKey key() { - return ValueKey("$rowId$fieldId${field.fieldType}"); + return ValueKey("$rowId$fieldId${fieldContext.fieldType}"); } } diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart index a7124b7a3d..6fb8e7e5b0 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cal_bloc.dart @@ -176,7 +176,7 @@ class DateCalBloc extends Bloc { final result = await FieldService.updateFieldTypeOption( gridId: cellController.gridId, - fieldId: cellController.field.id, + fieldId: cellController.fieldContext.id, typeOptionData: newDateTypeOption.writeToBuffer(), ); diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart index 4d453eca25..ae840e9e54 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/date_cell_bloc.dart @@ -1,5 +1,5 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -20,8 +20,6 @@ class DateCellBloc extends Bloc { emit(state.copyWith( data: cellData, dateStr: _dateStrFromCellData(cellData))); }, - didReceiveFieldUpdate: (FieldPB value) => - emit(state.copyWith(field: value)), ); }, ); @@ -53,8 +51,6 @@ class DateCellEvent with _$DateCellEvent { const factory DateCellEvent.initial() = _InitialCell; const factory DateCellEvent.didReceiveCellUpdate(DateCellDataPB? data) = _DidReceiveCellUpdate; - const factory DateCellEvent.didReceiveFieldUpdate(FieldPB field) = - _DidReceiveFieldUpdate; } @freezed @@ -62,14 +58,14 @@ class DateCellState with _$DateCellState { const factory DateCellState({ required DateCellDataPB? data, required String dateStr, - required FieldPB field, + required GridFieldContext fieldContext, }) = _DateCellState; factory DateCellState.initial(GridDateCellController context) { final cellData = context.getCellData(); return DateCellState( - field: context.field, + fieldContext: context.fieldContext, data: cellData, dateStr: _dateStrFromCellData(cellData), ); diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart index 44d4bdd4be..7d5be30eda 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/select_option_service.dart @@ -11,7 +11,7 @@ class SelectOptionService { SelectOptionService({required this.cellId}); String get gridId => cellId.gridId; - String get fieldId => cellId.field.id; + String get fieldId => cellId.fieldContext.id; String get rowId => cellId.rowId; Future> create({required String name}) { diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart index b83c261626..da12afff97 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_cache.dart @@ -1,36 +1,47 @@ import 'dart:collection'; - import 'package:app_flowy/plugins/grid/application/field/grid_listener.dart'; +import 'package:app_flowy/plugins/grid/application/grid_service.dart'; +import 'package:app_flowy/plugins/grid/application/setting/setting_listener.dart'; +import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/foundation.dart'; - import '../row/row_cache.dart'; -class FieldsNotifier extends ChangeNotifier { - List _fields = []; +class _GridFieldNotifier extends ChangeNotifier { + List _fieldContexts = []; - set fields(List fields) { - _fields = fields; + set fieldContexts(List fieldContexts) { + _fieldContexts = fieldContexts; notifyListeners(); } - List get fields => _fields; + void notify() { + notifyListeners(); + } + + List get fieldContexts => _fieldContexts; } -typedef FieldChangesetCallback = void Function(FieldChangesetPB); -typedef FieldsCallback = void Function(List); +typedef OnChangeset = void Function(FieldChangesetPB); +typedef OnReceiveFields = void Function(List); -class GridFieldCache { +class GridFieldController { final String gridId; final GridFieldsListener _fieldListener; - FieldsNotifier? _fieldNotifier = FieldsNotifier(); - final Map _fieldsCallbackMap = {}; - final Map - _changesetCallbackMap = {}; + final SettingListener _settingListener; + final Map _fieldCallbackMap = {}; + final Map _changesetCallbackMap = {}; - GridFieldCache({required this.gridId}) - : _fieldListener = GridFieldsListener(gridId: gridId) { + _GridFieldNotifier? _fieldNotifier = _GridFieldNotifier(); + final GridFFIService _gridFFIService; + + GridFieldController({required this.gridId}) + : _fieldListener = GridFieldsListener(gridId: gridId), + _gridFFIService = GridFFIService(gridId: gridId), + _settingListener = SettingListener(gridId: gridId) { + //Listen on field's changes _fieldListener.start(onFieldsChanged: (result) { result.fold( (changeset) { @@ -44,6 +55,28 @@ class GridFieldCache { (err) => Log.error(err), ); }); + + //Listen on setting changes + _settingListener.start(onSettingUpdated: (result) { + result.fold( + (setting) { + final List groupFieldIds = setting.groupConfigurations.items + .map((item) => item.groupFieldId) + .toList(); + bool isChanged = false; + if (_fieldNotifier != null) { + for (var field in _fieldNotifier!.fieldContexts) { + if (groupFieldIds.contains(field.id)) { + field._isGroupField = true; + isChanged = true; + } + } + if (isChanged) _fieldNotifier?.notify(); + } + }, + (r) => Log.error(r), + ); + }); } Future dispose() async { @@ -52,49 +85,62 @@ class GridFieldCache { _fieldNotifier = null; } - List get fields => [..._fieldNotifier?.fields ?? []]; + List get fieldContexts => + [..._fieldNotifier?.fieldContexts ?? []]; - set fields(List fields) { - _fieldNotifier?.fields = [...fields]; + Future> loadFields( + {required List fieldIds}) async { + final result = await _gridFFIService.getFields(fieldIds: fieldIds); + return Future( + () => result.fold( + (newFields) { + _fieldNotifier?.fieldContexts = newFields.items + .map((field) => GridFieldContext(field: field)) + .toList(); + return left(unit); + }, + (err) => right(err), + ), + ); } void addListener({ - FieldsCallback? onFields, - FieldChangesetCallback? onChangeset, + OnReceiveFields? onFields, + OnChangeset? onChangeset, bool Function()? listenWhen, }) { if (onChangeset != null) { - fn(c) { + callback(c) { if (listenWhen != null && listenWhen() == false) { return; } onChangeset(c); } - _changesetCallbackMap[onChangeset] = fn; + _changesetCallbackMap[onChangeset] = callback; } if (onFields != null) { - fn() { + callback() { if (listenWhen != null && listenWhen() == false) { return; } - onFields(fields); + onFields(fieldContexts); } - _fieldsCallbackMap[onFields] = fn; - _fieldNotifier?.addListener(fn); + _fieldCallbackMap[onFields] = callback; + _fieldNotifier?.addListener(callback); } } void removeListener({ - FieldsCallback? onFieldsListener, - FieldChangesetCallback? onChangesetListener, + OnReceiveFields? onFieldsListener, + OnChangeset? onChangesetListener, }) { if (onFieldsListener != null) { - final fn = _fieldsCallbackMap.remove(onFieldsListener); - if (fn != null) { - _fieldNotifier?.removeListener(fn); + final callback = _fieldCallbackMap.remove(onFieldsListener); + if (callback != null) { + _fieldNotifier?.removeListener(callback); } } @@ -107,56 +153,58 @@ class GridFieldCache { if (deletedFields.isEmpty) { return; } - final List newFields = fields; + final List newFields = fieldContexts; final Map deletedFieldMap = { for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder }; newFields.retainWhere((field) => (deletedFieldMap[field.id] == null)); - _fieldNotifier?.fields = newFields; + _fieldNotifier?.fieldContexts = newFields; } void _insertFields(List insertedFields) { if (insertedFields.isEmpty) { return; } - final List newFields = fields; + final List newFields = fieldContexts; for (final indexField in insertedFields) { + final gridField = GridFieldContext(field: indexField.field_1); if (newFields.length > indexField.index) { - newFields.insert(indexField.index, indexField.field_1); + newFields.insert(indexField.index, gridField); } else { - newFields.add(indexField.field_1); + newFields.add(gridField); } } - _fieldNotifier?.fields = newFields; + _fieldNotifier?.fieldContexts = newFields; } void _updateFields(List updatedFields) { if (updatedFields.isEmpty) { return; } - final List newFields = fields; + final List newFields = fieldContexts; for (final updatedField in updatedFields) { final index = newFields.indexWhere((field) => field.id == updatedField.id); if (index != -1) { newFields.removeAt(index); - newFields.insert(index, updatedField); + final gridField = GridFieldContext(field: updatedField); + newFields.insert(index, gridField); } } - _fieldNotifier?.fields = newFields; + _fieldNotifier?.fieldContexts = newFields; } } class GridRowFieldNotifierImpl extends IGridRowFieldNotifier { - final GridFieldCache _cache; - FieldChangesetCallback? _onChangesetFn; - FieldsCallback? _onFieldFn; - GridRowFieldNotifierImpl(GridFieldCache cache) : _cache = cache; + final GridFieldController _cache; + OnChangeset? _onChangesetFn; + OnReceiveFields? _onFieldFn; + GridRowFieldNotifierImpl(GridFieldController cache) : _cache = cache; @override - UnmodifiableListView get fields => - UnmodifiableListView(_cache.fields); + UnmodifiableListView get fields => + UnmodifiableListView(_cache.fieldContexts); @override void onRowFieldsChanged(VoidCallback callback) { @@ -188,3 +236,26 @@ class GridRowFieldNotifierImpl extends IGridRowFieldNotifier { } } } + +class GridFieldContext { + final FieldPB _field; + bool _isGroupField = false; + + String get id => _field.id; + + FieldType get fieldType => _field.fieldType; + + bool get visibility => _field.visibility; + + double get width => _field.width.toDouble(); + + bool get isPrimary => _field.isPrimary; + + String get name => _field.name; + + FieldPB get field => _field; + + bool get isGroupField => _isGroupField; + + GridFieldContext({required FieldPB field}) : _field = field; +} diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart b/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart index 816f32fe16..5466a8de08 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/field_service.dart @@ -5,6 +5,8 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; + +import 'field_cache.dart'; part 'field_service.freezed.dart'; /// FieldService consists of lots of event functions. We define the events in the backend(Rust), diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart index 632e333911..192c4f86f0 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_context.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart index 66f4c35c20..6f757be71d 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/field/type_option/type_option_data_controller.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_infra/notifier.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; @@ -17,12 +18,12 @@ class TypeOptionDataController { TypeOptionDataController({ required this.gridId, required this.loader, - FieldPB? field, + GridFieldContext? fieldContext, }) { - if (field != null) { + if (fieldContext != null) { _data = FieldTypeOptionDataPB.create() ..gridId = gridId - ..field_2 = field; + ..field_2 = fieldContext.field; } } diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart index 74f23a1b3e..139b08251e 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart @@ -7,6 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'block/block_cache.dart'; +import 'field/field_cache.dart'; import 'grid_data_controller.dart'; import 'row/row_cache.dart'; import 'dart:collection'; @@ -101,7 +102,7 @@ class GridEvent with _$GridEvent { RowsChangedReason listState, ) = _DidReceiveRowUpdate; const factory GridEvent.didReceiveFieldUpdate( - UnmodifiableListView fields, + UnmodifiableListView fields, ) = _DidReceiveFieldUpdate; const factory GridEvent.didReceiveGridUpdate( @@ -138,9 +139,9 @@ class GridLoadingState with _$GridLoadingState { } class GridFieldEquatable extends Equatable { - final UnmodifiableListView _fields; + final UnmodifiableListView _fields; const GridFieldEquatable( - UnmodifiableListView fields, + UnmodifiableListView fields, ) : _fields = fields; @override @@ -157,5 +158,6 @@ class GridFieldEquatable extends Equatable { ]; } - UnmodifiableListView get value => UnmodifiableListView(_fields); + UnmodifiableListView get value => + UnmodifiableListView(_fields); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart index 55733b9b7b..6caf699641 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_data_controller.dart @@ -4,7 +4,6 @@ import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; @@ -13,7 +12,7 @@ import 'field/field_cache.dart'; import 'prelude.dart'; import 'row/row_cache.dart'; -typedef OnFieldsChanged = void Function(UnmodifiableListView); +typedef OnFieldsChanged = void Function(UnmodifiableListView); typedef OnGridChanged = void Function(GridPB); typedef OnRowsChanged = void Function( @@ -25,7 +24,7 @@ typedef ListenOnRowChangedCondition = bool Function(); class GridDataController { final String gridId; final GridFFIService _gridFFIService; - final GridFieldCache fieldCache; + final GridFieldController fieldController; // key: the block id final LinkedHashMap _blocks; @@ -49,7 +48,7 @@ class GridDataController { // ignore: prefer_collection_literals _blocks = LinkedHashMap(), _gridFFIService = GridFFIService(gridId: view.id), - fieldCache = GridFieldCache(gridId: view.id); + fieldController = GridFieldController(gridId: view.id); void addListener({ required OnGridChanged onGridChanged, @@ -60,7 +59,7 @@ class GridDataController { _onRowChanged = onRowsChanged; _onFieldsChanged = onFieldsChanged; - fieldCache.addListener(onFields: (fields) { + fieldController.addListener(onFields: (fields) { _onFieldsChanged?.call(UnmodifiableListView(fields)); }); } @@ -72,7 +71,7 @@ class GridDataController { (grid) async { _initialBlocks(grid.blocks); _onGridChanged?.call(grid); - return await _loadFields(grid); + return await fieldController.loadFields(fieldIds: grid.fields); }, (err) => right(err), ), @@ -85,7 +84,7 @@ class GridDataController { Future dispose() async { await _gridFFIService.closeGrid(); - await fieldCache.dispose(); + await fieldController.dispose(); for (final blockCache in _blocks.values) { blockCache.dispose(); @@ -102,7 +101,7 @@ class GridDataController { final cache = GridBlockCache( gridId: gridId, block: block, - fieldCache: fieldCache, + fieldController: fieldController, ); cache.addListener( @@ -114,18 +113,4 @@ class GridDataController { _blocks[block.id] = cache; } } - - Future> _loadFields(GridPB grid) async { - final result = await _gridFFIService.getFields(fieldIds: grid.fields); - return Future( - () => result.fold( - (fields) { - fieldCache.fields = fields.items; - _onFieldsChanged?.call(UnmodifiableListView(fieldCache.fields)); - return left(unit); - }, - (err) => right(err), - ), - ); - } } diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart index 125bd8d652..b7e1ade527 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_header_bloc.dart @@ -4,19 +4,18 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; - import 'field/field_cache.dart'; part 'grid_header_bloc.freezed.dart'; class GridHeaderBloc extends Bloc { - final GridFieldCache fieldCache; + final GridFieldController fieldController; final String gridId; GridHeaderBloc({ required this.gridId, - required this.fieldCache, - }) : super(GridHeaderState.initial(fieldCache.fields)) { + required this.fieldController, + }) : super(GridHeaderState.initial(fieldController.fieldContexts)) { on( (event, emit) async { await event.map( @@ -36,7 +35,7 @@ class GridHeaderBloc extends Bloc { Future _moveField( _MoveField value, Emitter emit) async { - final fields = List.from(state.fields); + final fields = List.from(state.fields); fields.insert(value.toIndex, fields.removeAt(value.fromIndex)); emit(state.copyWith(fields: fields)); @@ -49,7 +48,7 @@ class GridHeaderBloc extends Bloc { } Future _startListening() async { - fieldCache.addListener( + fieldController.addListener( onFields: (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)), listenWhen: () => !isClosed, ); @@ -64,18 +63,18 @@ class GridHeaderBloc extends Bloc { @freezed class GridHeaderEvent with _$GridHeaderEvent { const factory GridHeaderEvent.initial() = _InitialHeader; - const factory GridHeaderEvent.didReceiveFieldUpdate(List fields) = - _DidReceiveFieldUpdate; + const factory GridHeaderEvent.didReceiveFieldUpdate( + List fields) = _DidReceiveFieldUpdate; const factory GridHeaderEvent.moveField( FieldPB field, int fromIndex, int toIndex) = _MoveField; } @freezed class GridHeaderState with _$GridHeaderState { - const factory GridHeaderState({required List fields}) = + const factory GridHeaderState({required List fields}) = _GridHeaderState; - factory GridHeaderState.initial(List fields) { + factory GridHeaderState.initial(List fields) { // final List newFields = List.from(fields); // newFields.retainWhere((field) => field.visibility); return GridHeaderState(fields: fields); diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart index bea25d8008..c5676616b3 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_bloc.dart @@ -1,7 +1,7 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:equatable/equatable.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -35,7 +35,7 @@ class RowBloc extends Bloc { }, didReceiveCells: (_DidReceiveCells value) async { final cells = value.gridCellMap.values - .map((e) => GridCellEquatable(e.field)) + .map((e) => GridCellEquatable(e.fieldContext)) .toList(); emit(state.copyWith( gridCellMap: value.gridCellMap, @@ -87,21 +87,23 @@ class RowState with _$RowState { rowInfo: rowInfo, gridCellMap: cellDataMap, cells: UnmodifiableListView( - cellDataMap.values.map((e) => GridCellEquatable(e.field)).toList(), + cellDataMap.values + .map((e) => GridCellEquatable(e.fieldContext)) + .toList(), ), ); } class GridCellEquatable extends Equatable { - final FieldPB _field; + final GridFieldContext _fieldContext; - const GridCellEquatable(FieldPB field) : _field = field; + const GridCellEquatable(GridFieldContext field) : _fieldContext = field; @override List get props => [ - _field.id, - _field.fieldType, - _field.visibility, - _field.width, + _fieldContext.id, + _fieldContext.fieldType, + _fieldContext.visibility, + _fieldContext.width, ]; } diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart index 618d73cbc1..d1e8eaa1bf 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_cache.dart @@ -1,5 +1,6 @@ import 'dart:collection'; import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; @@ -12,7 +13,7 @@ part 'row_cache.freezed.dart'; typedef RowUpdateCallback = void Function(); abstract class IGridRowFieldNotifier { - UnmodifiableListView get fields; + UnmodifiableListView get fields; void onRowFieldsChanged(VoidCallback callback); void onRowFieldChanged(void Function(FieldPB) callback); void onRowDispose(); @@ -217,7 +218,7 @@ class GridRowCache { cellDataMap[field.id] = GridCellIdentifier( rowId: rowId, gridId: gridId, - field: field, + fieldContext: field, ); } } @@ -284,7 +285,7 @@ class _RowChangesetNotifier extends ChangeNotifier { class RowInfo with _$RowInfo { const factory RowInfo({ required String gridId, - required UnmodifiableListView fields, + required UnmodifiableListView fields, required RowPB rowPB, }) = _RowInfo; } diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart index b4618b397a..5ed0f24965 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_data_controller.dart @@ -10,14 +10,14 @@ typedef OnRowChanged = void Function(GridCellMap, RowsChangedReason); class GridRowDataController extends GridCellBuilderDelegate { final RowInfo rowInfo; final List _onRowChangedListeners = []; - final GridFieldCache _fieldCache; + final GridFieldController _fieldController; final GridRowCache _rowCache; GridRowDataController({ required this.rowInfo, - required GridFieldCache fieldCache, + required GridFieldController fieldController, required GridRowCache rowCache, - }) : _fieldCache = fieldCache, + }) : _fieldController = fieldController, _rowCache = rowCache; GridCellMap loadData() { @@ -41,7 +41,7 @@ class GridRowDataController extends GridCellBuilderDelegate { @override GridCellFieldNotifier buildFieldNotifier() { return GridCellFieldNotifier( - notifier: GridCellFieldNotifierImpl(_fieldCache)); + notifier: GridCellFieldNotifierImpl(_fieldController)); } @override diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart index 691371bd8a..b960a2c2f0 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/group_bloc.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -11,14 +10,15 @@ import 'setting_controller.dart'; part 'group_bloc.freezed.dart'; class GridGroupBloc extends Bloc { - final GridFieldCache _fieldCache; + final GridFieldController _fieldController; final SettingController _settingController; - Function(List)? _onFieldsFn; + Function(List)? _onFieldsFn; - GridGroupBloc({required String viewId, required GridFieldCache fieldCache}) - : _fieldCache = fieldCache, + GridGroupBloc( + {required String viewId, required GridFieldController fieldController}) + : _fieldController = fieldController, _settingController = SettingController(viewId: viewId), - super(GridGroupState.initial(viewId, fieldCache.fields)) { + super(GridGroupState.initial(viewId, fieldController.fieldContexts)) { on( (event, emit) async { await event.map( @@ -36,7 +36,7 @@ class GridGroupBloc extends Bloc { ); }, didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { - emit(state.copyWith(fields: value.fields)); + emit(state.copyWith(fieldContexts: value.fields)); }, moveField: (_MoveField value) { // @@ -49,7 +49,7 @@ class GridGroupBloc extends Bloc { @override Future close() async { if (_onFieldsFn != null) { - _fieldCache.removeListener(onFieldsListener: _onFieldsFn!); + _fieldController.removeListener(onFieldsListener: _onFieldsFn!); _onFieldsFn = null; } return super.close(); @@ -57,7 +57,7 @@ class GridGroupBloc extends Bloc { void _startListening() { _onFieldsFn = (fields) => add(GridGroupEvent.didReceiveFieldUpdate(fields)); - _fieldCache.addListener( + _fieldController.addListener( onFields: _onFieldsFn, listenWhen: () => !isClosed, ); @@ -74,8 +74,8 @@ class GridGroupEvent with _$GridGroupEvent { const factory GridGroupEvent.initial() = _Initial; const factory GridGroupEvent.setFieldVisibility( String fieldId, bool visibility) = _SetFieldVisibility; - const factory GridGroupEvent.didReceiveFieldUpdate(List fields) = - _DidReceiveFieldUpdate; + const factory GridGroupEvent.didReceiveFieldUpdate( + List fields) = _DidReceiveFieldUpdate; const factory GridGroupEvent.moveField(int fromIndex, int toIndex) = _MoveField; } @@ -84,12 +84,13 @@ class GridGroupEvent with _$GridGroupEvent { class GridGroupState with _$GridGroupState { const factory GridGroupState({ required String gridId, - required List fields, + required List fieldContexts, }) = _GridGroupState; - factory GridGroupState.initial(String gridId, List fields) => + factory GridGroupState.initial( + String gridId, List fieldContexts) => GridGroupState( gridId: gridId, - fields: fields, + fieldContexts: fieldContexts, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart index fc0c2b4b12..2e268aff84 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/property_bloc.dart @@ -1,6 +1,5 @@ import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; @@ -10,12 +9,14 @@ import '../field/field_cache.dart'; part 'property_bloc.freezed.dart'; class GridPropertyBloc extends Bloc { - final GridFieldCache _fieldCache; - Function(List)? _onFieldsFn; + final GridFieldController _fieldController; + Function(List)? _onFieldsFn; - GridPropertyBloc({required String gridId, required GridFieldCache fieldCache}) - : _fieldCache = fieldCache, - super(GridPropertyState.initial(gridId, fieldCache.fields)) { + GridPropertyBloc( + {required String gridId, required GridFieldController fieldController}) + : _fieldController = fieldController, + super( + GridPropertyState.initial(gridId, fieldController.fieldContexts)) { on( (event, emit) async { await event.map( @@ -33,7 +34,7 @@ class GridPropertyBloc extends Bloc { ); }, didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { - emit(state.copyWith(fields: value.fields)); + emit(state.copyWith(fieldContexts: value.fields)); }, moveField: (_MoveField value) { // @@ -46,7 +47,7 @@ class GridPropertyBloc extends Bloc { @override Future close() async { if (_onFieldsFn != null) { - _fieldCache.removeListener(onFieldsListener: _onFieldsFn!); + _fieldController.removeListener(onFieldsListener: _onFieldsFn!); _onFieldsFn = null; } return super.close(); @@ -55,7 +56,7 @@ class GridPropertyBloc extends Bloc { void _startListening() { _onFieldsFn = (fields) => add(GridPropertyEvent.didReceiveFieldUpdate(fields)); - _fieldCache.addListener( + _fieldController.addListener( onFields: _onFieldsFn, listenWhen: () => !isClosed, ); @@ -67,8 +68,8 @@ class GridPropertyEvent with _$GridPropertyEvent { const factory GridPropertyEvent.initial() = _Initial; const factory GridPropertyEvent.setFieldVisibility( String fieldId, bool visibility) = _SetFieldVisibility; - const factory GridPropertyEvent.didReceiveFieldUpdate(List fields) = - _DidReceiveFieldUpdate; + const factory GridPropertyEvent.didReceiveFieldUpdate( + List fields) = _DidReceiveFieldUpdate; const factory GridPropertyEvent.moveField(int fromIndex, int toIndex) = _MoveField; } @@ -77,12 +78,15 @@ class GridPropertyEvent with _$GridPropertyEvent { class GridPropertyState with _$GridPropertyState { const factory GridPropertyState({ required String gridId, - required List fields, + required List fieldContexts, }) = _GridPropertyState; - factory GridPropertyState.initial(String gridId, List fields) => + factory GridPropertyState.initial( + String gridId, + List fieldContexts, + ) => GridPropertyState( gridId: gridId, - fields: fields, + fieldContexts: fieldContexts, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart index 721e5d35f1..795adc4622 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/setting/setting_controller.dart @@ -41,6 +41,7 @@ class SettingController { required OnError onError, }) { assert(_onSettingUpdated == null, 'Should call once'); + assert(_onError == null, 'Should call once'); _onSettingUpdated = onSettingUpdated; _onError = onError; } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart index 2c6c1e2180..e8d251c04f 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart @@ -157,10 +157,11 @@ class _FlowyGridState extends State { } Widget _gridHeader(BuildContext context, String gridId) { - final fieldCache = context.read().dataController.fieldCache; + final fieldController = + context.read().dataController.fieldController; return GridHeaderSliverAdaptor( gridId: gridId, - fieldCache: fieldCache, + fieldController: fieldController, anchorScrollController: headerScrollController, ); } @@ -173,10 +174,11 @@ class _GridToolbarAdaptor extends StatelessWidget { Widget build(BuildContext context) { return BlocSelector( selector: (state) { - final fieldCache = context.read().dataController.fieldCache; + final fieldController = + context.read().dataController.fieldController; return GridToolbarContext( gridId: state.gridId, - fieldCache: fieldCache, + fieldController: fieldController, ); }, builder: (context, toolbarContext) { @@ -247,10 +249,11 @@ class _GridRowsState extends State<_GridRows> { /// Return placeholder widget if the rowCache is null. if (rowCache == null) return const SizedBox(); - final fieldCache = context.read().dataController.fieldCache; + final fieldController = + context.read().dataController.fieldController; final dataController = GridRowDataController( rowInfo: rowInfo, - fieldCache: fieldCache, + fieldController: fieldController, rowCache: rowCache, ); @@ -264,7 +267,7 @@ class _GridRowsState extends State<_GridRows> { _openRowDetailPage( context, rowInfo, - fieldCache, + fieldController, rowCache, cellBuilder, ); @@ -277,13 +280,13 @@ class _GridRowsState extends State<_GridRows> { void _openRowDetailPage( BuildContext context, RowInfo rowInfo, - GridFieldCache fieldCache, + GridFieldController fieldController, GridRowCache rowCache, GridCellBuilder cellBuilder, ) { final dataController = GridRowDataController( rowInfo: rowInfo, - fieldCache: fieldCache, + fieldController: fieldController, rowCache: rowCache, ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart b/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart index e47b47a267..5d09200b33 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/layout/layout.dart @@ -1,8 +1,8 @@ -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'sizes.dart'; class GridLayout { - static double headerWidth(List fields) { + static double headerWidth(List fields) { if (fields.isEmpty) return 0; final fieldsWidth = fields diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart index c1de0eca31..fd5f087c40 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/field_cell.dart @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/plugins/grid/application/field/field_cell_bloc.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart index c5bdb448c3..fd0a0c2863 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/grid_header.dart @@ -18,11 +18,11 @@ import 'field_cell.dart'; class GridHeaderSliverAdaptor extends StatefulWidget { final String gridId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; final ScrollController anchorScrollController; const GridHeaderSliverAdaptor({ required this.gridId, - required this.fieldCache, + required this.fieldController, required this.anchorScrollController, Key? key, }) : super(key: key); @@ -38,7 +38,7 @@ class _GridHeaderSliverAdaptorState extends State { return BlocProvider( create: (context) { final bloc = getIt( - param1: widget.gridId, param2: widget.fieldCache); + param1: widget.gridId, param2: widget.fieldController); bloc.add(const GridHeaderEvent.initial()); return bloc; }, @@ -84,7 +84,7 @@ class _GridHeaderState extends State<_GridHeader> { final cells = state.fields .where((field) => field.visibility) .map((field) => - GridFieldCellContext(gridId: widget.gridId, field: field)) + GridFieldCellContext(gridId: widget.gridId, field: field.field)) .map((ctx) => GridFieldCell(ctx, key: ValueKey(ctx.field.id))) .toList(); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart index 2ea19eb1e8..bce95edb96 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/header/type_option/builder.dart @@ -1,5 +1,6 @@ import 'dart:typed_data'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart'; import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart'; @@ -129,17 +130,18 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({ TypeOptionContext makeTypeOptionContext({ required String gridId, - required FieldPB field, + required GridFieldContext fieldContext, }) { - final loader = FieldTypeOptionLoader(gridId: gridId, field: field); + final loader = + FieldTypeOptionLoader(gridId: gridId, field: fieldContext.field); final dataController = TypeOptionDataController( gridId: gridId, loader: loader, - field: field, + fieldContext: fieldContext, ); return makeTypeOptionContextWithDataController( gridId: gridId, - fieldType: field.fieldType, + fieldType: fieldContext.fieldType, dataController: dataController, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart index 55ec7b9832..621f53cf1a 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/grid_row.dart @@ -189,13 +189,13 @@ class RowContent extends StatelessWidget { final GridCellWidget child = builder.build(cellId); return CellContainer( - width: cellId.field.width.toDouble(), + width: cellId.fieldContext.width.toDouble(), rowStateNotifier: Provider.of(context, listen: false), accessoryBuilder: (buildContext) { final builder = child.accessoryBuilder; List accessories = []; - if (cellId.field.isPrimary) { + if (cellId.fieldContext.isPrimary) { accessories.add(PrimaryCellAccessory( onTapCallback: onExpand, isCellEditing: buildContext.isCellEditing, diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart index 58e9b2808c..1fbe1bfb84 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_detail.dart @@ -215,7 +215,7 @@ class _RowDetailCell extends StatelessWidget { SizedBox( width: 150, child: FieldCellButton( - field: cellId.field, + field: cellId.fieldContext.fieldContext, onTap: () => _showFieldEditor(context), ), ), @@ -230,10 +230,10 @@ class _RowDetailCell extends StatelessWidget { void _showFieldEditor(BuildContext context) { FieldEditor( gridId: cellId.gridId, - fieldName: cellId.field.name, + fieldName: cellId.fieldContext.name, typeOptionLoader: FieldTypeOptionLoader( gridId: cellId.gridId, - field: cellId.field, + field: cellId.fieldContext.fieldContext, ), ).show(context); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart index 770e16e2bf..3550c1274c 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_group.dart @@ -6,7 +6,6 @@ import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:app_flowy/plugins/grid/application/setting/group_bloc.dart'; @@ -14,10 +13,10 @@ import 'package:flutter_bloc/flutter_bloc.dart'; class GridGroupList extends StatelessWidget { final String viewId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; const GridGroupList({ required this.viewId, - required this.fieldCache, + required this.fieldController, Key? key, }) : super(key: key); @@ -26,13 +25,13 @@ class GridGroupList extends StatelessWidget { return BlocProvider( create: (context) => GridGroupBloc( viewId: viewId, - fieldCache: fieldCache, + fieldController: fieldController, )..add(const GridGroupEvent.initial()), child: BlocBuilder( builder: (context, state) { - final cells = state.fields.map((field) { + final cells = state.fieldContexts.map((field) { return _GridGroupCell( - field: field, + fieldContext: field, key: ValueKey(field.id), ); }).toList(); @@ -56,8 +55,9 @@ class GridGroupList extends StatelessWidget { } class _GridGroupCell extends StatelessWidget { - final FieldPB field; - const _GridGroupCell({required this.field, Key? key}) : super(key: key); + final GridFieldContext fieldContext; + const _GridGroupCell({required this.fieldContext, Key? key}) + : super(key: key); @override Widget build(BuildContext context) { @@ -73,9 +73,10 @@ class _GridGroupCell extends StatelessWidget { // ), return FlowyButton( - text: FlowyText.medium(field.name, fontSize: 12), + text: FlowyText.medium(fieldContext.name, fontSize: 12), hoverColor: theme.hover, - leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + leftIcon: + svgWidget(fieldContext.fieldType.iconName(), color: theme.iconColor), onTap: () {}, ); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart index 08ba3dcd08..e57ff26bcb 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_property.dart @@ -9,7 +9,6 @@ import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; @@ -20,10 +19,10 @@ import '../header/field_editor.dart'; class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate { final String gridId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; const GridPropertyList({ required this.gridId, - required this.fieldCache, + required this.fieldController, Key? key, }) : super(key: key); @@ -45,13 +44,13 @@ class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate { Widget build(BuildContext context) { return BlocProvider( create: (context) => - getIt(param1: gridId, param2: fieldCache) + getIt(param1: gridId, param2: fieldController) ..add(const GridPropertyEvent.initial()), child: BlocBuilder( builder: (context, state) { - final cells = state.fields.map((field) { + final cells = state.fieldContexts.map((field) { return _GridPropertyCell( - gridId: gridId, field: field, key: ValueKey(field.id)); + gridId: gridId, fieldContext: field, key: ValueKey(field.id)); }).toList(); return ListView.separated( @@ -78,16 +77,17 @@ class GridPropertyList extends StatelessWidget with FlowyOverlayDelegate { } class _GridPropertyCell extends StatelessWidget { - final FieldPB field; + final GridFieldContext fieldContext; final String gridId; - const _GridPropertyCell({required this.gridId, required this.field, Key? key}) + const _GridPropertyCell( + {required this.gridId, required this.fieldContext, Key? key}) : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); - final checkmark = field.visibility + final checkmark = fieldContext.visibility ? svgWidget('home/show', color: theme.iconColor) : svgWidget('home/hide', color: theme.iconColor); @@ -105,7 +105,7 @@ class _GridPropertyCell extends StatelessWidget { onPressed: () { context.read().add( GridPropertyEvent.setFieldVisibility( - field.id, !field.visibility)); + fieldContext.id, !fieldContext.visibility)); }, icon: checkmark.padding(all: 6), ) @@ -115,14 +115,18 @@ class _GridPropertyCell extends StatelessWidget { FlowyButton _editFieldButton(AppTheme theme, BuildContext context) { return FlowyButton( - text: FlowyText.medium(field.name, fontSize: 12), + text: FlowyText.medium(fieldContext.name, fontSize: 12), hoverColor: theme.hover, - leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor), + leftIcon: + svgWidget(fieldContext.fieldType.iconName(), color: theme.iconColor), onTap: () { FieldEditor( gridId: gridId, - fieldName: field.name, - typeOptionLoader: FieldTypeOptionLoader(gridId: gridId, field: field), + fieldName: fieldContext.name, + typeOptionLoader: FieldTypeOptionLoader( + gridId: gridId, + field: fieldContext.field, + ), ).show(context, anchorDirection: AnchorDirection.bottomRight); }, ); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart index 289d84141f..4bbcd66fe2 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_setting.dart @@ -17,11 +17,11 @@ import 'grid_property.dart'; class GridSettingContext { final String gridId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; GridSettingContext({ required this.gridId, - required this.fieldCache, + required this.fieldController, }); } @@ -44,7 +44,7 @@ class GridSettingList extends StatelessWidget { case GridSettingAction.properties: GridPropertyList( gridId: settingContext.gridId, - fieldCache: settingContext.fieldCache) + fieldController: settingContext.fieldController) .show(context); break; } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart index 4ced06bf99..56c6947430 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/toolbar/grid_toolbar.dart @@ -11,10 +11,10 @@ import 'grid_setting.dart'; class GridToolbarContext { final String gridId; - final GridFieldCache fieldCache; + final GridFieldController fieldController; GridToolbarContext({ required this.gridId, - required this.fieldCache, + required this.fieldController, }); } @@ -26,7 +26,7 @@ class GridToolbar extends StatelessWidget { Widget build(BuildContext context) { final settingContext = GridSettingContext( gridId: toolbarContext.gridId, - fieldCache: toolbarContext.fieldCache, + fieldController: toolbarContext.fieldController, ); return SizedBox( height: 40, diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index be3c617943..cd73c3fbbc 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -154,10 +154,10 @@ void _resolveGridDeps(GetIt getIt) { (view, _) => GridBloc(view: view), ); - getIt.registerFactoryParam( - (gridId, fieldCache) => GridHeaderBloc( + getIt.registerFactoryParam( + (gridId, fieldController) => GridHeaderBloc( gridId: gridId, - fieldCache: fieldCache, + fieldController: fieldController, ), ); @@ -200,7 +200,7 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam( - (gridId, cache) => GridPropertyBloc(gridId: gridId, fieldCache: cache), + getIt.registerFactoryParam( + (gridId, cache) => GridPropertyBloc(gridId: gridId, fieldController: cache), ); }