field_cache.dart 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. import 'dart:collection';
  2. import 'package:app_flowy/plugins/grid/application/field/grid_listener.dart';
  3. import 'package:flowy_sdk/log.dart';
  4. import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
  5. import 'package:flutter/foundation.dart';
  6. import '../row/row_cache.dart';
  7. class FieldsNotifier extends ChangeNotifier {
  8. List<FieldPB> _fields = [];
  9. set fields(List<FieldPB> fields) {
  10. _fields = fields;
  11. notifyListeners();
  12. }
  13. List<FieldPB> get fields => _fields;
  14. }
  15. typedef FieldChangesetCallback = void Function(FieldChangesetPB);
  16. typedef FieldsCallback = void Function(List<FieldPB>);
  17. class GridFieldCache {
  18. final String gridId;
  19. final GridFieldsListener _fieldListener;
  20. FieldsNotifier? _fieldNotifier = FieldsNotifier();
  21. final Map<FieldsCallback, VoidCallback> _fieldsCallbackMap = {};
  22. final Map<FieldChangesetCallback, FieldChangesetCallback>
  23. _changesetCallbackMap = {};
  24. GridFieldCache({required this.gridId})
  25. : _fieldListener = GridFieldsListener(gridId: gridId) {
  26. _fieldListener.start(onFieldsChanged: (result) {
  27. result.fold(
  28. (changeset) {
  29. _deleteFields(changeset.deletedFields);
  30. _insertFields(changeset.insertedFields);
  31. _updateFields(changeset.updatedFields);
  32. for (final listener in _changesetCallbackMap.values) {
  33. listener(changeset);
  34. }
  35. },
  36. (err) => Log.error(err),
  37. );
  38. });
  39. }
  40. Future<void> dispose() async {
  41. await _fieldListener.stop();
  42. _fieldNotifier?.dispose();
  43. _fieldNotifier = null;
  44. }
  45. List<FieldPB> get fields => [..._fieldNotifier?.fields ?? []];
  46. set fields(List<FieldPB> fields) {
  47. _fieldNotifier?.fields = [...fields];
  48. }
  49. void addListener({
  50. FieldsCallback? onFields,
  51. FieldChangesetCallback? onChangeset,
  52. bool Function()? listenWhen,
  53. }) {
  54. if (onChangeset != null) {
  55. fn(c) {
  56. if (listenWhen != null && listenWhen() == false) {
  57. return;
  58. }
  59. onChangeset(c);
  60. }
  61. _changesetCallbackMap[onChangeset] = fn;
  62. }
  63. if (onFields != null) {
  64. fn() {
  65. if (listenWhen != null && listenWhen() == false) {
  66. return;
  67. }
  68. onFields(fields);
  69. }
  70. _fieldsCallbackMap[onFields] = fn;
  71. _fieldNotifier?.addListener(fn);
  72. }
  73. }
  74. void removeListener({
  75. FieldsCallback? onFieldsListener,
  76. FieldChangesetCallback? onChangesetListener,
  77. }) {
  78. if (onFieldsListener != null) {
  79. final fn = _fieldsCallbackMap.remove(onFieldsListener);
  80. if (fn != null) {
  81. _fieldNotifier?.removeListener(fn);
  82. }
  83. }
  84. if (onChangesetListener != null) {
  85. _changesetCallbackMap.remove(onChangesetListener);
  86. }
  87. }
  88. void _deleteFields(List<FieldIdPB> deletedFields) {
  89. if (deletedFields.isEmpty) {
  90. return;
  91. }
  92. final List<FieldPB> newFields = fields;
  93. final Map<String, FieldIdPB> deletedFieldMap = {
  94. for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder
  95. };
  96. newFields.retainWhere((field) => (deletedFieldMap[field.id] == null));
  97. _fieldNotifier?.fields = newFields;
  98. }
  99. void _insertFields(List<IndexFieldPB> insertedFields) {
  100. if (insertedFields.isEmpty) {
  101. return;
  102. }
  103. final List<FieldPB> newFields = fields;
  104. for (final indexField in insertedFields) {
  105. if (newFields.length > indexField.index) {
  106. newFields.insert(indexField.index, indexField.field_1);
  107. } else {
  108. newFields.add(indexField.field_1);
  109. }
  110. }
  111. _fieldNotifier?.fields = newFields;
  112. }
  113. void _updateFields(List<FieldPB> updatedFields) {
  114. if (updatedFields.isEmpty) {
  115. return;
  116. }
  117. final List<FieldPB> newFields = fields;
  118. for (final updatedField in updatedFields) {
  119. final index =
  120. newFields.indexWhere((field) => field.id == updatedField.id);
  121. if (index != -1) {
  122. newFields.removeAt(index);
  123. newFields.insert(index, updatedField);
  124. }
  125. }
  126. _fieldNotifier?.fields = newFields;
  127. }
  128. }
  129. class GridRowFieldNotifierImpl extends IGridRowFieldNotifier {
  130. final GridFieldCache _cache;
  131. FieldChangesetCallback? _onChangesetFn;
  132. FieldsCallback? _onFieldFn;
  133. GridRowFieldNotifierImpl(GridFieldCache cache) : _cache = cache;
  134. @override
  135. UnmodifiableListView<FieldPB> get fields =>
  136. UnmodifiableListView(_cache.fields);
  137. @override
  138. void onRowFieldsChanged(VoidCallback callback) {
  139. _onFieldFn = (_) => callback();
  140. _cache.addListener(onFields: _onFieldFn);
  141. }
  142. @override
  143. void onRowFieldChanged(void Function(FieldPB) callback) {
  144. _onChangesetFn = (FieldChangesetPB changeset) {
  145. for (final updatedField in changeset.updatedFields) {
  146. callback(updatedField);
  147. }
  148. };
  149. _cache.addListener(onChangeset: _onChangesetFn);
  150. }
  151. @override
  152. void onRowDispose() {
  153. if (_onFieldFn != null) {
  154. _cache.removeListener(onFieldsListener: _onFieldFn!);
  155. _onFieldFn = null;
  156. }
  157. if (_onChangesetFn != null) {
  158. _cache.removeListener(onChangesetListener: _onChangesetFn!);
  159. _onChangesetFn = null;
  160. }
  161. }
  162. }