import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_sdk/dispatch/dispatch.dart'; import 'package:flowy_sdk/log.dart'; import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'row/row_service.dart'; class GridService { final String gridId; GridService({ required this.gridId, }); Future> loadGrid() async { await FolderEventSetLatestView(ViewId(value: gridId)).send(); final payload = GridId(value: gridId); return GridEventGetGridData(payload).send(); } Future> createRow({Option? startRowId}) { CreateRowPayload payload = CreateRowPayload.create()..gridId = gridId; startRowId?.fold(() => null, (id) => payload.startRowId = id); return GridEventCreateRow(payload).send(); } Future> getFields({required List fieldOrders}) { final payload = QueryFieldPayload.create() ..gridId = gridId ..fieldOrders = RepeatedFieldOrder(items: fieldOrders); return GridEventGetFields(payload).send(); } Future> closeGrid() { final request = ViewId(value: gridId); return FolderEventCloseView(request).send(); } } class FieldsNotifier extends ChangeNotifier { List _fields = []; set fields(List fields) { _fields = fields; notifyListeners(); } List get fields => _fields; } class GridFieldCache { final String gridId; late final GridFieldsListener _fieldListener; final FieldsNotifier _fieldNotifier = FieldsNotifier(); GridFieldCache({required this.gridId}) { _fieldListener = GridFieldsListener(gridId: gridId); _fieldListener.updateFieldsNotifier?.addPublishListener((result) { result.fold( (changeset) { _deleteFields(changeset.deletedFields); _insertFields(changeset.insertedFields); _updateFields(changeset.updatedFields); }, (err) => Log.error(err), ); }); _fieldListener.start(); } Future dispose() async { await _fieldListener.stop(); _fieldNotifier.dispose(); } void applyChangeset(GridFieldChangeset changeset) {} UnmodifiableListView get unmodifiableFields => UnmodifiableListView(_fieldNotifier.fields); List get clonedFields => [..._fieldNotifier.fields]; set fields(List fields) { _fieldNotifier.fields = [...fields]; } VoidCallback addListener( {VoidCallback? listener, void Function(List)? onChanged, bool Function()? listenWhen}) { f() { if (listenWhen != null && listenWhen() == false) { return; } if (onChanged != null) { onChanged(clonedFields); } if (listener != null) { listener(); } } _fieldNotifier.addListener(f); return f; } void removeListener(VoidCallback f) { _fieldNotifier.removeListener(f); } void _deleteFields(List deletedFields) { if (deletedFields.isEmpty) { return; } final List fields = _fieldNotifier.fields; final Map deletedFieldMap = { for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder }; fields.retainWhere((field) => (deletedFieldMap[field.id] == null)); _fieldNotifier.fields = fields; } void _insertFields(List insertedFields) { if (insertedFields.isEmpty) { return; } final List fields = _fieldNotifier.fields; for (final indexField in insertedFields) { if (fields.length > indexField.index) { fields.insert(indexField.index, indexField.field_1); } else { fields.add(indexField.field_1); } } _fieldNotifier.fields = fields; } void _updateFields(List updatedFields) { if (updatedFields.isEmpty) { return; } final List fields = _fieldNotifier.fields; for (final updatedField in updatedFields) { final index = fields.indexWhere((field) => field.id == updatedField.id); if (index != -1) { fields.removeAt(index); fields.insert(index, updatedField); } } _fieldNotifier.fields = fields; } } class GridRowDataDelegateAdaptor extends GridRowDataDelegate { final GridFieldCache _cache; GridRowDataDelegateAdaptor(GridFieldCache cache) : _cache = cache; @override UnmodifiableListView get fields => _cache.unmodifiableFields; @override GridRow buildGridRow(RowOrder rowOrder) { return GridRow( gridId: _cache.gridId, fields: _cache.unmodifiableFields, rowId: rowOrder.rowId, height: rowOrder.height.toDouble(), ); } @override void onFieldChanged(FieldDidUpdateCallback callback) { _cache.addListener(listener: () { callback(); }); } @override CellDataMap buildCellDataMap(Row rowData) { var map = CellDataMap.new(); for (final field in fields) { if (field.visibility) { map[field.id] = GridCell( rowId: rowData.id, gridId: _cache.gridId, cell: rowData.cellByFieldId[field.id], field: field, ); } } return map; } }