import 'dart:async'; import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart'; import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'; class AppBackendService { Future> createView({ required String appId, required String name, String? desc, required ViewLayoutPB layoutType, /// The initial data should be a JSON that represent the DocumentDataPB. /// Currently, only support create document with initial data. List? initialDataBytes, /// The [ext] is used to pass through the custom configuration /// to the backend. /// Linking the view to the existing database, it needs to pass /// the database id. For example: "database_id": "xxx" /// Map ext = const {}, }) { final payload = CreateViewPayloadPB.create() ..belongToId = appId ..name = name ..desc = desc ?? "" ..layout = layoutType ..initialData = initialDataBytes ?? []; if (ext.isNotEmpty) { payload.ext.addAll(ext); } return FolderEventCreateView(payload).send(); } Future, FlowyError>> getViews({required String viewId}) { final payload = ViewIdPB.create()..value = viewId; return FolderEventReadView(payload).send().then((result) { return result.fold( (app) => left(app.childViews), (error) => right(error), ); }); } Future> delete({required String viewId}) { final request = RepeatedViewIdPB.create()..items.add(viewId); return FolderEventDeleteView(request).send(); } Future> deleteView({required String viewId}) { final request = RepeatedViewIdPB.create()..items.add(viewId); return FolderEventDeleteView(request).send(); } Future> updateApp({ required String appId, String? name, }) { var payload = UpdateViewPayloadPB.create()..viewId = appId; if (name != null) { payload.name = name; } return FolderEventUpdateView(payload).send(); } Future> moveView({ required String viewId, required int fromIndex, required int toIndex, }) { final payload = MoveFolderItemPayloadPB.create() ..itemId = viewId ..from = fromIndex ..to = toIndex ..ty = MoveFolderItemType.MoveView; return FolderEventMoveItem(payload).send(); } Future)>> fetchViews( ViewLayoutPB layoutType, ) async { final result = <(ViewPB, List)>[]; return FolderEventReadCurrentWorkspace().send().then((value) async { final workspaces = value.getLeftOrNull(); if (workspaces != null) { final views = workspaces.workspace.views; for (var view in views) { final childViews = await getViews(viewId: view.id).then( (value) => value .getLeftOrNull>() ?.where((e) => e.layout == layoutType) .toList(), ); if (childViews != null && childViews.isNotEmpty) { result.add((view, childViews)); } } } return result; }); } Future> getView( String viewID, ) async { final payload = ViewIdPB.create()..value = viewID; return FolderEventReadView(payload).send(); } Future> getChildView( String viewID, String childViewID, ) async { final payload = ViewIdPB.create()..value = viewID; return FolderEventReadView(payload).send().then((result) { return result.fold( (app) => left( app.childViews.firstWhere((e) => e.id == childViewID), ), (error) => right(error), ); }); } } extension AppFlowy on Either { T? getLeftOrNull() { if (isLeft()) { final result = fold((l) => l, (r) => null); return result; } return null; } }