233 lines
6.6 KiB
Dart
Raw Normal View History

2022-05-14 18:21:32 +08:00
import 'dart:collection';
2022-08-09 11:59:22 +08:00
import 'package:app_flowy/plugins/grid/application/field/grid_listener.dart';
2022-04-10 16:29:45 +08:00
import 'package:dartz/dartz.dart';
2022-03-03 10:51:52 +08:00
import 'package:flowy_sdk/dispatch/dispatch.dart';
import 'package:flowy_sdk/log.dart';
2022-03-03 10:51:52 +08:00
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
2022-07-04 15:00:54 +08:00
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';
2022-04-14 13:29:42 +08:00
import 'package:flutter/foundation.dart';
2022-04-19 21:52:46 +08:00
import 'row/row_service.dart';
2022-03-03 10:51:52 +08:00
class GridService {
2022-04-10 16:29:45 +08:00
final String gridId;
GridService({
required this.gridId,
});
2022-07-17 13:38:53 +08:00
Future<Either<GridPB, FlowyError>> loadGrid() async {
2022-07-19 14:11:29 +08:00
await FolderEventSetLatestView(ViewIdPB(value: gridId)).send();
2022-03-06 21:22:42 +08:00
2022-07-17 13:38:53 +08:00
final payload = GridIdPB(value: gridId);
2022-06-27 20:53:47 +08:00
return GridEventGetGrid(payload).send();
2022-03-03 10:51:52 +08:00
}
Future<Either<GridRowPB, FlowyError>> createRow(
{Option<String>? startRowId}) {
2022-07-17 14:13:12 +08:00
CreateRowPayloadPB payload = CreateRowPayloadPB.create()..gridId = gridId;
2022-03-20 17:17:06 +08:00
startRowId?.fold(() => null, (id) => payload.startRowId = id);
return GridEventCreateRow(payload).send();
2022-03-03 22:17:07 +08:00
}
Future<Either<RepeatedGridFieldPB, FlowyError>> getFields(
{required List<GridFieldIdPB> fieldIds}) {
2022-07-17 14:13:12 +08:00
final payload = QueryFieldPayloadPB.create()
2022-03-05 17:52:25 +08:00
..gridId = gridId
2022-07-17 14:13:12 +08:00
..fieldIds = RepeatedGridFieldIdPB(items: fieldIds);
2022-03-05 17:52:25 +08:00
return GridEventGetFields(payload).send();
2022-03-03 10:51:52 +08:00
}
2022-04-10 16:29:45 +08:00
Future<Either<Unit, FlowyError>> closeGrid() {
2022-07-19 14:11:29 +08:00
final request = ViewIdPB(value: gridId);
2022-04-10 16:29:45 +08:00
return FolderEventCloseView(request).send();
}
2022-03-03 10:51:52 +08:00
}
2022-04-14 13:29:42 +08:00
class FieldsNotifier extends ChangeNotifier {
2022-07-17 14:13:12 +08:00
List<GridFieldPB> _fields = [];
2022-04-14 13:29:42 +08:00
2022-07-17 14:13:12 +08:00
set fields(List<GridFieldPB> fields) {
2022-04-14 13:29:42 +08:00
_fields = fields;
notifyListeners();
}
2022-07-17 14:13:12 +08:00
List<GridFieldPB> get fields => _fields;
2022-04-14 13:29:42 +08:00
}
2022-07-17 14:13:12 +08:00
typedef FieldChangesetCallback = void Function(GridFieldChangesetPB);
typedef FieldsCallback = void Function(List<GridFieldPB>);
2022-04-25 22:03:10 +08:00
2022-04-14 13:29:42 +08:00
class GridFieldCache {
final String gridId;
final GridFieldsListener _fieldListener;
FieldsNotifier? _fieldNotifier = FieldsNotifier();
2022-07-03 15:53:28 +08:00
final Map<FieldsCallback, VoidCallback> _fieldsCallbackMap = {};
final Map<FieldChangesetCallback, FieldChangesetCallback>
_changesetCallbackMap = {};
2022-04-25 22:03:10 +08:00
GridFieldCache({required this.gridId})
: _fieldListener = GridFieldsListener(gridId: gridId) {
2022-04-25 08:13:09 +08:00
_fieldListener.start(onFieldsChanged: (result) {
result.fold(
(changeset) {
_deleteFields(changeset.deletedFields);
_insertFields(changeset.insertedFields);
_updateFields(changeset.updatedFields);
2022-07-03 15:53:28 +08:00
for (final listener in _changesetCallbackMap.values) {
2022-04-25 22:03:10 +08:00
listener(changeset);
}
},
(err) => Log.error(err),
);
});
}
2022-04-14 13:29:42 +08:00
Future<void> dispose() async {
await _fieldListener.stop();
_fieldNotifier?.dispose();
_fieldNotifier = null;
2022-04-14 13:29:42 +08:00
}
UnmodifiableListView<GridFieldPB> get unmodifiableFields =>
UnmodifiableListView(_fieldNotifier?.fields ?? []);
2022-04-14 13:29:42 +08:00
2022-07-17 14:13:12 +08:00
List<GridFieldPB> get fields => [..._fieldNotifier?.fields ?? []];
2022-04-14 13:29:42 +08:00
2022-07-17 14:13:12 +08:00
set fields(List<GridFieldPB> fields) {
_fieldNotifier?.fields = [...fields];
2022-04-14 13:29:42 +08:00
}
2022-07-03 15:53:28 +08:00
void addListener({
FieldsCallback? onFields,
FieldChangesetCallback? onChangeset,
bool Function()? listenWhen,
}) {
if (onChangeset != null) {
fn(c) {
if (listenWhen != null && listenWhen() == false) {
return;
}
onChangeset(c);
}
2022-07-03 15:53:28 +08:00
_changesetCallbackMap[onChangeset] = fn;
2022-04-17 14:50:29 +08:00
}
2022-07-03 15:53:28 +08:00
if (onFields != null) {
fn() {
if (listenWhen != null && listenWhen() == false) {
return;
}
onFields(fields);
}
2022-04-17 14:50:29 +08:00
2022-07-03 15:53:28 +08:00
_fieldsCallbackMap[onFields] = fn;
_fieldNotifier?.addListener(fn);
}
2022-04-14 21:16:29 +08:00
}
2022-07-03 15:53:28 +08:00
void removeListener({
FieldsCallback? onFieldsListener,
2022-08-09 11:59:22 +08:00
FieldChangesetCallback? onChangesetListener,
2022-07-03 15:53:28 +08:00
}) {
if (onFieldsListener != null) {
final fn = _fieldsCallbackMap.remove(onFieldsListener);
if (fn != null) {
_fieldNotifier?.removeListener(fn);
}
}
2022-04-25 22:03:10 +08:00
2022-08-09 11:59:22 +08:00
if (onChangesetListener != null) {
_changesetCallbackMap.remove(onChangesetListener);
2022-04-25 22:03:10 +08:00
}
}
2022-07-17 14:13:12 +08:00
void _deleteFields(List<GridFieldIdPB> deletedFields) {
2022-04-14 13:29:42 +08:00
if (deletedFields.isEmpty) {
return;
}
2022-07-17 14:13:12 +08:00
final List<GridFieldPB> newFields = fields;
final Map<String, GridFieldIdPB> deletedFieldMap = {
2022-04-14 13:29:42 +08:00
for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder
};
newFields.retainWhere((field) => (deletedFieldMap[field.id] == null));
_fieldNotifier?.fields = newFields;
2022-04-14 13:29:42 +08:00
}
2022-07-17 14:13:12 +08:00
void _insertFields(List<IndexFieldPB> insertedFields) {
2022-04-14 13:29:42 +08:00
if (insertedFields.isEmpty) {
return;
}
2022-07-17 14:13:12 +08:00
final List<GridFieldPB> newFields = fields;
2022-04-14 13:29:42 +08:00
for (final indexField in insertedFields) {
if (newFields.length > indexField.index) {
newFields.insert(indexField.index, indexField.field_1);
2022-04-14 13:29:42 +08:00
} else {
newFields.add(indexField.field_1);
2022-04-14 13:29:42 +08:00
}
}
_fieldNotifier?.fields = newFields;
2022-04-14 13:29:42 +08:00
}
2022-07-17 14:13:12 +08:00
void _updateFields(List<GridFieldPB> updatedFields) {
2022-04-14 13:29:42 +08:00
if (updatedFields.isEmpty) {
return;
}
2022-07-17 14:13:12 +08:00
final List<GridFieldPB> newFields = fields;
2022-04-14 13:29:42 +08:00
for (final updatedField in updatedFields) {
final index =
newFields.indexWhere((field) => field.id == updatedField.id);
2022-04-14 13:29:42 +08:00
if (index != -1) {
newFields.removeAt(index);
newFields.insert(index, updatedField);
2022-04-14 13:29:42 +08:00
}
}
_fieldNotifier?.fields = newFields;
2022-04-14 13:29:42 +08:00
}
}
2022-04-19 21:52:46 +08:00
2022-07-16 11:53:39 +08:00
class GridRowCacheFieldNotifierImpl extends GridRowCacheFieldNotifier {
2022-04-19 21:52:46 +08:00
final GridFieldCache _cache;
2022-07-03 15:53:28 +08:00
FieldChangesetCallback? _onChangesetFn;
FieldsCallback? _onFieldFn;
2022-07-16 11:53:39 +08:00
GridRowCacheFieldNotifierImpl(GridFieldCache cache) : _cache = cache;
2022-04-19 21:52:46 +08:00
@override
2022-07-17 14:13:12 +08:00
UnmodifiableListView<GridFieldPB> get fields => _cache.unmodifiableFields;
2022-04-19 21:52:46 +08:00
@override
2022-07-03 15:53:28 +08:00
void onFieldsChanged(VoidCallback callback) {
_onFieldFn = (_) => callback();
_cache.addListener(onFields: _onFieldFn);
2022-04-19 21:52:46 +08:00
}
@override
2022-07-17 14:13:12 +08:00
void onFieldChanged(void Function(GridFieldPB) callback) {
_onChangesetFn = (GridFieldChangesetPB changeset) {
2022-04-25 22:03:10 +08:00
for (final updatedField in changeset.updatedFields) {
2022-07-03 15:53:28 +08:00
callback(updatedField);
2022-04-19 21:52:46 +08:00
}
2022-07-03 15:53:28 +08:00
};
2022-04-25 22:03:10 +08:00
2022-07-03 15:53:28 +08:00
_cache.addListener(onChangeset: _onChangesetFn);
2022-04-25 22:03:10 +08:00
}
@override
void dispose() {
2022-07-03 15:53:28 +08:00
if (_onFieldFn != null) {
_cache.removeListener(onFieldsListener: _onFieldFn!);
_onFieldFn = null;
}
if (_onChangesetFn != null) {
2022-08-09 11:59:22 +08:00
_cache.removeListener(onChangesetListener: _onChangesetFn!);
2022-07-03 15:53:28 +08:00
_onChangesetFn = null;
2022-04-25 22:03:10 +08:00
}
2022-04-19 21:52:46 +08:00
}
}