From 9930706d9a354074f882ac902295e8318ab85a5a Mon Sep 17 00:00:00 2001 From: appflowy Date: Tue, 9 Aug 2022 19:06:15 +0800 Subject: [PATCH] refactor: separate cache from service file --- .../grid/application/block/block_cache.dart | 6 +- .../cell_service/cell_field_notifier.dart | 13 +- .../cell/cell_service/cell_service.dart | 3 +- .../cell/cell_service/context_builder.dart | 13 +- .../plugins/grid/application/grid_bloc.dart | 2 +- .../application/grid_data_controller.dart | 2 + .../grid/application/grid_header_bloc.dart | 3 +- .../grid/application/grid_service.dart | 190 ---------- .../row/row_action_sheet_bloc.dart | 2 + .../grid/application/row/row_bloc.dart | 1 + .../application/row/row_data_controller.dart | 4 +- .../grid/application/row/row_detail_bloc.dart | 3 +- .../grid/application/row/row_service.dart | 326 ------------------ .../application/setting/property_bloc.dart | 3 +- .../plugins/grid/presentation/grid_page.dart | 2 +- .../widgets/cell/cell_builder.dart | 2 +- .../widgets/cell/checkbox_cell.dart | 4 +- .../widgets/cell/date_cell/date_cell.dart | 4 +- .../widgets/cell/number_cell.dart | 4 +- .../select_option_cell.dart | 8 +- .../presentation/widgets/cell/text_cell.dart | 4 +- .../widgets/cell/url_cell/url_cell.dart | 4 +- .../widgets/header/grid_header.dart | 1 + .../presentation/widgets/row/grid_row.dart | 1 + .../widgets/row/row_action_sheet.dart | 2 +- .../presentation/widgets/row/row_detail.dart | 2 +- .../widgets/toolbar/grid_property.dart | 2 +- .../widgets/toolbar/grid_setting.dart | 2 +- .../widgets/toolbar/grid_toolbar.dart | 2 +- .../app_flowy/lib/startup/deps_resolver.dart | 2 + 30 files changed, 57 insertions(+), 560 deletions(-) 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 5ccff7c838..5569311228 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 @@ -1,9 +1,9 @@ import 'dart:async'; -import 'package:app_flowy/plugins/grid/application/grid_service.dart'; -import 'package:app_flowy/plugins/grid/application/row/row_service.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart'; +import '../field/field_cache.dart'; +import '../row/row_cache.dart'; import 'block_listener.dart'; /// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid for more information @@ -24,7 +24,7 @@ class GridBlockCache { _rowCache = GridRowCache( gridId: gridId, block: block, - notifier: GridRowCacheFieldNotifierImpl(fieldCache), + notifier: GridRowFieldNotifierImpl(fieldCache), ); _listener = GridBlockListener(blockId: block.id); diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_field_notifier.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_field_notifier.dart index 950832c674..1b2393671c 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_field_notifier.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/cell_field_notifier.dart @@ -3,20 +3,22 @@ import 'package:flutter/foundation.dart'; import 'cell_service.dart'; -abstract class IGridFieldChangedNotifier { - void onFieldChanged(void Function(GridFieldPB) callback); - void dispose(); +abstract class IGridCellFieldNotifier { + void onCellFieldChanged(void Function(GridFieldPB) callback); + void onCellDispose(); } /// GridPB's cell helper wrapper that enables each cell will get notified when the corresponding field was changed. /// You Register an onFieldChanged callback to listen to the cell changes, and unregister if you don't want to listen. class GridCellFieldNotifier { + final IGridCellFieldNotifier notifier; + /// fieldId: {objectId: callback} final Map>> _fieldListenerByFieldId = {}; - GridCellFieldNotifier({required IGridFieldChangedNotifier notifier}) { - notifier.onFieldChanged( + GridCellFieldNotifier({required this.notifier}) { + notifier.onCellFieldChanged( (field) { final map = _fieldListenerByFieldId[field.id]; if (map != null) { @@ -56,6 +58,7 @@ class GridCellFieldNotifier { } Future dispose() async { + notifier.onCellDispose(); _fieldListenerByFieldId.clear(); } } 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 2bef94c16a..106db1e754 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 @@ -1,7 +1,5 @@ import 'dart:async'; import 'dart:collection'; - -import 'package:app_flowy/plugins/grid/application/grid_service.dart'; import 'package:dartz/dartz.dart'; import 'package:equatable/equatable.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; @@ -18,6 +16,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_listener.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'dart:convert' show utf8; +import '../../field/field_cache.dart'; import '../../field/type_option/type_option_service.dart'; import 'cell_field_notifier.dart'; part 'cell_service.freezed.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart index 526213ee4d..12cadcca40 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/cell/cell_service/context_builder.dart @@ -21,8 +21,8 @@ class GridCellControllerBuilder { _cellId = cellId; IGridCellController build() { - final cellFieldNotifier = GridCellFieldNotifier( - notifier: _GridFieldChangedNotifierImpl(_fieldCache)); + final cellFieldNotifier = + GridCellFieldNotifier(notifier: GridCellFieldNotifierImpl(_fieldCache)); switch (_cellId.fieldType) { case FieldType.Checkbox: @@ -295,6 +295,7 @@ class IGridCellController extends Equatable { if (_onFieldChangedFn != null) { _fieldNotifier.unregister(_cacheKey, _onFieldChangedFn!); + _fieldNotifier.dispose(); _onFieldChangedFn = null; } } @@ -304,14 +305,14 @@ class IGridCellController extends Equatable { [_cellsCache.get(_cacheKey) ?? "", cellId.rowId + cellId.field.id]; } -class _GridFieldChangedNotifierImpl extends IGridFieldChangedNotifier { +class GridCellFieldNotifierImpl extends IGridCellFieldNotifier { final GridFieldCache _cache; FieldChangesetCallback? _onChangesetFn; - _GridFieldChangedNotifierImpl(GridFieldCache cache) : _cache = cache; + GridCellFieldNotifierImpl(GridFieldCache cache) : _cache = cache; @override - void dispose() { + void onCellDispose() { if (_onChangesetFn != null) { _cache.removeListener(onChangesetListener: _onChangesetFn!); _onChangesetFn = null; @@ -319,7 +320,7 @@ class _GridFieldChangedNotifierImpl extends IGridFieldChangedNotifier { } @override - void onFieldChanged(void Function(GridFieldPB p1) callback) { + void onCellFieldChanged(void Function(GridFieldPB p1) callback) { _onChangesetFn = (GridFieldChangesetPB changeset) { for (final updatedField in changeset.updatedFields) { callback(updatedField); 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 4516d01ba3..44881b9f54 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_bloc.dart @@ -8,7 +8,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'block/block_cache.dart'; import 'grid_data_controller.dart'; -import 'row/row_service.dart'; +import 'row/row_cache.dart'; import 'dart:collection'; part 'grid_bloc.freezed.dart'; 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 3563a13528..4833bc3ae0 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 @@ -9,7 +9,9 @@ import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; import 'block/block_cache.dart'; +import 'field/field_cache.dart'; import 'prelude.dart'; +import 'row/row_cache.dart'; typedef OnFieldsChanged = void Function(UnmodifiableListView); typedef OnGridChanged = void Function(GridPB); 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 06a6b791d8..a0ab1aa343 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,7 +4,8 @@ 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 'grid_service.dart'; + +import 'field/field_cache.dart'; part 'grid_header_bloc.freezed.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart b/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart index dff03f636e..6eaaab7be8 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/grid_service.dart @@ -1,17 +1,11 @@ -import 'dart:collection'; - -import 'package:app_flowy/plugins/grid/application/field/grid_listener.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -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 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; -import 'package:flutter/foundation.dart'; -import 'row/row_service.dart'; class GridService { final String gridId; @@ -46,187 +40,3 @@ class GridService { return FolderEventCloseView(request).send(); } } - -class FieldsNotifier extends ChangeNotifier { - List _fields = []; - - set fields(List fields) { - _fields = fields; - notifyListeners(); - } - - List get fields => _fields; -} - -typedef FieldChangesetCallback = void Function(GridFieldChangesetPB); -typedef FieldsCallback = void Function(List); - -class GridFieldCache { - final String gridId; - final GridFieldsListener _fieldListener; - FieldsNotifier? _fieldNotifier = FieldsNotifier(); - final Map _fieldsCallbackMap = {}; - final Map - _changesetCallbackMap = {}; - - GridFieldCache({required this.gridId}) - : _fieldListener = GridFieldsListener(gridId: gridId) { - _fieldListener.start(onFieldsChanged: (result) { - result.fold( - (changeset) { - _deleteFields(changeset.deletedFields); - _insertFields(changeset.insertedFields); - _updateFields(changeset.updatedFields); - for (final listener in _changesetCallbackMap.values) { - listener(changeset); - } - }, - (err) => Log.error(err), - ); - }); - } - - Future dispose() async { - await _fieldListener.stop(); - _fieldNotifier?.dispose(); - _fieldNotifier = null; - } - - UnmodifiableListView get unmodifiableFields => - UnmodifiableListView(_fieldNotifier?.fields ?? []); - - List get fields => [..._fieldNotifier?.fields ?? []]; - - set fields(List fields) { - _fieldNotifier?.fields = [...fields]; - } - - void addListener({ - FieldsCallback? onFields, - FieldChangesetCallback? onChangeset, - bool Function()? listenWhen, - }) { - if (onChangeset != null) { - fn(c) { - if (listenWhen != null && listenWhen() == false) { - return; - } - onChangeset(c); - } - - _changesetCallbackMap[onChangeset] = fn; - } - - if (onFields != null) { - fn() { - if (listenWhen != null && listenWhen() == false) { - return; - } - onFields(fields); - } - - _fieldsCallbackMap[onFields] = fn; - _fieldNotifier?.addListener(fn); - } - } - - void removeListener({ - FieldsCallback? onFieldsListener, - FieldChangesetCallback? onChangesetListener, - }) { - if (onFieldsListener != null) { - final fn = _fieldsCallbackMap.remove(onFieldsListener); - if (fn != null) { - _fieldNotifier?.removeListener(fn); - } - } - - if (onChangesetListener != null) { - _changesetCallbackMap.remove(onChangesetListener); - } - } - - void _deleteFields(List deletedFields) { - if (deletedFields.isEmpty) { - return; - } - final List newFields = fields; - final Map deletedFieldMap = { - for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder - }; - - newFields.retainWhere((field) => (deletedFieldMap[field.id] == null)); - _fieldNotifier?.fields = newFields; - } - - void _insertFields(List insertedFields) { - if (insertedFields.isEmpty) { - return; - } - final List newFields = fields; - for (final indexField in insertedFields) { - if (newFields.length > indexField.index) { - newFields.insert(indexField.index, indexField.field_1); - } else { - newFields.add(indexField.field_1); - } - } - _fieldNotifier?.fields = newFields; - } - - void _updateFields(List updatedFields) { - if (updatedFields.isEmpty) { - return; - } - final List newFields = fields; - for (final updatedField in updatedFields) { - final index = - newFields.indexWhere((field) => field.id == updatedField.id); - if (index != -1) { - newFields.removeAt(index); - newFields.insert(index, updatedField); - } - } - _fieldNotifier?.fields = newFields; - } -} - -class GridRowCacheFieldNotifierImpl extends GridRowCacheFieldNotifier { - final GridFieldCache _cache; - FieldChangesetCallback? _onChangesetFn; - FieldsCallback? _onFieldFn; - GridRowCacheFieldNotifierImpl(GridFieldCache cache) : _cache = cache; - - @override - UnmodifiableListView get fields => _cache.unmodifiableFields; - - @override - void onFieldsChanged(VoidCallback callback) { - _onFieldFn = (_) => callback(); - _cache.addListener(onFields: _onFieldFn); - } - - @override - void onFieldChanged(void Function(GridFieldPB) callback) { - _onChangesetFn = (GridFieldChangesetPB changeset) { - for (final updatedField in changeset.updatedFields) { - callback(updatedField); - } - }; - - _cache.addListener(onChangeset: _onChangesetFn); - } - - @override - void dispose() { - if (_onFieldFn != null) { - _cache.removeListener(onFieldsListener: _onFieldFn!); - _onFieldFn = null; - } - - if (_onChangesetFn != null) { - _cache.removeListener(onChangesetListener: _onChangesetFn!); - _onChangesetFn = null; - } - } -} diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart index 7881e485cb..cedd426348 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_action_sheet_bloc.dart @@ -6,6 +6,8 @@ import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; import 'package:dartz/dartz.dart'; +import 'row_cache.dart'; + part 'row_action_sheet_bloc.freezed.dart'; class RowActionSheetBloc 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 b6079b6764..b2579930ad 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 @@ -5,6 +5,7 @@ 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 'row_cache.dart'; import 'row_data_controller.dart'; import 'row_service.dart'; 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 fb05ff5920..6975bd6a51 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 @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import '../cell/cell_service/cell_service.dart'; -import '../grid_service.dart'; -import 'row_service.dart'; +import '../field/field_cache.dart'; +import 'row_cache.dart'; typedef OnRowChanged = void Function(GridCellMap, GridRowChangeReason); diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_detail_bloc.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_detail_bloc.dart index 900b56f9a5..17f6ef4990 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_detail_bloc.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_detail_bloc.dart @@ -2,8 +2,7 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_servic import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'dart:async'; -import 'row_service.dart'; - +import 'row_cache.dart'; part 'row_detail_bloc.freezed.dart'; class RowDetailBloc extends Bloc { diff --git a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart index d72a05089a..2dce917da4 100644 --- a/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart +++ b/frontend/app_flowy/lib/plugins/grid/application/row/row_service.dart @@ -1,283 +1,9 @@ -import 'dart:collection'; -import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; -import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.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 'package:flowy_sdk/protobuf/flowy-grid/row_entities.pb.dart'; -import 'package:flutter/foundation.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -part 'row_service.freezed.dart'; - -typedef RowUpdateCallback = void Function(); - -abstract class GridRowCacheFieldNotifier { - UnmodifiableListView get fields; - void onFieldsChanged(VoidCallback callback); - void onFieldChanged(void Function(GridFieldPB) callback); - void dispose(); -} - -/// Cache the rows in memory -/// Insert / delete / update row -/// -/// Read https://appflowy.gitbook.io/docs/essential-documentation/contribute-to-appflowy/architecture/frontend/grid for more information. - -class GridRowCache { - final String gridId; - final GridBlockPB block; - - /// _rows containers the current block's rows - /// Use List to reverse the order of the GridRow. - List _rowInfos = []; - - /// Use Map for faster access the raw row data. - final HashMap _rowByRowId; - - final GridCellCache _cellCache; - final GridRowCacheFieldNotifier _fieldNotifier; - final _GridRowChangesetNotifier _rowChangeReasonNotifier; - - UnmodifiableListView get rows => UnmodifiableListView(_rowInfos); - GridCellCache get cellCache => _cellCache; - - GridRowCache({ - required this.gridId, - required this.block, - required GridRowCacheFieldNotifier notifier, - }) : _cellCache = GridCellCache(gridId: gridId), - _rowByRowId = HashMap(), - _rowChangeReasonNotifier = _GridRowChangesetNotifier(), - _fieldNotifier = notifier { - // - notifier.onFieldsChanged(() => _rowChangeReasonNotifier - .receive(const GridRowChangeReason.fieldDidChange())); - notifier.onFieldChanged((field) => _cellCache.remove(field.id)); - _rowInfos = block.rows - .map((rowInfo) => buildGridRow(rowInfo.id, rowInfo.height.toDouble())) - .toList(); - } - - Future dispose() async { - _fieldNotifier.dispose(); - _rowChangeReasonNotifier.dispose(); - await _cellCache.dispose(); - } - - void applyChangesets(List changesets) { - for (final changeset in changesets) { - _deleteRows(changeset.deletedRows); - _insertRows(changeset.insertedRows); - _updateRows(changeset.updatedRows); - _hideRows(changeset.hideRows); - _showRows(changeset.visibleRows); - } - } - - void _deleteRows(List deletedRows) { - if (deletedRows.isEmpty) { - return; - } - - final List newRows = []; - final DeletedIndexs deletedIndex = []; - final Map deletedRowByRowId = { - for (var rowId in deletedRows) rowId: rowId - }; - - _rowInfos.asMap().forEach((index, row) { - if (deletedRowByRowId[row.id] == null) { - newRows.add(row); - } else { - _rowByRowId.remove(row.id); - deletedIndex.add(DeletedIndex(index: index, row: row)); - } - }); - _rowInfos = newRows; - _rowChangeReasonNotifier.receive(GridRowChangeReason.delete(deletedIndex)); - } - - void _insertRows(List insertRows) { - if (insertRows.isEmpty) { - return; - } - - InsertedIndexs insertIndexs = []; - for (final insertRow in insertRows) { - final insertIndex = InsertedIndex( - index: insertRow.index, - rowId: insertRow.rowId, - ); - insertIndexs.add(insertIndex); - _rowInfos.insert(insertRow.index, - (buildGridRow(insertRow.rowId, insertRow.height.toDouble()))); - } - - _rowChangeReasonNotifier.receive(GridRowChangeReason.insert(insertIndexs)); - } - - void _updateRows(List updatedRows) { - if (updatedRows.isEmpty) { - return; - } - - final UpdatedIndexs updatedIndexs = UpdatedIndexs(); - for (final updatedRow in updatedRows) { - final rowId = updatedRow.rowId; - final index = _rowInfos.indexWhere((row) => row.id == rowId); - if (index != -1) { - _rowByRowId[rowId] = updatedRow.row; - - _rowInfos.removeAt(index); - _rowInfos.insert( - index, buildGridRow(rowId, updatedRow.row.height.toDouble())); - updatedIndexs[rowId] = UpdatedIndex(index: index, rowId: rowId); - } - } - - _rowChangeReasonNotifier.receive(GridRowChangeReason.update(updatedIndexs)); - } - - void _hideRows(List hideRows) {} - - void _showRows(List visibleRows) {} - - void onRowsChanged( - void Function(GridRowChangeReason) onRowChanged, - ) { - _rowChangeReasonNotifier.addListener(() { - onRowChanged(_rowChangeReasonNotifier.reason); - }); - } - - RowUpdateCallback addListener({ - required String rowId, - void Function(GridCellMap, GridRowChangeReason)? onCellUpdated, - bool Function()? listenWhen, - }) { - listenerHandler() async { - if (listenWhen != null && listenWhen() == false) { - return; - } - - notifyUpdate() { - if (onCellUpdated != null) { - final row = _rowByRowId[rowId]; - if (row != null) { - final GridCellMap cellDataMap = _makeGridCells(rowId, row); - onCellUpdated(cellDataMap, _rowChangeReasonNotifier.reason); - } - } - } - - _rowChangeReasonNotifier.reason.whenOrNull( - update: (indexs) { - if (indexs[rowId] != null) notifyUpdate(); - }, - fieldDidChange: () => notifyUpdate(), - ); - } - - _rowChangeReasonNotifier.addListener(listenerHandler); - return listenerHandler; - } - - void removeRowListener(VoidCallback callback) { - _rowChangeReasonNotifier.removeListener(callback); - } - - GridCellMap loadGridCells(String rowId) { - final GridRowPB? data = _rowByRowId[rowId]; - if (data == null) { - _loadRow(rowId); - } - return _makeGridCells(rowId, data); - } - - Future _loadRow(String rowId) async { - final payload = GridRowIdPB.create() - ..gridId = gridId - ..blockId = block.id - ..rowId = rowId; - - final result = await GridEventGetRow(payload).send(); - result.fold( - (optionRow) => _refreshRow(optionRow), - (err) => Log.error(err), - ); - } - - GridCellMap _makeGridCells(String rowId, GridRowPB? row) { - var cellDataMap = GridCellMap.new(); - for (final field in _fieldNotifier.fields) { - if (field.visibility) { - cellDataMap[field.id] = GridCellIdentifier( - rowId: rowId, - gridId: gridId, - field: field, - ); - } - } - return cellDataMap; - } - - void _refreshRow(OptionalRowPB optionRow) { - if (!optionRow.hasRow()) { - return; - } - final updatedRow = optionRow.row; - updatedRow.freeze(); - - _rowByRowId[updatedRow.id] = updatedRow; - final index = - _rowInfos.indexWhere((gridRow) => gridRow.id == updatedRow.id); - if (index != -1) { - // update the corresponding row in _rows if they are not the same - if (_rowInfos[index].rawRow != updatedRow) { - final row = _rowInfos.removeAt(index).copyWith(rawRow: updatedRow); - _rowInfos.insert(index, row); - - // Calculate the update index - final UpdatedIndexs updatedIndexs = UpdatedIndexs(); - updatedIndexs[row.id] = UpdatedIndex(index: index, rowId: row.id); - - // - _rowChangeReasonNotifier - .receive(GridRowChangeReason.update(updatedIndexs)); - } - } - } - - GridRowInfo buildGridRow(String rowId, double rowHeight) { - return GridRowInfo( - gridId: gridId, - blockId: block.id, - fields: _fieldNotifier.fields, - id: rowId, - height: rowHeight, - ); - } -} - -class _GridRowChangesetNotifier extends ChangeNotifier { - GridRowChangeReason reason = const InitialListState(); - - _GridRowChangesetNotifier(); - - void receive(GridRowChangeReason newReason) { - reason = newReason; - reason.map( - insert: (_) => notifyListeners(), - delete: (_) => notifyListeners(), - update: (_) => notifyListeners(), - fieldDidChange: (_) => notifyListeners(), - initial: (_) {}, - ); - } -} class RowService { final String gridId; @@ -334,55 +60,3 @@ class RowService { return GridEventDuplicateRow(payload).send(); } } - -@freezed -class GridRowInfo with _$GridRowInfo { - const factory GridRowInfo({ - required String gridId, - required String blockId, - required String id, - required UnmodifiableListView fields, - required double height, - GridRowPB? rawRow, - }) = _GridRowInfo; -} - -typedef InsertedIndexs = List; -typedef DeletedIndexs = List; -typedef UpdatedIndexs = LinkedHashMap; - -@freezed -class GridRowChangeReason with _$GridRowChangeReason { - const factory GridRowChangeReason.insert(InsertedIndexs items) = _Insert; - const factory GridRowChangeReason.delete(DeletedIndexs items) = _Delete; - const factory GridRowChangeReason.update(UpdatedIndexs indexs) = _Update; - const factory GridRowChangeReason.fieldDidChange() = _FieldDidChange; - const factory GridRowChangeReason.initial() = InitialListState; -} - -class InsertedIndex { - final int index; - final String rowId; - InsertedIndex({ - required this.index, - required this.rowId, - }); -} - -class DeletedIndex { - final int index; - final GridRowInfo row; - DeletedIndex({ - required this.index, - required this.row, - }); -} - -class UpdatedIndex { - final int index; - final String rowId; - UpdatedIndex({ - required this.index, - required this.rowId, - }); -} 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 7c185279ae..972b64f69a 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,11 +1,12 @@ import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; -import 'package:app_flowy/plugins/grid/application/grid_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'; +import '../field/field_cache.dart'; + part 'property_bloc.freezed.dart'; class GridPropertyBloc extends Bloc { 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 d267e4aca9..c4fbbf4e92 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/grid_page.dart @@ -1,7 +1,6 @@ import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/grid_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/row/row_service.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; @@ -12,6 +11,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter/material.dart'; import 'package:linked_scroll_controller/linked_scroll_controller.dart'; +import '../application/row/row_cache.dart'; import 'controller/grid_scroll.dart'; import 'layout/layout.dart'; import 'layout/sizes.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart index c53bee8423..1220d39a9d 100755 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/cell_builder.dart @@ -1,5 +1,5 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; -import 'package:app_flowy/plugins/grid/application/grid_service.dart'; +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart index d334cc38af..ac80303f0d 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/checkbox_cell.dart @@ -22,8 +22,8 @@ class _CheckboxCellState extends GridCellState { @override void initState() { - final cellContext = widget.cellControllerBuilder.build(); - _cellBloc = getIt(param1: cellContext) + final cellController = widget.cellControllerBuilder.build(); + _cellBloc = getIt(param1: cellController) ..add(const CheckboxCellEvent.initial()); super.initState(); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart index 3254f58e6c..94e8ceeb71 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/date_cell/date_cell.dart @@ -43,8 +43,8 @@ class _DateCellState extends GridCellState { @override void initState() { - final cellContext = widget.cellControllerBuilder.build(); - _cellBloc = getIt(param1: cellContext) + final cellController = widget.cellControllerBuilder.build(); + _cellBloc = getIt(param1: cellController) ..add(const DateCellEvent.initial()); super.initState(); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart index a24243ef99..004c34b657 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/number_cell.dart @@ -25,8 +25,8 @@ class _NumberCellState extends GridFocusNodeCellState { @override void initState() { - final cellContext = widget.cellControllerBuilder.build(); - _cellBloc = getIt(param1: cellContext) + final cellController = widget.cellControllerBuilder.build(); + _cellBloc = getIt(param1: cellController) ..add(const NumberCellEvent.initial()); _controller = TextEditingController(text: contentFromState(_cellBloc.state)); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart index f4ebfa8d4d..a4e09ec0b9 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/select_option_cell/select_option_cell.dart @@ -46,9 +46,9 @@ class _SingleSelectCellState extends State { @override void initState() { - final cellContext = + final cellController = widget.cellControllerBuilder.build() as GridSelectOptionCellController; - _cellBloc = getIt(param1: cellContext) + _cellBloc = getIt(param1: cellController) ..add(const SelectOptionCellEvent.initial()); super.initState(); } @@ -102,9 +102,9 @@ class _MultiSelectCellState extends State { @override void initState() { - final cellContext = + final cellController = widget.cellControllerBuilder.build() as GridSelectOptionCellController; - _cellBloc = getIt(param1: cellContext) + _cellBloc = getIt(param1: cellController) ..add(const SelectOptionCellEvent.initial()); super.initState(); } diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart index 21f9c60631..04be48b9ea 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/text_cell.dart @@ -39,8 +39,8 @@ class _GridTextCellState extends GridFocusNodeCellState { @override void initState() { - final cellContext = widget.cellControllerBuilder.build(); - _cellBloc = getIt(param1: cellContext); + final cellController = widget.cellControllerBuilder.build(); + _cellBloc = getIt(param1: cellController); _cellBloc.add(const TextCellEvent.initial()); _controller = TextEditingController(text: _cellBloc.state.content); super.initState(); diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart index 506cc3bc2b..7295228daf 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/cell/url_cell/url_cell.dart @@ -52,10 +52,10 @@ class GridURLCell extends GridCellWidget { GridURLCellAccessoryType ty, GridCellAccessoryBuildContext buildContext) { switch (ty) { case GridURLCellAccessoryType.edit: - final cellContext = + final cellController = cellControllerBuilder.build() as GridURLCellController; return _EditURLAccessory( - cellContext: cellContext, + cellContext: cellController, anchorContext: buildContext.anchorContext); case GridURLCellAccessoryType.copyURL: 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 df7be4ee2b..caa40b2e7a 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 @@ -1,3 +1,4 @@ +import 'package:app_flowy/plugins/grid/application/field/field_cache.dart'; import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/prelude.dart'; import 'package:flowy_infra/image.dart'; 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 d37a45d210..7ea59ab7e9 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 @@ -1,4 +1,5 @@ import 'package:app_flowy/plugins/grid/application/prelude.dart'; +import 'package:app_flowy/plugins/grid/application/row/row_cache.dart'; import 'package:app_flowy/plugins/grid/application/row/row_data_controller.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; diff --git a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart index 67c7b4893b..9c31bab5f3 100644 --- a/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart +++ b/frontend/app_flowy/lib/plugins/grid/presentation/widgets/row/row_action_sheet.dart @@ -1,5 +1,4 @@ import 'package:app_flowy/plugins/grid/application/row/row_action_sheet_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/row/row_service.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; import 'package:flowy_infra/image.dart'; @@ -12,6 +11,7 @@ import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import '../../../application/row/row_cache.dart'; import '../../layout/sizes.dart'; class GridRowActionSheet extends StatelessWidget { 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 b45457fffd..6394b98874 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 @@ -1,7 +1,6 @@ import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; import 'package:app_flowy/plugins/grid/application/row/row_detail_bloc.dart'; -import 'package:app_flowy/plugins/grid/application/row/row_service.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -14,6 +13,7 @@ import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import '../../../application/row/row_cache.dart'; import '../../layout/sizes.dart'; import '../cell/cell_accessory.dart'; import '../cell/prelude.dart'; 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 df4eb2115c..28f2b860ff 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 @@ -1,6 +1,5 @@ import 'package:app_flowy/startup/startup.dart'; import 'package:app_flowy/plugins/grid/application/field/field_service.dart'; -import 'package:app_flowy/plugins/grid/application/grid_service.dart'; import 'package:app_flowy/plugins/grid/application/setting/property_bloc.dart'; import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart'; import 'package:flowy_infra/image.dart'; @@ -15,6 +14,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:styled_widget/styled_widget.dart'; +import '../../../application/field/field_cache.dart'; import '../../layout/sizes.dart'; import '../header/field_editor.dart'; 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 d7c084fe2d..f555b6266a 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 @@ -1,4 +1,3 @@ -import 'package:app_flowy/plugins/grid/application/grid_service.dart'; import 'package:app_flowy/plugins/grid/application/setting/setting_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/image.dart'; @@ -12,6 +11,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; +import '../../../application/field/field_cache.dart'; import '../../layout/sizes.dart'; import 'grid_property.dart'; 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 2f332ffe2f..4ced06bf99 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 @@ -1,4 +1,3 @@ -import 'package:app_flowy/plugins/grid/application/grid_service.dart'; import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra_ui/style_widget/extension.dart'; @@ -6,6 +5,7 @@ import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import '../../../application/field/field_cache.dart'; import '../../layout/sizes.dart'; import 'grid_setting.dart'; diff --git a/frontend/app_flowy/lib/startup/deps_resolver.dart b/frontend/app_flowy/lib/startup/deps_resolver.dart index 8b173a4002..7062a9f3a8 100644 --- a/frontend/app_flowy/lib/startup/deps_resolver.dart +++ b/frontend/app_flowy/lib/startup/deps_resolver.dart @@ -21,6 +21,8 @@ import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:get_it/get_it.dart'; +import '../plugins/grid/application/field/field_cache.dart'; + class DependencyResolver { static Future resolve(GetIt getIt) async { _resolveUserDeps(getIt);