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 0d24e9974c..080d6e79fc 100644 --- a/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart +++ b/frontend/app_flowy/lib/workspace/application/grid/grid_service.dart @@ -85,8 +85,9 @@ class GridFieldCache { _fieldNotifier.fields = [...fields]; } - void addListener({VoidCallback? listener, void Function(List)? onChanged, bool Function()? listenWhen}) { - _fieldNotifier.addListener(() { + VoidCallback addListener( + {VoidCallback? listener, void Function(List)? onChanged, bool Function()? listenWhen}) { + f() { if (listenWhen != null && listenWhen() == false) { return; } @@ -98,7 +99,14 @@ class GridFieldCache { if (listener != null) { listener(); } - }); + } + + _fieldNotifier.addListener(f); + return f; + } + + void removeListener(VoidCallback f) { + _fieldNotifier.removeListener(f); } void _deleteFields(List deletedFields) { 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 1f026a0af6..7d853ce97e 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 @@ -1,4 +1,5 @@ import 'dart:collection'; + import 'package:app_flowy/workspace/application/grid/grid_service.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -13,9 +14,10 @@ typedef CellDataMap = LinkedHashMap; class RowBloc extends Bloc { final RowService _rowService; - final GridFieldCache _fieldCache; final GridRowCache _rowCache; + void Function()? _rowListenCallback; + void Function()? _fieldListenCallback; RowBloc({ required GridRow rowData, @@ -72,16 +74,23 @@ class RowBloc extends Bloc { @override Future close() async { + if (_rowListenCallback != null) { + _rowCache.removeRowListener(_rowListenCallback!); + } + + if (_fieldListenCallback != null) { + _fieldCache.removeListener(_fieldListenCallback!); + } return super.close(); } Future _startListening() async { - _fieldCache.addListener( + _fieldListenCallback = _fieldCache.addListener( listener: () => add(const RowEvent.fieldsDidUpdate()), listenWhen: () => !isClosed, ); - _rowCache.addRowListener( + _rowListenCallback = _rowCache.addRowListener( rowId: state.rowData.rowId, onUpdated: (row) => add(RowEvent.didUpdateRow(row)), listenWhen: () => !isClosed, 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 bed21d1691..9cb1ac81a9 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:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/log.dart'; @@ -8,61 +7,10 @@ import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; - import 'package:app_flowy/workspace/application/grid/grid_listener.dart'; part 'row_service.freezed.dart'; -class RowService { - final String gridId; - final String rowId; - - RowService({required this.gridId, required this.rowId}); - - Future> createRow() { - CreateRowPayload payload = CreateRowPayload.create() - ..gridId = gridId - ..startRowId = rowId; - - return GridEventCreateRow(payload).send(); - } - - Future> moveRow(String rowId, int fromIndex, int toIndex) { - final payload = MoveItemPayload.create() - ..gridId = gridId - ..itemId = rowId - ..ty = MoveItemType.MoveRow - ..fromIndex = fromIndex - ..toIndex = toIndex; - - return GridEventMoveItem(payload).send(); - } - - Future> getRow() { - final payload = RowIdentifierPayload.create() - ..gridId = gridId - ..rowId = rowId; - - return GridEventGetRow(payload).send(); - } - - Future> deleteRow() { - final payload = RowIdentifierPayload.create() - ..gridId = gridId - ..rowId = rowId; - - return GridEventDeleteRow(payload).send(); - } - - Future> duplicateRow() { - final payload = RowIdentifierPayload.create() - ..gridId = gridId - ..rowId = rowId; - - return GridEventDuplicateRow(payload).send(); - } -} - class RowsNotifier extends ChangeNotifier { List _rows = []; GridRowChangeReason _changeReason = const InitialListState(); @@ -84,13 +32,12 @@ class RowsNotifier extends ChangeNotifier { class GridRowCache { final String gridId; - late GridRowListener _rowsListener; + final GridRowListener _rowsListener; final RowsNotifier _rowNotifier = RowsNotifier(); final HashMap _rowDataMap = HashMap(); UnmodifiableListView _fields = UnmodifiableListView([]); - GridRowCache({required this.gridId}) { - _rowsListener = GridRowListener(gridId: gridId); + GridRowCache({required this.gridId}) : _rowsListener = GridRowListener(gridId: gridId) { _rowsListener.rowsUpdateNotifier.addPublishListener((result) { result.fold( (changesets) { @@ -106,18 +53,18 @@ class GridRowCache { _rowsListener.start(); } - List get clonedRows => [..._rowNotifier.rows]; - Future dispose() async { await _rowsListener.stop(); _rowNotifier.dispose(); } + List get clonedRows => [..._rowNotifier.rows]; + void addListener({ void Function(List, GridRowChangeReason)? onChanged, bool Function()? listenWhen, }) { - listener() { + _rowNotifier.addListener(() { if (listenWhen != null && listenWhen() == false) { return; } @@ -125,17 +72,15 @@ class GridRowCache { if (onChanged != null) { onChanged(clonedRows, _rowNotifier._changeReason); } - } - - _rowNotifier.addListener(listener); + }); } - void addRowListener({ + VoidCallback addRowListener({ required String rowId, void Function(Row)? onUpdated, bool Function()? listenWhen, }) { - _rowNotifier.addListener(() { + f() { if (onUpdated == null) { return; } @@ -145,13 +90,19 @@ class GridRowCache { } _rowNotifier._changeReason.whenOrNull(update: (indexs) { - final updatedIndex = indexs.firstWhereOrNull((updatedIndex) => updatedIndex.rowId == rowId); final row = _rowDataMap[rowId]; - if (updatedIndex != null && row != null) { + if (indexs[rowId] != null && row != null) { onUpdated(row); } }); - }); + } + + _rowNotifier.addListener(f); + return f; + } + + void removeRowListener(VoidCallback callback) { + _rowNotifier.removeListener(callback); } Future> getRowData(String rowId) async { @@ -234,7 +185,7 @@ class GridRowCache { return; } - final UpdatedIndexs updatedIndexs = []; + final UpdatedIndexs updatedIndexs = UpdatedIndexs(); final List newRows = _rowNotifier.rows; for (final rowOrder in updatedRows) { final index = newRows.indexWhere((row) => row.rowId == rowOrder.rowId); @@ -242,7 +193,7 @@ class GridRowCache { newRows.removeAt(index); newRows.insert(index, GridRow.fromBlockRow(gridId, rowOrder, _fields)); _rowDataMap.remove(rowOrder.rowId); - updatedIndexs.add(UpdatedIndex(index: index, rowId: rowOrder.rowId)); + updatedIndexs[rowOrder.rowId] = UpdatedIndex(index: index, rowId: rowOrder.rowId); } } @@ -250,6 +201,56 @@ class GridRowCache { } } +class RowService { + final String gridId; + final String rowId; + + RowService({required this.gridId, required this.rowId}); + + Future> createRow() { + CreateRowPayload payload = CreateRowPayload.create() + ..gridId = gridId + ..startRowId = rowId; + + return GridEventCreateRow(payload).send(); + } + + Future> moveRow(String rowId, int fromIndex, int toIndex) { + final payload = MoveItemPayload.create() + ..gridId = gridId + ..itemId = rowId + ..ty = MoveItemType.MoveRow + ..fromIndex = fromIndex + ..toIndex = toIndex; + + return GridEventMoveItem(payload).send(); + } + + Future> getRow() { + final payload = RowIdentifierPayload.create() + ..gridId = gridId + ..rowId = rowId; + + return GridEventGetRow(payload).send(); + } + + Future> deleteRow() { + final payload = RowIdentifierPayload.create() + ..gridId = gridId + ..rowId = rowId; + + return GridEventDeleteRow(payload).send(); + } + + Future> duplicateRow() { + final payload = RowIdentifierPayload.create() + ..gridId = gridId + ..rowId = rowId; + + return GridEventDuplicateRow(payload).send(); + } +} + @freezed class GridCellIdentifier with _$GridCellIdentifier { const factory GridCellIdentifier({ @@ -283,7 +284,7 @@ class GridRow with _$GridRow { typedef InsertedIndexs = List; typedef DeletedIndexs = List; -typedef UpdatedIndexs = List; +typedef UpdatedIndexs = LinkedHashMap; class InsertedIndex { int index;