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

This commit is contained in:
appflowy 2021-10-31 14:44:33 +08:00
parent 5d0ef5baf3
commit 74c1e3fcc6
9 changed files with 259 additions and 80 deletions

View File

@ -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

View File

@ -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();

View File

@ -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 {

View File

@ -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),
);

View File

@ -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,
),
),
);
},
);
}

View File

@ -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;

View File

@ -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

View File

@ -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:

View File

@ -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: