Browse Source

migrate to flutter_bloc 8.0

appflowy 3 years ago
parent
commit
b354fb79c8

+ 11 - 8
frontend/app_flowy/lib/startup/tasks/application_widget.dart

@@ -18,14 +18,17 @@ class AppWidgetTask extends LaunchTask {
   Future<void> initialize(LaunchContext context) {
     final widget = context.getIt<EntryPoint>().create();
     final app = ApplicationWidget(child: widget);
-    Bloc.observer = ApplicationBlocObserver();
-
-    runApp(
-      EasyLocalization(
-          supportedLocales: const [Locale('en'), Locale('zh_CN'), Locale('it_IT')],
-          path: 'assets/translations',
-          fallbackLocale: const Locale('en'),
-          child: app),
+    BlocOverrides.runZoned(
+      () {
+        runApp(
+          EasyLocalization(
+              supportedLocales: const [Locale('en'), Locale('zh_CN'), Locale('it_IT')],
+              path: 'assets/translations',
+              fallbackLocale: const Locale('en'),
+              child: app),
+        );
+      },
+      blocObserver: ApplicationBlocObserver(),
     );
 
     return Future(() => {});

+ 21 - 23
frontend/app_flowy/lib/user/application/sign_in_bloc.dart

@@ -9,35 +9,33 @@ part 'sign_in_bloc.freezed.dart';
 
 class SignInBloc extends Bloc<SignInEvent, SignInState> {
   final IAuth authManager;
-  SignInBloc(this.authManager) : super(SignInState.initial());
-
-  @override
-  Stream<SignInState> mapEventToState(
-    SignInEvent event,
-  ) async* {
-    yield* event.map(
-      signedInWithUserEmailAndPassword: (e) async* {
-        yield* _performActionOnSignIn(
-          state,
-        );
-      },
-      emailChanged: (EmailChanged value) async* {
-        yield state.copyWith(email: value.email, emailError: none(), successOrFail: none());
-      },
-      passwordChanged: (PasswordChanged value) async* {
-        yield state.copyWith(password: value.password, passwordError: none(), successOrFail: none());
-      },
-    );
+  SignInBloc(this.authManager) : super(SignInState.initial()) {
+    on<SignInEvent>((event, emit) async {
+      await event.map(
+        signedInWithUserEmailAndPassword: (e) async {
+          await _performActionOnSignIn(
+            state,
+            emit,
+          );
+        },
+        emailChanged: (EmailChanged value) async {
+          emit(state.copyWith(email: value.email, emailError: none(), successOrFail: none()));
+        },
+        passwordChanged: (PasswordChanged value) async {
+          emit(state.copyWith(password: value.password, passwordError: none(), successOrFail: none()));
+        },
+      );
+    });
   }
 
-  Stream<SignInState> _performActionOnSignIn(SignInState state) async* {
-    yield state.copyWith(isSubmitting: true, emailError: none(), passwordError: none(), successOrFail: none());
+  Future<void> _performActionOnSignIn(SignInState state, Emitter<SignInState> emit) async {
+    emit(state.copyWith(isSubmitting: true, emailError: none(), passwordError: none(), successOrFail: none()));
 
     final result = await authManager.signIn(state.email, state.password);
-    yield result.fold(
+    emit(result.fold(
       (userProfile) => state.copyWith(isSubmitting: false, successOrFail: some(left(userProfile))),
       (error) => stateFromCode(error),
-    );
+    ));
   }
 
   SignInState stateFromCode(FlowyError error) {

+ 24 - 27
frontend/app_flowy/lib/user/application/sign_up_bloc.dart

@@ -11,62 +11,59 @@ part 'sign_up_bloc.freezed.dart';
 
 class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
   final IAuth authManager;
-  SignUpBloc(this.authManager) : super(SignUpState.initial());
-
-  @override
-  Stream<SignUpState> mapEventToState(
-    SignUpEvent event,
-  ) async* {
-    yield* event.map(signUpWithUserEmailAndPassword: (e) async* {
-      yield* _performActionOnSignUp();
-    }, emailChanged: (EmailChanged value) async* {
-      yield state.copyWith(email: value.email, emailError: none(), successOrFail: none());
-    }, passwordChanged: (PasswordChanged value) async* {
-      yield state.copyWith(password: value.password, passwordError: none(), successOrFail: none());
-    }, repeatPasswordChanged: (RepeatPasswordChanged value) async* {
-      yield state.copyWith(repeatedPassword: value.password, repeatPasswordError: none(), successOrFail: none());
+  SignUpBloc(this.authManager) : super(SignUpState.initial()) {
+    on<SignUpEvent>((event, emit) async {
+      await event.map(signUpWithUserEmailAndPassword: (e) async {
+        await _performActionOnSignUp(emit);
+      }, emailChanged: (EmailChanged value) async {
+        emit(state.copyWith(email: value.email, emailError: none(), successOrFail: none()));
+      }, passwordChanged: (PasswordChanged value) async {
+        emit(state.copyWith(password: value.password, passwordError: none(), successOrFail: none()));
+      }, repeatPasswordChanged: (RepeatPasswordChanged value) async {
+        emit(state.copyWith(repeatedPassword: value.password, repeatPasswordError: none(), successOrFail: none()));
+      });
     });
   }
 
-  Stream<SignUpState> _performActionOnSignUp() async* {
-    yield state.copyWith(
+  Future<void> _performActionOnSignUp(Emitter<SignUpState> emit) async {
+    emit(state.copyWith(
       isSubmitting: true,
       successOrFail: none(),
-    );
+    ));
 
     final password = state.password;
     final repeatedPassword = state.repeatedPassword;
     if (password == null) {
-      yield state.copyWith(
+      emit(state.copyWith(
         isSubmitting: false,
         passwordError: some(LocaleKeys.signUp_emptyPasswordError.tr()),
-      );
+      ));
       return;
     }
 
     if (repeatedPassword == null) {
-      yield state.copyWith(
+      emit(state.copyWith(
         isSubmitting: false,
         repeatPasswordError: some(LocaleKeys.signUp_repeatPasswordEmptyError.tr()),
-      );
+      ));
       return;
     }
 
     if (password != repeatedPassword) {
-      yield state.copyWith(
+      emit(state.copyWith(
         isSubmitting: false,
         repeatPasswordError: some(LocaleKeys.signUp_unmatchedPasswordError.tr()),
-      );
+      ));
       return;
     }
 
-    yield state.copyWith(
+    emit(state.copyWith(
       passwordError: none(),
       repeatPasswordError: none(),
-    );
+    ));
 
     final result = await authManager.signUp(state.email, state.password, state.email);
-    yield result.fold(
+    emit(result.fold(
       (profile) => state.copyWith(
         isSubmitting: false,
         successOrFail: some(left(profile)),
@@ -75,7 +72,7 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
         repeatPasswordError: none(),
       ),
       (error) => stateFromCode(error),
-    );
+    ));
   }
 
   SignUpState stateFromCode(FlowyError error) {

+ 9 - 10
frontend/app_flowy/lib/user/application/splash_bloc.dart

@@ -7,16 +7,15 @@ part 'splash_bloc.freezed.dart';
 
 class SplashBloc extends Bloc<SplashEvent, SplashState> {
   final ISplashUser authImpl;
-  SplashBloc(this.authImpl) : super(SplashState.initial());
-
-  @override
-  Stream<SplashState> mapEventToState(SplashEvent event) async* {
-    yield* event.map(
-      getUser: (val) async* {
-        final authState = await authImpl.currentUserProfile();
-        yield state.copyWith(auth: authState);
-      },
-    );
+  SplashBloc(this.authImpl) : super(SplashState.initial()) {
+    on<SplashEvent>((event, emit) async {
+      await event.map(
+        getUser: (val) async {
+          final authState = await authImpl.currentUserProfile();
+          emit(state.copyWith(auth: authState));
+        },
+      );
+    });
   }
 }
 

+ 2 - 2
frontend/app_flowy/lib/user/infrastructure/i_splash_impl.dart

@@ -24,8 +24,8 @@ class SplashUserImpl implements ISplashUser {
         (userProfile) {
           return AuthState.authenticated(userProfile);
         },
-        (FlowyError) {
-          return AuthState.unauthenticated(FlowyError);
+        (error) {
+          return AuthState.unauthenticated(error);
         },
       );
     });

+ 43 - 46
frontend/app_flowy/lib/workspace/application/app/app_bloc.dart

@@ -12,46 +12,43 @@ part 'app_bloc.freezed.dart';
 class AppBloc extends Bloc<AppEvent, AppState> {
   final IApp appManager;
   final IAppListenr listener;
-  AppBloc({required App app, required this.appManager, required this.listener}) : super(AppState.initial(app));
-
-  @override
-  Stream<AppState> mapEventToState(
-    AppEvent event,
-  ) async* {
-    yield* event.map(initial: (e) async* {
-      listener.start(
-        viewsChangeCallback: _handleViewsChanged,
-        updatedCallback: (app) => add(AppEvent.appDidUpdate(app)),
-      );
-      yield* _fetchViews();
-    }, createView: (CreateView value) async* {
-      final viewOrFailed = await appManager.createView(name: value.name, desc: value.desc, viewType: value.viewType);
-      yield viewOrFailed.fold(
-        (view) => state.copyWith(
-          latestCreatedView: view,
-          successOrFailure: left(unit),
-        ),
-        (error) {
-          Log.error(error);
-          return state.copyWith(successOrFailure: right(error));
-        },
-      );
-    }, didReceiveViews: (e) async* {
-      yield* handleDidReceiveViews(e.views);
-    }, delete: (e) async* {
-      final result = await appManager.delete();
-      yield result.fold(
-        (unit) => state.copyWith(successOrFailure: left(unit)),
-        (error) => state.copyWith(successOrFailure: right(error)),
-      );
-    }, rename: (e) async* {
-      final result = await appManager.rename(e.newName);
-      yield result.fold(
-        (l) => state.copyWith(successOrFailure: left(unit)),
-        (error) => state.copyWith(successOrFailure: right(error)),
-      );
-    }, appDidUpdate: (e) async* {
-      yield state.copyWith(app: e.app);
+  AppBloc({required App app, required this.appManager, required this.listener}) : super(AppState.initial(app)) {
+    on<AppEvent>((event, emit) async {
+      await event.map(initial: (e) async {
+        listener.start(
+          viewsChangeCallback: _handleViewsChanged,
+          updatedCallback: (app) => add(AppEvent.appDidUpdate(app)),
+        );
+        await _fetchViews(emit);
+      }, createView: (CreateView value) async {
+        final viewOrFailed = await appManager.createView(name: value.name, desc: value.desc, viewType: value.viewType);
+        viewOrFailed.fold(
+          (view) => emit(state.copyWith(
+            latestCreatedView: view,
+            successOrFailure: left(unit),
+          )),
+          (error) {
+            Log.error(error);
+            emit(state.copyWith(successOrFailure: right(error)));
+          },
+        );
+      }, didReceiveViews: (e) async {
+        await handleDidReceiveViews(e.views, emit);
+      }, delete: (e) async {
+        final result = await appManager.delete();
+        result.fold(
+          (unit) => emit(state.copyWith(successOrFailure: left(unit))),
+          (error) => emit(state.copyWith(successOrFailure: right(error))),
+        );
+      }, rename: (e) async {
+        final result = await appManager.rename(e.newName);
+        result.fold(
+          (l) => emit(state.copyWith(successOrFailure: left(unit))),
+          (error) => emit(state.copyWith(successOrFailure: right(error))),
+        );
+      }, appDidUpdate: (e) async {
+        emit(state.copyWith(app: e.app));
+      });
     });
   }
 
@@ -70,7 +67,7 @@ class AppBloc extends Bloc<AppEvent, AppState> {
     );
   }
 
-  Stream<AppState> handleDidReceiveViews(List<View> views) async* {
+  Future<void> handleDidReceiveViews(List<View> views, Emitter<AppState> emit) async {
     final latestCreatedView = state.latestCreatedView;
     AppState newState = state.copyWith(views: views);
     if (latestCreatedView != null) {
@@ -80,16 +77,16 @@ class AppBloc extends Bloc<AppEvent, AppState> {
       }
     }
 
-    yield newState;
+    emit(newState);
   }
 
-  Stream<AppState> _fetchViews() async* {
+  Future<void> _fetchViews(Emitter<AppState> emit) async {
     final viewsOrFailed = await appManager.getViews();
-    yield viewsOrFailed.fold(
-      (apps) => state.copyWith(views: apps),
+    viewsOrFailed.fold(
+      (apps) => emit(state.copyWith(views: apps)),
       (error) {
         Log.error(error);
-        return state.copyWith(successOrFailure: right(error));
+        emit(state.copyWith(successOrFailure: right(error)));
       },
     );
   }

+ 29 - 31
frontend/app_flowy/lib/workspace/application/doc/doc_bloc.dart

@@ -27,31 +27,30 @@ class DocBloc extends Bloc<DocEvent, DocState> {
     required this.docManager,
     required this.listener,
     required this.trasnManager,
-  }) : super(DocState.initial());
-
-  @override
-  Stream<DocState> mapEventToState(DocEvent event) async* {
-    yield* event.map(
-      initial: _initial,
-      deleted: (Deleted value) async* {
-        yield state.copyWith(isDeleted: true);
-      },
-      restore: (Restore value) async* {
-        yield state.copyWith(isDeleted: false);
-      },
-      deletePermanently: (DeletePermanently value) async* {
-        final result = await trasnManager.deleteViews([Tuple2(view.id, TrashType.View)]);
-        yield result.fold((l) => state.copyWith(forceClose: true), (r) {
-          return state;
-        });
-      },
-      restorePage: (RestorePage value) async* {
-        final result = await trasnManager.putback(view.id);
-        yield result.fold((l) => state.copyWith(isDeleted: false), (r) {
-          return state;
-        });
-      },
-    );
+  }) : super(DocState.initial()) {
+    on<DocEvent>((event, emit) async {
+      await event.map(
+        initial: (Initial value) async {
+          await _initial(value, emit);
+        },
+        deleted: (Deleted value) async {
+          emit(state.copyWith(isDeleted: true));
+        },
+        restore: (Restore value) async {
+          emit(state.copyWith(isDeleted: false));
+        },
+        deletePermanently: (DeletePermanently value) async {
+          final result = await trasnManager.deleteViews([Tuple2(view.id, TrashType.View)]);
+          final newState = result.fold((l) => state.copyWith(forceClose: true), (r) => state);
+          emit(newState);
+        },
+        restorePage: (RestorePage value) async {
+          final result = await trasnManager.putback(view.id);
+          final newState = result.fold((l) => state.copyWith(isDeleted: false), (r) => state);
+          emit(newState);
+        },
+      );
+    });
   }
 
   @override
@@ -62,11 +61,11 @@ class DocBloc extends Bloc<DocEvent, DocState> {
       await _subscription?.cancel();
     }
 
-    // docManager.closeDoc();
+    docManager.closeDoc();
     return super.close();
   }
 
-  Stream<DocState> _initial(Initial value) async* {
+  Future<void> _initial(Initial value, Emitter<DocState> emit) async {
     listener.deletedNotifier.addPublishListener((result) {
       result.fold(
         (view) => add(const DocEvent.deleted()),
@@ -82,9 +81,8 @@ class DocBloc extends Bloc<DocEvent, DocState> {
     });
 
     listener.start();
-
     final result = await docManager.readDoc();
-    yield result.fold(
+    result.fold(
       (doc) {
         document = _decodeJsonToDocument(doc.deltaJson);
         _subscription = document.changes.listen((event) {
@@ -92,10 +90,10 @@ class DocBloc extends Bloc<DocEvent, DocState> {
           final documentDelta = document.toDelta();
           _composeDelta(delta, documentDelta);
         });
-        return state.copyWith(loadState: DocLoadState.finish(left(unit)));
+        emit(state.copyWith(loadState: DocLoadState.finish(left(unit))));
       },
       (err) {
-        return state.copyWith(loadState: DocLoadState.finish(right(err)));
+        emit(state.copyWith(loadState: DocLoadState.finish(right(err))));
       },
     );
   }

+ 11 - 14
frontend/app_flowy/lib/workspace/application/edit_pannel/edit_pannel_bloc.dart

@@ -7,20 +7,17 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 part 'edit_pannel_bloc.freezed.dart';
 
 class EditPannelBloc extends Bloc<EditPannelEvent, EditPannelState> {
-  EditPannelBloc() : super(EditPannelState.initial());
-
-  @override
-  Stream<EditPannelState> mapEventToState(
-    EditPannelEvent event,
-  ) async* {
-    yield* event.map(
-      startEdit: (e) async* {
-        yield state.copyWith(isEditing: true, editContext: some(e.context));
-      },
-      endEdit: (value) async* {
-        yield state.copyWith(isEditing: false, editContext: none());
-      },
-    );
+  EditPannelBloc() : super(EditPannelState.initial()) {
+    on<EditPannelEvent>((event, emit) async {
+      await event.map(
+        startEdit: (e) async {
+          emit(state.copyWith(isEditing: true, editContext: some(e.context)));
+        },
+        endEdit: (value) async {
+          emit(state.copyWith(isEditing: false, editContext: none()));
+        },
+      );
+    });
   }
 }
 

+ 18 - 22
frontend/app_flowy/lib/workspace/application/home/home_bloc.dart

@@ -5,26 +5,23 @@ import 'package:dartz/dartz.dart';
 part 'home_bloc.freezed.dart';
 
 class HomeBloc extends Bloc<HomeEvent, HomeState> {
-  HomeBloc() : super(HomeState.initial());
-
-  @override
-  Stream<HomeState> mapEventToState(
-    HomeEvent event,
-  ) async* {
-    yield* event.map(
-      showLoading: (e) async* {
-        yield state.copyWith(isLoading: e.isLoading);
-      },
-      setEditPannel: (e) async* {
-        yield state.copyWith(editContext: some(e.editContext));
-      },
-      dismissEditPannel: (value) async* {
-        yield state.copyWith(editContext: none());
-      },
-      forceCollapse: (e) async* {
-        yield state.copyWith(forceCollapse: e.forceCollapse);
-      },
-    );
+  HomeBloc() : super(HomeState.initial()) {
+    on<HomeEvent>((event, emit) async {
+      await event.map(
+        showLoading: (e) async {
+          emit(state.copyWith(isLoading: e.isLoading));
+        },
+        setEditPannel: (e) async {
+          emit(state.copyWith(editContext: some(e.editContext)));
+        },
+        dismissEditPannel: (value) async {
+          emit(state.copyWith(editContext: none()));
+        },
+        forceCollapse: (e) async {
+          emit(state.copyWith(forceCollapse: e.forceCollapse));
+        },
+      );
+    });
   }
 
   @override
@@ -37,8 +34,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
 class HomeEvent with _$HomeEvent {
   const factory HomeEvent.showLoading(bool isLoading) = _ShowLoading;
   const factory HomeEvent.forceCollapse(bool forceCollapse) = _ForceCollapse;
-  const factory HomeEvent.setEditPannel(EditPannelContext editContext) =
-      _ShowEditPannel;
+  const factory HomeEvent.setEditPannel(EditPannelContext editContext) = _ShowEditPannel;
   const factory HomeEvent.dismissEditPannel() = _DismissEditPannel;
 }
 

+ 15 - 16
frontend/app_flowy/lib/workspace/application/home/home_listen_bloc.dart

@@ -8,22 +8,21 @@ part 'home_listen_bloc.freezed.dart';
 
 class HomeListenBloc extends Bloc<HomeListenEvent, HomeListenState> {
   final IUserListener listener;
-  HomeListenBloc(this.listener) : super(const HomeListenState.loading());
-
-  @override
-  Stream<HomeListenState> mapEventToState(
-    HomeListenEvent event,
-  ) async* {
-    yield* event.map(
-      started: (_) async* {
-        listener.authDidChangedNotifier.addPublishListener(_authDidChanged);
-        listener.start();
-      },
-      stop: (_) async* {},
-      unauthorized: (e) async* {
-        yield HomeListenState.unauthorized(e.msg);
-      },
-    );
+  HomeListenBloc(this.listener) : super(const HomeListenState.loading()) {
+    on<HomeListenEvent>((event, emit) async {
+      await event.map(
+        started: (_) async {
+          listener.authDidChangedNotifier.addPublishListener((result) {
+            _authDidChanged(result);
+          });
+          listener.start();
+        },
+        stop: (_) async {},
+        unauthorized: (e) async {
+          emit(HomeListenState.unauthorized(e.msg));
+        },
+      );
+    });
   }
 
   @override

+ 31 - 38
frontend/app_flowy/lib/workspace/application/menu/menu_bloc.dart

@@ -14,34 +14,31 @@ part 'menu_bloc.freezed.dart';
 class MenuBloc extends Bloc<MenuEvent, MenuState> {
   final IWorkspace workspaceManager;
   final IWorkspaceListener listener;
-  MenuBloc({required this.workspaceManager, required this.listener}) : super(MenuState.initial());
-
-  @override
-  Stream<MenuState> mapEventToState(
-    MenuEvent event,
-  ) async* {
-    yield* event.map(
-      initial: (e) async* {
-        listener.start(addAppCallback: _handleAppsOrFail);
-        yield* _fetchApps();
-      },
-      collapse: (e) async* {
-        final isCollapse = state.isCollapse;
-        yield state.copyWith(isCollapse: !isCollapse);
-      },
-      openPage: (e) async* {
-        yield* _performActionOnOpenPage(e);
-      },
-      createApp: (CreateApp event) async* {
-        yield* _performActionOnCreateApp(event);
-      },
-      didReceiveApps: (e) async* {
-        yield e.appsOrFail.fold(
-          (apps) => state.copyWith(apps: some(apps), successOrFailure: left(unit)),
-          (err) => state.copyWith(successOrFailure: right(err)),
-        );
-      },
-    );
+  MenuBloc({required this.workspaceManager, required this.listener}) : super(MenuState.initial()) {
+    on<MenuEvent>((event, emit) async {
+      await event.map(
+        initial: (e) async {
+          listener.start(addAppCallback: _handleAppsOrFail);
+          await _fetchApps(emit);
+        },
+        collapse: (e) async {
+          final isCollapse = state.isCollapse;
+          emit(state.copyWith(isCollapse: !isCollapse));
+        },
+        openPage: (e) async {
+          emit(state.copyWith(stackContext: e.context));
+        },
+        createApp: (CreateApp event) async {
+          await _performActionOnCreateApp(event, emit);
+        },
+        didReceiveApps: (e) async {
+          emit(e.appsOrFail.fold(
+            (apps) => state.copyWith(apps: some(apps), successOrFailure: left(unit)),
+            (err) => state.copyWith(successOrFailure: right(err)),
+          ));
+        },
+      );
+    });
   }
 
   @override
@@ -50,31 +47,27 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
     return super.close();
   }
 
-  Stream<MenuState> _performActionOnOpenPage(OpenPage e) async* {
-    yield state.copyWith(stackContext: e.context);
-  }
-
-  Stream<MenuState> _performActionOnCreateApp(CreateApp event) async* {
+  Future<void> _performActionOnCreateApp(CreateApp event, Emitter<MenuState> emit) async {
     final result = await workspaceManager.createApp(name: event.name, desc: event.desc);
-    yield result.fold(
+    emit(result.fold(
       (app) => state.copyWith(apps: some([app])),
       (error) {
         Log.error(error);
         return state.copyWith(successOrFailure: right(error));
       },
-    );
+    ));
   }
 
   // ignore: unused_element
-  Stream<MenuState> _fetchApps() async* {
+  Future<void> _fetchApps(Emitter<MenuState> emit) async {
     final appsOrFail = await workspaceManager.getApps();
-    yield appsOrFail.fold(
+    emit(appsOrFail.fold(
       (apps) => state.copyWith(apps: some(apps)),
       (error) {
         Log.error(error);
         return state.copyWith(successOrFailure: right(error));
       },
-    );
+    ));
   }
 
   void _handleAppsOrFail(Either<List<App>, FlowyError> appsOrFail) {

+ 12 - 14
frontend/app_flowy/lib/workspace/application/menu/menu_user_bloc.dart

@@ -12,20 +12,18 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
   final IUser userManager;
   final IUserListener listener;
 
-  MenuUserBloc(this.userManager, this.listener) : super(MenuUserState.initial(userManager.user));
-
-  @override
-  Stream<MenuUserState> mapEventToState(MenuUserEvent event) async* {
-    yield* event.map(
-      initial: (_) async* {
-        listener.profileUpdatedNotifier.addPublishListener(_profileUpdated);
-        listener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
-        listener.start();
-
-        await _initUser();
-      },
-      fetchWorkspaces: (_FetchWorkspaces value) async* {},
-    );
+  MenuUserBloc(this.userManager, this.listener) : super(MenuUserState.initial(userManager.user)) {
+    on<MenuUserEvent>((event, emit) async {
+      await event.map(
+        initial: (_) async {
+          listener.profileUpdatedNotifier.addPublishListener(_profileUpdated);
+          listener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
+          listener.start();
+          await _initUser();
+        },
+        fetchWorkspaces: (_FetchWorkspaces value) async {},
+      );
+    });
   }
 
   @override

+ 20 - 28
frontend/app_flowy/lib/workspace/application/trash/trash_bloc.dart

@@ -10,46 +10,38 @@ part 'trash_bloc.freezed.dart';
 class TrashBloc extends Bloc<TrashEvent, TrashState> {
   final ITrash trasnManager;
   final ITrashListener listener;
-  TrashBloc({required this.trasnManager, required this.listener}) : super(TrashState.init());
-
-  @override
-  Stream<TrashState> mapEventToState(TrashEvent event) async* {
-    yield* event.map(
-      initial: (e) async* {
+  TrashBloc({required this.trasnManager, required this.listener}) : super(TrashState.init()) {
+    on<TrashEvent>((event, emit) async {
+      await event.map(initial: (e) async {
         listener.start(_listenTrashUpdated);
         final result = await trasnManager.readTrash();
-        yield result.fold(
+        emit(result.fold(
           (objects) => state.copyWith(objects: objects, successOrFailure: left(unit)),
           (error) => state.copyWith(successOrFailure: right(error)),
-        );
-      },
-      didReceiveTrash: (e) async* {
-        yield state.copyWith(objects: e.trash);
-      },
-      putback: (e) async* {
+        ));
+      }, didReceiveTrash: (e) async {
+        emit(state.copyWith(objects: e.trash));
+      }, putback: (e) async {
         final result = await trasnManager.putback(e.trashId);
-        yield* _handleResult(result);
-      },
-      delete: (e) async* {
+        await _handleResult(result, emit);
+      }, delete: (e) async {
         final result = await trasnManager.deleteViews([Tuple2(e.trash.id, e.trash.ty)]);
-        yield* _handleResult(result);
-      },
-      deleteAll: (e) async* {
+        await _handleResult(result, emit);
+      }, deleteAll: (e) async {
         final result = await trasnManager.deleteAll();
-        yield* _handleResult(result);
-      },
-      restoreAll: (e) async* {
+        await _handleResult(result, emit);
+      }, restoreAll: (e) async {
         final result = await trasnManager.restoreAll();
-        yield* _handleResult(result);
-      },
-    );
+        await _handleResult(result, emit);
+      });
+    });
   }
 
-  Stream<TrashState> _handleResult(Either<dynamic, FlowyError> result) async* {
-    yield result.fold(
+  Future<void> _handleResult(Either<dynamic, FlowyError> result, Emitter<TrashState> emit) async {
+    emit(result.fold(
       (l) => state.copyWith(successOrFailure: left(unit)),
       (error) => state.copyWith(successOrFailure: right(error)),
-    );
+    ));
   }
 
   void _listenTrashUpdated(Either<List<Trash>, FlowyError> trashOrFailed) {

+ 50 - 47
frontend/app_flowy/lib/workspace/application/view/view_bloc.dart

@@ -14,53 +14,56 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
   ViewBloc({
     required this.viewManager,
     required this.listener,
-  }) : super(ViewState.init(viewManager.view));
-
-  @override
-  Stream<ViewState> mapEventToState(ViewEvent event) async* {
-    yield* event.map(
-      initial: (e) async* {
-        listener.updatedNotifier.addPublishListener((result) {
-          add(ViewEvent.viewDidUpdate(result));
-        });
-        listener.start();
-        yield state;
-      },
-      setIsEditing: (e) async* {
-        yield state.copyWith(isEditing: e.isEditing);
-      },
-      viewDidUpdate: (e) async* {
-        yield* _handleViewDidUpdate(e.result);
-      },
-      rename: (e) async* {
-        final result = await viewManager.rename(e.newName);
-        yield result.fold(
-          (l) => state.copyWith(successOrFailure: left(unit)),
-          (error) => state.copyWith(successOrFailure: right(error)),
-        );
-      },
-      delete: (e) async* {
-        final result = await viewManager.delete();
-        yield result.fold(
-          (l) => state.copyWith(successOrFailure: left(unit)),
-          (error) => state.copyWith(successOrFailure: right(error)),
-        );
-      },
-      duplicate: (e) async* {
-        final result = await viewManager.duplicate();
-        yield result.fold(
-          (l) => state.copyWith(successOrFailure: left(unit)),
-          (error) => state.copyWith(successOrFailure: right(error)),
-        );
-      },
-    );
-  }
-
-  Stream<ViewState> _handleViewDidUpdate(Either<View, FlowyError> result) async* {
-    yield result.fold(
-      (view) => state.copyWith(view: view, successOrFailure: left(unit)),
-      (error) => state.copyWith(successOrFailure: right(error)),
-    );
+  }) : super(ViewState.init(viewManager.view)) {
+    on<ViewEvent>((event, emit) async {
+      await event.map(
+        initial: (e) {
+          // TODO: Listener can be refctored to a stream.
+          listener.updatedNotifier.addPublishListener((result) {
+            // emit.forEach(stream, onData: onData)
+            add(ViewEvent.viewDidUpdate(result));
+          });
+          listener.start();
+          emit(state);
+        },
+        setIsEditing: (e) {
+          emit(state.copyWith(isEditing: e.isEditing));
+        },
+        viewDidUpdate: (e) {
+          e.result.fold(
+            (view) => emit(state.copyWith(view: view, successOrFailure: left(unit))),
+            (error) => emit(state.copyWith(successOrFailure: right(error))),
+          );
+        },
+        rename: (e) async {
+          final result = await viewManager.rename(e.newName);
+          emit(
+            result.fold(
+              (l) => state.copyWith(successOrFailure: left(unit)),
+              (error) => state.copyWith(successOrFailure: right(error)),
+            ),
+          );
+        },
+        delete: (e) async {
+          final result = await viewManager.delete();
+          emit(
+            result.fold(
+              (l) => state.copyWith(successOrFailure: left(unit)),
+              (error) => state.copyWith(successOrFailure: right(error)),
+            ),
+          );
+        },
+        duplicate: (e) async {
+          final result = await viewManager.duplicate();
+          emit(
+            result.fold(
+              (l) => state.copyWith(successOrFailure: left(unit)),
+              (error) => state.copyWith(successOrFailure: right(error)),
+            ),
+          );
+        },
+      );
+    });
   }
 
   @override

+ 29 - 30
frontend/app_flowy/lib/workspace/application/workspace/welcome_bloc.dart

@@ -12,27 +12,26 @@ part 'welcome_bloc.freezed.dart';
 class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
   final UserRepo repo;
   final IUserListener listener;
-  WelcomeBloc({required this.repo, required this.listener}) : super(WelcomeState.initial());
-
-  @override
-  Stream<WelcomeState> mapEventToState(
-    WelcomeEvent event,
-  ) async* {
-    yield* event.map(initial: (e) async* {
-      listener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
-      listener.start();
-      //
-      yield* _fetchWorkspaces();
-    }, openWorkspace: (e) async* {
-      yield* _openWorkspace(e.workspace);
-    }, createWorkspace: (e) async* {
-      yield* _createWorkspace(e.name, e.desc);
-    }, workspacesReveived: (e) async* {
-      yield e.workspacesOrFail.fold(
-        (workspaces) => state.copyWith(workspaces: workspaces, successOrFailure: left(unit)),
-        (error) => state.copyWith(successOrFailure: right(error)),
-      );
-    });
+  WelcomeBloc({required this.repo, required this.listener}) : super(WelcomeState.initial()) {
+    on<WelcomeEvent>(
+      (event, emit) async {
+        await event.map(initial: (e) async {
+          listener.workspaceUpdatedNotifier.addPublishListener(_workspacesUpdated);
+          listener.start();
+          //
+          await _fetchWorkspaces(emit);
+        }, openWorkspace: (e) async {
+          await _openWorkspace(e.workspace, emit);
+        }, createWorkspace: (e) async {
+          await _createWorkspace(e.name, e.desc, emit);
+        }, workspacesReveived: (e) async {
+          emit(e.workspacesOrFail.fold(
+            (workspaces) => state.copyWith(workspaces: workspaces, successOrFailure: left(unit)),
+            (error) => state.copyWith(successOrFailure: right(error)),
+          ));
+        });
+      },
+    );
   }
 
   @override
@@ -41,31 +40,31 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
     super.close();
   }
 
-  Stream<WelcomeState> _fetchWorkspaces() async* {
+  Future<void> _fetchWorkspaces(Emitter<WelcomeState> emit) async {
     final workspacesOrFailed = await repo.getWorkspaces();
-    yield workspacesOrFailed.fold(
+    emit(workspacesOrFailed.fold(
       (workspaces) => state.copyWith(workspaces: workspaces, successOrFailure: left(unit)),
       (error) {
         Log.error(error);
         return state.copyWith(successOrFailure: right(error));
       },
-    );
+    ));
   }
 
-  Stream<WelcomeState> _openWorkspace(Workspace workspace) async* {
+  Future<void> _openWorkspace(Workspace workspace, Emitter<WelcomeState> emit) async {
     final result = await repo.openWorkspace(workspace.id);
-    yield result.fold(
+    emit(result.fold(
       (workspaces) => state.copyWith(successOrFailure: left(unit)),
       (error) {
         Log.error(error);
         return state.copyWith(successOrFailure: right(error));
       },
-    );
+    ));
   }
 
-  Stream<WelcomeState> _createWorkspace(String name, String desc) async* {
+  Future<void> _createWorkspace(String name, String desc, Emitter<WelcomeState> emit) async {
     final result = await repo.createWorkspace(name, desc);
-    yield result.fold(
+    emit(result.fold(
       (workspace) {
         return state.copyWith(successOrFailure: left(unit));
       },
@@ -73,7 +72,7 @@ class WelcomeBloc extends Bloc<WelcomeEvent, WelcomeState> {
         Log.error(error);
         return state.copyWith(successOrFailure: right(error));
       },
-    );
+    ));
   }
 
   void _workspacesUpdated(Either<List<Workspace>, FlowyError> workspacesOrFail) {

+ 2 - 2
frontend/app_flowy/pubspec.lock

@@ -42,7 +42,7 @@ packages:
       name: bloc
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "7.2.1"
+    version: "8.0.2"
   boolean_selector:
     dependency: transitive
     description:
@@ -418,7 +418,7 @@ packages:
       name: flutter_bloc
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "7.3.3"
+    version: "8.0.0"
   flutter_colorpicker:
     dependency: "direct main"
     description:

+ 1 - 1
frontend/app_flowy/pubspec.yaml

@@ -50,7 +50,7 @@ dependencies:
   equatable: '^2.0.3'
   freezed_annotation:
   get_it: '^7.1.3'
-  flutter_bloc: '^7.3.1'
+  flutter_bloc: '8.0.0'
   provider: ^6.0.1
   path_provider: ^2.0.1
   window_size: