grid_data_controller.dart 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import 'dart:collection';
  2. import 'package:flowy_sdk/log.dart';
  3. import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
  4. import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
  5. import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
  6. import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
  7. import 'package:flowy_sdk/protobuf/flowy-grid/grid_entities.pb.dart';
  8. import 'dart:async';
  9. import 'package:dartz/dartz.dart';
  10. import 'block/block_cache.dart';
  11. import 'prelude.dart';
  12. typedef OnFieldsChanged = void Function(UnmodifiableListView<GridFieldPB>);
  13. typedef OnGridChanged = void Function(GridPB);
  14. typedef OnRowsChanged = void Function(
  15. List<GridRowInfo> rowInfos,
  16. GridRowChangeReason,
  17. );
  18. typedef ListenONRowChangedCondition = bool Function();
  19. class GridDataController {
  20. final String gridId;
  21. final GridService _gridFFIService;
  22. final GridFieldCache fieldCache;
  23. // key: the block id
  24. final LinkedHashMap<String, GridBlockCache> _blocks;
  25. UnmodifiableMapView<String, GridBlockCache> get blocks =>
  26. UnmodifiableMapView(_blocks);
  27. OnRowsChanged? _onRowChanged;
  28. OnFieldsChanged? _onFieldsChanged;
  29. OnGridChanged? _onGridChanged;
  30. List<GridRowInfo> get rowInfos {
  31. final List<GridRowInfo> rows = [];
  32. for (var block in _blocks.values) {
  33. rows.addAll(block.rows);
  34. }
  35. return rows;
  36. }
  37. GridDataController({required ViewPB view})
  38. : gridId = view.id,
  39. _blocks = LinkedHashMap.identity(),
  40. _gridFFIService = GridService(gridId: view.id),
  41. fieldCache = GridFieldCache(gridId: view.id);
  42. void addListener({
  43. required OnGridChanged onGridChanged,
  44. required OnRowsChanged onRowsChanged,
  45. required OnFieldsChanged onFieldsChanged,
  46. }) {
  47. _onGridChanged = onGridChanged;
  48. _onRowChanged = onRowsChanged;
  49. _onFieldsChanged = onFieldsChanged;
  50. fieldCache.addListener(onFields: (fields) {
  51. _onFieldsChanged?.call(UnmodifiableListView(fields));
  52. });
  53. }
  54. Future<Either<Unit, FlowyError>> loadData() async {
  55. final result = await _gridFFIService.loadGrid();
  56. return Future(
  57. () => result.fold(
  58. (grid) async {
  59. _initialBlocks(grid.blocks);
  60. _onGridChanged?.call(grid);
  61. return await _loadFields(grid);
  62. },
  63. (err) => right(err),
  64. ),
  65. );
  66. }
  67. void createRow() {
  68. _gridFFIService.createRow();
  69. }
  70. Future<void> dispose() async {
  71. await _gridFFIService.closeGrid();
  72. await fieldCache.dispose();
  73. for (final blockCache in _blocks.values) {
  74. blockCache.dispose();
  75. }
  76. }
  77. void _initialBlocks(List<GridBlockPB> blocks) {
  78. for (final block in blocks) {
  79. if (_blocks[block.id] != null) {
  80. Log.warn("Initial duplicate block's cache: ${block.id}");
  81. return;
  82. }
  83. final cache = GridBlockCache(
  84. gridId: gridId,
  85. block: block,
  86. fieldCache: fieldCache,
  87. );
  88. cache.addListener(
  89. onChangeReason: (reason) {
  90. _onRowChanged?.call(rowInfos, reason);
  91. },
  92. );
  93. _blocks[block.id] = cache;
  94. }
  95. }
  96. Future<Either<Unit, FlowyError>> _loadFields(GridPB grid) async {
  97. final result = await _gridFFIService.getFields(fieldIds: grid.fields);
  98. return Future(
  99. () => result.fold(
  100. (fields) {
  101. fieldCache.fields = fields.items;
  102. _onFieldsChanged?.call(UnmodifiableListView(fieldCache.fields));
  103. return left(unit);
  104. },
  105. (err) => right(err),
  106. ),
  107. );
  108. }
  109. }