Browse Source

combine event and state into bloc & add watch bloc of workspace

appflowy 3 years ago
parent
commit
9b9d462f36
36 changed files with 1823 additions and 391 deletions
  1. 22 3
      app_flowy/lib/home/application/app/app_bloc.dart
  2. 23 23
      app_flowy/lib/home/application/app/app_bloc.freezed.dart
  3. 0 8
      app_flowy/lib/home/application/app/app_event.dart
  4. 0 16
      app_flowy/lib/home/application/app/app_state.dart
  5. 56 0
      app_flowy/lib/home/application/app/app_watch_bloc.dart
  6. 683 0
      app_flowy/lib/home/application/app/app_watch_bloc.freezed.dart
  7. 31 3
      app_flowy/lib/home/application/home_bloc.dart
  8. 0 15
      app_flowy/lib/home/application/home_event.dart
  9. 0 18
      app_flowy/lib/home/application/home_state.dart
  10. 33 17
      app_flowy/lib/home/application/menu/menu_bloc.dart
  11. 0 168
      app_flowy/lib/home/application/menu/menu_bloc.freezed.dart
  12. 0 11
      app_flowy/lib/home/application/menu/menu_event.dart
  13. 0 18
      app_flowy/lib/home/application/menu/menu_state.dart
  14. 64 0
      app_flowy/lib/home/application/menu/menu_watch.dart
  15. 682 0
      app_flowy/lib/home/application/menu/menu_watch.freezed.dart
  16. 2 0
      app_flowy/lib/home/domain/i_app.dart
  17. 3 2
      app_flowy/lib/home/domain/i_workspace.dart
  18. 20 6
      app_flowy/lib/home/infrastructure/deps_resolver.dart
  19. 7 0
      app_flowy/lib/home/infrastructure/i_app_impl.dart
  20. 10 6
      app_flowy/lib/home/infrastructure/i_workspace_impl.dart
  21. 15 5
      app_flowy/lib/home/infrastructure/repos/app_repo.dart
  22. 19 8
      app_flowy/lib/home/infrastructure/repos/workspace_repo.dart
  23. 49 30
      app_flowy/lib/home/presentation/widgets/app/app_list_widget.dart
  24. 21 2
      app_flowy/lib/home/presentation/widgets/app/app_widget.dart
  25. 29 0
      app_flowy/lib/home/presentation/widgets/menu/app_list.dart
  26. 33 11
      app_flowy/lib/home/presentation/widgets/menu/menu.dart
  27. 0 0
      app_flowy/lib/home/presentation/widgets/menu/menu_size.dart
  28. 2 2
      app_flowy/lib/home/presentation/widgets/menu/prelude.dart
  29. 1 1
      app_flowy/lib/home/presentation/widgets/prelude.dart
  30. 3 3
      app_flowy/lib/startup/tasks/application_task.dart
  31. 1 1
      app_flowy/lib/startup/tasks/prelude.dart
  32. 4 4
      app_flowy/packages/flowy_infra_ui/example/pubspec.lock
  33. 4 4
      app_flowy/packages/flowy_infra_ui/pubspec.lock
  34. 1 1
      app_flowy/pubspec.lock
  35. 1 1
      app_flowy/pubspec.yaml
  36. 4 4
      rust-lib/dart-ffi/Cargo.toml

+ 22 - 3
app_flowy/lib/home/application/app/app_bloc.dart

@@ -1,13 +1,10 @@
 import 'package:app_flowy/home/domain/i_app.dart';
-import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:dartz/dartz.dart';
 
-part 'app_event.dart';
-part 'app_state.dart';
 part 'app_bloc.freezed.dart';
 
 class AppBloc extends Bloc<AppEvent, AppState> {
@@ -31,3 +28,25 @@ class AppBloc extends Bloc<AppEvent, AppState> {
     );
   }
 }
+
+@freezed
+abstract class AppEvent with _$AppEvent {
+  const factory AppEvent.initial() = _Initial;
+  const factory AppEvent.viewsReceived(
+      Either<List<View>, WorkspaceError> appsOrFail) = ViewsReceived;
+}
+
+@freezed
+abstract class AppState implements _$AppState {
+  const factory AppState({
+    required bool isLoading,
+    required Option<List<View>> views,
+    required Either<Unit, WorkspaceError> successOrFailure,
+  }) = _AppState;
+
+  factory AppState.initial() => AppState(
+        isLoading: false,
+        views: none(),
+        successOrFailure: left(unit),
+      );
+}

+ 23 - 23
app_flowy/lib/home/application/app/app_bloc.freezed.dart

@@ -288,11 +288,11 @@ class _$AppStateTearOff {
 
   _AppState call(
       {required bool isLoading,
-      required Option<List<App>> apps,
+      required Option<List<View>> views,
       required Either<Unit, WorkspaceError> successOrFailure}) {
     return _AppState(
       isLoading: isLoading,
-      apps: apps,
+      views: views,
       successOrFailure: successOrFailure,
     );
   }
@@ -304,7 +304,7 @@ const $AppState = _$AppStateTearOff();
 /// @nodoc
 mixin _$AppState {
   bool get isLoading => throw _privateConstructorUsedError;
-  Option<List<App>> get apps => throw _privateConstructorUsedError;
+  Option<List<View>> get views => throw _privateConstructorUsedError;
   Either<Unit, WorkspaceError> get successOrFailure =>
       throw _privateConstructorUsedError;
 
@@ -319,7 +319,7 @@ abstract class $AppStateCopyWith<$Res> {
       _$AppStateCopyWithImpl<$Res>;
   $Res call(
       {bool isLoading,
-      Option<List<App>> apps,
+      Option<List<View>> views,
       Either<Unit, WorkspaceError> successOrFailure});
 }
 
@@ -334,7 +334,7 @@ class _$AppStateCopyWithImpl<$Res> implements $AppStateCopyWith<$Res> {
   @override
   $Res call({
     Object? isLoading = freezed,
-    Object? apps = freezed,
+    Object? views = freezed,
     Object? successOrFailure = freezed,
   }) {
     return _then(_value.copyWith(
@@ -342,10 +342,10 @@ class _$AppStateCopyWithImpl<$Res> implements $AppStateCopyWith<$Res> {
           ? _value.isLoading
           : isLoading // ignore: cast_nullable_to_non_nullable
               as bool,
-      apps: apps == freezed
-          ? _value.apps
-          : apps // ignore: cast_nullable_to_non_nullable
-              as Option<List<App>>,
+      views: views == freezed
+          ? _value.views
+          : views // ignore: cast_nullable_to_non_nullable
+              as Option<List<View>>,
       successOrFailure: successOrFailure == freezed
           ? _value.successOrFailure
           : successOrFailure // ignore: cast_nullable_to_non_nullable
@@ -361,7 +361,7 @@ abstract class _$AppStateCopyWith<$Res> implements $AppStateCopyWith<$Res> {
   @override
   $Res call(
       {bool isLoading,
-      Option<List<App>> apps,
+      Option<List<View>> views,
       Either<Unit, WorkspaceError> successOrFailure});
 }
 
@@ -377,7 +377,7 @@ class __$AppStateCopyWithImpl<$Res> extends _$AppStateCopyWithImpl<$Res>
   @override
   $Res call({
     Object? isLoading = freezed,
-    Object? apps = freezed,
+    Object? views = freezed,
     Object? successOrFailure = freezed,
   }) {
     return _then(_AppState(
@@ -385,10 +385,10 @@ class __$AppStateCopyWithImpl<$Res> extends _$AppStateCopyWithImpl<$Res>
           ? _value.isLoading
           : isLoading // ignore: cast_nullable_to_non_nullable
               as bool,
-      apps: apps == freezed
-          ? _value.apps
-          : apps // ignore: cast_nullable_to_non_nullable
-              as Option<List<App>>,
+      views: views == freezed
+          ? _value.views
+          : views // ignore: cast_nullable_to_non_nullable
+              as Option<List<View>>,
       successOrFailure: successOrFailure == freezed
           ? _value.successOrFailure
           : successOrFailure // ignore: cast_nullable_to_non_nullable
@@ -402,19 +402,19 @@ class __$AppStateCopyWithImpl<$Res> extends _$AppStateCopyWithImpl<$Res>
 class _$_AppState implements _AppState {
   const _$_AppState(
       {required this.isLoading,
-      required this.apps,
+      required this.views,
       required this.successOrFailure});
 
   @override
   final bool isLoading;
   @override
-  final Option<List<App>> apps;
+  final Option<List<View>> views;
   @override
   final Either<Unit, WorkspaceError> successOrFailure;
 
   @override
   String toString() {
-    return 'AppState(isLoading: $isLoading, apps: $apps, successOrFailure: $successOrFailure)';
+    return 'AppState(isLoading: $isLoading, views: $views, successOrFailure: $successOrFailure)';
   }
 
   @override
@@ -424,8 +424,8 @@ class _$_AppState implements _AppState {
             (identical(other.isLoading, isLoading) ||
                 const DeepCollectionEquality()
                     .equals(other.isLoading, isLoading)) &&
-            (identical(other.apps, apps) ||
-                const DeepCollectionEquality().equals(other.apps, apps)) &&
+            (identical(other.views, views) ||
+                const DeepCollectionEquality().equals(other.views, views)) &&
             (identical(other.successOrFailure, successOrFailure) ||
                 const DeepCollectionEquality()
                     .equals(other.successOrFailure, successOrFailure)));
@@ -435,7 +435,7 @@ class _$_AppState implements _AppState {
   int get hashCode =>
       runtimeType.hashCode ^
       const DeepCollectionEquality().hash(isLoading) ^
-      const DeepCollectionEquality().hash(apps) ^
+      const DeepCollectionEquality().hash(views) ^
       const DeepCollectionEquality().hash(successOrFailure);
 
   @JsonKey(ignore: true)
@@ -447,13 +447,13 @@ class _$_AppState implements _AppState {
 abstract class _AppState implements AppState {
   const factory _AppState(
       {required bool isLoading,
-      required Option<List<App>> apps,
+      required Option<List<View>> views,
       required Either<Unit, WorkspaceError> successOrFailure}) = _$_AppState;
 
   @override
   bool get isLoading => throw _privateConstructorUsedError;
   @override
-  Option<List<App>> get apps => throw _privateConstructorUsedError;
+  Option<List<View>> get views => throw _privateConstructorUsedError;
   @override
   Either<Unit, WorkspaceError> get successOrFailure =>
       throw _privateConstructorUsedError;

+ 0 - 8
app_flowy/lib/home/application/app/app_event.dart

@@ -1,8 +0,0 @@
-part of 'app_bloc.dart';
-
-@freezed
-abstract class AppEvent with _$AppEvent {
-  const factory AppEvent.initial() = _Initial;
-  const factory AppEvent.viewsReceived(
-      Either<List<View>, WorkspaceError> appsOrFail) = ViewsReceived;
-}

+ 0 - 16
app_flowy/lib/home/application/app/app_state.dart

@@ -1,16 +0,0 @@
-part of 'app_bloc.dart';
-
-@freezed
-abstract class AppState implements _$AppState {
-  const factory AppState({
-    required bool isLoading,
-    required Option<List<App>> apps,
-    required Either<Unit, WorkspaceError> successOrFailure,
-  }) = _AppState;
-
-  factory AppState.initial() => AppState(
-        isLoading: false,
-        apps: none(),
-        successOrFailure: left(unit),
-      );
-}

+ 56 - 0
app_flowy/lib/home/application/app/app_watch_bloc.dart

@@ -0,0 +1,56 @@
+import 'package:app_flowy/home/domain/i_app.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:dartz/dartz.dart';
+
+part 'app_watch_bloc.freezed.dart';
+
+class AppWatchBloc extends Bloc<AppWatchEvent, AppWatchState> {
+  final IAppWatch watcher;
+  AppWatchBloc(this.watcher) : super(const AppWatchState.initial());
+
+  @override
+  Stream<AppWatchState> mapEventToState(
+    AppWatchEvent event,
+  ) async* {
+    yield* event.map(started: (_) {
+      watcher.startWatching(
+        addViewCallback: (viewsOrFail) => _handleViewsOrFail(viewsOrFail),
+      );
+    }, viewsReceived: (ViewsReceived value) async* {
+      yield value.viewsOrFail.fold(
+        (views) => AppWatchState.loadViews(views),
+        (error) => AppWatchState.loadFail(error),
+      );
+    });
+  }
+
+  void _handleViewsOrFail(Either<List<View>, WorkspaceError> viewsOrFail) {
+    viewsOrFail.fold(
+      (views) => add(AppWatchEvent.viewsReceived(left(views))),
+      (error) => add(AppWatchEvent.viewsReceived(right(error))),
+    );
+  }
+}
+
+@freezed
+abstract class AppWatchEvent with _$AppWatchEvent {
+  const factory AppWatchEvent.started() = _Started;
+  const factory AppWatchEvent.viewsReceived(
+      Either<List<View>, WorkspaceError> viewsOrFail) = ViewsReceived;
+}
+
+@freezed
+abstract class AppWatchState implements _$AppWatchState {
+  const factory AppWatchState.initial() = _Initial;
+
+  const factory AppWatchState.loadViews(
+    List<View> views,
+  ) = _LoadViews;
+
+  const factory AppWatchState.loadFail(
+    WorkspaceError error,
+  ) = _LoadFail;
+}

+ 683 - 0
app_flowy/lib/home/application/app/app_watch_bloc.freezed.dart

@@ -0,0 +1,683 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
+
+part of 'app_watch_bloc.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+T _$identity<T>(T value) => value;
+
+final _privateConstructorUsedError = UnsupportedError(
+    'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+
+/// @nodoc
+class _$AppWatchEventTearOff {
+  const _$AppWatchEventTearOff();
+
+  _Started started() {
+    return const _Started();
+  }
+
+  ViewsReceived viewsReceived(Either<List<View>, WorkspaceError> viewsOrFail) {
+    return ViewsReceived(
+      viewsOrFail,
+    );
+  }
+}
+
+/// @nodoc
+const $AppWatchEvent = _$AppWatchEventTearOff();
+
+/// @nodoc
+mixin _$AppWatchEvent {
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() started,
+    required TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)
+        viewsReceived,
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? started,
+    TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)?
+        viewsReceived,
+    required TResult orElse(),
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Started value) started,
+    required TResult Function(ViewsReceived value) viewsReceived,
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Started value)? started,
+    TResult Function(ViewsReceived value)? viewsReceived,
+    required TResult orElse(),
+  }) =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $AppWatchEventCopyWith<$Res> {
+  factory $AppWatchEventCopyWith(
+          AppWatchEvent value, $Res Function(AppWatchEvent) then) =
+      _$AppWatchEventCopyWithImpl<$Res>;
+}
+
+/// @nodoc
+class _$AppWatchEventCopyWithImpl<$Res>
+    implements $AppWatchEventCopyWith<$Res> {
+  _$AppWatchEventCopyWithImpl(this._value, this._then);
+
+  final AppWatchEvent _value;
+  // ignore: unused_field
+  final $Res Function(AppWatchEvent) _then;
+}
+
+/// @nodoc
+abstract class _$StartedCopyWith<$Res> {
+  factory _$StartedCopyWith(_Started value, $Res Function(_Started) then) =
+      __$StartedCopyWithImpl<$Res>;
+}
+
+/// @nodoc
+class __$StartedCopyWithImpl<$Res> extends _$AppWatchEventCopyWithImpl<$Res>
+    implements _$StartedCopyWith<$Res> {
+  __$StartedCopyWithImpl(_Started _value, $Res Function(_Started) _then)
+      : super(_value, (v) => _then(v as _Started));
+
+  @override
+  _Started get _value => super._value as _Started;
+}
+
+/// @nodoc
+
+class _$_Started implements _Started {
+  const _$_Started();
+
+  @override
+  String toString() {
+    return 'AppWatchEvent.started()';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) || (other is _Started);
+  }
+
+  @override
+  int get hashCode => runtimeType.hashCode;
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() started,
+    required TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)
+        viewsReceived,
+  }) {
+    return started();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? started,
+    TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)?
+        viewsReceived,
+    required TResult orElse(),
+  }) {
+    if (started != null) {
+      return started();
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Started value) started,
+    required TResult Function(ViewsReceived value) viewsReceived,
+  }) {
+    return started(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Started value)? started,
+    TResult Function(ViewsReceived value)? viewsReceived,
+    required TResult orElse(),
+  }) {
+    if (started != null) {
+      return started(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class _Started implements AppWatchEvent {
+  const factory _Started() = _$_Started;
+}
+
+/// @nodoc
+abstract class $ViewsReceivedCopyWith<$Res> {
+  factory $ViewsReceivedCopyWith(
+          ViewsReceived value, $Res Function(ViewsReceived) then) =
+      _$ViewsReceivedCopyWithImpl<$Res>;
+  $Res call({Either<List<View>, WorkspaceError> viewsOrFail});
+}
+
+/// @nodoc
+class _$ViewsReceivedCopyWithImpl<$Res>
+    extends _$AppWatchEventCopyWithImpl<$Res>
+    implements $ViewsReceivedCopyWith<$Res> {
+  _$ViewsReceivedCopyWithImpl(
+      ViewsReceived _value, $Res Function(ViewsReceived) _then)
+      : super(_value, (v) => _then(v as ViewsReceived));
+
+  @override
+  ViewsReceived get _value => super._value as ViewsReceived;
+
+  @override
+  $Res call({
+    Object? viewsOrFail = freezed,
+  }) {
+    return _then(ViewsReceived(
+      viewsOrFail == freezed
+          ? _value.viewsOrFail
+          : viewsOrFail // ignore: cast_nullable_to_non_nullable
+              as Either<List<View>, WorkspaceError>,
+    ));
+  }
+}
+
+/// @nodoc
+
+class _$ViewsReceived implements ViewsReceived {
+  const _$ViewsReceived(this.viewsOrFail);
+
+  @override
+  final Either<List<View>, WorkspaceError> viewsOrFail;
+
+  @override
+  String toString() {
+    return 'AppWatchEvent.viewsReceived(viewsOrFail: $viewsOrFail)';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) ||
+        (other is ViewsReceived &&
+            (identical(other.viewsOrFail, viewsOrFail) ||
+                const DeepCollectionEquality()
+                    .equals(other.viewsOrFail, viewsOrFail)));
+  }
+
+  @override
+  int get hashCode =>
+      runtimeType.hashCode ^ const DeepCollectionEquality().hash(viewsOrFail);
+
+  @JsonKey(ignore: true)
+  @override
+  $ViewsReceivedCopyWith<ViewsReceived> get copyWith =>
+      _$ViewsReceivedCopyWithImpl<ViewsReceived>(this, _$identity);
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() started,
+    required TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)
+        viewsReceived,
+  }) {
+    return viewsReceived(viewsOrFail);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? started,
+    TResult Function(Either<List<View>, WorkspaceError> viewsOrFail)?
+        viewsReceived,
+    required TResult orElse(),
+  }) {
+    if (viewsReceived != null) {
+      return viewsReceived(viewsOrFail);
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Started value) started,
+    required TResult Function(ViewsReceived value) viewsReceived,
+  }) {
+    return viewsReceived(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Started value)? started,
+    TResult Function(ViewsReceived value)? viewsReceived,
+    required TResult orElse(),
+  }) {
+    if (viewsReceived != null) {
+      return viewsReceived(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class ViewsReceived implements AppWatchEvent {
+  const factory ViewsReceived(Either<List<View>, WorkspaceError> viewsOrFail) =
+      _$ViewsReceived;
+
+  Either<List<View>, WorkspaceError> get viewsOrFail =>
+      throw _privateConstructorUsedError;
+  @JsonKey(ignore: true)
+  $ViewsReceivedCopyWith<ViewsReceived> get copyWith =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+class _$AppWatchStateTearOff {
+  const _$AppWatchStateTearOff();
+
+  _Initial initial() {
+    return const _Initial();
+  }
+
+  _LoadViews loadViews(List<View> views) {
+    return _LoadViews(
+      views,
+    );
+  }
+
+  _LoadFail loadFail(WorkspaceError error) {
+    return _LoadFail(
+      error,
+    );
+  }
+}
+
+/// @nodoc
+const $AppWatchState = _$AppWatchStateTearOff();
+
+/// @nodoc
+mixin _$AppWatchState {
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(List<View> views) loadViews,
+    required TResult Function(WorkspaceError error) loadFail,
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(List<View> views)? loadViews,
+    TResult Function(WorkspaceError error)? loadFail,
+    required TResult orElse(),
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Initial value) initial,
+    required TResult Function(_LoadViews value) loadViews,
+    required TResult Function(_LoadFail value) loadFail,
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Initial value)? initial,
+    TResult Function(_LoadViews value)? loadViews,
+    TResult Function(_LoadFail value)? loadFail,
+    required TResult orElse(),
+  }) =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $AppWatchStateCopyWith<$Res> {
+  factory $AppWatchStateCopyWith(
+          AppWatchState value, $Res Function(AppWatchState) then) =
+      _$AppWatchStateCopyWithImpl<$Res>;
+}
+
+/// @nodoc
+class _$AppWatchStateCopyWithImpl<$Res>
+    implements $AppWatchStateCopyWith<$Res> {
+  _$AppWatchStateCopyWithImpl(this._value, this._then);
+
+  final AppWatchState _value;
+  // ignore: unused_field
+  final $Res Function(AppWatchState) _then;
+}
+
+/// @nodoc
+abstract class _$InitialCopyWith<$Res> {
+  factory _$InitialCopyWith(_Initial value, $Res Function(_Initial) then) =
+      __$InitialCopyWithImpl<$Res>;
+}
+
+/// @nodoc
+class __$InitialCopyWithImpl<$Res> extends _$AppWatchStateCopyWithImpl<$Res>
+    implements _$InitialCopyWith<$Res> {
+  __$InitialCopyWithImpl(_Initial _value, $Res Function(_Initial) _then)
+      : super(_value, (v) => _then(v as _Initial));
+
+  @override
+  _Initial get _value => super._value as _Initial;
+}
+
+/// @nodoc
+
+class _$_Initial implements _Initial {
+  const _$_Initial();
+
+  @override
+  String toString() {
+    return 'AppWatchState.initial()';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) || (other is _Initial);
+  }
+
+  @override
+  int get hashCode => runtimeType.hashCode;
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(List<View> views) loadViews,
+    required TResult Function(WorkspaceError error) loadFail,
+  }) {
+    return initial();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(List<View> views)? loadViews,
+    TResult Function(WorkspaceError error)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (initial != null) {
+      return initial();
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Initial value) initial,
+    required TResult Function(_LoadViews value) loadViews,
+    required TResult Function(_LoadFail value) loadFail,
+  }) {
+    return initial(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Initial value)? initial,
+    TResult Function(_LoadViews value)? loadViews,
+    TResult Function(_LoadFail value)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (initial != null) {
+      return initial(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class _Initial implements AppWatchState {
+  const factory _Initial() = _$_Initial;
+}
+
+/// @nodoc
+abstract class _$LoadViewsCopyWith<$Res> {
+  factory _$LoadViewsCopyWith(
+          _LoadViews value, $Res Function(_LoadViews) then) =
+      __$LoadViewsCopyWithImpl<$Res>;
+  $Res call({List<View> views});
+}
+
+/// @nodoc
+class __$LoadViewsCopyWithImpl<$Res> extends _$AppWatchStateCopyWithImpl<$Res>
+    implements _$LoadViewsCopyWith<$Res> {
+  __$LoadViewsCopyWithImpl(_LoadViews _value, $Res Function(_LoadViews) _then)
+      : super(_value, (v) => _then(v as _LoadViews));
+
+  @override
+  _LoadViews get _value => super._value as _LoadViews;
+
+  @override
+  $Res call({
+    Object? views = freezed,
+  }) {
+    return _then(_LoadViews(
+      views == freezed
+          ? _value.views
+          : views // ignore: cast_nullable_to_non_nullable
+              as List<View>,
+    ));
+  }
+}
+
+/// @nodoc
+
+class _$_LoadViews implements _LoadViews {
+  const _$_LoadViews(this.views);
+
+  @override
+  final List<View> views;
+
+  @override
+  String toString() {
+    return 'AppWatchState.loadViews(views: $views)';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) ||
+        (other is _LoadViews &&
+            (identical(other.views, views) ||
+                const DeepCollectionEquality().equals(other.views, views)));
+  }
+
+  @override
+  int get hashCode =>
+      runtimeType.hashCode ^ const DeepCollectionEquality().hash(views);
+
+  @JsonKey(ignore: true)
+  @override
+  _$LoadViewsCopyWith<_LoadViews> get copyWith =>
+      __$LoadViewsCopyWithImpl<_LoadViews>(this, _$identity);
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(List<View> views) loadViews,
+    required TResult Function(WorkspaceError error) loadFail,
+  }) {
+    return loadViews(views);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(List<View> views)? loadViews,
+    TResult Function(WorkspaceError error)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (loadViews != null) {
+      return loadViews(views);
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Initial value) initial,
+    required TResult Function(_LoadViews value) loadViews,
+    required TResult Function(_LoadFail value) loadFail,
+  }) {
+    return loadViews(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Initial value)? initial,
+    TResult Function(_LoadViews value)? loadViews,
+    TResult Function(_LoadFail value)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (loadViews != null) {
+      return loadViews(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class _LoadViews implements AppWatchState {
+  const factory _LoadViews(List<View> views) = _$_LoadViews;
+
+  List<View> get views => throw _privateConstructorUsedError;
+  @JsonKey(ignore: true)
+  _$LoadViewsCopyWith<_LoadViews> get copyWith =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class _$LoadFailCopyWith<$Res> {
+  factory _$LoadFailCopyWith(_LoadFail value, $Res Function(_LoadFail) then) =
+      __$LoadFailCopyWithImpl<$Res>;
+  $Res call({WorkspaceError error});
+}
+
+/// @nodoc
+class __$LoadFailCopyWithImpl<$Res> extends _$AppWatchStateCopyWithImpl<$Res>
+    implements _$LoadFailCopyWith<$Res> {
+  __$LoadFailCopyWithImpl(_LoadFail _value, $Res Function(_LoadFail) _then)
+      : super(_value, (v) => _then(v as _LoadFail));
+
+  @override
+  _LoadFail get _value => super._value as _LoadFail;
+
+  @override
+  $Res call({
+    Object? error = freezed,
+  }) {
+    return _then(_LoadFail(
+      error == freezed
+          ? _value.error
+          : error // ignore: cast_nullable_to_non_nullable
+              as WorkspaceError,
+    ));
+  }
+}
+
+/// @nodoc
+
+class _$_LoadFail implements _LoadFail {
+  const _$_LoadFail(this.error);
+
+  @override
+  final WorkspaceError error;
+
+  @override
+  String toString() {
+    return 'AppWatchState.loadFail(error: $error)';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) ||
+        (other is _LoadFail &&
+            (identical(other.error, error) ||
+                const DeepCollectionEquality().equals(other.error, error)));
+  }
+
+  @override
+  int get hashCode =>
+      runtimeType.hashCode ^ const DeepCollectionEquality().hash(error);
+
+  @JsonKey(ignore: true)
+  @override
+  _$LoadFailCopyWith<_LoadFail> get copyWith =>
+      __$LoadFailCopyWithImpl<_LoadFail>(this, _$identity);
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(List<View> views) loadViews,
+    required TResult Function(WorkspaceError error) loadFail,
+  }) {
+    return loadFail(error);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(List<View> views)? loadViews,
+    TResult Function(WorkspaceError error)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (loadFail != null) {
+      return loadFail(error);
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Initial value) initial,
+    required TResult Function(_LoadViews value) loadViews,
+    required TResult Function(_LoadFail value) loadFail,
+  }) {
+    return loadFail(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Initial value)? initial,
+    TResult Function(_LoadViews value)? loadViews,
+    TResult Function(_LoadFail value)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (loadFail != null) {
+      return loadFail(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class _LoadFail implements AppWatchState {
+  const factory _LoadFail(WorkspaceError error) = _$_LoadFail;
+
+  WorkspaceError get error => throw _privateConstructorUsedError;
+  @JsonKey(ignore: true)
+  _$LoadFailCopyWith<_LoadFail> get copyWith =>
+      throw _privateConstructorUsedError;
+}

+ 31 - 3
app_flowy/lib/home/application/home_bloc.dart

@@ -4,9 +4,6 @@ import 'package:app_flowy/home/presentation/widgets/blank_page.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:dartz/dartz.dart';
-
-part 'home_event.dart';
-part 'home_state.dart';
 part 'home_bloc.freezed.dart';
 
 class HomeBloc extends Bloc<HomeEvent, HomeState> {
@@ -40,3 +37,34 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
     return super.close();
   }
 }
+
+@freezed
+abstract class HomeEvent with _$HomeEvent {
+  const factory HomeEvent.showLoading(bool isLoading) = _ShowLoading;
+  const factory HomeEvent.forceCollapse(bool forceCollapse) = _ForceCollapse;
+
+  //page
+  const factory HomeEvent.setPage(PageContext context) = SetCurrentPage;
+
+  //edit pannel
+  const factory HomeEvent.setEditPannel(EditPannelContext editContext) =
+      _ShowEditPannel;
+  const factory HomeEvent.dismissEditPannel() = _DismissEditPannel;
+}
+
+@freezed
+abstract class HomeState implements _$HomeState {
+  const factory HomeState({
+    required bool isLoading,
+    required bool forceCollapse,
+    required PageContext pageContext,
+    required Option<EditPannelContext> editContext,
+  }) = _HomeState;
+
+  factory HomeState.initial() => HomeState(
+        isLoading: false,
+        forceCollapse: false,
+        pageContext: const BlankPageContext(),
+        editContext: none(),
+      );
+}

+ 0 - 15
app_flowy/lib/home/application/home_event.dart

@@ -1,15 +0,0 @@
-part of 'home_bloc.dart';
-
-@freezed
-abstract class HomeEvent with _$HomeEvent {
-  const factory HomeEvent.showLoading(bool isLoading) = _ShowLoading;
-  const factory HomeEvent.forceCollapse(bool forceCollapse) = _ForceCollapse;
-
-  //page
-  const factory HomeEvent.setPage(PageContext context) = SetCurrentPage;
-
-  //edit pannel
-  const factory HomeEvent.setEditPannel(EditPannelContext editContext) =
-      _ShowEditPannel;
-  const factory HomeEvent.dismissEditPannel() = _DismissEditPannel;
-}

+ 0 - 18
app_flowy/lib/home/application/home_state.dart

@@ -1,18 +0,0 @@
-part of 'home_bloc.dart';
-
-@freezed
-abstract class HomeState implements _$HomeState {
-  const factory HomeState({
-    required bool isLoading,
-    required bool forceCollapse,
-    required PageContext pageContext,
-    required Option<EditPannelContext> editContext,
-  }) = _HomeState;
-
-  factory HomeState.initial() => HomeState(
-        isLoading: false,
-        forceCollapse: false,
-        pageContext: const BlankPageContext(),
-        editContext: none(),
-      );
-}

+ 33 - 17
app_flowy/lib/home/application/menu/menu_bloc.dart

@@ -7,8 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-part 'menu_event.dart';
-part 'menu_state.dart';
+
 part 'menu_bloc.freezed.dart';
 
 class MenuBloc extends Bloc<MenuEvent, MenuState> {
@@ -21,12 +20,7 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
   ) async* {
     yield* event.map(
       initial: (value) async* {
-        iWorkspaceImpl.startWatching(addAppCallback: (appsOrFail) {
-          appsOrFail.fold(
-            (apps) => add(MenuEvent.appsReceived(left(apps))),
-            (error) => add(MenuEvent.appsReceived(right(error))),
-          );
-        });
+        yield* _fetchApps();
       },
       collapse: (e) async* {
         final isCollapse = state.isCollapse;
@@ -38,12 +32,6 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
       createApp: (CreateApp event) async* {
         yield* _performActionOnCreateApp(event);
       },
-      appsReceived: (AppsReceived value) async* {
-        yield value.appsOrFail.fold(
-          (apps) => state.copyWith(apps: some(apps)),
-          (error) => state.copyWith(successOrFailure: right(error)),
-        );
-      },
     );
   }
 
@@ -64,8 +52,36 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
     });
   }
 
-  @override
-  Future<void> close() {
-    return super.close();
+  Stream<MenuState> _fetchApps() async* {
+    final appsOrFail = await iWorkspaceImpl.getApps();
+    yield appsOrFail.fold(
+      (apps) => state.copyWith(apps: some(apps)),
+      (error) => state.copyWith(successOrFailure: right(error)),
+    );
   }
 }
+
+@freezed
+abstract class MenuEvent with _$MenuEvent {
+  const factory MenuEvent.initial() = _Initial;
+  const factory MenuEvent.collapse() = Collapse;
+  const factory MenuEvent.openPage(PageContext context) = OpenPage;
+  const factory MenuEvent.createApp(String name, {String? desc}) = CreateApp;
+}
+
+@freezed
+abstract class MenuState implements _$MenuState {
+  const factory MenuState({
+    required bool isCollapse,
+    required Option<PageContext> pageContext,
+    required Option<List<App>> apps,
+    required Either<Unit, WorkspaceError> successOrFailure,
+  }) = _MenuState;
+
+  factory MenuState.initial() => MenuState(
+        isCollapse: false,
+        pageContext: none(),
+        apps: none(),
+        successOrFailure: left(unit),
+      );
+}

+ 0 - 168
app_flowy/lib/home/application/menu/menu_bloc.freezed.dart

@@ -36,12 +36,6 @@ class _$MenuEventTearOff {
       desc: desc,
     );
   }
-
-  AppsReceived appsReceived(Either<List<App>, WorkspaceError> appsOrFail) {
-    return AppsReceived(
-      appsOrFail,
-    );
-  }
 }
 
 /// @nodoc
@@ -55,8 +49,6 @@ mixin _$MenuEvent {
     required TResult Function() collapse,
     required TResult Function(PageContext context) openPage,
     required TResult Function(String name, String? desc) createApp,
-    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
-        appsReceived,
   }) =>
       throw _privateConstructorUsedError;
   @optionalTypeArgs
@@ -65,8 +57,6 @@ mixin _$MenuEvent {
     TResult Function()? collapse,
     TResult Function(PageContext context)? openPage,
     TResult Function(String name, String? desc)? createApp,
-    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
-        appsReceived,
     required TResult orElse(),
   }) =>
       throw _privateConstructorUsedError;
@@ -76,7 +66,6 @@ mixin _$MenuEvent {
     required TResult Function(Collapse value) collapse,
     required TResult Function(OpenPage value) openPage,
     required TResult Function(CreateApp value) createApp,
-    required TResult Function(AppsReceived value) appsReceived,
   }) =>
       throw _privateConstructorUsedError;
   @optionalTypeArgs
@@ -85,7 +74,6 @@ mixin _$MenuEvent {
     TResult Function(Collapse value)? collapse,
     TResult Function(OpenPage value)? openPage,
     TResult Function(CreateApp value)? createApp,
-    TResult Function(AppsReceived value)? appsReceived,
     required TResult orElse(),
   }) =>
       throw _privateConstructorUsedError;
@@ -147,8 +135,6 @@ class _$_Initial implements _Initial {
     required TResult Function() collapse,
     required TResult Function(PageContext context) openPage,
     required TResult Function(String name, String? desc) createApp,
-    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
-        appsReceived,
   }) {
     return initial();
   }
@@ -160,8 +146,6 @@ class _$_Initial implements _Initial {
     TResult Function()? collapse,
     TResult Function(PageContext context)? openPage,
     TResult Function(String name, String? desc)? createApp,
-    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
-        appsReceived,
     required TResult orElse(),
   }) {
     if (initial != null) {
@@ -177,7 +161,6 @@ class _$_Initial implements _Initial {
     required TResult Function(Collapse value) collapse,
     required TResult Function(OpenPage value) openPage,
     required TResult Function(CreateApp value) createApp,
-    required TResult Function(AppsReceived value) appsReceived,
   }) {
     return initial(this);
   }
@@ -189,7 +172,6 @@ class _$_Initial implements _Initial {
     TResult Function(Collapse value)? collapse,
     TResult Function(OpenPage value)? openPage,
     TResult Function(CreateApp value)? createApp,
-    TResult Function(AppsReceived value)? appsReceived,
     required TResult orElse(),
   }) {
     if (initial != null) {
@@ -244,8 +226,6 @@ class _$Collapse implements Collapse {
     required TResult Function() collapse,
     required TResult Function(PageContext context) openPage,
     required TResult Function(String name, String? desc) createApp,
-    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
-        appsReceived,
   }) {
     return collapse();
   }
@@ -257,8 +237,6 @@ class _$Collapse implements Collapse {
     TResult Function()? collapse,
     TResult Function(PageContext context)? openPage,
     TResult Function(String name, String? desc)? createApp,
-    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
-        appsReceived,
     required TResult orElse(),
   }) {
     if (collapse != null) {
@@ -274,7 +252,6 @@ class _$Collapse implements Collapse {
     required TResult Function(Collapse value) collapse,
     required TResult Function(OpenPage value) openPage,
     required TResult Function(CreateApp value) createApp,
-    required TResult Function(AppsReceived value) appsReceived,
   }) {
     return collapse(this);
   }
@@ -286,7 +263,6 @@ class _$Collapse implements Collapse {
     TResult Function(Collapse value)? collapse,
     TResult Function(OpenPage value)? openPage,
     TResult Function(CreateApp value)? createApp,
-    TResult Function(AppsReceived value)? appsReceived,
     required TResult orElse(),
   }) {
     if (collapse != null) {
@@ -366,8 +342,6 @@ class _$OpenPage implements OpenPage {
     required TResult Function() collapse,
     required TResult Function(PageContext context) openPage,
     required TResult Function(String name, String? desc) createApp,
-    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
-        appsReceived,
   }) {
     return openPage(context);
   }
@@ -379,8 +353,6 @@ class _$OpenPage implements OpenPage {
     TResult Function()? collapse,
     TResult Function(PageContext context)? openPage,
     TResult Function(String name, String? desc)? createApp,
-    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
-        appsReceived,
     required TResult orElse(),
   }) {
     if (openPage != null) {
@@ -396,7 +368,6 @@ class _$OpenPage implements OpenPage {
     required TResult Function(Collapse value) collapse,
     required TResult Function(OpenPage value) openPage,
     required TResult Function(CreateApp value) createApp,
-    required TResult Function(AppsReceived value) appsReceived,
   }) {
     return openPage(this);
   }
@@ -408,7 +379,6 @@ class _$OpenPage implements OpenPage {
     TResult Function(Collapse value)? collapse,
     TResult Function(OpenPage value)? openPage,
     TResult Function(CreateApp value)? createApp,
-    TResult Function(AppsReceived value)? appsReceived,
     required TResult orElse(),
   }) {
     if (openPage != null) {
@@ -504,8 +474,6 @@ class _$CreateApp implements CreateApp {
     required TResult Function() collapse,
     required TResult Function(PageContext context) openPage,
     required TResult Function(String name, String? desc) createApp,
-    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
-        appsReceived,
   }) {
     return createApp(name, desc);
   }
@@ -517,8 +485,6 @@ class _$CreateApp implements CreateApp {
     TResult Function()? collapse,
     TResult Function(PageContext context)? openPage,
     TResult Function(String name, String? desc)? createApp,
-    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
-        appsReceived,
     required TResult orElse(),
   }) {
     if (createApp != null) {
@@ -534,7 +500,6 @@ class _$CreateApp implements CreateApp {
     required TResult Function(Collapse value) collapse,
     required TResult Function(OpenPage value) openPage,
     required TResult Function(CreateApp value) createApp,
-    required TResult Function(AppsReceived value) appsReceived,
   }) {
     return createApp(this);
   }
@@ -546,7 +511,6 @@ class _$CreateApp implements CreateApp {
     TResult Function(Collapse value)? collapse,
     TResult Function(OpenPage value)? openPage,
     TResult Function(CreateApp value)? createApp,
-    TResult Function(AppsReceived value)? appsReceived,
     required TResult orElse(),
   }) {
     if (createApp != null) {
@@ -566,138 +530,6 @@ abstract class CreateApp implements MenuEvent {
       throw _privateConstructorUsedError;
 }
 
-/// @nodoc
-abstract class $AppsReceivedCopyWith<$Res> {
-  factory $AppsReceivedCopyWith(
-          AppsReceived value, $Res Function(AppsReceived) then) =
-      _$AppsReceivedCopyWithImpl<$Res>;
-  $Res call({Either<List<App>, WorkspaceError> appsOrFail});
-}
-
-/// @nodoc
-class _$AppsReceivedCopyWithImpl<$Res> extends _$MenuEventCopyWithImpl<$Res>
-    implements $AppsReceivedCopyWith<$Res> {
-  _$AppsReceivedCopyWithImpl(
-      AppsReceived _value, $Res Function(AppsReceived) _then)
-      : super(_value, (v) => _then(v as AppsReceived));
-
-  @override
-  AppsReceived get _value => super._value as AppsReceived;
-
-  @override
-  $Res call({
-    Object? appsOrFail = freezed,
-  }) {
-    return _then(AppsReceived(
-      appsOrFail == freezed
-          ? _value.appsOrFail
-          : appsOrFail // ignore: cast_nullable_to_non_nullable
-              as Either<List<App>, WorkspaceError>,
-    ));
-  }
-}
-
-/// @nodoc
-
-class _$AppsReceived implements AppsReceived {
-  const _$AppsReceived(this.appsOrFail);
-
-  @override
-  final Either<List<App>, WorkspaceError> appsOrFail;
-
-  @override
-  String toString() {
-    return 'MenuEvent.appsReceived(appsOrFail: $appsOrFail)';
-  }
-
-  @override
-  bool operator ==(dynamic other) {
-    return identical(this, other) ||
-        (other is AppsReceived &&
-            (identical(other.appsOrFail, appsOrFail) ||
-                const DeepCollectionEquality()
-                    .equals(other.appsOrFail, appsOrFail)));
-  }
-
-  @override
-  int get hashCode =>
-      runtimeType.hashCode ^ const DeepCollectionEquality().hash(appsOrFail);
-
-  @JsonKey(ignore: true)
-  @override
-  $AppsReceivedCopyWith<AppsReceived> get copyWith =>
-      _$AppsReceivedCopyWithImpl<AppsReceived>(this, _$identity);
-
-  @override
-  @optionalTypeArgs
-  TResult when<TResult extends Object?>({
-    required TResult Function() initial,
-    required TResult Function() collapse,
-    required TResult Function(PageContext context) openPage,
-    required TResult Function(String name, String? desc) createApp,
-    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
-        appsReceived,
-  }) {
-    return appsReceived(appsOrFail);
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult maybeWhen<TResult extends Object?>({
-    TResult Function()? initial,
-    TResult Function()? collapse,
-    TResult Function(PageContext context)? openPage,
-    TResult Function(String name, String? desc)? createApp,
-    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
-        appsReceived,
-    required TResult orElse(),
-  }) {
-    if (appsReceived != null) {
-      return appsReceived(appsOrFail);
-    }
-    return orElse();
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult map<TResult extends Object?>({
-    required TResult Function(_Initial value) initial,
-    required TResult Function(Collapse value) collapse,
-    required TResult Function(OpenPage value) openPage,
-    required TResult Function(CreateApp value) createApp,
-    required TResult Function(AppsReceived value) appsReceived,
-  }) {
-    return appsReceived(this);
-  }
-
-  @override
-  @optionalTypeArgs
-  TResult maybeMap<TResult extends Object?>({
-    TResult Function(_Initial value)? initial,
-    TResult Function(Collapse value)? collapse,
-    TResult Function(OpenPage value)? openPage,
-    TResult Function(CreateApp value)? createApp,
-    TResult Function(AppsReceived value)? appsReceived,
-    required TResult orElse(),
-  }) {
-    if (appsReceived != null) {
-      return appsReceived(this);
-    }
-    return orElse();
-  }
-}
-
-abstract class AppsReceived implements MenuEvent {
-  const factory AppsReceived(Either<List<App>, WorkspaceError> appsOrFail) =
-      _$AppsReceived;
-
-  Either<List<App>, WorkspaceError> get appsOrFail =>
-      throw _privateConstructorUsedError;
-  @JsonKey(ignore: true)
-  $AppsReceivedCopyWith<AppsReceived> get copyWith =>
-      throw _privateConstructorUsedError;
-}
-
 /// @nodoc
 class _$MenuStateTearOff {
   const _$MenuStateTearOff();

+ 0 - 11
app_flowy/lib/home/application/menu/menu_event.dart

@@ -1,11 +0,0 @@
-part of 'menu_bloc.dart';
-
-@freezed
-abstract class MenuEvent with _$MenuEvent {
-  const factory MenuEvent.initial() = _Initial;
-  const factory MenuEvent.collapse() = Collapse;
-  const factory MenuEvent.openPage(PageContext context) = OpenPage;
-  const factory MenuEvent.createApp(String name, {String? desc}) = CreateApp;
-  const factory MenuEvent.appsReceived(
-      Either<List<App>, WorkspaceError> appsOrFail) = AppsReceived;
-}

+ 0 - 18
app_flowy/lib/home/application/menu/menu_state.dart

@@ -1,18 +0,0 @@
-part of 'menu_bloc.dart';
-
-@freezed
-abstract class MenuState implements _$MenuState {
-  const factory MenuState({
-    required bool isCollapse,
-    required Option<PageContext> pageContext,
-    required Option<List<App>> apps,
-    required Either<Unit, WorkspaceError> successOrFailure,
-  }) = _MenuState;
-
-  factory MenuState.initial() => MenuState(
-        isCollapse: false,
-        pageContext: none(),
-        apps: none(),
-        successOrFailure: left(unit),
-      );
-}

+ 64 - 0
app_flowy/lib/home/application/menu/menu_watch.dart

@@ -0,0 +1,64 @@
+import 'package:app_flowy/home/domain/i_workspace.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
+import 'package:flutter/material.dart';
+import 'package:freezed_annotation/freezed_annotation.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'package:dartz/dartz.dart';
+
+part 'menu_watch.freezed.dart';
+
+class MenuWatchBloc extends Bloc<MenuWatchEvent, MenuWatchState> {
+  final IWorkspaceWatch watcher;
+  MenuWatchBloc(this.watcher) : super(const MenuWatchState.initial());
+
+  @override
+  Stream<MenuWatchState> mapEventToState(MenuWatchEvent event) async* {
+    yield* event.map(
+      started: (_) async* {
+        watcher.startWatching(
+          addAppCallback: (appsOrFail) => _handleAppsOrFail(appsOrFail),
+        );
+      },
+      appsReceived: (e) async* {
+        yield e.appsOrFail.fold(
+          (apps) => MenuWatchState.loadApps(apps),
+          (error) => MenuWatchState.loadFail(error),
+        );
+      },
+    );
+  }
+
+  @override
+  Future<void> close() async {
+    await watcher.stopWatching();
+    return super.close();
+  }
+
+  void _handleAppsOrFail(Either<List<App>, WorkspaceError> appsOrFail) {
+    appsOrFail.fold(
+      (apps) => add(MenuWatchEvent.appsReceived(left(apps))),
+      (error) => add(MenuWatchEvent.appsReceived(right(error))),
+    );
+  }
+}
+
+@freezed
+abstract class MenuWatchEvent with _$MenuWatchEvent {
+  const factory MenuWatchEvent.started() = _Started;
+  const factory MenuWatchEvent.appsReceived(
+      Either<List<App>, WorkspaceError> appsOrFail) = AppsReceived;
+}
+
+@freezed
+abstract class MenuWatchState with _$MenuWatchState {
+  const factory MenuWatchState.initial() = _Initial;
+
+  const factory MenuWatchState.loadApps(
+    List<App> apps,
+  ) = _LoadApps;
+
+  const factory MenuWatchState.loadFail(
+    WorkspaceError error,
+  ) = _LoadFail;
+}

+ 682 - 0
app_flowy/lib/home/application/menu/menu_watch.freezed.dart

@@ -0,0 +1,682 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides
+
+part of 'menu_watch.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+T _$identity<T>(T value) => value;
+
+final _privateConstructorUsedError = UnsupportedError(
+    'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
+
+/// @nodoc
+class _$MenuWatchEventTearOff {
+  const _$MenuWatchEventTearOff();
+
+  _Started started() {
+    return const _Started();
+  }
+
+  AppsReceived appsReceived(Either<List<App>, WorkspaceError> appsOrFail) {
+    return AppsReceived(
+      appsOrFail,
+    );
+  }
+}
+
+/// @nodoc
+const $MenuWatchEvent = _$MenuWatchEventTearOff();
+
+/// @nodoc
+mixin _$MenuWatchEvent {
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() started,
+    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
+        appsReceived,
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? started,
+    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
+        appsReceived,
+    required TResult orElse(),
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Started value) started,
+    required TResult Function(AppsReceived value) appsReceived,
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Started value)? started,
+    TResult Function(AppsReceived value)? appsReceived,
+    required TResult orElse(),
+  }) =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $MenuWatchEventCopyWith<$Res> {
+  factory $MenuWatchEventCopyWith(
+          MenuWatchEvent value, $Res Function(MenuWatchEvent) then) =
+      _$MenuWatchEventCopyWithImpl<$Res>;
+}
+
+/// @nodoc
+class _$MenuWatchEventCopyWithImpl<$Res>
+    implements $MenuWatchEventCopyWith<$Res> {
+  _$MenuWatchEventCopyWithImpl(this._value, this._then);
+
+  final MenuWatchEvent _value;
+  // ignore: unused_field
+  final $Res Function(MenuWatchEvent) _then;
+}
+
+/// @nodoc
+abstract class _$StartedCopyWith<$Res> {
+  factory _$StartedCopyWith(_Started value, $Res Function(_Started) then) =
+      __$StartedCopyWithImpl<$Res>;
+}
+
+/// @nodoc
+class __$StartedCopyWithImpl<$Res> extends _$MenuWatchEventCopyWithImpl<$Res>
+    implements _$StartedCopyWith<$Res> {
+  __$StartedCopyWithImpl(_Started _value, $Res Function(_Started) _then)
+      : super(_value, (v) => _then(v as _Started));
+
+  @override
+  _Started get _value => super._value as _Started;
+}
+
+/// @nodoc
+
+class _$_Started implements _Started {
+  const _$_Started();
+
+  @override
+  String toString() {
+    return 'MenuWatchEvent.started()';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) || (other is _Started);
+  }
+
+  @override
+  int get hashCode => runtimeType.hashCode;
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() started,
+    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
+        appsReceived,
+  }) {
+    return started();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? started,
+    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
+        appsReceived,
+    required TResult orElse(),
+  }) {
+    if (started != null) {
+      return started();
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Started value) started,
+    required TResult Function(AppsReceived value) appsReceived,
+  }) {
+    return started(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Started value)? started,
+    TResult Function(AppsReceived value)? appsReceived,
+    required TResult orElse(),
+  }) {
+    if (started != null) {
+      return started(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class _Started implements MenuWatchEvent {
+  const factory _Started() = _$_Started;
+}
+
+/// @nodoc
+abstract class $AppsReceivedCopyWith<$Res> {
+  factory $AppsReceivedCopyWith(
+          AppsReceived value, $Res Function(AppsReceived) then) =
+      _$AppsReceivedCopyWithImpl<$Res>;
+  $Res call({Either<List<App>, WorkspaceError> appsOrFail});
+}
+
+/// @nodoc
+class _$AppsReceivedCopyWithImpl<$Res>
+    extends _$MenuWatchEventCopyWithImpl<$Res>
+    implements $AppsReceivedCopyWith<$Res> {
+  _$AppsReceivedCopyWithImpl(
+      AppsReceived _value, $Res Function(AppsReceived) _then)
+      : super(_value, (v) => _then(v as AppsReceived));
+
+  @override
+  AppsReceived get _value => super._value as AppsReceived;
+
+  @override
+  $Res call({
+    Object? appsOrFail = freezed,
+  }) {
+    return _then(AppsReceived(
+      appsOrFail == freezed
+          ? _value.appsOrFail
+          : appsOrFail // ignore: cast_nullable_to_non_nullable
+              as Either<List<App>, WorkspaceError>,
+    ));
+  }
+}
+
+/// @nodoc
+
+class _$AppsReceived implements AppsReceived {
+  const _$AppsReceived(this.appsOrFail);
+
+  @override
+  final Either<List<App>, WorkspaceError> appsOrFail;
+
+  @override
+  String toString() {
+    return 'MenuWatchEvent.appsReceived(appsOrFail: $appsOrFail)';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) ||
+        (other is AppsReceived &&
+            (identical(other.appsOrFail, appsOrFail) ||
+                const DeepCollectionEquality()
+                    .equals(other.appsOrFail, appsOrFail)));
+  }
+
+  @override
+  int get hashCode =>
+      runtimeType.hashCode ^ const DeepCollectionEquality().hash(appsOrFail);
+
+  @JsonKey(ignore: true)
+  @override
+  $AppsReceivedCopyWith<AppsReceived> get copyWith =>
+      _$AppsReceivedCopyWithImpl<AppsReceived>(this, _$identity);
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() started,
+    required TResult Function(Either<List<App>, WorkspaceError> appsOrFail)
+        appsReceived,
+  }) {
+    return appsReceived(appsOrFail);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? started,
+    TResult Function(Either<List<App>, WorkspaceError> appsOrFail)?
+        appsReceived,
+    required TResult orElse(),
+  }) {
+    if (appsReceived != null) {
+      return appsReceived(appsOrFail);
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Started value) started,
+    required TResult Function(AppsReceived value) appsReceived,
+  }) {
+    return appsReceived(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Started value)? started,
+    TResult Function(AppsReceived value)? appsReceived,
+    required TResult orElse(),
+  }) {
+    if (appsReceived != null) {
+      return appsReceived(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class AppsReceived implements MenuWatchEvent {
+  const factory AppsReceived(Either<List<App>, WorkspaceError> appsOrFail) =
+      _$AppsReceived;
+
+  Either<List<App>, WorkspaceError> get appsOrFail =>
+      throw _privateConstructorUsedError;
+  @JsonKey(ignore: true)
+  $AppsReceivedCopyWith<AppsReceived> get copyWith =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+class _$MenuWatchStateTearOff {
+  const _$MenuWatchStateTearOff();
+
+  _Initial initial() {
+    return const _Initial();
+  }
+
+  _LoadApps loadApps(List<App> apps) {
+    return _LoadApps(
+      apps,
+    );
+  }
+
+  _LoadFail loadFail(WorkspaceError error) {
+    return _LoadFail(
+      error,
+    );
+  }
+}
+
+/// @nodoc
+const $MenuWatchState = _$MenuWatchStateTearOff();
+
+/// @nodoc
+mixin _$MenuWatchState {
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(List<App> apps) loadApps,
+    required TResult Function(WorkspaceError error) loadFail,
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(List<App> apps)? loadApps,
+    TResult Function(WorkspaceError error)? loadFail,
+    required TResult orElse(),
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Initial value) initial,
+    required TResult Function(_LoadApps value) loadApps,
+    required TResult Function(_LoadFail value) loadFail,
+  }) =>
+      throw _privateConstructorUsedError;
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Initial value)? initial,
+    TResult Function(_LoadApps value)? loadApps,
+    TResult Function(_LoadFail value)? loadFail,
+    required TResult orElse(),
+  }) =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $MenuWatchStateCopyWith<$Res> {
+  factory $MenuWatchStateCopyWith(
+          MenuWatchState value, $Res Function(MenuWatchState) then) =
+      _$MenuWatchStateCopyWithImpl<$Res>;
+}
+
+/// @nodoc
+class _$MenuWatchStateCopyWithImpl<$Res>
+    implements $MenuWatchStateCopyWith<$Res> {
+  _$MenuWatchStateCopyWithImpl(this._value, this._then);
+
+  final MenuWatchState _value;
+  // ignore: unused_field
+  final $Res Function(MenuWatchState) _then;
+}
+
+/// @nodoc
+abstract class _$InitialCopyWith<$Res> {
+  factory _$InitialCopyWith(_Initial value, $Res Function(_Initial) then) =
+      __$InitialCopyWithImpl<$Res>;
+}
+
+/// @nodoc
+class __$InitialCopyWithImpl<$Res> extends _$MenuWatchStateCopyWithImpl<$Res>
+    implements _$InitialCopyWith<$Res> {
+  __$InitialCopyWithImpl(_Initial _value, $Res Function(_Initial) _then)
+      : super(_value, (v) => _then(v as _Initial));
+
+  @override
+  _Initial get _value => super._value as _Initial;
+}
+
+/// @nodoc
+
+class _$_Initial implements _Initial {
+  const _$_Initial();
+
+  @override
+  String toString() {
+    return 'MenuWatchState.initial()';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) || (other is _Initial);
+  }
+
+  @override
+  int get hashCode => runtimeType.hashCode;
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(List<App> apps) loadApps,
+    required TResult Function(WorkspaceError error) loadFail,
+  }) {
+    return initial();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(List<App> apps)? loadApps,
+    TResult Function(WorkspaceError error)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (initial != null) {
+      return initial();
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Initial value) initial,
+    required TResult Function(_LoadApps value) loadApps,
+    required TResult Function(_LoadFail value) loadFail,
+  }) {
+    return initial(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Initial value)? initial,
+    TResult Function(_LoadApps value)? loadApps,
+    TResult Function(_LoadFail value)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (initial != null) {
+      return initial(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class _Initial implements MenuWatchState {
+  const factory _Initial() = _$_Initial;
+}
+
+/// @nodoc
+abstract class _$LoadAppsCopyWith<$Res> {
+  factory _$LoadAppsCopyWith(_LoadApps value, $Res Function(_LoadApps) then) =
+      __$LoadAppsCopyWithImpl<$Res>;
+  $Res call({List<App> apps});
+}
+
+/// @nodoc
+class __$LoadAppsCopyWithImpl<$Res> extends _$MenuWatchStateCopyWithImpl<$Res>
+    implements _$LoadAppsCopyWith<$Res> {
+  __$LoadAppsCopyWithImpl(_LoadApps _value, $Res Function(_LoadApps) _then)
+      : super(_value, (v) => _then(v as _LoadApps));
+
+  @override
+  _LoadApps get _value => super._value as _LoadApps;
+
+  @override
+  $Res call({
+    Object? apps = freezed,
+  }) {
+    return _then(_LoadApps(
+      apps == freezed
+          ? _value.apps
+          : apps // ignore: cast_nullable_to_non_nullable
+              as List<App>,
+    ));
+  }
+}
+
+/// @nodoc
+
+class _$_LoadApps implements _LoadApps {
+  const _$_LoadApps(this.apps);
+
+  @override
+  final List<App> apps;
+
+  @override
+  String toString() {
+    return 'MenuWatchState.loadApps(apps: $apps)';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) ||
+        (other is _LoadApps &&
+            (identical(other.apps, apps) ||
+                const DeepCollectionEquality().equals(other.apps, apps)));
+  }
+
+  @override
+  int get hashCode =>
+      runtimeType.hashCode ^ const DeepCollectionEquality().hash(apps);
+
+  @JsonKey(ignore: true)
+  @override
+  _$LoadAppsCopyWith<_LoadApps> get copyWith =>
+      __$LoadAppsCopyWithImpl<_LoadApps>(this, _$identity);
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(List<App> apps) loadApps,
+    required TResult Function(WorkspaceError error) loadFail,
+  }) {
+    return loadApps(apps);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(List<App> apps)? loadApps,
+    TResult Function(WorkspaceError error)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (loadApps != null) {
+      return loadApps(apps);
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Initial value) initial,
+    required TResult Function(_LoadApps value) loadApps,
+    required TResult Function(_LoadFail value) loadFail,
+  }) {
+    return loadApps(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Initial value)? initial,
+    TResult Function(_LoadApps value)? loadApps,
+    TResult Function(_LoadFail value)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (loadApps != null) {
+      return loadApps(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class _LoadApps implements MenuWatchState {
+  const factory _LoadApps(List<App> apps) = _$_LoadApps;
+
+  List<App> get apps => throw _privateConstructorUsedError;
+  @JsonKey(ignore: true)
+  _$LoadAppsCopyWith<_LoadApps> get copyWith =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class _$LoadFailCopyWith<$Res> {
+  factory _$LoadFailCopyWith(_LoadFail value, $Res Function(_LoadFail) then) =
+      __$LoadFailCopyWithImpl<$Res>;
+  $Res call({WorkspaceError error});
+}
+
+/// @nodoc
+class __$LoadFailCopyWithImpl<$Res> extends _$MenuWatchStateCopyWithImpl<$Res>
+    implements _$LoadFailCopyWith<$Res> {
+  __$LoadFailCopyWithImpl(_LoadFail _value, $Res Function(_LoadFail) _then)
+      : super(_value, (v) => _then(v as _LoadFail));
+
+  @override
+  _LoadFail get _value => super._value as _LoadFail;
+
+  @override
+  $Res call({
+    Object? error = freezed,
+  }) {
+    return _then(_LoadFail(
+      error == freezed
+          ? _value.error
+          : error // ignore: cast_nullable_to_non_nullable
+              as WorkspaceError,
+    ));
+  }
+}
+
+/// @nodoc
+
+class _$_LoadFail implements _LoadFail {
+  const _$_LoadFail(this.error);
+
+  @override
+  final WorkspaceError error;
+
+  @override
+  String toString() {
+    return 'MenuWatchState.loadFail(error: $error)';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) ||
+        (other is _LoadFail &&
+            (identical(other.error, error) ||
+                const DeepCollectionEquality().equals(other.error, error)));
+  }
+
+  @override
+  int get hashCode =>
+      runtimeType.hashCode ^ const DeepCollectionEquality().hash(error);
+
+  @JsonKey(ignore: true)
+  @override
+  _$LoadFailCopyWith<_LoadFail> get copyWith =>
+      __$LoadFailCopyWithImpl<_LoadFail>(this, _$identity);
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(List<App> apps) loadApps,
+    required TResult Function(WorkspaceError error) loadFail,
+  }) {
+    return loadFail(error);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(List<App> apps)? loadApps,
+    TResult Function(WorkspaceError error)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (loadFail != null) {
+      return loadFail(error);
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(_Initial value) initial,
+    required TResult Function(_LoadApps value) loadApps,
+    required TResult Function(_LoadFail value) loadFail,
+  }) {
+    return loadFail(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(_Initial value)? initial,
+    TResult Function(_LoadApps value)? loadApps,
+    TResult Function(_LoadFail value)? loadFail,
+    required TResult orElse(),
+  }) {
+    if (loadFail != null) {
+      return loadFail(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class _LoadFail implements MenuWatchState {
+  const factory _LoadFail(WorkspaceError error) = _$_LoadFail;
+
+  WorkspaceError get error => throw _privateConstructorUsedError;
+  @JsonKey(ignore: true)
+  _$LoadFailCopyWith<_LoadFail> get copyWith =>
+      throw _privateConstructorUsedError;
+}

+ 2 - 0
app_flowy/lib/home/domain/i_app.dart

@@ -13,7 +13,9 @@ abstract class IApp {
       required String name,
       String? desc,
       required ViewType viewType});
+}
 
+abstract class IAppWatch {
   void startWatching(
       {AppAddViewCallback? addViewCallback,
       AppUpdatedCallback? updatedCallback});

+ 3 - 2
app_flowy/lib/home/domain/i_workspace.dart

@@ -9,9 +9,10 @@ abstract class IWorkspace {
   Future<Either<App, WorkspaceError>> createApp(
       {required String name, String? desc});
 
-  Future<Either<List<App>, WorkspaceError>> getApps(
-      {required String workspaceId});
+  Future<Either<List<App>, WorkspaceError>> getApps();
+}
 
+abstract class IWorkspaceWatch {
   void startWatching(
       {WorkspaceAddAppCallback? addAppCallback,
       WorkspaceUpdatedCallback? updatedCallback});

+ 20 - 6
app_flowy/lib/home/infrastructure/deps_resolver.dart

@@ -1,4 +1,5 @@
 import 'package:app_flowy/home/application/menu/menu_bloc.dart';
+import 'package:app_flowy/home/application/menu/menu_watch.dart';
 import 'package:app_flowy/home/infrastructure/i_app_impl.dart';
 import 'package:app_flowy/home/infrastructure/i_workspace_impl.dart';
 import 'package:app_flowy/home/infrastructure/repos/app_repo.dart';
@@ -7,21 +8,34 @@ import 'package:get_it/get_it.dart';
 
 class HomeDepsResolver {
   static Future<void> resolve(GetIt getIt) async {
-    getIt.registerFactoryParam<WorkspaceRepository, String, void>(
-        (workspaceId, _) => WorkspaceRepository(workspaceId: workspaceId));
-
+    //App
     getIt.registerFactoryParam<AppRepository, String, void>(
         (appId, _) => AppRepository(appId: appId));
-
-    //Interface implementation
+    getIt.registerFactoryParam<AppWatchRepository, String, void>(
+        (appId, _) => AppWatchRepository(appId: appId));
     getIt.registerFactoryParam<IApp, String, void>(
         (appId, _) => IAppImpl(repo: getIt<AppRepository>(param1: appId)));
+    getIt.registerFactoryParam<IAppWatch, String, void>((appId, _) =>
+        IAppWatchImpl(repo: getIt<AppWatchRepository>(param1: appId)));
+
+    //workspace
+    getIt.registerFactoryParam<WorkspaceRepo, String, void>(
+        (workspaceId, _) => WorkspaceRepo(workspaceId: workspaceId));
+    getIt.registerFactoryParam<WorkspaceWatchRepo, String, void>(
+        (workspaceId, _) => WorkspaceWatchRepo(workspaceId: workspaceId));
 
     getIt.registerFactoryParam<IWorkspace, String, void>((workspacId, _) =>
-        IWorkspaceImpl(repo: getIt<WorkspaceRepository>(param1: workspacId)));
+        IWorkspaceImpl(repo: getIt<WorkspaceRepo>(param1: workspacId)));
+    getIt.registerFactoryParam<IWorkspaceWatch, String, void>((workspacId, _) =>
+        IWorkspaceWatchImpl(
+            repo: getIt<WorkspaceWatchRepo>(param1: workspacId)));
 
     //Bloc
     getIt.registerFactoryParam<MenuBloc, String, void>(
         (workspaceId, _) => MenuBloc(getIt<IWorkspace>(param1: workspaceId)));
+    getIt.registerFactoryParam<MenuWatchBloc, String, void>((workspaceId, _) =>
+        MenuWatchBloc(getIt<IWorkspaceWatch>(param1: workspaceId)));
+
+    // AppWatchBloc
   }
 }

+ 7 - 0
app_flowy/lib/home/infrastructure/i_app_impl.dart

@@ -25,6 +25,13 @@ class IAppImpl extends IApp {
       required ViewType viewType}) {
     return repo.createView(appId, name, desc ?? "", viewType);
   }
+}
+
+class IAppWatchImpl extends IAppWatch {
+  AppWatchRepository repo;
+  IAppWatchImpl({
+    required this.repo,
+  });
 
   @override
   void startWatching(

+ 10 - 6
app_flowy/lib/home/infrastructure/i_workspace_impl.dart

@@ -7,7 +7,7 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/errors.pb.dart';
 export 'package:app_flowy/home/domain/i_workspace.dart';
 
 class IWorkspaceImpl extends IWorkspace {
-  WorkspaceRepository repo;
+  WorkspaceRepo repo;
   IWorkspaceImpl({
     required this.repo,
   });
@@ -19,17 +19,21 @@ class IWorkspaceImpl extends IWorkspace {
   }
 
   @override
-  Future<Either<List<App>, WorkspaceError>> getApps(
-      {required String workspaceId}) {
-    return repo
-        .getWorkspace(workspaceId: workspaceId, readApps: true)
-        .then((result) {
+  Future<Either<List<App>, WorkspaceError>> getApps() {
+    return repo.getWorkspace(readApps: true).then((result) {
       return result.fold(
         (workspace) => left(workspace.apps.items),
         (error) => right(error),
       );
     });
   }
+}
+
+class IWorkspaceWatchImpl extends IWorkspaceWatch {
+  WorkspaceWatchRepo repo;
+  IWorkspaceWatchImpl({
+    required this.repo,
+  });
 
   @override
   void startWatching(

+ 15 - 5
app_flowy/lib/home/infrastructure/repos/app_repo.dart

@@ -13,9 +13,6 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pbenum.dart';
 import 'package:flowy_sdk/rust_stream.dart';
 
 class AppRepository {
-  StreamSubscription<ObservableSubject>? _subscription;
-  AppAddViewCallback? _addViewCallback;
-  AppUpdatedCallback? _updatedCallback;
   String appId;
   AppRepository({
     required this.appId,
@@ -52,6 +49,19 @@ class AppRepository {
       );
     });
   }
+}
+
+class AppWatchRepository {
+  StreamSubscription<ObservableSubject>? _subscription;
+  AppAddViewCallback? _addViewCallback;
+  AppUpdatedCallback? _updatedCallback;
+  String appId;
+  late AppRepository _repo;
+  AppWatchRepository({
+    required this.appId,
+  }) {
+    _repo = AppRepository(appId: appId);
+  }
 
   void startWatching(
       {AppAddViewCallback? addViewCallback,
@@ -76,7 +86,7 @@ class AppRepository {
         if (_addViewCallback == null) {
           return;
         }
-        getViews(appId: appId).then((result) {
+        _repo.getViews(appId: appId).then((result) {
           result.fold(
             (views) => _addViewCallback!(left(views)),
             (error) => _addViewCallback!(right(error)),
@@ -87,7 +97,7 @@ class AppRepository {
         if (_updatedCallback == null) {
           return;
         }
-        getAppDesc().then((result) {
+        _repo.getAppDesc().then((result) {
           result.fold(
             (app) => _updatedCallback!(app.name, app.desc),
             (error) => Log.error(error),

+ 19 - 8
app_flowy/lib/home/infrastructure/repos/workspace_repo.dart

@@ -12,12 +12,9 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_create.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/workspace_query.pb.dart';
 import 'package:flowy_sdk/rust_stream.dart';
 
-class WorkspaceRepository {
-  StreamSubscription<ObservableSubject>? _subscription;
-  WorkspaceAddAppCallback? _addAppCallback;
-  WorkspaceUpdatedCallback? _updatedCallback;
+class WorkspaceRepo {
   String workspaceId;
-  WorkspaceRepository({
+  WorkspaceRepo({
     required this.workspaceId,
   });
 
@@ -39,7 +36,7 @@ class WorkspaceRepository {
   }
 
   Future<Either<Workspace, WorkspaceError>> getWorkspace(
-      {required String workspaceId, bool readApps = false}) {
+      {bool readApps = false}) {
     final request = QueryWorkspaceRequest.create()
       ..workspaceId = workspaceId
       ..readApps = readApps;
@@ -51,6 +48,20 @@ class WorkspaceRepository {
       );
     });
   }
+}
+
+class WorkspaceWatchRepo {
+  StreamSubscription<ObservableSubject>? _subscription;
+  WorkspaceAddAppCallback? _addAppCallback;
+  WorkspaceUpdatedCallback? _updatedCallback;
+  final String workspaceId;
+  late WorkspaceRepo _repo;
+
+  WorkspaceWatchRepo({
+    required this.workspaceId,
+  }) {
+    _repo = WorkspaceRepo(workspaceId: workspaceId);
+  }
 
   void startWatching(
       {WorkspaceAddAppCallback? addAppCallback,
@@ -76,7 +87,7 @@ class WorkspaceRepository {
         if (_updatedCallback == null) {
           return;
         }
-        getWorkspace(workspaceId: workspaceId).then((result) {
+        _repo.getWorkspace().then((result) {
           result.fold(
             (workspace) => _updatedCallback!(workspace.name, workspace.desc),
             (error) => Log.error(error),
@@ -87,7 +98,7 @@ class WorkspaceRepository {
         if (_addAppCallback == null) {
           return;
         }
-        getWorkspace(workspaceId: workspaceId, readApps: true).then((result) {
+        _repo.getWorkspace(readApps: true).then((result) {
           result.fold(
             (workspace) => _addAppCallback!(left(workspace.apps.items)),
             (error) => _addAppCallback!(right(error)),

+ 49 - 30
app_flowy/lib/home/presentation/widgets/app/app_list_widget.dart

@@ -10,39 +10,44 @@ import 'package:flowy_infra_ui/widget/error_page.dart';
 
 import 'app_widget.dart';
 
+// class AppList extends StatelessWidget {
+//   const AppList({Key? key}) : super(key: key);
+//   @override
+//   Widget build(BuildContext context) {
+//     return MultiBlocProvider(
+//       providers: [
+//         BlocProvider(
+//           create: (context) => getIt<AppBloc>()..add(const AppEvent.initial()),
+//         ),
+//       ],
+//       child: BlocBuilder<AppBloc, AppState>(
+//         buildWhen: (p, c) => p.apps != c.apps,
+//         builder: (context, state) {
+//           Log.info('AppList build');
+//           if (state.isLoading) {
+//             return const Center(
+//               child: CircularProgressIndicator.adaptive(),
+//             );
+//           }
+
+//           return state.apps.fold(
+//             () => state.successOrFailure.fold(
+//               (_) => const Text('You have no apps, create one?'),
+//               (error) => FlowyErrorPage(error.toString()),
+//             ),
+//             (apps) => _buildBody(apps),
+//           );
+//         },
+//       ),
+//     );
+//   }
+
 class AppList extends StatelessWidget {
-  const AppList({Key? key}) : super(key: key);
+  final List<App> apps;
+  const AppList({required this.apps, Key? key}) : super(key: key);
+
   @override
   Widget build(BuildContext context) {
-    return MultiBlocProvider(
-      providers: [
-        BlocProvider(
-          create: (context) => getIt<AppBloc>()..add(const AppEvent.initial()),
-        ),
-      ],
-      child: BlocBuilder<AppBloc, AppState>(
-        buildWhen: (p, c) => p.apps != c.apps,
-        builder: (context, state) {
-          Log.info('AppList build');
-          if (state.isLoading) {
-            return const Center(
-              child: CircularProgressIndicator.adaptive(),
-            );
-          }
-
-          return state.apps.fold(
-            () => state.successOrFailure.fold(
-              (_) => const Text('You have no apps, create one?'),
-              (error) => FlowyErrorPage(error.toString()),
-            ),
-            (apps) => _buildBody(apps),
-          );
-        },
-      ),
-    );
-  }
-
-  Widget _buildBody(List<App> apps) {
     return ExpandableTheme(
         data: const ExpandableThemeData(
           iconColor: Colors.blue,
@@ -55,4 +60,18 @@ class AppList extends StatelessWidget {
           ),
         ));
   }
+
+  // Widget _buildBody(List<App> apps) {
+  //   return ExpandableTheme(
+  //       data: const ExpandableThemeData(
+  //         iconColor: Colors.blue,
+  //         useInkWell: true,
+  //       ),
+  //       child: Expanded(
+  //         child: ListView(
+  //           physics: const BouncingScrollPhysics(),
+  //           children: apps.map((app) => AppWidget(app)).toList(),
+  //         ),
+  //       ));
+  // }
 }

+ 21 - 2
app_flowy/lib/home/presentation/widgets/app/app_widget.dart

@@ -1,7 +1,9 @@
-// ignore: import_of_legacy_library_into_null_safe
-import 'package:app_flowy/home/presentation/widgets/menu/hom_menu_size.dart';
+import 'package:app_flowy/home/application/app/app_bloc.dart';
+import 'package:app_flowy/home/presentation/widgets/menu/menu_size.dart';
+import 'package:app_flowy/startup/startup.dart';
 import 'package:expandable/expandable.dart';
 import 'package:flowy_infra/size.dart';
+import 'package:flowy_infra_ui/widget/error_page.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
 import 'package:flowy_sdk/protobuf/flowy-workspace/view_create.pb.dart';
 import 'package:flutter/material.dart';
@@ -13,6 +15,22 @@ class AppWidget extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
+    // return MultiBlocProvider(
+    //   providers: [
+    //     BlocProvider<AppBloc>(create: (context) => getIt<AppBloc>()),
+    //   ],
+    //   child: BlocBuilder<AppBloc, AppState>(
+    //     builder: (context, state) {
+    //       // final child = state.map(
+    //       //   initial: (_) => const CircularProgressIndicator.adaptive(),
+    //       //   loadViews: (s) => ViewList(s.views),
+    //       //   successOrFailure: (s) => FlowyErrorPage(s.error),
+    //       // );
+
+    //       return expandableWrapper(context, Container());
+    //     },
+    //   ),
+    // );
     return Container();
   }
 
@@ -38,6 +56,7 @@ class AppWidget extends StatelessWidget {
                   padding: EdgeInsets.only(left: Sizes.iconMed),
                   child: child,
                 ),
+                collapsed: const Text("close"),
               ),
             ],
           ),

+ 29 - 0
app_flowy/lib/home/presentation/widgets/menu/app_list.dart

@@ -0,0 +1,29 @@
+import 'package:expandable/expandable.dart';
+import 'package:flowy_sdk/protobuf/flowy-workspace/app_create.pb.dart';
+import 'package:app_flowy/home/presentation/widgets/app/app_widget.dart';
+import 'package:flutter/material.dart';
+import 'package:dartz/dartz.dart';
+
+class AppList extends StatelessWidget {
+  final Option<List<App>> apps;
+  const AppList({required this.apps, Key? key}) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    return apps.fold(() {
+      return const Text('You have no apps, create one?');
+    }, (apps) {
+      return ExpandableTheme(
+          data: const ExpandableThemeData(
+            iconColor: Colors.blue,
+            useInkWell: true,
+          ),
+          child: Expanded(
+            child: ListView(
+              physics: const BouncingScrollPhysics(),
+              children: apps.map((app) => AppWidget(app)).toList(),
+            ),
+          ));
+    });
+  }
+}

+ 33 - 11
app_flowy/lib/home/presentation/widgets/menu/home_menu.dart → app_flowy/lib/home/presentation/widgets/menu/menu.dart

@@ -1,7 +1,9 @@
 import 'package:app_flowy/home/application/menu/menu_bloc.dart';
+import 'package:app_flowy/home/application/menu/menu_watch.dart';
 import 'package:app_flowy/home/domain/page_context.dart';
+import 'package:app_flowy/home/presentation/home_sizes.dart';
 import 'package:app_flowy/startup/startup.dart';
-import 'package:app_flowy/startup/tasks/app_widget_task.dart';
+import 'package:app_flowy/startup/tasks/application_task.dart';
 import 'package:dartz/dartz.dart';
 import 'package:flowy_infra/size.dart';
 import 'package:flowy_infra/text_style.dart';
@@ -9,12 +11,13 @@ import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/styled_text_input.dart';
 import 'package:flowy_infra_ui/widget/buttons/ok_cancel_button.dart';
 import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
+import 'package:flowy_infra_ui/widget/error_page.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import '../../home_sizes.dart';
 import 'package:styled_widget/styled_widget.dart';
 import 'package:textstyle_extensions/textstyle_extensions.dart';
+import 'app_list.dart';
 
 class HomeMenu extends StatelessWidget {
   final Function(Option<PageContext>) pageContextChanged;
@@ -30,9 +33,15 @@ class HomeMenu extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return BlocProvider(
-      create: (context) =>
-          getIt<MenuBloc>(param1: workspaceId)..add(const MenuEvent.initial()),
+    return MultiBlocProvider(
+      providers: [
+        BlocProvider<MenuBloc>(
+            create: (context) => getIt<MenuBloc>(param1: workspaceId)
+              ..add(const MenuEvent.initial())),
+        BlocProvider(
+            create: (context) => getIt<MenuWatchBloc>(param1: workspaceId)
+              ..add(const MenuWatchEvent.started())),
+      ],
       child: MultiBlocListener(
         listeners: [
           BlocListener<MenuBloc, MenuState>(
@@ -58,16 +67,29 @@ class HomeMenu extends StatelessWidget {
         mainAxisAlignment: MainAxisAlignment.start,
         children: [
           const MenuTopBar(),
-          Expanded(child: Container()),
-          NewAppButton(
-            createAppCallback: (appName) => context
-                .read<MenuBloc>()
-                .add(MenuEvent.createApp(appName, desc: "")),
-          ),
+          _renderAppList(context),
+          _renderNewButton(context),
         ],
       ).padding(horizontal: Insets.sm),
     );
   }
+
+  Widget _renderAppList(BuildContext context) {
+    return BlocBuilder<MenuWatchBloc, MenuWatchState>(
+      builder: (context, state) => state.map(
+        initial: (_) => AppList(apps: context.read<MenuBloc>().state.apps),
+        loadApps: (event) => AppList(apps: some(event.apps)),
+        loadFail: (error) => FlowyErrorPage(error.toString()),
+      ),
+    );
+  }
+
+  Widget _renderNewButton(BuildContext context) {
+    return NewAppButton(
+      createAppCallback: (appName) =>
+          context.read<MenuBloc>().add(MenuEvent.createApp(appName, desc: "")),
+    );
+  }
 }
 
 class MenuTopBar extends StatelessWidget {

+ 0 - 0
app_flowy/lib/home/presentation/widgets/menu/hom_menu_size.dart → app_flowy/lib/home/presentation/widgets/menu/menu_size.dart


+ 2 - 2
app_flowy/lib/home/presentation/widgets/menu/prelude.dart

@@ -1,2 +1,2 @@
-export 'home_menu.dart';
-export 'hom_menu_size.dart';
+export 'menu.dart';
+export 'menu_size.dart';

+ 1 - 1
app_flowy/lib/home/presentation/widgets/prelude.dart

@@ -2,4 +2,4 @@ export './blank_page.dart';
 export './edit_pannel/edit_pannel.dart';
 export './edit_pannel/pannel_animation.dart';
 export './home_top_bar.dart';
-export './menu/home_menu.dart';
+export 'menu/menu.dart';

+ 3 - 3
app_flowy/lib/startup/tasks/app_widget_task.dart → app_flowy/lib/startup/tasks/application_task.dart

@@ -12,16 +12,16 @@ class AppWidgetTask extends LaunchTask {
   @override
   Future<void> initialize(LaunchContext context) {
     final widget = context.getIt<AppFactory>().create();
-    final app = AppWidget(child: widget);
+    final app = ApplicationWidget(child: widget);
     runApp(app);
 
     return Future(() => {});
   }
 }
 
-class AppWidget extends StatelessWidget {
+class ApplicationWidget extends StatelessWidget {
   final Widget child;
-  const AppWidget({
+  const ApplicationWidget({
     Key? key,
     required this.child,
   }) : super(key: key);

+ 1 - 1
app_flowy/lib/startup/tasks/prelude.dart

@@ -1,2 +1,2 @@
-export 'app_widget_task.dart';
+export 'application_task.dart';
 export 'rust_sdk_init_task.dart';

+ 4 - 4
app_flowy/packages/flowy_infra_ui/example/pubspec.lock

@@ -14,7 +14,7 @@ packages:
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.6.1"
+    version: "2.7.0"
   boolean_selector:
     dependency: transitive
     description:
@@ -35,7 +35,7 @@ packages:
       name: charcode
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0"
+    version: "1.3.1"
   clock:
     dependency: transitive
     description:
@@ -176,7 +176,7 @@ packages:
       name: meta
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0"
+    version: "1.7.0"
   nested:
     dependency: transitive
     description:
@@ -258,7 +258,7 @@ packages:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.3.0"
+    version: "0.4.1"
   textstyle_extensions:
     dependency: transitive
     description:

+ 4 - 4
app_flowy/packages/flowy_infra_ui/pubspec.lock

@@ -14,7 +14,7 @@ packages:
       name: async
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "2.6.1"
+    version: "2.7.0"
   boolean_selector:
     dependency: transitive
     description:
@@ -35,7 +35,7 @@ packages:
       name: charcode
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.2.0"
+    version: "1.3.1"
   clock:
     dependency: transitive
     description:
@@ -162,7 +162,7 @@ packages:
       name: meta
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "1.3.0"
+    version: "1.7.0"
   nested:
     dependency: transitive
     description:
@@ -244,7 +244,7 @@ packages:
       name: test_api
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "0.3.0"
+    version: "0.4.1"
   textstyle_extensions:
     dependency: "direct main"
     description:

+ 1 - 1
app_flowy/pubspec.lock

@@ -203,7 +203,7 @@ packages:
       name: expandable
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "4.1.4"
+    version: "5.0.1"
   fake_async:
     dependency: transitive
     description:

+ 1 - 1
app_flowy/pubspec.yaml

@@ -52,7 +52,7 @@ dependencies:
       ref: e48abe7c3e9ebfe0b81622167c5201d4e783bb81
   sized_context: ^1.0.0+1
   styled_widget: '>=0.3.1'
-  expandable: ^4.1.4
+  expandable: ^5.0.1
 
 
   # The following adds the Cupertino Icons font to your application.

+ 4 - 4
rust-lib/dart-ffi/Cargo.toml

@@ -7,11 +7,11 @@ edition = "2018"
 [lib]
 name = "dart_ffi"
 # this value will change depending on the target os
-# for iOS it would be `rlib`
-# for Macos it would be `rlib`
+# for iOS it would be `cdylib`
+# for Macos it would be `cdylib`
 # for android it would be `c-dylib`
-# default rlib
-crate-type = ["rlib"]
+# default cdylib
+crate-type = ["cdylib"]
 
 
 [dependencies]