field_cache.dart 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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. UnmodifiableListView<FieldPB> get unmodifiableFields =>
  46. UnmodifiableListView(_fieldNotifier?.fields ?? []);
  47. List<FieldPB> get fields => [..._fieldNotifier?.fields ?? []];
  48. set fields(List<FieldPB> fields) {
  49. _fieldNotifier?.fields = [...fields];
  50. }
  51. void addListener({
  52. FieldsCallback? onFields,
  53. FieldChangesetCallback? onChangeset,
  54. bool Function()? listenWhen,
  55. }) {
  56. if (onChangeset != null) {
  57. fn(c) {
  58. if (listenWhen != null && listenWhen() == false) {
  59. return;
  60. }
  61. onChangeset(c);
  62. }
  63. _changesetCallbackMap[onChangeset] = fn;
  64. }
  65. if (onFields != null) {
  66. fn() {
  67. if (listenWhen != null && listenWhen() == false) {
  68. return;
  69. }
  70. onFields(fields);
  71. }
  72. _fieldsCallbackMap[onFields] = fn;
  73. _fieldNotifier?.addListener(fn);
  74. }
  75. }
  76. void removeListener({
  77. FieldsCallback? onFieldsListener,
  78. FieldChangesetCallback? onChangesetListener,
  79. }) {
  80. if (onFieldsListener != null) {
  81. final fn = _fieldsCallbackMap.remove(onFieldsListener);
  82. if (fn != null) {
  83. _fieldNotifier?.removeListener(fn);
  84. }
  85. }
  86. if (onChangesetListener != null) {
  87. _changesetCallbackMap.remove(onChangesetListener);
  88. }
  89. }
  90. void _deleteFields(List<FieldIdPB> deletedFields) {
  91. if (deletedFields.isEmpty) {
  92. return;
  93. }
  94. final List<FieldPB> newFields = fields;
  95. final Map<String, FieldIdPB> deletedFieldMap = {
  96. for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder
  97. };
  98. newFields.retainWhere((field) => (deletedFieldMap[field.id] == null));
  99. _fieldNotifier?.fields = newFields;
  100. }
  101. void _insertFields(List<IndexFieldPB> insertedFields) {
  102. if (insertedFields.isEmpty) {
  103. return;
  104. }
  105. final List<FieldPB> newFields = fields;
  106. for (final indexField in insertedFields) {
  107. if (newFields.length > indexField.index) {
  108. newFields.insert(indexField.index, indexField.field_1);
  109. } else {
  110. newFields.add(indexField.field_1);
  111. }
  112. }
  113. _fieldNotifier?.fields = newFields;
  114. }
  115. void _updateFields(List<FieldPB> updatedFields) {
  116. if (updatedFields.isEmpty) {
  117. return;
  118. }
  119. final List<FieldPB> newFields = fields;
  120. for (final updatedField in updatedFields) {
  121. final index =
  122. newFields.indexWhere((field) => field.id == updatedField.id);
  123. if (index != -1) {
  124. newFields.removeAt(index);
  125. newFields.insert(index, updatedField);
  126. }
  127. }
  128. _fieldNotifier?.fields = newFields;
  129. }
  130. }
  131. class GridRowFieldNotifierImpl extends IGridRowFieldNotifier {
  132. final GridFieldCache _cache;
  133. FieldChangesetCallback? _onChangesetFn;
  134. FieldsCallback? _onFieldFn;
  135. GridRowFieldNotifierImpl(GridFieldCache cache) : _cache = cache;
  136. @override
  137. UnmodifiableListView<FieldPB> get fields => _cache.unmodifiableFields;
  138. @override
  139. void onRowFieldsChanged(VoidCallback callback) {
  140. _onFieldFn = (_) => callback();
  141. _cache.addListener(onFields: _onFieldFn);
  142. }
  143. @override
  144. void onRowFieldChanged(void Function(FieldPB) callback) {
  145. _onChangesetFn = (FieldChangesetPB changeset) {
  146. for (final updatedField in changeset.updatedFields) {
  147. callback(updatedField);
  148. }
  149. };
  150. _cache.addListener(onChangeset: _onChangesetFn);
  151. }
  152. @override
  153. void onRowDispose() {
  154. if (_onFieldFn != null) {
  155. _cache.removeListener(onFieldsListener: _onFieldFn!);
  156. _onFieldFn = null;
  157. }
  158. if (_onChangesetFn != null) {
  159. _cache.removeListener(onChangesetListener: _onChangesetFn!);
  160. _onChangesetFn = null;
  161. }
  162. }
  163. }