[flutter]: expand the page contains the latest opened page

This commit is contained in:
appflowy 2021-11-11 13:38:54 +08:00
parent fa683e48c0
commit 2114dd7761
3 changed files with 49 additions and 15 deletions

View File

@ -36,21 +36,30 @@ class _MenuAppState extends State<MenuApp> {
],
child: BlocSelector<AppBloc, AppState, AppDataNotifier>(
selector: (state) {
final menuState = Provider.of<MenuSharedState>(context, listen: false);
if (state.latestCreatedView != null) {
Provider.of<MenuSharedState>(context, listen: false).forcedOpenView = state.latestCreatedView;
menuState.forcedOpenView = state.latestCreatedView;
}
notifier.views = state.views;
notifier.selectedView = menuState.selectedView;
return notifier;
},
builder: (context, state) {
return expandableWrapper(context, _renderViewSection(state));
},
builder: (context, notifier) => ChangeNotifierProvider.value(
value: notifier,
child: Consumer(
builder: (BuildContext context, AppDataNotifier notifier, Widget? child) {
return expandableWrapper(context, notifier);
},
),
),
),
);
}
ExpandableNotifier expandableWrapper(BuildContext context, Widget child) {
ExpandableNotifier expandableWrapper(BuildContext context, AppDataNotifier notifier) {
return ExpandableNotifier(
controller: notifier.expandController,
child: ScrollOnExpand(
scrollOnExpand: false,
scrollOnCollapse: false,
@ -66,7 +75,7 @@ class _MenuAppState extends State<MenuApp> {
hasIcon: false,
),
header: MenuAppHeader(widget.app),
expanded: child,
expanded: _renderViewSection(notifier),
collapsed: const SizedBox(),
),
],
@ -83,6 +92,12 @@ class _MenuAppState extends State<MenuApp> {
}),
);
}
@override
void dispose() {
notifier.dispose();
super.dispose();
}
}
class MenuAppSizes {
@ -97,10 +112,24 @@ class MenuAppSizes {
class AppDataNotifier extends ChangeNotifier {
List<View> _views = [];
ExpandableController expandController = ExpandableController(initialExpanded: false);
AppDataNotifier();
set views(List<View>? items) {
if (items == null) {
set selectedView(View? selectedView) {
if (selectedView != null) {
final isExpanded = _views.contains(selectedView);
if (expandController.expanded == false && expandController.expanded != isExpanded) {
// Workaround: Delay 150 milliseconds to make the smooth animation while expanding
Future.delayed(const Duration(milliseconds: 150), () {
expandController.expanded = isExpanded;
});
}
}
}
set views(List<View>? views) {
if (views == null) {
if (_views.isNotEmpty) {
_views = List.empty(growable: false);
notifyListeners();
@ -108,8 +137,8 @@ class AppDataNotifier extends ChangeNotifier {
return;
}
if (_views != items) {
_views = items;
if (_views != views) {
_views = views;
notifyListeners();
}
}

View File

@ -28,7 +28,7 @@ class ViewSectionItem extends StatelessWidget {
required this.view,
required this.isSelected,
required this.onSelected,
}) : super(key: ValueKey(view.hashCode));
}) : super(key: ValueKey('$view.hashCode/$isSelected'));
@override
Widget build(BuildContext context) {

View File

@ -21,10 +21,12 @@ class ViewSection extends StatelessWidget {
return ChangeNotifierProxyProvider<AppDataNotifier, ViewSectionNotifier>(
create: (_) {
final views = Provider.of<AppDataNotifier>(context, listen: false).views;
final menuState = Provider.of<MenuSharedState>(context, listen: false);
return ViewSectionNotifier(
context: context,
views: views,
selectedView: Provider.of<MenuSharedState>(context, listen: false).selectedView,
initialSelectedView: menuState.selectedView,
);
},
update: (_, notifier, controller) => controller!..update(notifier),
@ -67,16 +69,19 @@ class ViewSectionNotifier with ChangeNotifier {
ViewSectionNotifier({
required BuildContext context,
required List<View> views,
View? selectedView,
View? initialSelectedView,
}) : _views = views,
_selectedView = selectedView {
_selectedView = initialSelectedView {
final menuSharedState = Provider.of<MenuSharedState>(context, listen: false);
// The forcedOpenView will be the view after creating the new view
menuSharedState.addForcedOpenViewListener((forcedOpenView) {
selectedView = forcedOpenView;
});
menuSharedState.addSelectedViewListener((currentSelectedView) {
if (currentSelectedView != selectedView) {
// Cancel the selected view of this section by setting the selectedView to null
// that will notify the listener to refresh the ViewSection UI
if (currentSelectedView != _selectedView) {
selectedView = null;
}
});