view_service.dart 5.1 KB

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