view_service.dart 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. import 'dart:async';
  2. import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
  3. import 'package:dartz/dartz.dart';
  4. import 'package:appflowy_backend/dispatch/dispatch.dart';
  5. import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
  6. import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
  7. class ViewBackendService {
  8. static Future<Either<ViewPB, FlowyError>> createView({
  9. required ViewLayoutPB layoutType,
  10. required String parentViewId,
  11. required String name,
  12. String? desc,
  13. /// The initial data should be a JSON that represent the DocumentDataPB.
  14. /// Currently, only support create document with initial data.
  15. List<int>? initialDataBytes,
  16. /// The [ext] is used to pass through the custom configuration
  17. /// to the backend.
  18. /// Linking the view to the existing database, it needs to pass
  19. /// the database id. For example: "database_id": "xxx"
  20. ///
  21. Map<String, String> ext = const {},
  22. }) {
  23. final payload = CreateViewPayloadPB.create()
  24. ..parentViewId = parentViewId
  25. ..name = name
  26. ..desc = desc ?? ""
  27. ..layout = layoutType
  28. ..initialData = initialDataBytes ?? [];
  29. if (ext.isNotEmpty) {
  30. payload.ext.addAll(ext);
  31. }
  32. return FolderEventCreateView(payload).send();
  33. }
  34. static Future<Either<ViewPB, FlowyError>> createDatabaseReferenceView({
  35. required String parentViewId,
  36. required String databaseId,
  37. required ViewLayoutPB layoutType,
  38. required String name,
  39. }) {
  40. return ViewBackendService.createView(
  41. layoutType: layoutType,
  42. parentViewId: parentViewId,
  43. name: name,
  44. ext: {
  45. 'database_id': databaseId,
  46. },
  47. );
  48. }
  49. static Future<Either<List<ViewPB>, FlowyError>> getViews({
  50. required String viewId,
  51. }) {
  52. final payload = ViewIdPB.create()..value = viewId;
  53. return FolderEventReadView(payload).send().then((result) {
  54. return result.fold(
  55. (app) => left(app.childViews),
  56. (error) => right(error),
  57. );
  58. });
  59. }
  60. static Future<Either<Unit, FlowyError>> delete({required String viewId}) {
  61. final request = RepeatedViewIdPB.create()..items.add(viewId);
  62. return FolderEventDeleteView(request).send();
  63. }
  64. static Future<Either<Unit, FlowyError>> deleteView({required String viewId}) {
  65. final request = RepeatedViewIdPB.create()..items.add(viewId);
  66. return FolderEventDeleteView(request).send();
  67. }
  68. static Future<Either<Unit, FlowyError>> duplicate({required ViewPB view}) {
  69. return FolderEventDuplicateView(view).send();
  70. }
  71. static Future<Either<ViewPB, FlowyError>> updateView({
  72. required String viewId,
  73. String? name,
  74. }) {
  75. var payload = UpdateViewPayloadPB.create()..viewId = viewId;
  76. if (name != null) {
  77. payload.name = name;
  78. }
  79. return FolderEventUpdateView(payload).send();
  80. }
  81. static Future<Either<Unit, FlowyError>> moveView({
  82. required String viewId,
  83. required int fromIndex,
  84. required int toIndex,
  85. }) {
  86. final payload = MoveFolderItemPayloadPB.create()
  87. ..itemId = viewId
  88. ..from = fromIndex
  89. ..to = toIndex
  90. ..ty = MoveFolderItemType.MoveView;
  91. return FolderEventMoveItem(payload).send();
  92. }
  93. Future<List<(ViewPB, List<ViewPB>)>> fetchViews(
  94. ViewLayoutPB layoutType,
  95. ) async {
  96. final result = <(ViewPB, List<ViewPB>)>[];
  97. return FolderEventReadCurrentWorkspace().send().then((value) async {
  98. final workspaces = value.getLeftOrNull<WorkspaceSettingPB>();
  99. if (workspaces != null) {
  100. final views = workspaces.workspace.views;
  101. for (var view in views) {
  102. final childViews = await getViews(viewId: view.id).then(
  103. (value) => value
  104. .getLeftOrNull<List<ViewPB>>()
  105. ?.where((e) => e.layout == layoutType)
  106. .toList(),
  107. );
  108. if (childViews != null && childViews.isNotEmpty) {
  109. result.add((view, childViews));
  110. }
  111. }
  112. }
  113. return result;
  114. });
  115. }
  116. Future<Either<ViewPB, FlowyError>> getView(
  117. String viewID,
  118. ) async {
  119. final payload = ViewIdPB.create()..value = viewID;
  120. return FolderEventReadView(payload).send();
  121. }
  122. Future<Either<ViewPB, FlowyError>> getChildView({
  123. required String parentViewId,
  124. required String childViewId,
  125. }) async {
  126. final payload = ViewIdPB.create()..value = parentViewId;
  127. return FolderEventReadView(payload).send().then((result) {
  128. return result.fold(
  129. (app) => left(
  130. app.childViews.firstWhere((e) => e.id == childViewId),
  131. ),
  132. (error) => right(error),
  133. );
  134. });
  135. }
  136. }
  137. extension AppFlowy on Either {
  138. T? getLeftOrNull<T>() {
  139. if (isLeft()) {
  140. final result = fold<T?>((l) => l, (r) => null);
  141. return result;
  142. }
  143. return null;
  144. }
  145. }