mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
Merge pull request #584 from AppFlowy-IO/refactor/grid_block_cache
refactor: grid block cache
This commit is contained in:
commit
6fc7f63a8b
@ -1,58 +1,21 @@
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:typed_data';
|
||||
|
||||
import 'package:app_flowy/core/notification_helper.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_infra/notifier.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/dart_notification.pb.dart';
|
||||
|
||||
class GridBlockCache {
|
||||
final String gridId;
|
||||
void Function(GridBlockUpdateNotifierValue)? _onBlockChanged;
|
||||
final LinkedHashMap<String, _GridBlockListener> _listeners = LinkedHashMap();
|
||||
GridBlockCache({required this.gridId});
|
||||
|
||||
void start(void Function(GridBlockUpdateNotifierValue) onBlockChanged) {
|
||||
_onBlockChanged = onBlockChanged;
|
||||
for (final listener in _listeners.values) {
|
||||
listener.start(onBlockChanged);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
for (final listener in _listeners.values) {
|
||||
await listener.stop();
|
||||
}
|
||||
}
|
||||
|
||||
void addBlockListener(String blockId) {
|
||||
if (_onBlockChanged == null) {
|
||||
Log.error("Should call start() first");
|
||||
return;
|
||||
}
|
||||
if (_listeners.containsKey(blockId)) {
|
||||
Log.error("Duplicate block listener");
|
||||
return;
|
||||
}
|
||||
|
||||
final listener = _GridBlockListener(blockId: blockId);
|
||||
listener.start(_onBlockChanged!);
|
||||
_listeners[blockId] = listener;
|
||||
}
|
||||
}
|
||||
|
||||
typedef GridBlockUpdateNotifierValue = Either<List<GridRowsChangeset>, FlowyError>;
|
||||
|
||||
class _GridBlockListener {
|
||||
class GridBlockListener {
|
||||
final String blockId;
|
||||
PublishNotifier<GridBlockUpdateNotifierValue>? _rowsUpdateNotifier = PublishNotifier();
|
||||
GridNotificationListener? _listener;
|
||||
|
||||
_GridBlockListener({required this.blockId});
|
||||
GridBlockListener({required this.blockId});
|
||||
|
||||
void start(void Function(GridBlockUpdateNotifierValue) onBlockChanged) {
|
||||
if (_listener != null) {
|
||||
|
@ -0,0 +1,55 @@
|
||||
import 'dart:async';
|
||||
import 'package:app_flowy/workspace/application/grid/grid_service.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
|
||||
|
||||
import 'block_listener.dart';
|
||||
|
||||
class GridBlockCacheService {
|
||||
final String gridId;
|
||||
final GridBlock block;
|
||||
late GridRowCacheService _rowCache;
|
||||
late GridBlockListener _listener;
|
||||
|
||||
List<GridRow> get rows => _rowCache.rows;
|
||||
GridRowCacheService get rowCache => _rowCache;
|
||||
|
||||
GridBlockCacheService({
|
||||
required this.gridId,
|
||||
required this.block,
|
||||
required GridFieldCache fieldCache,
|
||||
}) {
|
||||
_rowCache = GridRowCacheService(
|
||||
gridId: gridId,
|
||||
block: block,
|
||||
delegate: GridRowCacheDelegateImpl(fieldCache),
|
||||
);
|
||||
|
||||
_listener = GridBlockListener(blockId: block.id);
|
||||
_listener.start((result) {
|
||||
result.fold(
|
||||
(changesets) => _rowCache.applyChangesets(changesets),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
await _listener.stop();
|
||||
await _rowCache.dispose();
|
||||
}
|
||||
|
||||
void addListener({
|
||||
required void Function(GridRowChangeReason) onChangeReason,
|
||||
bool Function()? listenWhen,
|
||||
}) {
|
||||
_rowCache.onRowsChanged((reason) {
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
onChangeReason(reason);
|
||||
});
|
||||
}
|
||||
}
|
@ -20,27 +20,26 @@ class _GridCellCacheKey {
|
||||
});
|
||||
}
|
||||
|
||||
abstract class GridCellFieldDelegate {
|
||||
void onFieldChanged(void Function(String) callback);
|
||||
void dispose();
|
||||
abstract class GridCellCacheDelegate {
|
||||
void onFieldUpdated(void Function(Field) callback);
|
||||
}
|
||||
|
||||
class GridCellCache {
|
||||
class GridCellCacheService {
|
||||
final String gridId;
|
||||
final GridCellFieldDelegate fieldDelegate;
|
||||
final GridCellCacheDelegate delegate;
|
||||
|
||||
/// fieldId: {objectId: callback}
|
||||
final Map<String, Map<String, List<VoidCallback>>> _fieldListenerByFieldId = {};
|
||||
|
||||
/// fieldId: {cacheKey: cacheData}
|
||||
final Map<String, Map<String, dynamic>> _cellDataByFieldId = {};
|
||||
GridCellCache({
|
||||
GridCellCacheService({
|
||||
required this.gridId,
|
||||
required this.fieldDelegate,
|
||||
required this.delegate,
|
||||
}) {
|
||||
fieldDelegate.onFieldChanged((fieldId) {
|
||||
_cellDataByFieldId.remove(fieldId);
|
||||
final map = _fieldListenerByFieldId[fieldId];
|
||||
delegate.onFieldUpdated((field) {
|
||||
_cellDataByFieldId.remove(field.id);
|
||||
final map = _fieldListenerByFieldId[field.id];
|
||||
if (map != null) {
|
||||
for (final callbacks in map.values) {
|
||||
for (final callback in callbacks) {
|
||||
@ -106,6 +105,5 @@ class GridCellCache {
|
||||
Future<void> dispose() async {
|
||||
_fieldListenerByFieldId.clear();
|
||||
_cellDataByFieldId.clear();
|
||||
fieldDelegate.dispose();
|
||||
}
|
||||
}
|
@ -20,7 +20,7 @@ import 'dart:convert' show utf8;
|
||||
part 'cell_service.freezed.dart';
|
||||
part 'cell_data_loader.dart';
|
||||
part 'context_builder.dart';
|
||||
part 'cell_data_cache.dart';
|
||||
part 'cache.dart';
|
||||
part 'cell_data_persistence.dart';
|
||||
|
||||
// key: rowId
|
||||
|
@ -6,10 +6,10 @@ typedef GridDateCellContext = _GridCellContext<DateCellData, CalendarData>;
|
||||
typedef GridURLCellContext = _GridCellContext<URLCellData, String>;
|
||||
|
||||
class GridCellContextBuilder {
|
||||
final GridCellCache _cellCache;
|
||||
final GridCellCacheService _cellCache;
|
||||
final GridCell _gridCell;
|
||||
GridCellContextBuilder({
|
||||
required GridCellCache cellCache,
|
||||
required GridCellCacheService cellCache,
|
||||
required GridCell gridCell,
|
||||
}) : _cellCache = cellCache,
|
||||
_gridCell = gridCell;
|
||||
@ -99,7 +99,7 @@ class GridCellContextBuilder {
|
||||
// ignore: must_be_immutable
|
||||
class _GridCellContext<T, D> extends Equatable {
|
||||
final GridCell gridCell;
|
||||
final GridCellCache cellCache;
|
||||
final GridCellCacheService cellCache;
|
||||
final _GridCellCacheKey _cacheKey;
|
||||
final IGridCellDataLoader<T> cellDataLoader;
|
||||
final _GridCellDataPersistence<D> cellDataPersistence;
|
||||
|
@ -7,8 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
||||
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_listener.dart';
|
||||
import 'cell/cell_service/cell_service.dart';
|
||||
import 'block/block_service.dart';
|
||||
import 'grid_service.dart';
|
||||
import 'row/row_service.dart';
|
||||
import 'dart:collection';
|
||||
@ -16,36 +15,27 @@ import 'dart:collection';
|
||||
part 'grid_bloc.freezed.dart';
|
||||
|
||||
class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
final String gridId;
|
||||
final GridService _gridService;
|
||||
final GridFieldCache fieldCache;
|
||||
late final GridRowCache rowCache;
|
||||
late final GridCellCache cellCache;
|
||||
|
||||
final GridBlockCache blockCache;
|
||||
// key: the block id
|
||||
final LinkedHashMap<String, GridBlockCacheService> _blocks;
|
||||
|
||||
List<GridRow> get rows {
|
||||
final List<GridRow> rows = [];
|
||||
for (var block in _blocks.values) {
|
||||
rows.addAll(block.rows);
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
GridBloc({required View view})
|
||||
: _gridService = GridService(gridId: view.id),
|
||||
: gridId = view.id,
|
||||
_blocks = LinkedHashMap.identity(),
|
||||
_gridService = GridService(gridId: view.id),
|
||||
fieldCache = GridFieldCache(gridId: view.id),
|
||||
blockCache = GridBlockCache(gridId: view.id),
|
||||
super(GridState.initial(view.id)) {
|
||||
rowCache = GridRowCache(
|
||||
gridId: view.id,
|
||||
blockId: "",
|
||||
fieldDelegate: GridRowCacheDelegateImpl(fieldCache),
|
||||
);
|
||||
|
||||
cellCache = GridCellCache(
|
||||
gridId: view.id,
|
||||
fieldDelegate: GridCellCacheDelegateImpl(fieldCache),
|
||||
);
|
||||
|
||||
blockCache.start((result) {
|
||||
result.fold(
|
||||
(changesets) => rowCache.applyChangesets(changesets),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
|
||||
on<GridEvent>(
|
||||
(event, emit) async {
|
||||
await event.when(
|
||||
@ -56,11 +46,11 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
createRow: () {
|
||||
_gridService.createRow();
|
||||
},
|
||||
didReceiveRowUpdate: (rows, listState) {
|
||||
emit(state.copyWith(rows: rows, listState: listState));
|
||||
didReceiveRowUpdate: (rows, reason) {
|
||||
emit(state.copyWith(rows: rows, reason: reason));
|
||||
},
|
||||
didReceiveFieldUpdate: (fields) {
|
||||
emit(state.copyWith(rows: rowCache.clonedRows, fields: GridFieldEquatable(fields)));
|
||||
emit(state.copyWith(rows: rows, fields: GridFieldEquatable(fields)));
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -70,22 +60,23 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await _gridService.closeGrid();
|
||||
await cellCache.dispose();
|
||||
await rowCache.dispose();
|
||||
await fieldCache.dispose();
|
||||
await blockCache.dispose();
|
||||
|
||||
for (final blockCache in _blocks.values) {
|
||||
blockCache.dispose();
|
||||
}
|
||||
return super.close();
|
||||
}
|
||||
|
||||
GridRowCacheService? getRowCache(String blockId, String rowId) {
|
||||
final GridBlockCacheService? blockCache = _blocks[blockId];
|
||||
return blockCache?.rowCache;
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
fieldCache.addListener(
|
||||
listenWhen: () => !isClosed,
|
||||
onChanged: (fields) => add(GridEvent.didReceiveFieldUpdate(fields)),
|
||||
);
|
||||
|
||||
rowCache.addListener(
|
||||
listenWhen: () => !isClosed,
|
||||
onChanged: (rows, listState) => add(GridEvent.didReceiveRowUpdate(rowCache.clonedRows, listState)),
|
||||
onFields: (fields) => add(GridEvent.didReceiveFieldUpdate(fields)),
|
||||
);
|
||||
}
|
||||
|
||||
@ -94,12 +85,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
return Future(
|
||||
() => result.fold(
|
||||
(grid) async {
|
||||
for (final block in grid.blocks) {
|
||||
blockCache.addBlockListener(block.id);
|
||||
}
|
||||
final rowInfos = grid.blocks.expand((block) => block.rowInfos).toList();
|
||||
rowCache.initialRows(rowInfos);
|
||||
|
||||
_initialBlocks(grid.blocks);
|
||||
await _loadFields(grid, emit);
|
||||
},
|
||||
(err) => emit(state.copyWith(loadingState: GridLoadingState.finish(right(err)))),
|
||||
@ -117,7 +103,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
emit(state.copyWith(
|
||||
grid: Some(grid),
|
||||
fields: GridFieldEquatable(fieldCache.fields),
|
||||
rows: rowCache.clonedRows,
|
||||
rows: rows,
|
||||
loadingState: GridLoadingState.finish(left(unit)),
|
||||
));
|
||||
},
|
||||
@ -125,6 +111,28 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _initialBlocks(List<GridBlock> blocks) {
|
||||
for (final block in blocks) {
|
||||
if (_blocks[block.id] != null) {
|
||||
Log.warn("Intial duplicate block's cache: ${block.id}");
|
||||
return;
|
||||
}
|
||||
|
||||
final cache = GridBlockCacheService(
|
||||
gridId: gridId,
|
||||
block: block,
|
||||
fieldCache: fieldCache,
|
||||
);
|
||||
|
||||
cache.addListener(
|
||||
listenWhen: () => !isClosed,
|
||||
onChangeReason: (reason) => add(GridEvent.didReceiveRowUpdate(rows, reason)),
|
||||
);
|
||||
|
||||
_blocks[block.id] = cache;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -143,7 +151,7 @@ class GridState with _$GridState {
|
||||
required GridFieldEquatable fields,
|
||||
required List<GridRow> rows,
|
||||
required GridLoadingState loadingState,
|
||||
required GridRowChangeReason listState,
|
||||
required GridRowChangeReason reason,
|
||||
}) = _GridState;
|
||||
|
||||
factory GridState.initial(String gridId) => GridState(
|
||||
@ -152,7 +160,7 @@ class GridState with _$GridState {
|
||||
grid: none(),
|
||||
gridId: gridId,
|
||||
loadingState: const _Loading(),
|
||||
listState: const InitialListState(),
|
||||
reason: const InitialListState(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
||||
|
||||
Future<void> _startListening() async {
|
||||
fieldCache.addListener(
|
||||
onChanged: (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)),
|
||||
onFields: (fields) => add(GridHeaderEvent.didReceiveFieldUpdate(fields)),
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ 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 'cell/cell_service/cell_service.dart';
|
||||
import 'row/row_service.dart';
|
||||
|
||||
class GridService {
|
||||
@ -57,13 +56,15 @@ class FieldsNotifier extends ChangeNotifier {
|
||||
List<Field> get fields => _fields;
|
||||
}
|
||||
|
||||
typedef ChangesetListener = void Function(GridFieldChangeset);
|
||||
typedef FieldChangesetCallback = void Function(GridFieldChangeset);
|
||||
typedef FieldsCallback = void Function(List<Field>);
|
||||
|
||||
class GridFieldCache {
|
||||
final String gridId;
|
||||
late final GridFieldsListener _fieldListener;
|
||||
FieldsNotifier? _fieldNotifier = FieldsNotifier();
|
||||
final List<ChangesetListener> _changesetListener = [];
|
||||
final Map<FieldsCallback, VoidCallback> _fieldsCallbackMap = {};
|
||||
final Map<FieldChangesetCallback, FieldChangesetCallback> _changesetCallbackMap = {};
|
||||
|
||||
GridFieldCache({required this.gridId}) {
|
||||
_fieldListener = GridFieldsListener(gridId: gridId);
|
||||
@ -73,7 +74,7 @@ class GridFieldCache {
|
||||
_deleteFields(changeset.deletedFields);
|
||||
_insertFields(changeset.insertedFields);
|
||||
_updateFields(changeset.updatedFields);
|
||||
for (final listener in _changesetListener) {
|
||||
for (final listener in _changesetCallbackMap.values) {
|
||||
listener(changeset);
|
||||
}
|
||||
},
|
||||
@ -96,38 +97,48 @@ class GridFieldCache {
|
||||
_fieldNotifier?.fields = [...fields];
|
||||
}
|
||||
|
||||
VoidCallback addListener(
|
||||
{VoidCallback? listener, void Function(List<Field>)? onChanged, bool Function()? listenWhen}) {
|
||||
f() {
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
void addListener({
|
||||
FieldsCallback? onFields,
|
||||
FieldChangesetCallback? onChangeset,
|
||||
bool Function()? listenWhen,
|
||||
}) {
|
||||
if (onChangeset != null) {
|
||||
fn(c) {
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
}
|
||||
onChangeset(c);
|
||||
}
|
||||
|
||||
if (onChanged != null) {
|
||||
onChanged(fields);
|
||||
_changesetCallbackMap[onChangeset] = fn;
|
||||
}
|
||||
|
||||
if (onFields != null) {
|
||||
fn() {
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
}
|
||||
onFields(fields);
|
||||
}
|
||||
|
||||
if (listener != null) {
|
||||
listener();
|
||||
_fieldsCallbackMap[onFields] = fn;
|
||||
_fieldNotifier?.addListener(fn);
|
||||
}
|
||||
}
|
||||
|
||||
void removeListener({
|
||||
FieldsCallback? onFieldsListener,
|
||||
FieldChangesetCallback? onChangsetListener,
|
||||
}) {
|
||||
if (onFieldsListener != null) {
|
||||
final fn = _fieldsCallbackMap.remove(onFieldsListener);
|
||||
if (fn != null) {
|
||||
_fieldNotifier?.removeListener(fn);
|
||||
}
|
||||
}
|
||||
|
||||
_fieldNotifier?.addListener(f);
|
||||
return f;
|
||||
}
|
||||
|
||||
void removeListener(VoidCallback f) {
|
||||
_fieldNotifier?.removeListener(f);
|
||||
}
|
||||
|
||||
void addChangesetListener(ChangesetListener listener) {
|
||||
_changesetListener.add(listener);
|
||||
}
|
||||
|
||||
void removeChangesetListener(ChangesetListener listener) {
|
||||
final index = _changesetListener.indexWhere((element) => element == listener);
|
||||
if (index != -1) {
|
||||
_changesetListener.removeAt(index);
|
||||
if (onChangsetListener != null) {
|
||||
_changesetCallbackMap.remove(onChangsetListener);
|
||||
}
|
||||
}
|
||||
|
||||
@ -175,43 +186,42 @@ class GridFieldCache {
|
||||
}
|
||||
}
|
||||
|
||||
class GridRowCacheDelegateImpl extends GridRowFieldDelegate {
|
||||
class GridRowCacheDelegateImpl extends GridRowCacheDelegate {
|
||||
final GridFieldCache _cache;
|
||||
FieldChangesetCallback? _onChangesetFn;
|
||||
FieldsCallback? _onFieldFn;
|
||||
GridRowCacheDelegateImpl(GridFieldCache cache) : _cache = cache;
|
||||
|
||||
@override
|
||||
UnmodifiableListView<Field> get fields => _cache.unmodifiableFields;
|
||||
|
||||
@override
|
||||
void onFieldChanged(FieldDidUpdateCallback callback) {
|
||||
_cache.addListener(listener: () {
|
||||
callback();
|
||||
});
|
||||
void onFieldsChanged(VoidCallback callback) {
|
||||
_onFieldFn = (_) => callback();
|
||||
_cache.addListener(onFields: _onFieldFn);
|
||||
}
|
||||
}
|
||||
|
||||
class GridCellCacheDelegateImpl extends GridCellFieldDelegate {
|
||||
final GridFieldCache _cache;
|
||||
ChangesetListener? _changesetFn;
|
||||
GridCellCacheDelegateImpl(GridFieldCache cache) : _cache = cache;
|
||||
|
||||
@override
|
||||
void onFieldChanged(void Function(String) callback) {
|
||||
changesetFn(GridFieldChangeset changeset) {
|
||||
void onFieldUpdated(void Function(Field) callback) {
|
||||
_onChangesetFn = (GridFieldChangeset changeset) {
|
||||
for (final updatedField in changeset.updatedFields) {
|
||||
callback(updatedField.id);
|
||||
callback(updatedField);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_cache.addChangesetListener(changesetFn);
|
||||
_changesetFn = changesetFn;
|
||||
_cache.addListener(onChangeset: _onChangesetFn);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
if (_changesetFn != null) {
|
||||
_cache.removeChangesetListener(_changesetFn!);
|
||||
_changesetFn = null;
|
||||
if (_onFieldFn != null) {
|
||||
_cache.removeListener(onFieldsListener: _onFieldFn!);
|
||||
_onFieldFn = null;
|
||||
}
|
||||
|
||||
if (_onChangesetFn != null) {
|
||||
_cache.removeListener(onChangsetListener: _onChangesetFn!);
|
||||
_onChangesetFn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,12 +11,12 @@ part 'row_bloc.freezed.dart';
|
||||
|
||||
class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
final RowService _rowService;
|
||||
final GridRowCache _rowCache;
|
||||
final GridRowCacheService _rowCache;
|
||||
void Function()? _rowListenFn;
|
||||
|
||||
RowBloc({
|
||||
required GridRow rowData,
|
||||
required GridRowCache rowCache,
|
||||
required GridRowCacheService rowCache,
|
||||
}) : _rowService = RowService(
|
||||
gridId: rowData.gridId,
|
||||
blockId: rowData.blockId,
|
||||
@ -57,9 +57,9 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
}
|
||||
|
||||
Future<void> _startListening() async {
|
||||
_rowListenFn = _rowCache.addRowListener(
|
||||
_rowListenFn = _rowCache.addListener(
|
||||
rowId: state.rowData.rowId,
|
||||
onUpdated: (cellDatas, reason) => add(RowEvent.didReceiveCellDatas(cellDatas, reason)),
|
||||
onCellUpdated: (cellDatas, reason) => add(RowEvent.didReceiveCellDatas(cellDatas, reason)),
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
}
|
||||
|
@ -8,12 +8,12 @@ part 'row_detail_bloc.freezed.dart';
|
||||
|
||||
class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
|
||||
final GridRow rowData;
|
||||
final GridRowCache _rowCache;
|
||||
final GridRowCacheService _rowCache;
|
||||
void Function()? _rowListenFn;
|
||||
|
||||
RowDetailBloc({
|
||||
required this.rowData,
|
||||
required GridRowCache rowCache,
|
||||
required GridRowCacheService rowCache,
|
||||
}) : _rowCache = rowCache,
|
||||
super(RowDetailState.initial()) {
|
||||
on<RowDetailEvent>(
|
||||
@ -40,9 +40,9 @@ class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
|
||||
}
|
||||
|
||||
Future<void> _startListening() async {
|
||||
_rowListenFn = _rowCache.addRowListener(
|
||||
_rowListenFn = _rowCache.addListener(
|
||||
rowId: rowData.rowId,
|
||||
onUpdated: (cellDatas, reason) => add(RowDetailEvent.didReceiveCellDatas(cellDatas.values.toList())),
|
||||
onCellUpdated: (cellDatas, reason) => add(RowDetailEvent.didReceiveCellDatas(cellDatas.values.toList())),
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
}
|
||||
|
@ -14,141 +14,182 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
part 'row_service.freezed.dart';
|
||||
|
||||
typedef RowUpdateCallback = void Function();
|
||||
typedef FieldDidUpdateCallback = void Function();
|
||||
|
||||
abstract class GridRowFieldDelegate {
|
||||
abstract class GridRowCacheDelegate with GridCellCacheDelegate {
|
||||
UnmodifiableListView<Field> get fields;
|
||||
void onFieldChanged(FieldDidUpdateCallback callback);
|
||||
void onFieldsChanged(void Function() callback);
|
||||
void dispose();
|
||||
}
|
||||
|
||||
class GridRowCache {
|
||||
class GridRowCacheService {
|
||||
final String gridId;
|
||||
final String blockId;
|
||||
final RowsNotifier _rowsNotifier;
|
||||
final GridRowFieldDelegate _fieldDelegate;
|
||||
List<GridRow> get clonedRows => _rowsNotifier.clonedRows;
|
||||
final GridBlock block;
|
||||
final _Notifier _notifier;
|
||||
List<GridRow> _rows = [];
|
||||
final HashMap<String, Row> _rowByRowId;
|
||||
final GridRowCacheDelegate _delegate;
|
||||
final GridCellCacheService _cellCache;
|
||||
|
||||
GridRowCache({
|
||||
List<GridRow> get rows => _rows;
|
||||
GridCellCacheService get cellCache => _cellCache;
|
||||
|
||||
GridRowCacheService({
|
||||
required this.gridId,
|
||||
required this.blockId,
|
||||
required GridRowFieldDelegate fieldDelegate,
|
||||
}) : _rowsNotifier = RowsNotifier(
|
||||
rowBuilder: (rowInfo) {
|
||||
return GridRow(
|
||||
gridId: gridId,
|
||||
blockId: "test",
|
||||
fields: fieldDelegate.fields,
|
||||
rowId: rowInfo.rowId,
|
||||
height: rowInfo.height.toDouble(),
|
||||
);
|
||||
},
|
||||
),
|
||||
_fieldDelegate = fieldDelegate {
|
||||
required this.block,
|
||||
required GridRowCacheDelegate delegate,
|
||||
}) : _cellCache = GridCellCacheService(gridId: gridId, delegate: delegate),
|
||||
_rowByRowId = HashMap(),
|
||||
_notifier = _Notifier(),
|
||||
_delegate = delegate {
|
||||
//
|
||||
fieldDelegate.onFieldChanged(() => _rowsNotifier.fieldDidChange());
|
||||
delegate.onFieldsChanged(() => _notifier.receive(const GridRowChangeReason.fieldDidChange()));
|
||||
_rows = block.rowInfos.map((rowInfo) => buildGridRow(rowInfo)).toList();
|
||||
}
|
||||
|
||||
Future<void> dispose() async {
|
||||
_rowsNotifier.dispose();
|
||||
_delegate.dispose();
|
||||
_notifier.dispose();
|
||||
await _cellCache.dispose();
|
||||
}
|
||||
|
||||
void applyChangesets(List<GridRowsChangeset> changesets) {
|
||||
for (final changeset in changesets) {
|
||||
_rowsNotifier.deleteRows(changeset.deletedRows);
|
||||
_rowsNotifier.insertRows(changeset.insertedRows);
|
||||
_rowsNotifier.updateRows(changeset.updatedRows);
|
||||
_deleteRows(changeset.deletedRows);
|
||||
_insertRows(changeset.insertedRows);
|
||||
_updateRows(changeset.updatedRows);
|
||||
}
|
||||
}
|
||||
|
||||
void addListener({
|
||||
void Function(List<GridRow>, GridRowChangeReason)? onChanged,
|
||||
bool Function()? listenWhen,
|
||||
}) {
|
||||
_rowsNotifier.addListener(() {
|
||||
if (onChanged == null) {
|
||||
return;
|
||||
}
|
||||
void _deleteRows(List<GridRowId> deletedRows) {
|
||||
if (deletedRows.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
}
|
||||
final List<GridRow> newRows = [];
|
||||
final DeletedIndexs deletedIndex = [];
|
||||
final Map<String, GridRowId> deletedRowByRowId = {for (var e in deletedRows) e.rowId: e};
|
||||
|
||||
onChanged(clonedRows, _rowsNotifier._changeReason);
|
||||
_rows.asMap().forEach((index, row) {
|
||||
if (deletedRowByRowId[row.rowId] == null) {
|
||||
newRows.add(row);
|
||||
} else {
|
||||
deletedIndex.add(DeletedIndex(index: index, row: row));
|
||||
}
|
||||
});
|
||||
_rows = newRows;
|
||||
_notifier.receive(GridRowChangeReason.delete(deletedIndex));
|
||||
}
|
||||
|
||||
void _insertRows(List<IndexRowOrder> insertRows) {
|
||||
if (insertRows.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
InsertedIndexs insertIndexs = [];
|
||||
final List<GridRow> newRows = _rows;
|
||||
for (final insertRow in insertRows) {
|
||||
final insertIndex = InsertedIndex(
|
||||
index: insertRow.index,
|
||||
rowId: insertRow.rowInfo.rowId,
|
||||
);
|
||||
insertIndexs.add(insertIndex);
|
||||
newRows.insert(insertRow.index, (buildGridRow(insertRow.rowInfo)));
|
||||
}
|
||||
|
||||
_notifier.receive(GridRowChangeReason.insert(insertIndexs));
|
||||
}
|
||||
|
||||
void _updateRows(List<UpdatedRowOrder> updatedRows) {
|
||||
if (updatedRows.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final UpdatedIndexs updatedIndexs = UpdatedIndexs();
|
||||
final List<GridRow> newRows = _rows;
|
||||
for (final updatedRow in updatedRows) {
|
||||
final rowOrder = updatedRow.rowInfo;
|
||||
final rowId = updatedRow.rowInfo.rowId;
|
||||
final index = newRows.indexWhere((row) => row.rowId == rowId);
|
||||
if (index != -1) {
|
||||
_rowByRowId[rowId] = updatedRow.row;
|
||||
|
||||
newRows.removeAt(index);
|
||||
newRows.insert(index, buildGridRow(rowOrder));
|
||||
updatedIndexs[rowId] = UpdatedIndex(index: index, rowId: rowId);
|
||||
}
|
||||
}
|
||||
|
||||
_notifier.receive(GridRowChangeReason.update(updatedIndexs));
|
||||
}
|
||||
|
||||
void onRowsChanged(
|
||||
void Function(GridRowChangeReason) onRowChanged,
|
||||
) {
|
||||
_notifier.addListener(() {
|
||||
onRowChanged(_notifier._reason);
|
||||
});
|
||||
}
|
||||
|
||||
RowUpdateCallback addRowListener({
|
||||
RowUpdateCallback addListener({
|
||||
required String rowId,
|
||||
void Function(GridCellMap, GridRowChangeReason)? onUpdated,
|
||||
void Function(GridCellMap, GridRowChangeReason)? onCellUpdated,
|
||||
bool Function()? listenWhen,
|
||||
}) {
|
||||
listenrHandler() async {
|
||||
if (onUpdated == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (listenWhen != null && listenWhen() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
notify() {
|
||||
final row = _rowsNotifier.rowDataWithId(rowId);
|
||||
if (row != null) {
|
||||
final GridCellMap cellDataMap = _makeGridCells(rowId, row);
|
||||
onUpdated(cellDataMap, _rowsNotifier._changeReason);
|
||||
notifyUpdate() {
|
||||
if (onCellUpdated != null) {
|
||||
final row = _rowByRowId[rowId];
|
||||
if (row != null) {
|
||||
final GridCellMap cellDataMap = _makeGridCells(rowId, row);
|
||||
onCellUpdated(cellDataMap, _notifier._reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_rowsNotifier._changeReason.whenOrNull(
|
||||
_notifier._reason.whenOrNull(
|
||||
update: (indexs) {
|
||||
if (indexs[rowId] != null) {
|
||||
notify();
|
||||
}
|
||||
if (indexs[rowId] != null) notifyUpdate();
|
||||
},
|
||||
fieldDidChange: () => notify(),
|
||||
fieldDidChange: () => notifyUpdate(),
|
||||
);
|
||||
}
|
||||
|
||||
_rowsNotifier.addListener(listenrHandler);
|
||||
_notifier.addListener(listenrHandler);
|
||||
return listenrHandler;
|
||||
}
|
||||
|
||||
void removeRowListener(VoidCallback callback) {
|
||||
_rowsNotifier.removeListener(callback);
|
||||
_notifier.removeListener(callback);
|
||||
}
|
||||
|
||||
GridCellMap loadGridCells(String rowId) {
|
||||
final Row? data = _rowsNotifier.rowDataWithId(rowId);
|
||||
final Row? data = _rowByRowId[rowId];
|
||||
if (data == null) {
|
||||
_loadRow(rowId);
|
||||
}
|
||||
return _makeGridCells(rowId, data);
|
||||
}
|
||||
|
||||
void initialRows(List<BlockRowInfo> rowInfos) {
|
||||
_rowsNotifier.initialRows(rowInfos);
|
||||
}
|
||||
|
||||
Future<void> _loadRow(String rowId) async {
|
||||
final payload = GridRowIdPayload.create()
|
||||
..gridId = gridId
|
||||
..blockId = blockId
|
||||
..blockId = block.id
|
||||
..rowId = rowId;
|
||||
|
||||
final result = await GridEventGetRow(payload).send();
|
||||
result.fold(
|
||||
(rowData) {
|
||||
if (rowData.hasRow()) {
|
||||
_rowsNotifier.rowData = rowData.row;
|
||||
}
|
||||
},
|
||||
(optionRow) => _refreshRow(optionRow),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
}
|
||||
|
||||
GridCellMap _makeGridCells(String rowId, Row? row) {
|
||||
var cellDataMap = GridCellMap.new();
|
||||
for (final field in _fieldDelegate.fields) {
|
||||
for (final field in _delegate.fields) {
|
||||
if (field.visibility) {
|
||||
cellDataMap[field.id] = GridCell(
|
||||
rowId: rowId,
|
||||
@ -159,96 +200,51 @@ class GridRowCache {
|
||||
}
|
||||
return cellDataMap;
|
||||
}
|
||||
|
||||
void _refreshRow(OptionalRow optionRow) {
|
||||
if (!optionRow.hasRow()) {
|
||||
return;
|
||||
}
|
||||
final updatedRow = optionRow.row;
|
||||
updatedRow.freeze();
|
||||
|
||||
_rowByRowId[updatedRow.id] = updatedRow;
|
||||
final index = _rows.indexWhere((gridRow) => gridRow.rowId == updatedRow.id);
|
||||
if (index != -1) {
|
||||
// update the corresponding row in _rows if they are not the same
|
||||
if (_rows[index].data != updatedRow) {
|
||||
final row = _rows.removeAt(index).copyWith(data: updatedRow);
|
||||
_rows.insert(index, row);
|
||||
|
||||
// Calculate the update index
|
||||
final UpdatedIndexs updatedIndexs = UpdatedIndexs();
|
||||
updatedIndexs[row.rowId] = UpdatedIndex(index: index, rowId: row.rowId);
|
||||
|
||||
//
|
||||
_notifier.receive(GridRowChangeReason.update(updatedIndexs));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GridRow buildGridRow(BlockRowInfo rowInfo) {
|
||||
return GridRow(
|
||||
gridId: gridId,
|
||||
blockId: block.id,
|
||||
fields: _delegate.fields,
|
||||
rowId: rowInfo.rowId,
|
||||
height: rowInfo.height.toDouble(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class RowsNotifier extends ChangeNotifier {
|
||||
List<GridRow> _allRows = [];
|
||||
HashMap<String, Row> _rowByRowId = HashMap();
|
||||
GridRowChangeReason _changeReason = const InitialListState();
|
||||
final GridRow Function(BlockRowInfo) rowBuilder;
|
||||
class _Notifier extends ChangeNotifier {
|
||||
GridRowChangeReason _reason = const InitialListState();
|
||||
|
||||
RowsNotifier({
|
||||
required this.rowBuilder,
|
||||
});
|
||||
_Notifier();
|
||||
|
||||
List<GridRow> get clonedRows => [..._allRows];
|
||||
|
||||
void initialRows(List<BlockRowInfo> rowInfos) {
|
||||
_rowByRowId = HashMap();
|
||||
final rows = rowInfos.map((rowOrder) => rowBuilder(rowOrder)).toList();
|
||||
_update(rows, const GridRowChangeReason.initial());
|
||||
}
|
||||
|
||||
void deleteRows(List<GridRowId> deletedRows) {
|
||||
if (deletedRows.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final List<GridRow> newRows = [];
|
||||
final DeletedIndexs deletedIndex = [];
|
||||
final Map<String, GridRowId> deletedRowByRowId = {for (var e in deletedRows) e.rowId: e};
|
||||
|
||||
_allRows.asMap().forEach((index, row) {
|
||||
if (deletedRowByRowId[row.rowId] == null) {
|
||||
newRows.add(row);
|
||||
} else {
|
||||
deletedIndex.add(DeletedIndex(index: index, row: row));
|
||||
}
|
||||
});
|
||||
|
||||
_update(newRows, GridRowChangeReason.delete(deletedIndex));
|
||||
}
|
||||
|
||||
void insertRows(List<IndexRowOrder> insertRows) {
|
||||
if (insertRows.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
InsertedIndexs insertIndexs = [];
|
||||
final List<GridRow> newRows = clonedRows;
|
||||
for (final insertRow in insertRows) {
|
||||
final insertIndex = InsertedIndex(
|
||||
index: insertRow.index,
|
||||
rowId: insertRow.rowInfo.rowId,
|
||||
);
|
||||
insertIndexs.add(insertIndex);
|
||||
newRows.insert(insertRow.index, (rowBuilder(insertRow.rowInfo)));
|
||||
}
|
||||
_update(newRows, GridRowChangeReason.insert(insertIndexs));
|
||||
}
|
||||
|
||||
void updateRows(List<UpdatedRowOrder> updatedRows) {
|
||||
if (updatedRows.isEmpty) {
|
||||
return;
|
||||
}
|
||||
|
||||
final UpdatedIndexs updatedIndexs = UpdatedIndexs();
|
||||
final List<GridRow> newRows = clonedRows;
|
||||
for (final updatedRow in updatedRows) {
|
||||
final rowOrder = updatedRow.rowInfo;
|
||||
final rowId = updatedRow.rowInfo.rowId;
|
||||
final index = newRows.indexWhere((row) => row.rowId == rowId);
|
||||
if (index != -1) {
|
||||
_rowByRowId[rowId] = updatedRow.row;
|
||||
|
||||
newRows.removeAt(index);
|
||||
newRows.insert(index, rowBuilder(rowOrder));
|
||||
updatedIndexs[rowId] = UpdatedIndex(index: index, rowId: rowId);
|
||||
}
|
||||
}
|
||||
|
||||
_update(newRows, GridRowChangeReason.update(updatedIndexs));
|
||||
}
|
||||
|
||||
void fieldDidChange() {
|
||||
_update(_allRows, const GridRowChangeReason.fieldDidChange());
|
||||
}
|
||||
|
||||
void _update(List<GridRow> rows, GridRowChangeReason reason) {
|
||||
_allRows = rows;
|
||||
_changeReason = reason;
|
||||
|
||||
_changeReason.map(
|
||||
void receive(GridRowChangeReason reason) {
|
||||
_reason = reason;
|
||||
reason.map(
|
||||
insert: (_) => notifyListeners(),
|
||||
delete: (_) => notifyListeners(),
|
||||
update: (_) => notifyListeners(),
|
||||
@ -256,32 +252,6 @@ class RowsNotifier extends ChangeNotifier {
|
||||
initial: (_) {},
|
||||
);
|
||||
}
|
||||
|
||||
set rowData(Row rowData) {
|
||||
rowData.freeze();
|
||||
|
||||
_rowByRowId[rowData.id] = rowData;
|
||||
final index = _allRows.indexWhere((row) => row.rowId == rowData.id);
|
||||
if (index != -1) {
|
||||
// update the corresponding row in _rows if they are not the same
|
||||
if (_allRows[index].data != rowData) {
|
||||
final row = _allRows.removeAt(index).copyWith(data: rowData);
|
||||
_allRows.insert(index, row);
|
||||
|
||||
// Calculate the update index
|
||||
final UpdatedIndexs updatedIndexs = UpdatedIndexs();
|
||||
updatedIndexs[row.rowId] = UpdatedIndex(index: index, rowId: row.rowId);
|
||||
_changeReason = GridRowChangeReason.update(updatedIndexs);
|
||||
|
||||
//
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row? rowDataWithId(String rowId) {
|
||||
return _rowByRowId[rowId];
|
||||
}
|
||||
}
|
||||
|
||||
class RowService {
|
||||
|
@ -10,7 +10,7 @@ part 'property_bloc.freezed.dart';
|
||||
|
||||
class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> {
|
||||
final GridFieldCache _fieldCache;
|
||||
Function()? _listenFieldCallback;
|
||||
Function(List<Field>)? _onFieldsFn;
|
||||
|
||||
GridPropertyBloc({required String gridId, required GridFieldCache fieldCache})
|
||||
: _fieldCache = fieldCache,
|
||||
@ -42,15 +42,17 @@ class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> {
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
if (_listenFieldCallback != null) {
|
||||
_fieldCache.removeListener(_listenFieldCallback!);
|
||||
if (_onFieldsFn != null) {
|
||||
_fieldCache.removeListener(onFieldsListener: _onFieldsFn!);
|
||||
_onFieldsFn = null;
|
||||
}
|
||||
return super.close();
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
_listenFieldCallback = _fieldCache.addListener(
|
||||
onChanged: (fields) => add(GridPropertyEvent.didReceiveFieldUpdate(fields)),
|
||||
_onFieldsFn = (fields) => add(GridPropertyEvent.didReceiveFieldUpdate(fields));
|
||||
_fieldCache.addListener(
|
||||
onFields: _onFieldsFn,
|
||||
listenWhen: () => !isClosed,
|
||||
);
|
||||
}
|
||||
|
@ -190,9 +190,9 @@ class _GridRowsState extends State<_GridRows> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocConsumer<GridBloc, GridState>(
|
||||
listenWhen: (previous, current) => previous.listState != current.listState,
|
||||
listenWhen: (previous, current) => previous.reason != current.reason,
|
||||
listener: (context, state) {
|
||||
state.listState.mapOrNull(
|
||||
state.reason.mapOrNull(
|
||||
insert: (value) {
|
||||
for (final item in value.items) {
|
||||
_key.currentState?.insertItem(item.index);
|
||||
@ -227,17 +227,19 @@ class _GridRowsState extends State<_GridRows> {
|
||||
GridRow rowData,
|
||||
Animation<double> animation,
|
||||
) {
|
||||
final rowCache = context.read<GridBloc>().rowCache;
|
||||
final cellCache = context.read<GridBloc>().cellCache;
|
||||
return SizeTransition(
|
||||
sizeFactor: animation,
|
||||
child: GridRowWidget(
|
||||
rowData: rowData,
|
||||
rowCache: rowCache,
|
||||
cellCache: cellCache,
|
||||
key: ValueKey(rowData.rowId),
|
||||
),
|
||||
);
|
||||
final rowCache = context.read<GridBloc>().getRowCache(rowData.blockId, rowData.rowId);
|
||||
if (rowCache != null) {
|
||||
return SizeTransition(
|
||||
sizeFactor: animation,
|
||||
child: GridRowWidget(
|
||||
rowData: rowData,
|
||||
rowCache: rowCache,
|
||||
key: ValueKey(rowData.rowId),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return const SizedBox();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ import 'select_option_cell/select_option_cell.dart';
|
||||
import 'text_cell.dart';
|
||||
import 'url_cell/url_cell.dart';
|
||||
|
||||
GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCache cellCache, {GridCellStyle? style}) {
|
||||
GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCacheService cellCache, {GridCellStyle? style}) {
|
||||
final key = ValueKey(gridCell.cellId());
|
||||
|
||||
final cellContextBuilder = GridCellContextBuilder(gridCell: gridCell, cellCache: cellCache);
|
||||
|
@ -16,13 +16,11 @@ import 'row_detail.dart';
|
||||
|
||||
class GridRowWidget extends StatefulWidget {
|
||||
final GridRow rowData;
|
||||
final GridRowCache rowCache;
|
||||
final GridCellCache cellCache;
|
||||
final GridRowCacheService rowCache;
|
||||
|
||||
const GridRowWidget({
|
||||
required this.rowData,
|
||||
required this.rowCache,
|
||||
required this.cellCache,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -54,7 +52,7 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
||||
return Row(
|
||||
children: [
|
||||
const _RowLeading(),
|
||||
Expanded(child: _RowCells(cellCache: widget.cellCache, onExpand: () => _expandRow(context))),
|
||||
Expanded(child: _RowCells(cellCache: widget.rowCache.cellCache, onExpand: () => _expandRow(context))),
|
||||
const _RowTrailing(),
|
||||
],
|
||||
);
|
||||
@ -74,7 +72,6 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
||||
final page = RowDetailPage(
|
||||
rowData: widget.rowData,
|
||||
rowCache: widget.rowCache,
|
||||
cellCache: widget.cellCache,
|
||||
);
|
||||
page.show(context);
|
||||
}
|
||||
@ -149,7 +146,7 @@ class _DeleteRowButton extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _RowCells extends StatelessWidget {
|
||||
final GridCellCache cellCache;
|
||||
final GridCellCacheService cellCache;
|
||||
final VoidCallback onExpand;
|
||||
const _RowCells({required this.cellCache, required this.onExpand, Key? key}) : super(key: key);
|
||||
|
||||
|
@ -23,13 +23,11 @@ import 'package:window_size/window_size.dart';
|
||||
|
||||
class RowDetailPage extends StatefulWidget with FlowyOverlayDelegate {
|
||||
final GridRow rowData;
|
||||
final GridRowCache rowCache;
|
||||
final GridCellCache cellCache;
|
||||
final GridRowCacheService rowCache;
|
||||
|
||||
const RowDetailPage({
|
||||
required this.rowData,
|
||||
required this.rowCache,
|
||||
required this.cellCache,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@ -77,7 +75,7 @@ class _RowDetailPageState extends State<RowDetailPage> {
|
||||
children: const [Spacer(), _CloseButton()],
|
||||
),
|
||||
),
|
||||
Expanded(child: _PropertyList(cellCache: widget.cellCache)),
|
||||
Expanded(child: _PropertyList(cellCache: widget.rowCache.cellCache)),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -101,7 +99,7 @@ class _CloseButton extends StatelessWidget {
|
||||
}
|
||||
|
||||
class _PropertyList extends StatelessWidget {
|
||||
final GridCellCache cellCache;
|
||||
final GridCellCacheService cellCache;
|
||||
final ScrollController _scrollController;
|
||||
_PropertyList({
|
||||
required this.cellCache,
|
||||
@ -139,7 +137,7 @@ class _PropertyList extends StatelessWidget {
|
||||
|
||||
class _RowDetailCell extends StatelessWidget {
|
||||
final GridCell gridCell;
|
||||
final GridCellCache cellCache;
|
||||
final GridCellCacheService cellCache;
|
||||
const _RowDetailCell({
|
||||
required this.gridCell,
|
||||
required this.cellCache,
|
||||
|
@ -31,12 +31,12 @@ impl TryInto<GridRowId> for GridRowIdPayload {
|
||||
|
||||
fn try_into(self) -> Result<GridRowId, Self::Error> {
|
||||
let grid_id = NotEmptyStr::parse(self.grid_id).map_err(|_| ErrorCode::GridIdIsEmpty)?;
|
||||
// let block_id = NotEmptyStr::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?;
|
||||
let block_id = NotEmptyStr::parse(self.block_id).map_err(|_| ErrorCode::BlockIdIsEmpty)?;
|
||||
let row_id = NotEmptyStr::parse(self.row_id).map_err(|_| ErrorCode::RowIdIsEmpty)?;
|
||||
|
||||
Ok(GridRowId {
|
||||
grid_id: grid_id.0,
|
||||
block_id: self.block_id,
|
||||
block_id: block_id.0,
|
||||
row_id: row_id.0,
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user