diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 10b51438e4..e61096831c 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -16,7 +16,6 @@ import 'package:app_flowy/user/presentation/router.dart'; import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell; import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; @@ -182,19 +181,19 @@ void _resolveGridDeps(GetIt getIt) { ), ); - getIt.registerFactoryParam, void>( + getIt.registerFactoryParam( (context, _) => NumberCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam, void>( + getIt.registerFactoryParam( (context, _) => DateCellBloc( cellContext: context, ), ); - getIt.registerFactoryParam, void>( + getIt.registerFactoryParam( (cellData, _) => CheckboxCellBloc( service: CellService(), cellContext: cellData, diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart index 224e8b0d3a..b4d67e41ac 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/cell_service.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:collection'; import 'package:dartz/dartz.dart'; @@ -6,6 +7,7 @@ import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/cell_entities.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -13,6 +15,9 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart'; part 'cell_service.freezed.dart'; +typedef GridDefaultCellContext = GridCellContext; +typedef GridSelectOptionCellContext = GridCellContext; + class GridCellContext { final GridCell gridCell; final GridCellCache cellCache; @@ -22,6 +27,7 @@ class GridCellContext { final CellListener _cellListener; final CellService _cellService = CellService(); final ValueNotifier _cellDataNotifier = ValueNotifier(null); + Timer? _delayOperation; GridCellContext({ required this.gridCell, @@ -41,6 +47,12 @@ class GridCellContext { objectId: "$hashCode", fieldId: gridCell.field.id, ); + + if (cellDataLoader.reloadOnFieldChanged) { + cellCache.addListener(cacheKey, () { + reloadCellData(); + }); + } } String get gridId => gridCell.gridId; @@ -73,16 +85,18 @@ class GridCellContext { _cellService.updateCell(gridId: gridId, fieldId: field.id, rowId: rowId, data: data); } - void _loadData() { - // It may trigger getCell multiple times. Use cancel operation to fix this. - cellDataLoader.loadData().then((data) { - _cellDataNotifier.value = data; - setCellData(data); - }); + void reloadCellData() { + _loadData(); } - void onFieldChanged(VoidCallback callback) { - cellCache.addListener(cacheKey, callback); + void _loadData() { + _delayOperation?.cancel(); + _delayOperation = Timer(const Duration(milliseconds: 10), () { + cellDataLoader.loadData().then((data) { + _cellDataNotifier.value = data; + setCellData(data); + }); + }); } void onCellChanged(void Function(T) callback) { @@ -94,13 +108,15 @@ class GridCellContext { }); } - void removeListener() { - cellCache.removeListener(cacheKey); + void dispose() { + _delayOperation?.cancel(); } } abstract class GridCellDataLoader { Future loadData(); + + bool get reloadOnFieldChanged => true; } class DefaultCellDataLoader implements GridCellDataLoader { @@ -125,6 +141,9 @@ class DefaultCellDataLoader implements GridCellDataLoader { }); }); } + + @override + bool get reloadOnFieldChanged => true; } // key: rowId 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 5a36c7f5a8..01d6540e4d 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 @@ -7,13 +7,12 @@ import 'cell_service.dart'; part 'checkbox_cell_bloc.freezed.dart'; class CheckboxCellBloc extends Bloc { - final GridCellContext _cellContext; + final GridDefaultCellContext cellContext; CheckboxCellBloc({ required CellService service, - required GridCellContext cellContext, - }) : _cellContext = cellContext, - super(CheckboxCellState.initial(cellContext)) { + required this.cellContext, + }) : super(CheckboxCellState.initial(cellContext)) { on( (event, emit) async { await event.map( @@ -33,11 +32,12 @@ class CheckboxCellBloc extends Bloc { @override Future close() async { + cellContext.dispose(); return super.close(); } void _startListening() { - _cellContext.onCellChanged((cell) { + cellContext.onCellChanged((cell) { if (!isClosed) { add(CheckboxCellEvent.didReceiveCellUpdate(cell)); } @@ -45,7 +45,7 @@ class CheckboxCellBloc extends Bloc { } void _updateCellData() { - _cellContext.saveCellData(!state.isSelected ? "Yes" : "No"); + cellContext.saveCellData(!state.isSelected ? "Yes" : "No"); } } 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 b1eacce788..5a52e59de1 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 @@ -1,5 +1,3 @@ -import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; -import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, Field; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -9,12 +7,9 @@ import 'cell_service.dart'; part 'date_cell_bloc.freezed.dart'; class DateCellBloc extends Bloc { - final SingleFieldListener _fieldListener; - final GridCellContext cellContext; + final GridDefaultCellContext cellContext; - DateCellBloc({required this.cellContext}) - : _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId), - super(DateCellState.initial(cellContext)) { + DateCellBloc({required this.cellContext}) : super(DateCellState.initial(cellContext)) { on( (event, emit) async { event.map( @@ -39,7 +34,7 @@ class DateCellBloc extends Bloc { @override Future close() async { - await _fieldListener.stop(); + cellContext.dispose(); return super.close(); } @@ -49,14 +44,6 @@ class DateCellBloc extends Bloc { add(DateCellEvent.didReceiveCellUpdate(cell)); } }); - - _fieldListener.updateFieldNotifier?.addPublishListener((result) { - result.fold( - (field) => add(DateCellEvent.didReceiveFieldUpdate(field)), - (err) => Log.error(err), - ); - }, listenWhen: () => !isClosed); - _fieldListener.start(); } void _updateCellData(DateTime day) { 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 28eca05498..43044271b4 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 @@ -1,5 +1,3 @@ -import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; -import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -9,13 +7,11 @@ import 'cell_service.dart'; part 'number_cell_bloc.freezed.dart'; class NumberCellBloc extends Bloc { - final GridCellContext cellContext; - final SingleFieldListener _fieldListener; + final GridDefaultCellContext cellContext; NumberCellBloc({ required this.cellContext, - }) : _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId), - super(NumberCellState.initial(cellContext)) { + }) : super(NumberCellState.initial(cellContext)) { on( (event, emit) async { await event.map( @@ -40,7 +36,7 @@ class NumberCellBloc extends Bloc { @override Future close() async { - await _fieldListener.stop(); + cellContext.dispose(); return super.close(); } @@ -50,14 +46,6 @@ class NumberCellBloc extends Bloc { add(NumberCellEvent.didReceiveCellUpdate(cell)); } }); - - _fieldListener.updateFieldNotifier?.addPublishListener((result) { - result.fold( - (field) => cellContext.reloadCellData(), - (err) => Log.error(err), - ); - }); - _fieldListener.start(); } } @@ -74,7 +62,8 @@ class NumberCellState with _$NumberCellState { required String content, }) = _NumberCellState; - factory NumberCellState.initial(GridCellContext context) { - return NumberCellState(content: context.getCellData().cell?.content ?? ""); + factory NumberCellState.initial(GridDefaultCellContext context) { + final cell = context.getCellData(); + return NumberCellState(content: cell?.content ?? ""); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart index aaac04ee49..f6eac64e85 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/select_option_service.dart @@ -27,6 +27,9 @@ class SelectOptionCellDataLoader implements GridCellDataLoader true; } class SelectOptionService { diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart index 6a4a038ac4..6c1d700d9d 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/selection_cell_bloc.dart @@ -3,18 +3,15 @@ import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart'; -import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; part 'selection_cell_bloc.freezed.dart'; class SelectionCellBloc extends Bloc { - final SingleFieldListener _fieldListener; final GridCellContext cellContext; SelectionCellBloc({ required this.cellContext, - }) : _fieldListener = SingleFieldListener(fieldId: cellContext.fieldId), - super(SelectionCellState.initial(cellContext)) { + }) : super(SelectionCellState.initial(cellContext)) { on( (event, emit) async { await event.map( @@ -34,8 +31,7 @@ class SelectionCellBloc extends Bloc { @override Future close() async { - await _fieldListener.stop(); - cellContext.removeListener(); + cellContext.dispose(); return super.close(); } @@ -48,8 +44,6 @@ class SelectionCellBloc extends Bloc { )); } }); - - cellContext.onFieldChanged(() => cellContext.reloadCellData()); } } diff --git a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart b/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart index b7eb32d18e..bd3eb0961e 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/cell/selection_editor_bloc.dart @@ -1,8 +1,5 @@ -import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart'; import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart'; -import 'package:app_flowy/workspace/application/grid/field/field_listener.dart'; import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -14,7 +11,6 @@ part 'selection_editor_bloc.freezed.dart'; class SelectOptionEditorBloc extends Bloc { final SelectOptionService _selectOptionService; final GridCellContext cellContext; - Timer? _delayOperation; SelectOptionEditorBloc({ required this.cellContext, @@ -51,8 +47,7 @@ class SelectOptionEditorBloc extends Bloc close() async { - _delayOperation?.cancel(); - cellContext.removeListener(); + cellContext.dispose(); return super.close(); } @@ -86,27 +81,6 @@ class SelectOptionEditorBloc extends Bloc add(SelectOptionEditorEvent.didReceiveOptions( - // selectOptionContext.options, - // selectOptionContext.selectOptions, - // )), - // (err) => Log.error(err), - // ); - // }, - // ); - // } - void _startListening() { cellContext.onCellChanged((selectOptionContext) { if (!isClosed) { @@ -116,8 +90,6 @@ class SelectOptionEditorBloc extends Bloc cellContext.reloadCellData()); } } 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 a051eca2d5..4aa8aef027 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 @@ -1,22 +1,16 @@ -import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'cell_listener.dart'; import 'cell_service.dart'; part 'text_cell_bloc.freezed.dart'; class TextCellBloc extends Bloc { - final CellService _service; - final CellListener _cellListener; - + final GridCellContext cellContext; TextCellBloc({ - required GridCellContext cellContext, - }) : _service = CellService(), - _cellListener = CellListener(rowId: cellContext.rowId, fieldId: cellContext.fieldId), - super(TextCellState.initial(cellContext.gridCell)) { + required this.cellContext, + }) : super(TextCellState.initial(cellContext.gridCell)) { on( (event, emit) async { await event.map( @@ -24,7 +18,7 @@ class TextCellBloc extends Bloc { _startListening(); }, updateText: (_UpdateText value) { - updateCellContent(value.text); + cellContext.saveCellData(value.text); emit(state.copyWith(content: value.text)); }, didReceiveCellData: (_DidReceiveCellData value) { @@ -46,45 +40,16 @@ class TextCellBloc extends Bloc { @override Future close() async { - await _cellListener.stop(); + cellContext.dispose(); return super.close(); } - void updateCellContent(String content) { - final fieldId = state.cellData.field.id; - final gridId = state.cellData.gridId; - final rowId = state.cellData.rowId; - _service.updateCell( - data: content, - fieldId: fieldId, - gridId: gridId, - rowId: rowId, - ); - } - void _startListening() { - _cellListener.updateCellNotifier?.addPublishListener((result) { - result.fold( - (notificationData) async => await _loadCellData(), - (err) => Log.error(err), - ); + cellContext.onCellChanged((cell) { + if (!isClosed) { + add(TextCellEvent.didReceiveCellUpdate(cell)); + } }); - _cellListener.start(); - } - - Future _loadCellData() async { - final result = await _service.getCell( - gridId: state.cellData.gridId, - fieldId: state.cellData.field.id, - rowId: state.cellData.rowId, - ); - if (isClosed) { - return; - } - result.fold( - (cell) => add(TextCellEvent.didReceiveCellUpdate(cell)), - (err) => Log.error(err), - ); } } 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 195449f4f9..2b43569d26 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,7 +1,7 @@ import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart'; import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; -import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Cell, FieldType; +import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show FieldType; import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart'; import 'package:flutter/widgets.dart'; import 'checkbox_cell.dart'; @@ -39,7 +39,7 @@ GridCellContext makeCellContext(GridCell gridCell, GridCellCache cellCache) { case FieldType.DateTime: case FieldType.Number: case FieldType.RichText: - return GridCellContext( + return GridDefaultCellContext( gridCell: gridCell, cellCache: cellCache, cellDataLoader: DefaultCellDataLoader(gridCell: gridCell), diff --git a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart index 13a4a590c0..fcf263256d 100644 --- a/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart +++ b/frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/selection_cell/selection_editor.dart @@ -1,7 +1,6 @@ import 'dart:collection'; import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart'; import 'package:app_flowy/workspace/application/grid/cell/selection_editor_bloc.dart'; -import 'package:app_flowy/workspace/application/grid/row/row_service.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/edit_option_pannel.dart'; import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/header/type_option/widget.dart';