mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
refactor: add documentation to GridCellContext
This commit is contained in:
parent
6020459f76
commit
3844d6aad1
@ -9,18 +9,18 @@ import 'block_listener.dart';
|
|||||||
class GridBlockCacheService {
|
class GridBlockCacheService {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
final GridBlock block;
|
final GridBlock block;
|
||||||
late GridRowCacheService _rowCache;
|
late GridRowsCache _rowCache;
|
||||||
late GridBlockListener _listener;
|
late GridBlockListener _listener;
|
||||||
|
|
||||||
List<GridRow> get rows => _rowCache.rows;
|
List<GridRow> get rows => _rowCache.rows;
|
||||||
GridRowCacheService get rowCache => _rowCache;
|
GridRowsCache get rowCache => _rowCache;
|
||||||
|
|
||||||
GridBlockCacheService({
|
GridBlockCacheService({
|
||||||
required this.gridId,
|
required this.gridId,
|
||||||
required this.block,
|
required this.block,
|
||||||
required GridFieldCache fieldCache,
|
required GridFieldCache fieldCache,
|
||||||
}) {
|
}) {
|
||||||
_rowCache = GridRowCacheService(
|
_rowCache = GridRowsCache(
|
||||||
gridId: gridId,
|
gridId: gridId,
|
||||||
block: block,
|
block: block,
|
||||||
delegate: GridRowCacheDelegateImpl(fieldCache),
|
delegate: GridRowCacheDelegateImpl(fieldCache),
|
||||||
|
@ -3,7 +3,7 @@ part of 'cell_service.dart';
|
|||||||
typedef GridCellMap = LinkedHashMap<String, GridCell>;
|
typedef GridCellMap = LinkedHashMap<String, GridCell>;
|
||||||
|
|
||||||
class _GridCellCacheObject {
|
class _GridCellCacheObject {
|
||||||
_GridCellCacheKey key;
|
GridCellCacheKey key;
|
||||||
dynamic object;
|
dynamic object;
|
||||||
_GridCellCacheObject({
|
_GridCellCacheObject({
|
||||||
required this.key,
|
required this.key,
|
||||||
@ -11,67 +11,26 @@ class _GridCellCacheObject {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GridCellCacheKey {
|
class GridCellCacheKey {
|
||||||
final String fieldId;
|
final String fieldId;
|
||||||
final String rowId;
|
final String rowId;
|
||||||
_GridCellCacheKey({
|
GridCellCacheKey({
|
||||||
required this.fieldId,
|
required this.fieldId,
|
||||||
required this.rowId,
|
required this.rowId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class GridCellCacheDelegate {
|
class GridCellsCache {
|
||||||
void onFieldUpdated(void Function(Field) callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
class GridCellCacheService {
|
|
||||||
final String gridId;
|
final String gridId;
|
||||||
final GridCellCacheDelegate delegate;
|
|
||||||
|
|
||||||
/// fieldId: {objectId: callback}
|
|
||||||
final Map<String, Map<String, List<VoidCallback>>> _fieldListenerByFieldId = {};
|
|
||||||
|
|
||||||
/// fieldId: {cacheKey: cacheData}
|
/// fieldId: {cacheKey: cacheData}
|
||||||
final Map<String, Map<String, dynamic>> _cellDataByFieldId = {};
|
final Map<String, Map<String, dynamic>> _cellDataByFieldId = {};
|
||||||
GridCellCacheService({
|
GridCellsCache({
|
||||||
required this.gridId,
|
required this.gridId,
|
||||||
required this.delegate,
|
});
|
||||||
}) {
|
|
||||||
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) {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void addFieldListener(_GridCellCacheKey cacheKey, VoidCallback onFieldChanged) {
|
void remove(String fieldId) {
|
||||||
var map = _fieldListenerByFieldId[cacheKey.fieldId];
|
_cellDataByFieldId.remove(fieldId);
|
||||||
if (map == null) {
|
|
||||||
_fieldListenerByFieldId[cacheKey.fieldId] = {};
|
|
||||||
map = _fieldListenerByFieldId[cacheKey.fieldId];
|
|
||||||
map![cacheKey.rowId] = [onFieldChanged];
|
|
||||||
} else {
|
|
||||||
var objects = map[cacheKey.rowId];
|
|
||||||
if (objects == null) {
|
|
||||||
map[cacheKey.rowId] = [onFieldChanged];
|
|
||||||
} else {
|
|
||||||
objects.add(onFieldChanged);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void removeFieldListener(_GridCellCacheKey cacheKey, VoidCallback fn) {
|
|
||||||
var callbacks = _fieldListenerByFieldId[cacheKey.fieldId]?[cacheKey.rowId];
|
|
||||||
final index = callbacks?.indexWhere((callback) => callback == fn);
|
|
||||||
if (index != null && index != -1) {
|
|
||||||
callbacks?.removeAt(index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert<T extends _GridCellCacheObject>(T item) {
|
void insert<T extends _GridCellCacheObject>(T item) {
|
||||||
@ -84,7 +43,7 @@ class GridCellCacheService {
|
|||||||
map![item.key.rowId] = item.object;
|
map![item.key.rowId] = item.object;
|
||||||
}
|
}
|
||||||
|
|
||||||
T? get<T>(_GridCellCacheKey key) {
|
T? get<T>(GridCellCacheKey key) {
|
||||||
final map = _cellDataByFieldId[key.fieldId];
|
final map = _cellDataByFieldId[key.fieldId];
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
return null;
|
return null;
|
||||||
@ -103,7 +62,6 @@ class GridCellCacheService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> dispose() async {
|
Future<void> dispose() async {
|
||||||
_fieldListenerByFieldId.clear();
|
|
||||||
_cellDataByFieldId.clear();
|
_cellDataByFieldId.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,23 +3,13 @@ part of 'cell_service.dart';
|
|||||||
abstract class IGridCellDataConfig {
|
abstract class IGridCellDataConfig {
|
||||||
// The cell data will reload if it receives the field's change notification.
|
// The cell data will reload if it receives the field's change notification.
|
||||||
bool get reloadOnFieldChanged;
|
bool get reloadOnFieldChanged;
|
||||||
|
|
||||||
// When the reloadOnCellChanged is true, it will load the cell data after user input.
|
|
||||||
// For example: The number cell reload the cell data that carries the format
|
|
||||||
// user input: 12
|
|
||||||
// cell display: $12
|
|
||||||
bool get reloadOnCellChanged;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridCellDataConfig implements IGridCellDataConfig {
|
class GridCellDataConfig implements IGridCellDataConfig {
|
||||||
@override
|
|
||||||
final bool reloadOnCellChanged;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
final bool reloadOnFieldChanged;
|
final bool reloadOnFieldChanged;
|
||||||
|
|
||||||
const GridCellDataConfig({
|
const GridCellDataConfig({
|
||||||
this.reloadOnCellChanged = false,
|
|
||||||
this.reloadOnFieldChanged = false,
|
this.reloadOnFieldChanged = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -72,29 +62,6 @@ class GridCellDataLoader<T> extends IGridCellDataLoader<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SelectOptionCellDataLoader extends IGridCellDataLoader<SelectOptionCellData> {
|
|
||||||
final SelectOptionService service;
|
|
||||||
final GridCell gridCell;
|
|
||||||
SelectOptionCellDataLoader({
|
|
||||||
required this.gridCell,
|
|
||||||
}) : service = SelectOptionService(gridCell: gridCell);
|
|
||||||
@override
|
|
||||||
Future<SelectOptionCellData?> loadData() async {
|
|
||||||
return service.getOpitonContext().then((result) {
|
|
||||||
return result.fold(
|
|
||||||
(data) => data,
|
|
||||||
(err) {
|
|
||||||
Log.error(err);
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
IGridCellDataConfig get config => const GridCellDataConfig(reloadOnFieldChanged: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
class StringCellDataParser implements ICellDataParser<String> {
|
class StringCellDataParser implements ICellDataParser<String> {
|
||||||
@override
|
@override
|
||||||
String? parserData(List<int> data) {
|
String? parserData(List<int> data) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
part of 'cell_service.dart';
|
part of 'cell_service.dart';
|
||||||
|
|
||||||
abstract class _GridCellDataPersistence<D> {
|
abstract class IGridCellDataPersistence<D> {
|
||||||
Future<Option<FlowyError>> save(D data);
|
Future<Option<FlowyError>> save(D data);
|
||||||
}
|
}
|
||||||
|
|
||||||
class CellDataPersistence implements _GridCellDataPersistence<String> {
|
class CellDataPersistence implements IGridCellDataPersistence<String> {
|
||||||
final GridCell gridCell;
|
final GridCell gridCell;
|
||||||
|
|
||||||
CellDataPersistence({
|
CellDataPersistence({
|
||||||
@ -35,7 +35,7 @@ class CalendarData with _$CalendarData {
|
|||||||
const factory CalendarData({required DateTime date, String? time}) = _CalendarData;
|
const factory CalendarData({required DateTime date, String? time}) = _CalendarData;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DateCellDataPersistence implements _GridCellDataPersistence<CalendarData> {
|
class DateCellDataPersistence implements IGridCellDataPersistence<CalendarData> {
|
||||||
final GridCell gridCell;
|
final GridCell gridCell;
|
||||||
DateCellDataPersistence({
|
DateCellDataPersistence({
|
||||||
required this.gridCell,
|
required this.gridCell,
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
|
import 'cell_service.dart';
|
||||||
|
|
||||||
|
abstract class GridFieldChangedNotifier {
|
||||||
|
void onFieldChanged(void Function(Field) callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
class GridCellFieldNotifier {
|
||||||
|
/// fieldId: {objectId: callback}
|
||||||
|
final Map<String, Map<String, List<VoidCallback>>> _fieldListenerByFieldId = {};
|
||||||
|
|
||||||
|
GridCellFieldNotifier({required GridFieldChangedNotifier notifier}) {
|
||||||
|
notifier.onFieldChanged(
|
||||||
|
(field) {
|
||||||
|
final map = _fieldListenerByFieldId[field.id];
|
||||||
|
if (map != null) {
|
||||||
|
for (final callbacks in map.values) {
|
||||||
|
for (final callback in callbacks) {
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addFieldListener(GridCellCacheKey cacheKey, VoidCallback onFieldChanged) {
|
||||||
|
var map = _fieldListenerByFieldId[cacheKey.fieldId];
|
||||||
|
if (map == null) {
|
||||||
|
_fieldListenerByFieldId[cacheKey.fieldId] = {};
|
||||||
|
map = _fieldListenerByFieldId[cacheKey.fieldId];
|
||||||
|
map![cacheKey.rowId] = [onFieldChanged];
|
||||||
|
} else {
|
||||||
|
var objects = map[cacheKey.rowId];
|
||||||
|
if (objects == null) {
|
||||||
|
map[cacheKey.rowId] = [onFieldChanged];
|
||||||
|
} else {
|
||||||
|
objects.add(onFieldChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void removeFieldListener(GridCellCacheKey cacheKey, VoidCallback fn) {
|
||||||
|
var callbacks = _fieldListenerByFieldId[cacheKey.fieldId]?[cacheKey.rowId];
|
||||||
|
final index = callbacks?.indexWhere((callback) => callback == fn);
|
||||||
|
if (index != null && index != -1) {
|
||||||
|
callbacks?.removeAt(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> dispose() async {
|
||||||
|
_fieldListenerByFieldId.clear();
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,6 @@ import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart';
|
|||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
|
import 'package:app_flowy/workspace/application/grid/cell/cell_listener.dart';
|
||||||
import 'package:app_flowy/workspace/application/grid/cell/select_option_service.dart';
|
|
||||||
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
|
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
|
||||||
import 'dart:convert' show utf8;
|
import 'dart:convert' show utf8;
|
||||||
part 'cell_service.freezed.dart';
|
part 'cell_service.freezed.dart';
|
||||||
|
@ -6,15 +6,19 @@ typedef GridDateCellContext = _GridCellContext<DateCellData, CalendarData>;
|
|||||||
typedef GridURLCellContext = _GridCellContext<URLCellData, String>;
|
typedef GridURLCellContext = _GridCellContext<URLCellData, String>;
|
||||||
|
|
||||||
class GridCellContextBuilder {
|
class GridCellContextBuilder {
|
||||||
final GridCellCacheService _cellCache;
|
|
||||||
final GridCell _gridCell;
|
final GridCell _gridCell;
|
||||||
GridCellContextBuilder({
|
final GridCellsCache _cellCache;
|
||||||
required GridCellCacheService cellCache,
|
final GridFieldCache _fieldCache;
|
||||||
required GridCell gridCell,
|
|
||||||
}) : _cellCache = cellCache,
|
GridCellContextBuilder(
|
||||||
|
{required GridCell gridCell, required GridCellsCache cellCache, required GridFieldCache fieldCache})
|
||||||
|
: _cellCache = cellCache,
|
||||||
|
_fieldCache = fieldCache,
|
||||||
_gridCell = gridCell;
|
_gridCell = gridCell;
|
||||||
|
|
||||||
_GridCellContext build() {
|
_GridCellContext build() {
|
||||||
|
final cellFieldNotifier = GridCellFieldNotifier(notifier: _GridFieldChangedNotifierImpl(_fieldCache));
|
||||||
|
|
||||||
switch (_gridCell.field.fieldType) {
|
switch (_gridCell.field.fieldType) {
|
||||||
case FieldType.Checkbox:
|
case FieldType.Checkbox:
|
||||||
final cellDataLoader = GridCellDataLoader(
|
final cellDataLoader = GridCellDataLoader(
|
||||||
@ -25,6 +29,7 @@ class GridCellContextBuilder {
|
|||||||
gridCell: _gridCell,
|
gridCell: _gridCell,
|
||||||
cellCache: _cellCache,
|
cellCache: _cellCache,
|
||||||
cellDataLoader: cellDataLoader,
|
cellDataLoader: cellDataLoader,
|
||||||
|
cellFieldNotifier: cellFieldNotifier,
|
||||||
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
||||||
);
|
);
|
||||||
case FieldType.DateTime:
|
case FieldType.DateTime:
|
||||||
@ -38,18 +43,20 @@ class GridCellContextBuilder {
|
|||||||
gridCell: _gridCell,
|
gridCell: _gridCell,
|
||||||
cellCache: _cellCache,
|
cellCache: _cellCache,
|
||||||
cellDataLoader: cellDataLoader,
|
cellDataLoader: cellDataLoader,
|
||||||
|
cellFieldNotifier: cellFieldNotifier,
|
||||||
cellDataPersistence: DateCellDataPersistence(gridCell: _gridCell),
|
cellDataPersistence: DateCellDataPersistence(gridCell: _gridCell),
|
||||||
);
|
);
|
||||||
case FieldType.Number:
|
case FieldType.Number:
|
||||||
final cellDataLoader = GridCellDataLoader(
|
final cellDataLoader = GridCellDataLoader(
|
||||||
gridCell: _gridCell,
|
gridCell: _gridCell,
|
||||||
parser: StringCellDataParser(),
|
parser: StringCellDataParser(),
|
||||||
config: const GridCellDataConfig(reloadOnCellChanged: true, reloadOnFieldChanged: true),
|
config: const GridCellDataConfig(reloadOnFieldChanged: true),
|
||||||
);
|
);
|
||||||
return GridCellContext(
|
return GridCellContext(
|
||||||
gridCell: _gridCell,
|
gridCell: _gridCell,
|
||||||
cellCache: _cellCache,
|
cellCache: _cellCache,
|
||||||
cellDataLoader: cellDataLoader,
|
cellDataLoader: cellDataLoader,
|
||||||
|
cellFieldNotifier: cellFieldNotifier,
|
||||||
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
||||||
);
|
);
|
||||||
case FieldType.RichText:
|
case FieldType.RichText:
|
||||||
@ -61,6 +68,7 @@ class GridCellContextBuilder {
|
|||||||
gridCell: _gridCell,
|
gridCell: _gridCell,
|
||||||
cellCache: _cellCache,
|
cellCache: _cellCache,
|
||||||
cellDataLoader: cellDataLoader,
|
cellDataLoader: cellDataLoader,
|
||||||
|
cellFieldNotifier: cellFieldNotifier,
|
||||||
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
||||||
);
|
);
|
||||||
case FieldType.MultiSelect:
|
case FieldType.MultiSelect:
|
||||||
@ -75,6 +83,7 @@ class GridCellContextBuilder {
|
|||||||
gridCell: _gridCell,
|
gridCell: _gridCell,
|
||||||
cellCache: _cellCache,
|
cellCache: _cellCache,
|
||||||
cellDataLoader: cellDataLoader,
|
cellDataLoader: cellDataLoader,
|
||||||
|
cellFieldNotifier: cellFieldNotifier,
|
||||||
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -87,6 +96,7 @@ class GridCellContextBuilder {
|
|||||||
gridCell: _gridCell,
|
gridCell: _gridCell,
|
||||||
cellCache: _cellCache,
|
cellCache: _cellCache,
|
||||||
cellDataLoader: cellDataLoader,
|
cellDataLoader: cellDataLoader,
|
||||||
|
cellFieldNotifier: cellFieldNotifier,
|
||||||
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
cellDataPersistence: CellDataPersistence(gridCell: _gridCell),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -99,14 +109,17 @@ class GridCellContextBuilder {
|
|||||||
// ignore: must_be_immutable
|
// ignore: must_be_immutable
|
||||||
class _GridCellContext<T, D> extends Equatable {
|
class _GridCellContext<T, D> extends Equatable {
|
||||||
final GridCell gridCell;
|
final GridCell gridCell;
|
||||||
final GridCellCacheService cellCache;
|
final GridCellsCache _cellsCache;
|
||||||
final _GridCellCacheKey _cacheKey;
|
final GridCellCacheKey _cacheKey;
|
||||||
final IGridCellDataLoader<T> cellDataLoader;
|
|
||||||
final _GridCellDataPersistence<D> cellDataPersistence;
|
|
||||||
final FieldService _fieldService;
|
final FieldService _fieldService;
|
||||||
|
final GridCellFieldNotifier _cellFieldNotifier;
|
||||||
|
// final GridCellFieldNotifier _fieldNotifier;
|
||||||
|
final IGridCellDataLoader<T> _cellDataLoader;
|
||||||
|
final IGridCellDataPersistence<D> _cellDataPersistence;
|
||||||
|
|
||||||
late final CellListener _cellListener;
|
late final CellListener _cellListener;
|
||||||
late final ValueNotifier<T?>? _cellDataNotifier;
|
late final ValueNotifier<T?>? _cellDataNotifier;
|
||||||
|
|
||||||
bool isListening = false;
|
bool isListening = false;
|
||||||
VoidCallback? _onFieldChangedFn;
|
VoidCallback? _onFieldChangedFn;
|
||||||
Timer? _loadDataOperation;
|
Timer? _loadDataOperation;
|
||||||
@ -114,18 +127,25 @@ class _GridCellContext<T, D> extends Equatable {
|
|||||||
|
|
||||||
_GridCellContext({
|
_GridCellContext({
|
||||||
required this.gridCell,
|
required this.gridCell,
|
||||||
required this.cellCache,
|
required GridCellsCache cellCache,
|
||||||
required this.cellDataLoader,
|
required GridCellFieldNotifier cellFieldNotifier,
|
||||||
required this.cellDataPersistence,
|
required IGridCellDataLoader<T> cellDataLoader,
|
||||||
}) : _fieldService = FieldService(gridId: gridCell.gridId, fieldId: gridCell.field.id),
|
required IGridCellDataPersistence<D> cellDataPersistence,
|
||||||
_cacheKey = _GridCellCacheKey(rowId: gridCell.rowId, fieldId: gridCell.field.id);
|
// required GridFieldChangedNotifier notifierDelegate,
|
||||||
|
}) : _cellsCache = cellCache,
|
||||||
|
_cellDataLoader = cellDataLoader,
|
||||||
|
_cellDataPersistence = cellDataPersistence,
|
||||||
|
_cellFieldNotifier = cellFieldNotifier,
|
||||||
|
_fieldService = FieldService(gridId: gridCell.gridId, fieldId: gridCell.field.id),
|
||||||
|
_cacheKey = GridCellCacheKey(rowId: gridCell.rowId, fieldId: gridCell.field.id);
|
||||||
|
|
||||||
_GridCellContext<T, D> clone() {
|
_GridCellContext<T, D> clone() {
|
||||||
return _GridCellContext(
|
return _GridCellContext(
|
||||||
gridCell: gridCell,
|
gridCell: gridCell,
|
||||||
cellDataLoader: cellDataLoader,
|
cellDataLoader: _cellDataLoader,
|
||||||
cellCache: cellCache,
|
cellCache: _cellsCache,
|
||||||
cellDataPersistence: cellDataPersistence);
|
cellFieldNotifier: _cellFieldNotifier,
|
||||||
|
cellDataPersistence: _cellDataPersistence);
|
||||||
}
|
}
|
||||||
|
|
||||||
String get gridId => gridCell.gridId;
|
String get gridId => gridCell.gridId;
|
||||||
@ -145,10 +165,18 @@ class _GridCellContext<T, D> extends Equatable {
|
|||||||
Log.error("Already started. It seems like you should call clone first");
|
Log.error("Already started. It seems like you should call clone first");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
isListening = true;
|
isListening = true;
|
||||||
_cellDataNotifier = ValueNotifier(cellCache.get(_cacheKey));
|
|
||||||
|
/// The cell data will be changed by two reasons:
|
||||||
|
/// 1. User edit the cell
|
||||||
|
/// 2. User edit the field
|
||||||
|
/// For example: The number cell reload the cell data that carries the format
|
||||||
|
/// user input: 12
|
||||||
|
/// cell display: $12
|
||||||
|
_cellDataNotifier = ValueNotifier(_cellsCache.get(_cacheKey));
|
||||||
_cellListener = CellListener(rowId: gridCell.rowId, fieldId: gridCell.field.id);
|
_cellListener = CellListener(rowId: gridCell.rowId, fieldId: gridCell.field.id);
|
||||||
|
|
||||||
|
/// Listen on user edit event and load the new cell data if needed.
|
||||||
_cellListener.start(onCellChanged: (result) {
|
_cellListener.start(onCellChanged: (result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(_) => _loadData(),
|
(_) => _loadData(),
|
||||||
@ -156,21 +184,14 @@ class _GridCellContext<T, D> extends Equatable {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (cellDataLoader.config.reloadOnFieldChanged) {
|
/// Listen on the field event and load the cell data if needed.
|
||||||
_onFieldChangedFn = () {
|
if (_cellDataLoader.config.reloadOnFieldChanged) {
|
||||||
_loadData();
|
_onFieldChangedFn = () => _loadData();
|
||||||
};
|
_cellFieldNotifier.addFieldListener(_cacheKey, _onFieldChangedFn!);
|
||||||
cellCache.addFieldListener(_cacheKey, _onFieldChangedFn!);
|
|
||||||
}
|
|
||||||
|
|
||||||
onCellChangedFn() {
|
|
||||||
onCellChanged(_cellDataNotifier?.value);
|
|
||||||
|
|
||||||
if (cellDataLoader.config.reloadOnCellChanged) {
|
|
||||||
_loadData();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Notify the listener, the cell data was changed.
|
||||||
|
onCellChangedFn() => onCellChanged(_cellDataNotifier?.value);
|
||||||
_cellDataNotifier?.addListener(onCellChangedFn);
|
_cellDataNotifier?.addListener(onCellChangedFn);
|
||||||
return onCellChangedFn;
|
return onCellChangedFn;
|
||||||
}
|
}
|
||||||
@ -180,7 +201,7 @@ class _GridCellContext<T, D> extends Equatable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
T? getCellData({bool loadIfNoCache = true}) {
|
T? getCellData({bool loadIfNoCache = true}) {
|
||||||
final data = cellCache.get(_cacheKey);
|
final data = _cellsCache.get(_cacheKey);
|
||||||
if (data == null && loadIfNoCache) {
|
if (data == null && loadIfNoCache) {
|
||||||
_loadData();
|
_loadData();
|
||||||
}
|
}
|
||||||
@ -195,13 +216,13 @@ class _GridCellContext<T, D> extends Equatable {
|
|||||||
if (deduplicate) {
|
if (deduplicate) {
|
||||||
_loadDataOperation?.cancel();
|
_loadDataOperation?.cancel();
|
||||||
_loadDataOperation = Timer(const Duration(milliseconds: 300), () async {
|
_loadDataOperation = Timer(const Duration(milliseconds: 300), () async {
|
||||||
final result = await cellDataPersistence.save(data);
|
final result = await _cellDataPersistence.save(data);
|
||||||
if (resultCallback != null) {
|
if (resultCallback != null) {
|
||||||
resultCallback(result);
|
resultCallback(result);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
final result = await cellDataPersistence.save(data);
|
final result = await _cellDataPersistence.save(data);
|
||||||
if (resultCallback != null) {
|
if (resultCallback != null) {
|
||||||
resultCallback(result);
|
resultCallback(result);
|
||||||
}
|
}
|
||||||
@ -211,9 +232,9 @@ class _GridCellContext<T, D> extends Equatable {
|
|||||||
void _loadData() {
|
void _loadData() {
|
||||||
_loadDataOperation?.cancel();
|
_loadDataOperation?.cancel();
|
||||||
_loadDataOperation = Timer(const Duration(milliseconds: 10), () {
|
_loadDataOperation = Timer(const Duration(milliseconds: 10), () {
|
||||||
cellDataLoader.loadData().then((data) {
|
_cellDataLoader.loadData().then((data) {
|
||||||
_cellDataNotifier?.value = data;
|
_cellDataNotifier?.value = data;
|
||||||
cellCache.insert(_GridCellCacheObject(key: _cacheKey, object: data));
|
_cellsCache.insert(_GridCellCacheObject(key: _cacheKey, object: data));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -224,11 +245,36 @@ class _GridCellContext<T, D> extends Equatable {
|
|||||||
_saveDataOperation?.cancel();
|
_saveDataOperation?.cancel();
|
||||||
|
|
||||||
if (_onFieldChangedFn != null) {
|
if (_onFieldChangedFn != null) {
|
||||||
cellCache.removeFieldListener(_cacheKey, _onFieldChangedFn!);
|
_cellFieldNotifier.removeFieldListener(_cacheKey, _onFieldChangedFn!);
|
||||||
_onFieldChangedFn = null;
|
_onFieldChangedFn = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object> get props => [cellCache.get(_cacheKey) ?? "", cellId];
|
List<Object> get props => [_cellsCache.get(_cacheKey) ?? "", cellId];
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GridFieldChangedNotifierImpl extends GridFieldChangedNotifier {
|
||||||
|
final GridFieldCache _cache;
|
||||||
|
FieldChangesetCallback? _onChangesetFn;
|
||||||
|
|
||||||
|
_GridFieldChangedNotifierImpl(GridFieldCache cache) : _cache = cache;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
if (_onChangesetFn != null) {
|
||||||
|
_cache.removeListener(onChangsetListener: _onChangesetFn!);
|
||||||
|
_onChangesetFn = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void onFieldChanged(void Function(Field p1) callback) {
|
||||||
|
_onChangesetFn = (GridFieldChangeset changeset) {
|
||||||
|
for (final updatedField in changeset.updatedFields) {
|
||||||
|
callback(updatedField);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
_cache.addListener(onChangeset: _onChangesetFn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
|||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
GridRowCacheService? getRowCache(String blockId, String rowId) {
|
GridRowsCache? getRowCache(String blockId, String rowId) {
|
||||||
final GridBlockCacheService? blockCache = _blocks[blockId];
|
final GridBlockCacheService? blockCache = _blocks[blockId];
|
||||||
return blockCache?.rowCache;
|
return blockCache?.rowCache;
|
||||||
}
|
}
|
||||||
|
@ -202,7 +202,7 @@ class GridRowCacheDelegateImpl extends GridRowCacheDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void onFieldUpdated(void Function(Field) callback) {
|
void onFieldChanged(void Function(Field) callback) {
|
||||||
_onChangesetFn = (GridFieldChangeset changeset) {
|
_onChangesetFn = (GridFieldChangeset changeset) {
|
||||||
for (final updatedField in changeset.updatedFields) {
|
for (final updatedField in changeset.updatedFields) {
|
||||||
callback(updatedField);
|
callback(updatedField);
|
||||||
|
@ -11,12 +11,12 @@ part 'row_bloc.freezed.dart';
|
|||||||
|
|
||||||
class RowBloc extends Bloc<RowEvent, RowState> {
|
class RowBloc extends Bloc<RowEvent, RowState> {
|
||||||
final RowService _rowService;
|
final RowService _rowService;
|
||||||
final GridRowCacheService _rowCache;
|
final GridRowsCache _rowCache;
|
||||||
void Function()? _rowListenFn;
|
void Function()? _rowListenFn;
|
||||||
|
|
||||||
RowBloc({
|
RowBloc({
|
||||||
required GridRow rowData,
|
required GridRow rowData,
|
||||||
required GridRowCacheService rowCache,
|
required GridRowsCache rowCache,
|
||||||
}) : _rowService = RowService(
|
}) : _rowService = RowService(
|
||||||
gridId: rowData.gridId,
|
gridId: rowData.gridId,
|
||||||
blockId: rowData.blockId,
|
blockId: rowData.blockId,
|
||||||
|
@ -8,12 +8,12 @@ part 'row_detail_bloc.freezed.dart';
|
|||||||
|
|
||||||
class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
|
class RowDetailBloc extends Bloc<RowDetailEvent, RowDetailState> {
|
||||||
final GridRow rowData;
|
final GridRow rowData;
|
||||||
final GridRowCacheService _rowCache;
|
final GridRowsCache _rowCache;
|
||||||
void Function()? _rowListenFn;
|
void Function()? _rowListenFn;
|
||||||
|
|
||||||
RowDetailBloc({
|
RowDetailBloc({
|
||||||
required this.rowData,
|
required this.rowData,
|
||||||
required GridRowCacheService rowCache,
|
required GridRowsCache rowCache,
|
||||||
}) : _rowCache = rowCache,
|
}) : _rowCache = rowCache,
|
||||||
super(RowDetailState.initial()) {
|
super(RowDetailState.initial()) {
|
||||||
on<RowDetailEvent>(
|
on<RowDetailEvent>(
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart';
|
import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart';
|
||||||
import 'package:dartz/dartz.dart';
|
import 'package:dartz/dartz.dart';
|
||||||
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
import 'package:flowy_sdk/dispatch/dispatch.dart';
|
||||||
@ -15,34 +14,36 @@ part 'row_service.freezed.dart';
|
|||||||
|
|
||||||
typedef RowUpdateCallback = void Function();
|
typedef RowUpdateCallback = void Function();
|
||||||
|
|
||||||
abstract class GridRowCacheDelegate with GridCellCacheDelegate {
|
abstract class GridRowCacheDelegate {
|
||||||
UnmodifiableListView<Field> get fields;
|
UnmodifiableListView<Field> get fields;
|
||||||
void onFieldsChanged(void Function() callback);
|
void onFieldsChanged(VoidCallback callback);
|
||||||
|
void onFieldChanged(void Function(Field) callback);
|
||||||
void dispose();
|
void dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridRowCacheService {
|
class GridRowsCache {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
final GridBlock block;
|
final GridBlock block;
|
||||||
final _Notifier _notifier;
|
final _Notifier _notifier;
|
||||||
List<GridRow> _rows = [];
|
List<GridRow> _rows = [];
|
||||||
final HashMap<String, Row> _rowByRowId;
|
final HashMap<String, Row> _rowByRowId;
|
||||||
final GridRowCacheDelegate _delegate;
|
final GridRowCacheDelegate _delegate;
|
||||||
final GridCellCacheService _cellCache;
|
final GridCellsCache _cellCache;
|
||||||
|
|
||||||
List<GridRow> get rows => _rows;
|
List<GridRow> get rows => _rows;
|
||||||
GridCellCacheService get cellCache => _cellCache;
|
GridCellsCache get cellCache => _cellCache;
|
||||||
|
|
||||||
GridRowCacheService({
|
GridRowsCache({
|
||||||
required this.gridId,
|
required this.gridId,
|
||||||
required this.block,
|
required this.block,
|
||||||
required GridRowCacheDelegate delegate,
|
required GridRowCacheDelegate delegate,
|
||||||
}) : _cellCache = GridCellCacheService(gridId: gridId, delegate: delegate),
|
}) : _cellCache = GridCellsCache(gridId: gridId),
|
||||||
_rowByRowId = HashMap(),
|
_rowByRowId = HashMap(),
|
||||||
_notifier = _Notifier(),
|
_notifier = _Notifier(),
|
||||||
_delegate = delegate {
|
_delegate = delegate {
|
||||||
//
|
//
|
||||||
delegate.onFieldsChanged(() => _notifier.receive(const GridRowChangeReason.fieldDidChange()));
|
delegate.onFieldsChanged(() => _notifier.receive(const GridRowChangeReason.fieldDidChange()));
|
||||||
|
delegate.onFieldChanged((field) => _cellCache.remove(field.id));
|
||||||
_rows = block.rowInfos.map((rowInfo) => buildGridRow(rowInfo.rowId, rowInfo.height.toDouble())).toList();
|
_rows = block.rowInfos.map((rowInfo) => buildGridRow(rowInfo.rowId, rowInfo.height.toDouble())).toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart';
|
import 'package:app_flowy/workspace/application/grid/cell/cell_service/cell_service.dart';
|
||||||
|
import 'package:app_flowy/workspace/application/grid/grid_service.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
import 'package:flutter/widgets.dart';
|
||||||
@ -12,10 +13,56 @@ import 'select_option_cell/select_option_cell.dart';
|
|||||||
import 'text_cell.dart';
|
import 'text_cell.dart';
|
||||||
import 'url_cell/url_cell.dart';
|
import 'url_cell/url_cell.dart';
|
||||||
|
|
||||||
GridCellWidget buildGridCellWidget(GridCell gridCell, GridCellCacheService cellCache, {GridCellStyle? style}) {
|
class GridCellBuilder {
|
||||||
|
final GridCellsCache cellCache;
|
||||||
|
final GridFieldCache fieldCache;
|
||||||
|
GridCellBuilder({
|
||||||
|
required this.cellCache,
|
||||||
|
required this.fieldCache,
|
||||||
|
});
|
||||||
|
|
||||||
|
GridCellWidget build(GridCell cell, {GridCellStyle? style}) {
|
||||||
|
final key = ValueKey(gridCell.cellId());
|
||||||
|
|
||||||
|
final cellContextBuilder = GridCellContextBuilder(
|
||||||
|
gridCell: gridCell,
|
||||||
|
cellCache: cellCache,
|
||||||
|
fieldCache: fieldCache,
|
||||||
|
);
|
||||||
|
|
||||||
|
switch (gridCell.field.fieldType) {
|
||||||
|
case FieldType.Checkbox:
|
||||||
|
return CheckboxCell(cellContextBuilder: cellContextBuilder, key: key);
|
||||||
|
case FieldType.DateTime:
|
||||||
|
return DateCell(cellContextBuilder: cellContextBuilder, key: key, style: style);
|
||||||
|
case FieldType.SingleSelect:
|
||||||
|
return SingleSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
|
||||||
|
case FieldType.MultiSelect:
|
||||||
|
return MultiSelectCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
|
||||||
|
case FieldType.Number:
|
||||||
|
return NumberCell(cellContextBuilder: cellContextBuilder, key: key);
|
||||||
|
case FieldType.RichText:
|
||||||
|
return GridTextCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
|
||||||
|
case FieldType.URL:
|
||||||
|
return GridURLCell(cellContextBuilder: cellContextBuilder, style: style, key: key);
|
||||||
|
}
|
||||||
|
throw UnimplementedError;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GridCellWidget buildGridCellWidget(
|
||||||
|
GridCell gridCell, {
|
||||||
|
required GridCellsCache cellCache,
|
||||||
|
required GridFieldCache fieldCache,
|
||||||
|
GridCellStyle? style,
|
||||||
|
}) {
|
||||||
final key = ValueKey(gridCell.cellId());
|
final key = ValueKey(gridCell.cellId());
|
||||||
|
|
||||||
final cellContextBuilder = GridCellContextBuilder(gridCell: gridCell, cellCache: cellCache);
|
final cellContextBuilder = GridCellContextBuilder(
|
||||||
|
gridCell: gridCell,
|
||||||
|
cellCache: cellCache,
|
||||||
|
fieldCache: fieldCache,
|
||||||
|
);
|
||||||
|
|
||||||
switch (gridCell.field.fieldType) {
|
switch (gridCell.field.fieldType) {
|
||||||
case FieldType.Checkbox:
|
case FieldType.Checkbox:
|
||||||
|
@ -10,19 +10,25 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'row_action_sheet.dart';
|
|
||||||
|
|
||||||
|
import 'row_action_sheet.dart';
|
||||||
import 'row_detail.dart';
|
import 'row_detail.dart';
|
||||||
|
|
||||||
class GridRowWidget extends StatefulWidget {
|
class GridRowWidget extends StatefulWidget {
|
||||||
final GridRow rowData;
|
final GridRow rowData;
|
||||||
final GridRowCacheService rowCache;
|
final GridRowsCache rowCache;
|
||||||
|
final GridCellBuilder cellBuilder;
|
||||||
|
|
||||||
const GridRowWidget({
|
GridRowWidget({
|
||||||
required this.rowData,
|
required this.rowData,
|
||||||
required this.rowCache,
|
required this.rowCache,
|
||||||
|
required GridFieldCache fieldCache,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : cellBuilder = GridCellBuilder(
|
||||||
|
cellCache: rowCache.cellCache,
|
||||||
|
fieldCache: fieldCache,
|
||||||
|
),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GridRowWidget> createState() => _GridRowWidgetState();
|
State<GridRowWidget> createState() => _GridRowWidgetState();
|
||||||
@ -52,7 +58,11 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
|||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
const _RowLeading(),
|
const _RowLeading(),
|
||||||
Expanded(child: _RowCells(cellCache: widget.rowCache.cellCache, onExpand: () => _expandRow(context))),
|
Expanded(
|
||||||
|
child: _RowCells(
|
||||||
|
builder: widget.cellBuilder,
|
||||||
|
onExpand: () => _expandRow(context),
|
||||||
|
)),
|
||||||
const _RowTrailing(),
|
const _RowTrailing(),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@ -72,6 +82,7 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
|||||||
final page = RowDetailPage(
|
final page = RowDetailPage(
|
||||||
rowData: widget.rowData,
|
rowData: widget.rowData,
|
||||||
rowCache: widget.rowCache,
|
rowCache: widget.rowCache,
|
||||||
|
cellBuilder: widget.cellBuilder,
|
||||||
);
|
);
|
||||||
page.show(context);
|
page.show(context);
|
||||||
}
|
}
|
||||||
@ -146,9 +157,13 @@ class _DeleteRowButton extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _RowCells extends StatelessWidget {
|
class _RowCells extends StatelessWidget {
|
||||||
final GridCellCacheService cellCache;
|
|
||||||
final VoidCallback onExpand;
|
final VoidCallback onExpand;
|
||||||
const _RowCells({required this.cellCache, required this.onExpand, Key? key}) : super(key: key);
|
final GridCellBuilder builder;
|
||||||
|
const _RowCells({
|
||||||
|
required this.builder,
|
||||||
|
required this.onExpand,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@ -169,8 +184,7 @@ class _RowCells extends StatelessWidget {
|
|||||||
List<Widget> _makeCells(BuildContext context, GridCellMap gridCellMap) {
|
List<Widget> _makeCells(BuildContext context, GridCellMap gridCellMap) {
|
||||||
return gridCellMap.values.map(
|
return gridCellMap.values.map(
|
||||||
(gridCell) {
|
(gridCell) {
|
||||||
final GridCellWidget child = buildGridCellWidget(gridCell, cellCache);
|
final GridCellWidget child = builder.build(gridCell);
|
||||||
|
|
||||||
accessoryBuilder(GridCellAccessoryBuildContext buildContext) {
|
accessoryBuilder(GridCellAccessoryBuildContext buildContext) {
|
||||||
final builder = child.accessoryBuilder;
|
final builder = child.accessoryBuilder;
|
||||||
List<GridCellAccessory> accessories = [];
|
List<GridCellAccessory> accessories = [];
|
||||||
|
@ -22,11 +22,13 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
|
|
||||||
class RowDetailPage extends StatefulWidget with FlowyOverlayDelegate {
|
class RowDetailPage extends StatefulWidget with FlowyOverlayDelegate {
|
||||||
final GridRow rowData;
|
final GridRow rowData;
|
||||||
final GridRowCacheService rowCache;
|
final GridRowsCache rowCache;
|
||||||
|
final GridCellBuilder cellBuilder;
|
||||||
|
|
||||||
const RowDetailPage({
|
const RowDetailPage({
|
||||||
required this.rowData,
|
required this.rowData,
|
||||||
required this.rowCache,
|
required this.rowCache,
|
||||||
|
required this.cellBuilder,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@ -74,7 +76,7 @@ class _RowDetailPageState extends State<RowDetailPage> {
|
|||||||
children: const [Spacer(), _CloseButton()],
|
children: const [Spacer(), _CloseButton()],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(child: _PropertyList(cellCache: widget.rowCache.cellCache)),
|
Expanded(child: _PropertyList(cellBuilder: widget.cellBuilder)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -98,10 +100,10 @@ class _CloseButton extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _PropertyList extends StatelessWidget {
|
class _PropertyList extends StatelessWidget {
|
||||||
final GridCellCacheService cellCache;
|
final GridCellBuilder cellBuilder;
|
||||||
final ScrollController _scrollController;
|
final ScrollController _scrollController;
|
||||||
_PropertyList({
|
_PropertyList({
|
||||||
required this.cellCache,
|
required this.cellBuilder,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : _scrollController = ScrollController(),
|
}) : _scrollController = ScrollController(),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
@ -121,7 +123,7 @@ class _PropertyList extends StatelessWidget {
|
|||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
return _RowDetailCell(
|
return _RowDetailCell(
|
||||||
gridCell: state.gridCells[index],
|
gridCell: state.gridCells[index],
|
||||||
cellCache: cellCache,
|
cellBuilder: cellBuilder,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (BuildContext context, int index) {
|
separatorBuilder: (BuildContext context, int index) {
|
||||||
@ -136,10 +138,10 @@ class _PropertyList extends StatelessWidget {
|
|||||||
|
|
||||||
class _RowDetailCell extends StatelessWidget {
|
class _RowDetailCell extends StatelessWidget {
|
||||||
final GridCell gridCell;
|
final GridCell gridCell;
|
||||||
final GridCellCacheService cellCache;
|
final GridCellBuilder cellBuilder;
|
||||||
const _RowDetailCell({
|
const _RowDetailCell({
|
||||||
required this.gridCell,
|
required this.gridCell,
|
||||||
required this.cellCache,
|
required this.cellBuilder,
|
||||||
Key? key,
|
Key? key,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@ -147,7 +149,7 @@ class _RowDetailCell extends StatelessWidget {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = context.watch<AppTheme>();
|
final theme = context.watch<AppTheme>();
|
||||||
final style = _customCellStyle(theme, gridCell.field.fieldType);
|
final style = _customCellStyle(theme, gridCell.field.fieldType);
|
||||||
final cell = buildGridCellWidget(gridCell, cellCache, style: style);
|
final cell = cellBuilder.build(gridCell, style: style);
|
||||||
|
|
||||||
final gesture = GestureDetector(
|
final gesture = GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user