menu_bloc.dart 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. import 'dart:async';
  2. import 'package:app_flowy/workspace/domain/i_workspace.dart';
  3. import 'package:app_flowy/workspace/domain/page_stack/page_stack.dart';
  4. import 'package:app_flowy/workspace/presentation/stack_page/blank/blank_page.dart';
  5. import 'package:dartz/dartz.dart';
  6. import 'package:flowy_log/flowy_log.dart';
  7. import 'package:flowy_sdk/protobuf/flowy-folder-data-model/app.pb.dart';
  8. import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
  9. import 'package:freezed_annotation/freezed_annotation.dart';
  10. import 'package:flutter_bloc/flutter_bloc.dart';
  11. part 'menu_bloc.freezed.dart';
  12. class MenuBloc extends Bloc<MenuEvent, MenuState> {
  13. final IWorkspace workspaceManager;
  14. final IWorkspaceListener listener;
  15. MenuBloc({required this.workspaceManager, required this.listener}) : super(MenuState.initial()) {
  16. on<MenuEvent>((event, emit) async {
  17. await event.map(
  18. initial: (e) async {
  19. listener.start(addAppCallback: _handleAppsOrFail);
  20. await _fetchApps(emit);
  21. },
  22. collapse: (e) async {
  23. final isCollapse = state.isCollapse;
  24. emit(state.copyWith(isCollapse: !isCollapse));
  25. },
  26. openPage: (e) async {
  27. emit(state.copyWith(stackContext: e.context));
  28. },
  29. createApp: (CreateApp event) async {
  30. await _performActionOnCreateApp(event, emit);
  31. },
  32. didReceiveApps: (e) async {
  33. emit(e.appsOrFail.fold(
  34. (apps) => state.copyWith(apps: some(apps), successOrFailure: left(unit)),
  35. (err) => state.copyWith(successOrFailure: right(err)),
  36. ));
  37. },
  38. );
  39. });
  40. }
  41. @override
  42. Future<void> close() async {
  43. await listener.stop();
  44. return super.close();
  45. }
  46. Future<void> _performActionOnCreateApp(CreateApp event, Emitter<MenuState> emit) async {
  47. final result = await workspaceManager.createApp(name: event.name, desc: event.desc);
  48. emit(result.fold(
  49. (app) => state.copyWith(apps: some([app])),
  50. (error) {
  51. Log.error(error);
  52. return state.copyWith(successOrFailure: right(error));
  53. },
  54. ));
  55. }
  56. // ignore: unused_element
  57. Future<void> _fetchApps(Emitter<MenuState> emit) async {
  58. final appsOrFail = await workspaceManager.getApps();
  59. emit(appsOrFail.fold(
  60. (apps) => state.copyWith(apps: some(apps)),
  61. (error) {
  62. Log.error(error);
  63. return state.copyWith(successOrFailure: right(error));
  64. },
  65. ));
  66. }
  67. void _handleAppsOrFail(Either<List<App>, FlowyError> appsOrFail) {
  68. appsOrFail.fold(
  69. (apps) => add(MenuEvent.didReceiveApps(left(apps))),
  70. (error) => add(MenuEvent.didReceiveApps(right(error))),
  71. );
  72. }
  73. }
  74. @freezed
  75. class MenuEvent with _$MenuEvent {
  76. const factory MenuEvent.initial() = _Initial;
  77. const factory MenuEvent.collapse() = Collapse;
  78. const factory MenuEvent.openPage(HomeStackContext context) = OpenPage;
  79. const factory MenuEvent.createApp(String name, {String? desc}) = CreateApp;
  80. const factory MenuEvent.didReceiveApps(Either<List<App>, FlowyError> appsOrFail) = ReceiveApps;
  81. }
  82. @freezed
  83. class MenuState with _$MenuState {
  84. const factory MenuState({
  85. required bool isCollapse,
  86. required Option<List<App>> apps,
  87. required Either<Unit, FlowyError> successOrFailure,
  88. required HomeStackContext stackContext,
  89. }) = _MenuState;
  90. factory MenuState.initial() => MenuState(
  91. isCollapse: false,
  92. apps: none(),
  93. successOrFailure: left(unit),
  94. stackContext: BlankStackContext(),
  95. );
  96. }