viewer: expand one submenu at once

This commit is contained in:
Thibault Deckers 2022-06-18 15:42:23 +09:00
parent 9bced31927
commit 1f3a81e243
3 changed files with 52 additions and 35 deletions

View file

@ -284,6 +284,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
padding: EdgeInsets.zero,
child: PopupMenuItemExpansionPanel<EntrySetAction>(
enabled: canApplyEditActions,
value: 'edit',
icon: AIcons.edit,
title: context.l10n.collectionActionEdit,
items: [

View file

@ -55,25 +55,27 @@ class MenuIconTheme extends StatelessWidget {
class PopupMenuItemExpansionPanel<T> extends StatefulWidget {
final bool enabled;
final String value;
final ValueNotifier<String?> expandedNotifier;
final IconData icon;
final String title;
final List<PopupMenuEntry<T>> items;
const PopupMenuItemExpansionPanel({
PopupMenuItemExpansionPanel({
super.key,
this.enabled = true,
required this.value,
ValueNotifier<String?>? expandedNotifier,
required this.icon,
required this.title,
required this.items,
});
}) : expandedNotifier = expandedNotifier ?? ValueNotifier(null);
@override
State<PopupMenuItemExpansionPanel<T>> createState() => _PopupMenuItemExpansionPanelState<T>();
}
class _PopupMenuItemExpansionPanelState<T> extends State<PopupMenuItemExpansionPanel<T>> {
bool _isExpanded = false;
// ref `_kMenuHorizontalPadding` used in `PopupMenuItem`
static const double _horizontalPadding = 16;
@ -86,9 +88,12 @@ class _PopupMenuItemExpansionPanelState<T> extends State<PopupMenuItemExpansionP
}
final animationDuration = context.select<DurationsData, Duration>((v) => v.expansionTileAnimation);
Widget child = ExpansionPanelList(
Widget child = ValueListenableBuilder<String?>(
valueListenable: widget.expandedNotifier,
builder: (context, expandedValue, child) {
return ExpansionPanelList(
expansionCallback: (index, isExpanded) {
setState(() => _isExpanded = !isExpanded);
widget.expandedNotifier.value = isExpanded ? null : widget.value;
},
animationDuration: animationDuration,
expandedHeaderPadding: EdgeInsets.zero,
@ -113,12 +118,14 @@ class _PopupMenuItemExpansionPanelState<T> extends State<PopupMenuItemExpansionP
const PopupMenuDivider(height: 0),
],
),
isExpanded: _isExpanded,
isExpanded: expandedValue == widget.value,
canTapOnHeader: true,
backgroundColor: Colors.transparent,
),
],
);
},
);
if (!widget.enabled) {
child = IgnorePointer(child: child);
}

View file

@ -142,12 +142,13 @@ class ViewerButtonRowContent extends StatelessWidget {
final List<EntryAction> quickActions, topLevelActions, exportActions, videoActions;
final Animation<double> scale;
final AvesEntry mainEntry, pageEntry;
final ValueNotifier<String?> _popupExpandedNotifier = ValueNotifier(null);
AvesEntry get favouriteTargetEntry => mainEntry.isBurst ? pageEntry : mainEntry;
static const double padding = 8;
const ViewerButtonRowContent({
ViewerButtonRowContent({
super.key,
required this.quickActions,
required this.topLevelActions,
@ -188,6 +189,8 @@ class ViewerButtonRowContent extends StatelessWidget {
PopupMenuItem<EntryAction>(
padding: EdgeInsets.zero,
child: PopupMenuItemExpansionPanel<EntryAction>(
value: 'export',
expandedNotifier: _popupExpandedNotifier,
icon: AIcons.export,
title: context.l10n.entryActionExport,
items: [
@ -201,6 +204,8 @@ class ViewerButtonRowContent extends StatelessWidget {
PopupMenuItem<EntryAction>(
padding: EdgeInsets.zero,
child: PopupMenuItemExpansionPanel<EntryAction>(
value: 'video',
expandedNotifier: _popupExpandedNotifier,
icon: AIcons.video,
title: context.l10n.settingsSectionVideo,
items: [
@ -215,9 +220,13 @@ class ViewerButtonRowContent extends StatelessWidget {
];
},
onSelected: (action) {
_popupExpandedNotifier.value = null;
// wait for the popup menu to hide before proceeding with the action
Future.delayed(Durations.popupMenuAnimation * timeDilation, () => _onActionSelected(context, action));
},
onCanceled: () {
_popupExpandedNotifier.value = null;
},
onMenuOpened: () {
// if the menu is opened while overlay is hiding,
// the popup menu button is disposed and menu items are ineffective,