瀏覽代碼

[flutter]: update menu app name automatically after rename the app

appflowy 3 年之前
父節點
當前提交
74c1e3fcc6

+ 36 - 36
app_flowy/lib/workspace/application/app/app_bloc.dart

@@ -18,42 +18,41 @@ class AppBloc extends Bloc<AppEvent, AppState> {
   Stream<AppState> mapEventToState(
     AppEvent event,
   ) async* {
-    yield* event.map(
-      initial: (e) async* {
-        listener.start(viewsChangeCallback: _handleViewsOrFail);
-        yield* _fetchViews();
-      },
-      createView: (CreateView value) async* {
-        final viewOrFailed = await appManager.createView(name: value.name, desc: value.desc, viewType: value.viewType);
-        yield viewOrFailed.fold(
-          (view) => state.copyWith(
-            selectedView: view,
-            successOrFailure: left(unit),
-          ),
-          (error) {
-            Log.error(error);
-            return state.copyWith(successOrFailure: right(error));
-          },
-        );
-      },
-      didReceiveViews: (e) async* {
-        yield state.copyWith(views: e.views);
-      },
-      delete: (e) async* {
-        final result = await appManager.delete();
-        yield result.fold(
-          (l) => state.copyWith(successOrFailure: left(unit)),
-          (error) => state.copyWith(successOrFailure: right(error)),
-        );
-      },
-      rename: (e) async* {
-        final result = await appManager.rename(e.newName);
-        yield result.fold(
-          (l) => state.copyWith(successOrFailure: left(unit)),
-          (error) => state.copyWith(successOrFailure: right(error)),
-        );
-      },
-    );
+    yield* event.map(initial: (e) async* {
+      listener.start(
+        viewsChangeCallback: _handleViewsOrFail,
+        updatedCallback: (app) => add(AppEvent.appDidUpdate(app)),
+      );
+      yield* _fetchViews();
+    }, createView: (CreateView value) async* {
+      final viewOrFailed = await appManager.createView(name: value.name, desc: value.desc, viewType: value.viewType);
+      yield viewOrFailed.fold(
+        (view) => state.copyWith(
+          selectedView: view,
+          successOrFailure: left(unit),
+        ),
+        (error) {
+          Log.error(error);
+          return state.copyWith(successOrFailure: right(error));
+        },
+      );
+    }, didReceiveViews: (e) async* {
+      yield state.copyWith(views: e.views);
+    }, delete: (e) async* {
+      final result = await appManager.delete();
+      yield result.fold(
+        (l) => state.copyWith(successOrFailure: left(unit)),
+        (error) => state.copyWith(successOrFailure: right(error)),
+      );
+    }, rename: (e) async* {
+      final result = await appManager.rename(e.newName);
+      yield result.fold(
+        (l) => state.copyWith(successOrFailure: left(unit)),
+        (error) => state.copyWith(successOrFailure: right(error)),
+      );
+    }, appDidUpdate: (e) async* {
+      yield state.copyWith(app: e.app);
+    });
   }
 
   @override
@@ -90,6 +89,7 @@ class AppEvent with _$AppEvent {
   const factory AppEvent.delete() = Delete;
   const factory AppEvent.rename(String newName) = Rename;
   const factory AppEvent.didReceiveViews(List<View> views) = ReceiveViews;
+  const factory AppEvent.appDidUpdate(App app) = AppDidUpdate;
 }
 
 @freezed

+ 162 - 0
app_flowy/lib/workspace/application/app/app_bloc.freezed.dart

@@ -43,6 +43,12 @@ class _$AppEventTearOff {
       views,
     );
   }
+
+  AppDidUpdate appDidUpdate(App app) {
+    return AppDidUpdate(
+      app,
+    );
+  }
 }
 
 /// @nodoc
@@ -58,6 +64,7 @@ mixin _$AppEvent {
     required TResult Function() delete,
     required TResult Function(String newName) rename,
     required TResult Function(List<View> views) didReceiveViews,
+    required TResult Function(App app) appDidUpdate,
   }) =>
       throw _privateConstructorUsedError;
   @optionalTypeArgs
@@ -67,6 +74,7 @@ mixin _$AppEvent {
     TResult Function()? delete,
     TResult Function(String newName)? rename,
     TResult Function(List<View> views)? didReceiveViews,
+    TResult Function(App app)? appDidUpdate,
     required TResult orElse(),
   }) =>
       throw _privateConstructorUsedError;
@@ -77,6 +85,7 @@ mixin _$AppEvent {
     required TResult Function(Delete value) delete,
     required TResult Function(Rename value) rename,
     required TResult Function(ReceiveViews value) didReceiveViews,
+    required TResult Function(AppDidUpdate value) appDidUpdate,
   }) =>
       throw _privateConstructorUsedError;
   @optionalTypeArgs
@@ -86,6 +95,7 @@ mixin _$AppEvent {
     TResult Function(Delete value)? delete,
     TResult Function(Rename value)? rename,
     TResult Function(ReceiveViews value)? didReceiveViews,
+    TResult Function(AppDidUpdate value)? appDidUpdate,
     required TResult orElse(),
   }) =>
       throw _privateConstructorUsedError;
@@ -149,6 +159,7 @@ class _$Initial implements Initial {
     required TResult Function() delete,
     required TResult Function(String newName) rename,
     required TResult Function(List<View> views) didReceiveViews,
+    required TResult Function(App app) appDidUpdate,
   }) {
     return initial();
   }
@@ -161,6 +172,7 @@ class _$Initial implements Initial {
     TResult Function()? delete,
     TResult Function(String newName)? rename,
     TResult Function(List<View> views)? didReceiveViews,
+    TResult Function(App app)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (initial != null) {
@@ -177,6 +189,7 @@ class _$Initial implements Initial {
     required TResult Function(Delete value) delete,
     required TResult Function(Rename value) rename,
     required TResult Function(ReceiveViews value) didReceiveViews,
+    required TResult Function(AppDidUpdate value) appDidUpdate,
   }) {
     return initial(this);
   }
@@ -189,6 +202,7 @@ class _$Initial implements Initial {
     TResult Function(Delete value)? delete,
     TResult Function(Rename value)? rename,
     TResult Function(ReceiveViews value)? didReceiveViews,
+    TResult Function(AppDidUpdate value)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (initial != null) {
@@ -293,6 +307,7 @@ class _$CreateView implements CreateView {
     required TResult Function() delete,
     required TResult Function(String newName) rename,
     required TResult Function(List<View> views) didReceiveViews,
+    required TResult Function(App app) appDidUpdate,
   }) {
     return createView(name, desc, viewType);
   }
@@ -305,6 +320,7 @@ class _$CreateView implements CreateView {
     TResult Function()? delete,
     TResult Function(String newName)? rename,
     TResult Function(List<View> views)? didReceiveViews,
+    TResult Function(App app)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (createView != null) {
@@ -321,6 +337,7 @@ class _$CreateView implements CreateView {
     required TResult Function(Delete value) delete,
     required TResult Function(Rename value) rename,
     required TResult Function(ReceiveViews value) didReceiveViews,
+    required TResult Function(AppDidUpdate value) appDidUpdate,
   }) {
     return createView(this);
   }
@@ -333,6 +350,7 @@ class _$CreateView implements CreateView {
     TResult Function(Delete value)? delete,
     TResult Function(Rename value)? rename,
     TResult Function(ReceiveViews value)? didReceiveViews,
+    TResult Function(AppDidUpdate value)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (createView != null) {
@@ -397,6 +415,7 @@ class _$Delete implements Delete {
     required TResult Function() delete,
     required TResult Function(String newName) rename,
     required TResult Function(List<View> views) didReceiveViews,
+    required TResult Function(App app) appDidUpdate,
   }) {
     return delete();
   }
@@ -409,6 +428,7 @@ class _$Delete implements Delete {
     TResult Function()? delete,
     TResult Function(String newName)? rename,
     TResult Function(List<View> views)? didReceiveViews,
+    TResult Function(App app)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (delete != null) {
@@ -425,6 +445,7 @@ class _$Delete implements Delete {
     required TResult Function(Delete value) delete,
     required TResult Function(Rename value) rename,
     required TResult Function(ReceiveViews value) didReceiveViews,
+    required TResult Function(AppDidUpdate value) appDidUpdate,
   }) {
     return delete(this);
   }
@@ -437,6 +458,7 @@ class _$Delete implements Delete {
     TResult Function(Delete value)? delete,
     TResult Function(Rename value)? rename,
     TResult Function(ReceiveViews value)? didReceiveViews,
+    TResult Function(AppDidUpdate value)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (delete != null) {
@@ -518,6 +540,7 @@ class _$Rename implements Rename {
     required TResult Function() delete,
     required TResult Function(String newName) rename,
     required TResult Function(List<View> views) didReceiveViews,
+    required TResult Function(App app) appDidUpdate,
   }) {
     return rename(newName);
   }
@@ -530,6 +553,7 @@ class _$Rename implements Rename {
     TResult Function()? delete,
     TResult Function(String newName)? rename,
     TResult Function(List<View> views)? didReceiveViews,
+    TResult Function(App app)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (rename != null) {
@@ -546,6 +570,7 @@ class _$Rename implements Rename {
     required TResult Function(Delete value) delete,
     required TResult Function(Rename value) rename,
     required TResult Function(ReceiveViews value) didReceiveViews,
+    required TResult Function(AppDidUpdate value) appDidUpdate,
   }) {
     return rename(this);
   }
@@ -558,6 +583,7 @@ class _$Rename implements Rename {
     TResult Function(Delete value)? delete,
     TResult Function(Rename value)? rename,
     TResult Function(ReceiveViews value)? didReceiveViews,
+    TResult Function(AppDidUpdate value)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (rename != null) {
@@ -645,6 +671,7 @@ class _$ReceiveViews implements ReceiveViews {
     required TResult Function() delete,
     required TResult Function(String newName) rename,
     required TResult Function(List<View> views) didReceiveViews,
+    required TResult Function(App app) appDidUpdate,
   }) {
     return didReceiveViews(views);
   }
@@ -657,6 +684,7 @@ class _$ReceiveViews implements ReceiveViews {
     TResult Function()? delete,
     TResult Function(String newName)? rename,
     TResult Function(List<View> views)? didReceiveViews,
+    TResult Function(App app)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (didReceiveViews != null) {
@@ -673,6 +701,7 @@ class _$ReceiveViews implements ReceiveViews {
     required TResult Function(Delete value) delete,
     required TResult Function(Rename value) rename,
     required TResult Function(ReceiveViews value) didReceiveViews,
+    required TResult Function(AppDidUpdate value) appDidUpdate,
   }) {
     return didReceiveViews(this);
   }
@@ -685,6 +714,7 @@ class _$ReceiveViews implements ReceiveViews {
     TResult Function(Delete value)? delete,
     TResult Function(Rename value)? rename,
     TResult Function(ReceiveViews value)? didReceiveViews,
+    TResult Function(AppDidUpdate value)? appDidUpdate,
     required TResult orElse(),
   }) {
     if (didReceiveViews != null) {
@@ -703,6 +733,138 @@ abstract class ReceiveViews implements AppEvent {
       throw _privateConstructorUsedError;
 }
 
+/// @nodoc
+abstract class $AppDidUpdateCopyWith<$Res> {
+  factory $AppDidUpdateCopyWith(
+          AppDidUpdate value, $Res Function(AppDidUpdate) then) =
+      _$AppDidUpdateCopyWithImpl<$Res>;
+  $Res call({App app});
+}
+
+/// @nodoc
+class _$AppDidUpdateCopyWithImpl<$Res> extends _$AppEventCopyWithImpl<$Res>
+    implements $AppDidUpdateCopyWith<$Res> {
+  _$AppDidUpdateCopyWithImpl(
+      AppDidUpdate _value, $Res Function(AppDidUpdate) _then)
+      : super(_value, (v) => _then(v as AppDidUpdate));
+
+  @override
+  AppDidUpdate get _value => super._value as AppDidUpdate;
+
+  @override
+  $Res call({
+    Object? app = freezed,
+  }) {
+    return _then(AppDidUpdate(
+      app == freezed
+          ? _value.app
+          : app // ignore: cast_nullable_to_non_nullable
+              as App,
+    ));
+  }
+}
+
+/// @nodoc
+
+class _$AppDidUpdate implements AppDidUpdate {
+  const _$AppDidUpdate(this.app);
+
+  @override
+  final App app;
+
+  @override
+  String toString() {
+    return 'AppEvent.appDidUpdate(app: $app)';
+  }
+
+  @override
+  bool operator ==(dynamic other) {
+    return identical(this, other) ||
+        (other is AppDidUpdate &&
+            (identical(other.app, app) ||
+                const DeepCollectionEquality().equals(other.app, app)));
+  }
+
+  @override
+  int get hashCode =>
+      runtimeType.hashCode ^ const DeepCollectionEquality().hash(app);
+
+  @JsonKey(ignore: true)
+  @override
+  $AppDidUpdateCopyWith<AppDidUpdate> get copyWith =>
+      _$AppDidUpdateCopyWithImpl<AppDidUpdate>(this, _$identity);
+
+  @override
+  @optionalTypeArgs
+  TResult when<TResult extends Object?>({
+    required TResult Function() initial,
+    required TResult Function(String name, String desc, ViewType viewType)
+        createView,
+    required TResult Function() delete,
+    required TResult Function(String newName) rename,
+    required TResult Function(List<View> views) didReceiveViews,
+    required TResult Function(App app) appDidUpdate,
+  }) {
+    return appDidUpdate(app);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeWhen<TResult extends Object?>({
+    TResult Function()? initial,
+    TResult Function(String name, String desc, ViewType viewType)? createView,
+    TResult Function()? delete,
+    TResult Function(String newName)? rename,
+    TResult Function(List<View> views)? didReceiveViews,
+    TResult Function(App app)? appDidUpdate,
+    required TResult orElse(),
+  }) {
+    if (appDidUpdate != null) {
+      return appDidUpdate(app);
+    }
+    return orElse();
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult map<TResult extends Object?>({
+    required TResult Function(Initial value) initial,
+    required TResult Function(CreateView value) createView,
+    required TResult Function(Delete value) delete,
+    required TResult Function(Rename value) rename,
+    required TResult Function(ReceiveViews value) didReceiveViews,
+    required TResult Function(AppDidUpdate value) appDidUpdate,
+  }) {
+    return appDidUpdate(this);
+  }
+
+  @override
+  @optionalTypeArgs
+  TResult maybeMap<TResult extends Object?>({
+    TResult Function(Initial value)? initial,
+    TResult Function(CreateView value)? createView,
+    TResult Function(Delete value)? delete,
+    TResult Function(Rename value)? rename,
+    TResult Function(ReceiveViews value)? didReceiveViews,
+    TResult Function(AppDidUpdate value)? appDidUpdate,
+    required TResult orElse(),
+  }) {
+    if (appDidUpdate != null) {
+      return appDidUpdate(this);
+    }
+    return orElse();
+  }
+}
+
+abstract class AppDidUpdate implements AppEvent {
+  const factory AppDidUpdate(App app) = _$AppDidUpdate;
+
+  App get app => throw _privateConstructorUsedError;
+  @JsonKey(ignore: true)
+  $AppDidUpdateCopyWith<AppDidUpdate> get copyWith =>
+      throw _privateConstructorUsedError;
+}
+
 /// @nodoc
 class _$AppStateTearOff {
   const _$AppStateTearOff();

+ 1 - 1
app_flowy/lib/workspace/domain/i_app.dart

@@ -1,7 +1,7 @@
 import 'package:flowy_sdk/protobuf/flowy-workspace/protobuf.dart';
 import 'package:dartz/dartz.dart';
 
-typedef AppUpdatedCallback = void Function(String name, String desc);
+typedef AppUpdatedCallback = void Function(App app);
 typedef AppViewsChangeCallback = void Function(Either<List<View>, WorkspaceError> viewsOrFailed);
 
 abstract class IApp {

+ 1 - 1
app_flowy/lib/workspace/infrastructure/repos/app_repo.dart

@@ -100,7 +100,7 @@ class AppListenerRepository {
           result.fold(
             (payload) {
               final app = App.fromBuffer(payload);
-              _update!(app.name, app.desc);
+              _update!(app);
             },
             (error) => Log.error(error),
           );

+ 24 - 19
app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart

@@ -66,25 +66,30 @@ class MenuAppHeader extends StatelessWidget {
   }
 
   Widget _renderTitle(BuildContext context) {
-    return Expanded(
-      child: GestureDetector(
-        behavior: HitTestBehavior.opaque,
-        onTap: () {
-          ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle();
-        },
-        onSecondaryTap: () {
-          final actionList = AppDisclosureActions(onSelected: (action) => _handleAction(context, action));
-          actionList.show(
-            context,
-            context,
-            anchorDirection: AnchorDirection.bottomWithCenterAligned,
-          );
-        },
-        child: FlowyText.medium(
-          app.name,
-          fontSize: 12,
-        ),
-      ),
+    return BlocSelector<AppBloc, AppState, App>(
+      selector: (state) => state.app,
+      builder: (context, state) {
+        return Expanded(
+          child: GestureDetector(
+            behavior: HitTestBehavior.opaque,
+            onTap: () {
+              ExpandableController.of(context, rebuildOnChange: false, required: true)?.toggle();
+            },
+            onSecondaryTap: () {
+              final actionList = AppDisclosureActions(onSelected: (action) => _handleAction(context, action));
+              actionList.show(
+                context,
+                context,
+                anchorDirection: AnchorDirection.bottomWithCenterAligned,
+              );
+            },
+            child: FlowyText.medium(
+              state.name,
+              fontSize: 12,
+            ),
+          ),
+        );
+      },
     );
   }
 

+ 27 - 16
app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart

@@ -29,16 +29,15 @@ class MenuApp extends MenuItem {
           },
         ),
       ],
-      child: BlocListener<AppBloc, AppState>(
-        listenWhen: (p, c) => p.selectedView != c.selectedView,
-        listener: (context, state) => notifier.selectView = state.selectedView,
-        child: BlocBuilder<AppBloc, AppState>(
-          buildWhen: (p, c) => p.views != c.views,
-          builder: (context, state) {
-            notifier.views = state.views;
-            return expandableWrapper(context, _renderViewSection(notifier));
-          },
-        ),
+      child: BlocSelector<AppBloc, AppState, AppDataNotifier>(
+        selector: (state) {
+          notifier.selectView = state.selectedView;
+          notifier.views = state.views;
+          return notifier;
+        },
+        builder: (context, state) {
+          return expandableWrapper(context, _renderViewSection(state));
+        },
       ),
     );
   }
@@ -69,9 +68,9 @@ class MenuApp extends MenuItem {
     );
   }
 
-  Widget _renderViewSection(AppDataNotifier viewListNotifier) {
+  Widget _renderViewSection(AppDataNotifier notifier) {
     return MultiProvider(
-      providers: [ChangeNotifierProvider.value(value: viewListNotifier)],
+      providers: [ChangeNotifierProvider.value(value: notifier)],
       child: Consumer(builder: (context, AppDataNotifier notifier, child) {
         return const ViewSection().padding(vertical: 8);
       }),
@@ -98,13 +97,25 @@ class AppDataNotifier extends ChangeNotifier {
   AppDataNotifier();
 
   set views(List<View>? items) {
-    _views = items ?? List.empty(growable: false);
-    notifyListeners();
+    if (items == null) {
+      if (_views.isNotEmpty) {
+        _views = List.empty(growable: false);
+        notifyListeners();
+      }
+      return;
+    }
+
+    if (_views != items) {
+      _views = items;
+      notifyListeners();
+    }
   }
 
   set selectView(View? view) {
-    _selectedView = view;
-    notifyListeners();
+    if (_selectedView != view) {
+      _selectedView = view;
+      notifyListeners();
+    }
   }
 
   get selectedView => _selectedView;

+ 1 - 1
app_flowy/packages/flowy_infra_ui/pubspec.yaml

@@ -15,7 +15,7 @@ dependencies:
   # Thirdparty packages
   textstyle_extensions: '2.0.0-nullsafety'
   dartz: '0.10.0-nullsafety.2'
-  provider: ^5.0.0
+  provider: ^6.0.1
   styled_widget: '>=0.3.1'
   equatable: '>=2.0.2'
   animations: ^2.0.0

+ 5 - 5
app_flowy/pubspec.lock

@@ -42,7 +42,7 @@ packages:
       name: bloc
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "7.0.0"
+    version: "7.2.1"
   boolean_selector:
     dependency: transitive
     description:
@@ -313,7 +313,7 @@ packages:
       name: flutter_bloc
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "7.0.1"
+    version: "7.3.1"
   flutter_colorpicker:
     dependency: "direct main"
     description:
@@ -369,7 +369,7 @@ packages:
       path: "packages/flutter-quill"
       relative: true
     source: path
-    version: "2.0.10"
+    version: "2.0.11"
   flutter_svg:
     dependency: "direct main"
     description:
@@ -710,12 +710,12 @@ packages:
     source: hosted
     version: "2.0.0"
   provider:
-    dependency: transitive
+    dependency: "direct main"
     description:
       name: provider
       url: "https://pub.dartlang.org"
     source: hosted
-    version: "5.0.0"
+    version: "6.0.1"
   pub_semver:
     dependency: transitive
     description:

+ 2 - 1
app_flowy/pubspec.yaml

@@ -50,7 +50,8 @@ dependencies:
   equatable: '>=2.0.2'
   freezed_annotation:
   get_it: '>=7.1.3'
-  flutter_bloc: '>=7.0.1'
+  flutter_bloc: '>=7.3.1'
+  provider: ^6.0.1
   path_provider: ">=1.6.24"
   window_size:
     git: