From 74c1e3fcc655869777d43f8c5a7f510e153ef418 Mon Sep 17 00:00:00 2001 From: appflowy Date: Sun, 31 Oct 2021 14:44:33 +0800 Subject: [PATCH] [flutter]: update menu app name automatically after rename the app --- .../workspace/application/app/app_bloc.dart | 72 ++++---- .../application/app/app_bloc.freezed.dart | 162 ++++++++++++++++++ app_flowy/lib/workspace/domain/i_app.dart | 2 +- .../infrastructure/repos/app_repo.dart | 2 +- .../menu/widget/app/header/header.dart | 43 +++-- .../widgets/menu/widget/app/menu_app.dart | 43 +++-- .../packages/flowy_infra_ui/pubspec.yaml | 2 +- app_flowy/pubspec.lock | 10 +- app_flowy/pubspec.yaml | 3 +- 9 files changed, 259 insertions(+), 80 deletions(-) diff --git a/app_flowy/lib/workspace/application/app/app_bloc.dart b/app_flowy/lib/workspace/application/app/app_bloc.dart index 7cb74dd881..0bf12b0065 100644 --- a/app_flowy/lib/workspace/application/app/app_bloc.dart +++ b/app_flowy/lib/workspace/application/app/app_bloc.dart @@ -18,42 +18,41 @@ class AppBloc extends Bloc { Stream 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 views) = ReceiveViews; + const factory AppEvent.appDidUpdate(App app) = AppDidUpdate; } @freezed diff --git a/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart b/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart index ad9fadce57..c59d76a11e 100644 --- a/app_flowy/lib/workspace/application/app/app_bloc.freezed.dart +++ b/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 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 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 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 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 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 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 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 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 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 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 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 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 get copyWith => + _$AppDidUpdateCopyWithImpl(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + 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 views) didReceiveViews, + required TResult Function(App app) appDidUpdate, + }) { + return appDidUpdate(app); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function(String name, String desc, ViewType viewType)? createView, + TResult Function()? delete, + TResult Function(String newName)? rename, + TResult Function(List views)? didReceiveViews, + TResult Function(App app)? appDidUpdate, + required TResult orElse(), + }) { + if (appDidUpdate != null) { + return appDidUpdate(app); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + 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 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 get copyWith => + throw _privateConstructorUsedError; +} + /// @nodoc class _$AppStateTearOff { const _$AppStateTearOff(); diff --git a/app_flowy/lib/workspace/domain/i_app.dart b/app_flowy/lib/workspace/domain/i_app.dart index e568e12d86..34e1f1b52c 100644 --- a/app_flowy/lib/workspace/domain/i_app.dart +++ b/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, WorkspaceError> viewsOrFailed); abstract class IApp { diff --git a/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart b/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart index 92cc92a540..3663d77e1e 100644 --- a/app_flowy/lib/workspace/infrastructure/repos/app_repo.dart +++ b/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), ); diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart index 9965327b43..302b3b7000 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/header/header.dart +++ b/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( + 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, + ), + ), + ); + }, ); } diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart index fe9ffe50a5..980ce63f9f 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/widget/app/menu_app.dart @@ -29,16 +29,15 @@ class MenuApp extends MenuItem { }, ), ], - child: BlocListener( - listenWhen: (p, c) => p.selectedView != c.selectedView, - listener: (context, state) => notifier.selectView = state.selectedView, - child: BlocBuilder( - buildWhen: (p, c) => p.views != c.views, - builder: (context, state) { - notifier.views = state.views; - return expandableWrapper(context, _renderViewSection(notifier)); - }, - ), + child: BlocSelector( + 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? 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; diff --git a/app_flowy/packages/flowy_infra_ui/pubspec.yaml b/app_flowy/packages/flowy_infra_ui/pubspec.yaml index bc3293a8d3..35c3fc397a 100644 --- a/app_flowy/packages/flowy_infra_ui/pubspec.yaml +++ b/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 diff --git a/app_flowy/pubspec.lock b/app_flowy/pubspec.lock index a2887b8196..390f0bdc28 100644 --- a/app_flowy/pubspec.lock +++ b/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: diff --git a/app_flowy/pubspec.yaml b/app_flowy/pubspec.yaml index 7b2e2cde03..876f7ad3d3 100644 --- a/app_flowy/pubspec.yaml +++ b/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: