viewer: expand one submenu at once
This commit is contained in:
parent
9bced31927
commit
1f3a81e243
3 changed files with 52 additions and 35 deletions
|
@ -284,6 +284,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
child: PopupMenuItemExpansionPanel<EntrySetAction>(
|
child: PopupMenuItemExpansionPanel<EntrySetAction>(
|
||||||
enabled: canApplyEditActions,
|
enabled: canApplyEditActions,
|
||||||
|
value: 'edit',
|
||||||
icon: AIcons.edit,
|
icon: AIcons.edit,
|
||||||
title: context.l10n.collectionActionEdit,
|
title: context.l10n.collectionActionEdit,
|
||||||
items: [
|
items: [
|
||||||
|
|
|
@ -55,25 +55,27 @@ class MenuIconTheme extends StatelessWidget {
|
||||||
|
|
||||||
class PopupMenuItemExpansionPanel<T> extends StatefulWidget {
|
class PopupMenuItemExpansionPanel<T> extends StatefulWidget {
|
||||||
final bool enabled;
|
final bool enabled;
|
||||||
|
final String value;
|
||||||
|
final ValueNotifier<String?> expandedNotifier;
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
final String title;
|
final String title;
|
||||||
final List<PopupMenuEntry<T>> items;
|
final List<PopupMenuEntry<T>> items;
|
||||||
|
|
||||||
const PopupMenuItemExpansionPanel({
|
PopupMenuItemExpansionPanel({
|
||||||
super.key,
|
super.key,
|
||||||
this.enabled = true,
|
this.enabled = true,
|
||||||
|
required this.value,
|
||||||
|
ValueNotifier<String?>? expandedNotifier,
|
||||||
required this.icon,
|
required this.icon,
|
||||||
required this.title,
|
required this.title,
|
||||||
required this.items,
|
required this.items,
|
||||||
});
|
}) : expandedNotifier = expandedNotifier ?? ValueNotifier(null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<PopupMenuItemExpansionPanel<T>> createState() => _PopupMenuItemExpansionPanelState<T>();
|
State<PopupMenuItemExpansionPanel<T>> createState() => _PopupMenuItemExpansionPanelState<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PopupMenuItemExpansionPanelState<T> extends State<PopupMenuItemExpansionPanel<T>> {
|
class _PopupMenuItemExpansionPanelState<T> extends State<PopupMenuItemExpansionPanel<T>> {
|
||||||
bool _isExpanded = false;
|
|
||||||
|
|
||||||
// ref `_kMenuHorizontalPadding` used in `PopupMenuItem`
|
// ref `_kMenuHorizontalPadding` used in `PopupMenuItem`
|
||||||
static const double _horizontalPadding = 16;
|
static const double _horizontalPadding = 16;
|
||||||
|
|
||||||
|
@ -86,38 +88,43 @@ class _PopupMenuItemExpansionPanelState<T> extends State<PopupMenuItemExpansionP
|
||||||
}
|
}
|
||||||
final animationDuration = context.select<DurationsData, Duration>((v) => v.expansionTileAnimation);
|
final animationDuration = context.select<DurationsData, Duration>((v) => v.expansionTileAnimation);
|
||||||
|
|
||||||
Widget child = ExpansionPanelList(
|
Widget child = ValueListenableBuilder<String?>(
|
||||||
expansionCallback: (index, isExpanded) {
|
valueListenable: widget.expandedNotifier,
|
||||||
setState(() => _isExpanded = !isExpanded);
|
builder: (context, expandedValue, child) {
|
||||||
},
|
return ExpansionPanelList(
|
||||||
animationDuration: animationDuration,
|
expansionCallback: (index, isExpanded) {
|
||||||
expandedHeaderPadding: EdgeInsets.zero,
|
widget.expandedNotifier.value = isExpanded ? null : widget.value;
|
||||||
elevation: 0,
|
},
|
||||||
children: [
|
animationDuration: animationDuration,
|
||||||
ExpansionPanel(
|
expandedHeaderPadding: EdgeInsets.zero,
|
||||||
headerBuilder: (context, isExpanded) => DefaultTextStyle(
|
elevation: 0,
|
||||||
style: style,
|
children: [
|
||||||
child: Padding(
|
ExpansionPanel(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding),
|
headerBuilder: (context, isExpanded) => DefaultTextStyle(
|
||||||
child: MenuRow(
|
style: style,
|
||||||
text: widget.title,
|
child: Padding(
|
||||||
icon: Icon(widget.icon),
|
padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding),
|
||||||
|
child: MenuRow(
|
||||||
|
text: widget.title,
|
||||||
|
icon: Icon(widget.icon),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const PopupMenuDivider(height: 0),
|
||||||
|
...widget.items,
|
||||||
|
const PopupMenuDivider(height: 0),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
isExpanded: expandedValue == widget.value,
|
||||||
|
canTapOnHeader: true,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
body: Column(
|
);
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
},
|
||||||
children: [
|
|
||||||
const PopupMenuDivider(height: 0),
|
|
||||||
...widget.items,
|
|
||||||
const PopupMenuDivider(height: 0),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
isExpanded: _isExpanded,
|
|
||||||
canTapOnHeader: true,
|
|
||||||
backgroundColor: Colors.transparent,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
if (!widget.enabled) {
|
if (!widget.enabled) {
|
||||||
child = IgnorePointer(child: child);
|
child = IgnorePointer(child: child);
|
||||||
|
|
|
@ -142,12 +142,13 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
final List<EntryAction> quickActions, topLevelActions, exportActions, videoActions;
|
final List<EntryAction> quickActions, topLevelActions, exportActions, videoActions;
|
||||||
final Animation<double> scale;
|
final Animation<double> scale;
|
||||||
final AvesEntry mainEntry, pageEntry;
|
final AvesEntry mainEntry, pageEntry;
|
||||||
|
final ValueNotifier<String?> _popupExpandedNotifier = ValueNotifier(null);
|
||||||
|
|
||||||
AvesEntry get favouriteTargetEntry => mainEntry.isBurst ? pageEntry : mainEntry;
|
AvesEntry get favouriteTargetEntry => mainEntry.isBurst ? pageEntry : mainEntry;
|
||||||
|
|
||||||
static const double padding = 8;
|
static const double padding = 8;
|
||||||
|
|
||||||
const ViewerButtonRowContent({
|
ViewerButtonRowContent({
|
||||||
super.key,
|
super.key,
|
||||||
required this.quickActions,
|
required this.quickActions,
|
||||||
required this.topLevelActions,
|
required this.topLevelActions,
|
||||||
|
@ -188,6 +189,8 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
PopupMenuItem<EntryAction>(
|
PopupMenuItem<EntryAction>(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
child: PopupMenuItemExpansionPanel<EntryAction>(
|
child: PopupMenuItemExpansionPanel<EntryAction>(
|
||||||
|
value: 'export',
|
||||||
|
expandedNotifier: _popupExpandedNotifier,
|
||||||
icon: AIcons.export,
|
icon: AIcons.export,
|
||||||
title: context.l10n.entryActionExport,
|
title: context.l10n.entryActionExport,
|
||||||
items: [
|
items: [
|
||||||
|
@ -201,6 +204,8 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
PopupMenuItem<EntryAction>(
|
PopupMenuItem<EntryAction>(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
child: PopupMenuItemExpansionPanel<EntryAction>(
|
child: PopupMenuItemExpansionPanel<EntryAction>(
|
||||||
|
value: 'video',
|
||||||
|
expandedNotifier: _popupExpandedNotifier,
|
||||||
icon: AIcons.video,
|
icon: AIcons.video,
|
||||||
title: context.l10n.settingsSectionVideo,
|
title: context.l10n.settingsSectionVideo,
|
||||||
items: [
|
items: [
|
||||||
|
@ -215,9 +220,13 @@ class ViewerButtonRowContent extends StatelessWidget {
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
onSelected: (action) {
|
onSelected: (action) {
|
||||||
|
_popupExpandedNotifier.value = null;
|
||||||
// wait for the popup menu to hide before proceeding with the action
|
// wait for the popup menu to hide before proceeding with the action
|
||||||
Future.delayed(Durations.popupMenuAnimation * timeDilation, () => _onActionSelected(context, action));
|
Future.delayed(Durations.popupMenuAnimation * timeDilation, () => _onActionSelected(context, action));
|
||||||
},
|
},
|
||||||
|
onCanceled: () {
|
||||||
|
_popupExpandedNotifier.value = null;
|
||||||
|
},
|
||||||
onMenuOpened: () {
|
onMenuOpened: () {
|
||||||
// if the menu is opened while overlay is hiding,
|
// if the menu is opened while overlay is hiding,
|
||||||
// the popup menu button is disposed and menu items are ineffective,
|
// the popup menu button is disposed and menu items are ineffective,
|
||||||
|
|
Loading…
Reference in a new issue