|
@@ -133,7 +133,7 @@ class IGridCellController<T, D> extends Equatable {
|
|
final IGridCellDataPersistence<D> _cellDataPersistence;
|
|
final IGridCellDataPersistence<D> _cellDataPersistence;
|
|
|
|
|
|
CellListener? _cellListener;
|
|
CellListener? _cellListener;
|
|
- ValueNotifier<T?>? _cellDataNotifier;
|
|
|
|
|
|
+ CellDataNotifier<T?>? _cellDataNotifier;
|
|
|
|
|
|
bool isListening = false;
|
|
bool isListening = false;
|
|
VoidCallback? _onFieldChangedFn;
|
|
VoidCallback? _onFieldChangedFn;
|
|
@@ -170,8 +170,20 @@ class IGridCellController<T, D> extends Equatable {
|
|
|
|
|
|
FieldType get fieldType => cellId.fieldInfo.fieldType;
|
|
FieldType get fieldType => cellId.fieldInfo.fieldType;
|
|
|
|
|
|
|
|
+ /// Listen on the cell content or field changes
|
|
|
|
+ ///
|
|
|
|
+ /// An optional [listenWhenOnCellChanged] can be implemented for more
|
|
|
|
+ /// granular control over when [listener] is called.
|
|
|
|
+ /// [listenWhenOnCellChanged] will be invoked on each [onCellChanged]
|
|
|
|
+ /// get called.
|
|
|
|
+ /// [listenWhenOnCellChanged] takes the previous `value` and current
|
|
|
|
+ /// `value` and must return a [bool] which determines whether or not
|
|
|
|
+ /// the [onCellChanged] function will be invoked.
|
|
|
|
+ /// [onCellChanged] is optional and if omitted, it will default to `true`.
|
|
|
|
+ ///
|
|
VoidCallback? startListening({
|
|
VoidCallback? startListening({
|
|
required void Function(T?) onCellChanged,
|
|
required void Function(T?) onCellChanged,
|
|
|
|
+ bool Function(T? oldValue, T? newValue)? listenWhenOnCellChanged,
|
|
VoidCallback? onCellFieldChanged,
|
|
VoidCallback? onCellFieldChanged,
|
|
}) {
|
|
}) {
|
|
if (isListening) {
|
|
if (isListening) {
|
|
@@ -180,7 +192,10 @@ class IGridCellController<T, D> extends Equatable {
|
|
}
|
|
}
|
|
isListening = true;
|
|
isListening = true;
|
|
|
|
|
|
- _cellDataNotifier = ValueNotifier(_cellsCache.get(_cacheKey));
|
|
|
|
|
|
+ _cellDataNotifier = CellDataNotifier(
|
|
|
|
+ value: _cellsCache.get(_cacheKey),
|
|
|
|
+ listenWhen: listenWhenOnCellChanged,
|
|
|
|
+ );
|
|
_cellListener =
|
|
_cellListener =
|
|
CellListener(rowId: cellId.rowId, fieldId: cellId.fieldInfo.id);
|
|
CellListener(rowId: cellId.rowId, fieldId: cellId.fieldInfo.id);
|
|
|
|
|
|
@@ -255,24 +270,21 @@ class IGridCellController<T, D> extends Equatable {
|
|
/// You can set [deduplicate] to true (default is false) to reduce the save operation.
|
|
/// You can set [deduplicate] to true (default is false) to reduce the save operation.
|
|
/// It's useful when you call this method when user editing the [TextField].
|
|
/// It's useful when you call this method when user editing the [TextField].
|
|
/// The default debounce interval is 300 milliseconds.
|
|
/// The default debounce interval is 300 milliseconds.
|
|
- void saveCellData(D data,
|
|
|
|
- {bool deduplicate = false,
|
|
|
|
- void Function(Option<FlowyError>)? resultCallback}) async {
|
|
|
|
|
|
+ void saveCellData(
|
|
|
|
+ D data, {
|
|
|
|
+ bool deduplicate = false,
|
|
|
|
+ void Function(Option<FlowyError>)? onFinish,
|
|
|
|
+ }) async {
|
|
|
|
+ _loadDataOperation?.cancel();
|
|
if (deduplicate) {
|
|
if (deduplicate) {
|
|
- _loadDataOperation?.cancel();
|
|
|
|
-
|
|
|
|
_saveDataOperation?.cancel();
|
|
_saveDataOperation?.cancel();
|
|
_saveDataOperation = Timer(const Duration(milliseconds: 300), () async {
|
|
_saveDataOperation = Timer(const Duration(milliseconds: 300), () async {
|
|
final result = await _cellDataPersistence.save(data);
|
|
final result = await _cellDataPersistence.save(data);
|
|
- if (resultCallback != null) {
|
|
|
|
- resultCallback(result);
|
|
|
|
- }
|
|
|
|
|
|
+ onFinish?.call(result);
|
|
});
|
|
});
|
|
} else {
|
|
} else {
|
|
final result = await _cellDataPersistence.save(data);
|
|
final result = await _cellDataPersistence.save(data);
|
|
- if (resultCallback != null) {
|
|
|
|
- resultCallback(result);
|
|
|
|
- }
|
|
|
|
|
|
+ onFinish?.call(result);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -302,6 +314,7 @@ class IGridCellController<T, D> extends Equatable {
|
|
await _cellListener?.stop();
|
|
await _cellListener?.stop();
|
|
_loadDataOperation?.cancel();
|
|
_loadDataOperation?.cancel();
|
|
_saveDataOperation?.cancel();
|
|
_saveDataOperation?.cancel();
|
|
|
|
+ _cellDataNotifier?.dispose();
|
|
_cellDataNotifier = null;
|
|
_cellDataNotifier = null;
|
|
|
|
|
|
if (_onFieldChangedFn != null) {
|
|
if (_onFieldChangedFn != null) {
|
|
@@ -343,3 +356,23 @@ class GridCellFieldNotifierImpl extends IGridCellFieldNotifier {
|
|
);
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+class CellDataNotifier<T> extends ChangeNotifier {
|
|
|
|
+ T _value;
|
|
|
|
+ bool Function(T? oldValue, T? newValue)? listenWhen;
|
|
|
|
+ CellDataNotifier({required T value, this.listenWhen}) : _value = value;
|
|
|
|
+
|
|
|
|
+ set value(T newValue) {
|
|
|
|
+ if (listenWhen?.call(_value, newValue) ?? false) {
|
|
|
|
+ _value = newValue;
|
|
|
|
+ notifyListeners();
|
|
|
|
+ } else {
|
|
|
|
+ if (_value != newValue) {
|
|
|
|
+ _value = newValue;
|
|
|
|
+ notifyListeners();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ T get value => _value;
|
|
|
|
+}
|