diff --git a/CHANGELOG.md b/CHANGELOG.md
index c1f2f4ffd..4b2858f33 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+### Fixed
+
+- Accessibility: navigation with TalkBack
+
## [v1.8.2] - 2023-02-28
### Added
diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart
index 684a5629b..d9206938a 100644
--- a/lib/widgets/collection/app_bar.dart
+++ b/lib/widgets/collection/app_bar.dart
@@ -23,7 +23,9 @@ import 'package:aves/widgets/common/action_controls/togglers/favourite.dart';
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/container.dart';
+import 'package:aves/widgets/common/basic/popup/expansion_panel.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_app_bar.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
@@ -405,19 +407,15 @@ class _CollectionAppBarState extends State with SingleTickerPr
},
),
if (isSelecting && !settings.isReadOnly && appMode == AppMode.main && !isTrash)
- PopupMenuItem(
+ PopupMenuExpansionPanel(
enabled: hasSelection,
- padding: EdgeInsets.zero,
- child: PopupMenuItemExpansionPanel(
- enabled: hasSelection,
- value: 'edit',
- icon: AIcons.edit,
- title: context.l10n.collectionActionEdit,
- items: [
- _buildRotateAndFlipMenuItems(context, canApply: canApply),
- ...EntrySetActions.edit.where((v) => isVisible(v) && !selectionQuickActions.contains(v)).map((action) => _toMenuItem(action, enabled: canApply(action), selection: selection)),
- ],
- ),
+ value: 'edit',
+ icon: AIcons.edit,
+ title: context.l10n.collectionActionEdit,
+ items: [
+ _buildRotateAndFlipMenuItems(context, canApply: canApply),
+ ...EntrySetActions.edit.where((v) => isVisible(v) && !selectionQuickActions.contains(v)).map((action) => _toMenuItem(action, enabled: canApply(action), selection: selection)),
+ ],
),
];
@@ -529,7 +527,7 @@ class _CollectionAppBarState extends State with SingleTickerPr
);
}
- PopupMenuItem _buildRotateAndFlipMenuItems(
+ PopupMenuEntry _buildRotateAndFlipMenuItems(
BuildContext context, {
required bool Function(EntrySetAction action) canApply,
}) {
@@ -558,22 +556,17 @@ class _CollectionAppBarState extends State with SingleTickerPr
),
);
- return PopupMenuItem(
- child: TooltipTheme(
- data: TooltipTheme.of(context).copyWith(
- preferBelow: false,
- ),
- child: Row(
- children: [
- buildDivider(),
- buildItem(EntrySetAction.rotateCCW),
- buildDivider(),
- buildItem(EntrySetAction.rotateCW),
- buildDivider(),
- buildItem(EntrySetAction.flip),
- buildDivider(),
- ],
- ),
+ return PopupMenuItemContainer(
+ child: Row(
+ children: [
+ buildDivider(),
+ buildItem(EntrySetAction.rotateCCW),
+ buildDivider(),
+ buildItem(EntrySetAction.rotateCW),
+ buildDivider(),
+ buildItem(EntrySetAction.flip),
+ buildDivider(),
+ ],
),
);
}
diff --git a/lib/widgets/common/action_controls/quick_choosers/common/button.dart b/lib/widgets/common/action_controls/quick_choosers/common/button.dart
index 4dcd42334..eddc578a2 100644
--- a/lib/widgets/common/action_controls/quick_choosers/common/button.dart
+++ b/lib/widgets/common/action_controls/quick_choosers/common/button.dart
@@ -56,6 +56,19 @@ abstract class ChooserQuickButtonState, U> exten
Widget build(BuildContext context) {
final _hasChooser = hasChooser;
+ Widget child = IconButton(
+ icon: icon,
+ onPressed: widget.onPressed,
+ focusNode: widget.focusNode,
+ tooltip: _hasChooser ? null : tooltip,
+ );
+ if (_hasChooser) {
+ child = Semantics(
+ tooltip: tooltip,
+ child: child,
+ );
+ }
+
return GestureDetector(
behavior: HitTestBehavior.opaque,
onLongPressStart: _hasChooser ? _showChooser : null,
@@ -70,12 +83,7 @@ abstract class ChooserQuickButtonState, U> exten
}
: null,
onLongPressCancel: _clearChooserOverlayEntry,
- child: IconButton(
- icon: icon,
- onPressed: widget.onPressed,
- focusNode: widget.focusNode,
- tooltip: _hasChooser ? null : tooltip,
- ),
+ child: child,
);
}
diff --git a/lib/widgets/common/action_controls/quick_choosers/share_chooser.dart b/lib/widgets/common/action_controls/quick_choosers/share_chooser.dart
index 3600877e6..d9d8e6176 100644
--- a/lib/widgets/common/action_controls/quick_choosers/share_chooser.dart
+++ b/lib/widgets/common/action_controls/quick_choosers/share_chooser.dart
@@ -2,7 +2,7 @@ import 'dart:async';
import 'package:aves/model/actions/share_actions.dart';
import 'package:aves/widgets/common/action_controls/quick_choosers/common/menu.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:flutter/material.dart';
class ShareQuickChooser extends StatelessWidget {
diff --git a/lib/widgets/common/action_controls/togglers/favourite.dart b/lib/widgets/common/action_controls/togglers/favourite.dart
index c19c646d1..510853037 100644
--- a/lib/widgets/common/action_controls/togglers/favourite.dart
+++ b/lib/widgets/common/action_controls/togglers/favourite.dart
@@ -2,7 +2,7 @@ import 'package:aves/model/entry.dart';
import 'package:aves/model/favourites.dart';
import 'package:aves/theme/colors.dart';
import 'package:aves/theme/icons.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/fx/sweeper.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
diff --git a/lib/widgets/common/action_controls/togglers/mute.dart b/lib/widgets/common/action_controls/togglers/mute.dart
index e42bcab80..7eec6faac 100644
--- a/lib/widgets/common/action_controls/togglers/mute.dart
+++ b/lib/widgets/common/action_controls/togglers/mute.dart
@@ -1,7 +1,7 @@
import 'dart:async';
import 'package:aves/theme/icons.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
import 'package:aves/widgets/viewer/video/controller.dart';
diff --git a/lib/widgets/common/action_controls/togglers/play.dart b/lib/widgets/common/action_controls/togglers/play.dart
index 354da0ddf..e2f5bbe6b 100644
--- a/lib/widgets/common/action_controls/togglers/play.dart
+++ b/lib/widgets/common/action_controls/togglers/play.dart
@@ -2,7 +2,7 @@ import 'dart:async';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
import 'package:aves/widgets/viewer/video/controller.dart';
diff --git a/lib/widgets/common/action_controls/togglers/title_search.dart b/lib/widgets/common/action_controls/togglers/title_search.dart
index dfe577994..b7badcd93 100644
--- a/lib/widgets/common/action_controls/togglers/title_search.dart
+++ b/lib/widgets/common/action_controls/togglers/title_search.dart
@@ -1,6 +1,6 @@
import 'package:aves/model/query.dart';
import 'package:aves/theme/icons.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
import 'package:flutter/material.dart';
diff --git a/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart b/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart
index 564ed445b..0813a93a3 100644
--- a/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart
+++ b/lib/widgets/common/basic/draggable_scrollbar/scrollbar.dart
@@ -212,37 +212,40 @@ class _DraggableScrollbarState extends State with TickerProv
),
);
}),
- RepaintBoundary(
- child: GestureDetector(
- onLongPressStart: (details) {
- _longPressLastGlobalPosition = details.globalPosition;
- _onVerticalDragStart();
- },
- onLongPressMoveUpdate: (details) {
- final dy = (details.globalPosition - _longPressLastGlobalPosition).dy;
- _longPressLastGlobalPosition = details.globalPosition;
- _onVerticalDragUpdate(dy);
- },
- onLongPressEnd: (_) => _onVerticalDragEnd(),
- onVerticalDragStart: (_) => _onVerticalDragStart(),
- onVerticalDragUpdate: (details) => _onVerticalDragUpdate(details.delta.dy),
- onVerticalDragEnd: (_) => _onVerticalDragEnd(),
- child: ValueListenableBuilder(
- valueListenable: _thumbOffsetNotifier,
- builder: (context, thumbOffset, child) => Container(
- alignment: AlignmentDirectional.topEnd,
- padding: EdgeInsets.only(top: thumbOffset) + widget.padding,
- child: widget.scrollThumbBuilder(
- widget.backgroundColor,
- _thumbAnimation,
- _labelAnimation,
- widget.scrollThumbSize.height,
- labelText: _isDragInProcess
- ? ValueListenableBuilder(
- valueListenable: _viewOffsetNotifier,
- builder: (context, viewOffset, child) => widget.labelTextBuilder(viewOffset + thumbOffset),
- )
- : null,
+ // exclude semantics, otherwise this layer will block access to content layers below when using TalkBack
+ ExcludeSemantics(
+ child: RepaintBoundary(
+ child: GestureDetector(
+ onLongPressStart: (details) {
+ _longPressLastGlobalPosition = details.globalPosition;
+ _onVerticalDragStart();
+ },
+ onLongPressMoveUpdate: (details) {
+ final dy = (details.globalPosition - _longPressLastGlobalPosition).dy;
+ _longPressLastGlobalPosition = details.globalPosition;
+ _onVerticalDragUpdate(dy);
+ },
+ onLongPressEnd: (_) => _onVerticalDragEnd(),
+ onVerticalDragStart: (_) => _onVerticalDragStart(),
+ onVerticalDragUpdate: (details) => _onVerticalDragUpdate(details.delta.dy),
+ onVerticalDragEnd: (_) => _onVerticalDragEnd(),
+ child: ValueListenableBuilder(
+ valueListenable: _thumbOffsetNotifier,
+ builder: (context, thumbOffset, child) => Container(
+ alignment: AlignmentDirectional.topEnd,
+ padding: EdgeInsets.only(top: thumbOffset) + widget.padding,
+ child: widget.scrollThumbBuilder(
+ widget.backgroundColor,
+ _thumbAnimation,
+ _labelAnimation,
+ widget.scrollThumbSize.height,
+ labelText: _isDragInProcess
+ ? ValueListenableBuilder(
+ valueListenable: _viewOffsetNotifier,
+ builder: (context, viewOffset, child) => widget.labelTextBuilder(viewOffset + thumbOffset),
+ )
+ : null,
+ ),
),
),
),
diff --git a/lib/widgets/common/basic/popup/container.dart b/lib/widgets/common/basic/popup/container.dart
new file mode 100644
index 000000000..eaa767536
--- /dev/null
+++ b/lib/widgets/common/basic/popup/container.dart
@@ -0,0 +1,35 @@
+import 'package:flutter/material.dart';
+
+class PopupMenuItemContainer extends PopupMenuEntry {
+ final Widget child;
+
+ const PopupMenuItemContainer({
+ super.key,
+ this.height = kMinInteractiveDimension,
+ required this.child,
+ });
+
+ @override
+ final double height;
+
+ @override
+ bool represents(void value) => false;
+
+ @override
+ State createState() => _TransitionPopupMenuItemState();
+}
+
+class _TransitionPopupMenuItemState extends State {
+ @override
+ Widget build(BuildContext context) {
+ return TooltipTheme(
+ data: TooltipTheme.of(context).copyWith(
+ preferBelow: false,
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: 16),
+ child: widget.child,
+ ),
+ );
+ }
+}
diff --git a/lib/widgets/common/basic/menu.dart b/lib/widgets/common/basic/popup/expansion_panel.dart
similarity index 55%
rename from lib/widgets/common/basic/menu.dart
rename to lib/widgets/common/basic/popup/expansion_panel.dart
index d25e30b83..50b887c3f 100644
--- a/lib/widgets/common/basic/menu.dart
+++ b/lib/widgets/common/basic/popup/expansion_panel.dart
@@ -1,62 +1,9 @@
import 'package:aves/theme/durations.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
-class MenuRow extends StatelessWidget {
- final String text;
- final Widget? icon;
-
- const MenuRow({
- super.key,
- required this.text,
- this.icon,
- });
-
- @override
- Widget build(BuildContext context) {
- return Row(
- mainAxisSize: MainAxisSize.min,
- children: [
- if (icon != null)
- Padding(
- padding: const EdgeInsetsDirectional.only(end: 12),
- child: IconTheme.merge(
- data: IconThemeData(
- color: ListTileTheme.of(context).iconColor,
- ),
- child: icon!,
- ),
- ),
- Flexible(
- child: Text(text),
- ),
- ],
- );
- }
-}
-
-// scale icons according to text scale
-class MenuIconTheme extends StatelessWidget {
- final Widget child;
-
- const MenuIconTheme({
- super.key,
- required this.child,
- });
-
- @override
- Widget build(BuildContext context) {
- final iconTheme = IconTheme.of(context);
- return IconTheme(
- data: iconTheme.copyWith(
- size: iconTheme.size! * MediaQuery.textScaleFactorOf(context),
- ),
- child: child,
- );
- }
-}
-
-class PopupMenuItemExpansionPanel extends StatefulWidget {
+class PopupMenuExpansionPanel extends PopupMenuEntry {
final bool enabled;
final String value;
final ValueNotifier expandedNotifier;
@@ -64,9 +11,10 @@ class PopupMenuItemExpansionPanel extends StatefulWidget {
final String title;
final List> items;
- PopupMenuItemExpansionPanel({
+ PopupMenuExpansionPanel({
super.key,
this.enabled = true,
+ this.height = kMinInteractiveDimension,
required this.value,
ValueNotifier? expandedNotifier,
required this.icon,
@@ -75,10 +23,16 @@ class PopupMenuItemExpansionPanel extends StatefulWidget {
}) : expandedNotifier = expandedNotifier ?? ValueNotifier(null);
@override
- State> createState() => _PopupMenuItemExpansionPanelState();
+ final double height;
+
+ @override
+ bool represents(void value) => false;
+
+ @override
+ State> createState() => _PopupMenuExpansionPanelState();
}
-class _PopupMenuItemExpansionPanelState extends State> {
+class _PopupMenuExpansionPanelState extends State> {
// ref `_kMenuHorizontalPadding` used in `PopupMenuItem`
static const double _horizontalPadding = 16;
@@ -103,16 +57,23 @@ class _PopupMenuItemExpansionPanelState extends State DefaultTextStyle(
- style: style,
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding),
- child: MenuRow(
- text: widget.title,
- icon: Icon(widget.icon),
+ headerBuilder: (context, isExpanded) {
+ return DefaultTextStyle(
+ style: style,
+ child: IconTheme.merge(
+ data: IconThemeData(
+ color: widget.enabled ? null : Theme.of(context).disabledColor,
+ ),
+ child: Padding(
+ padding: const EdgeInsets.symmetric(horizontal: _horizontalPadding),
+ child: MenuRow(
+ text: widget.title,
+ icon: Icon(widget.icon),
+ ),
+ ),
),
- ),
- ),
+ );
+ },
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
diff --git a/lib/widgets/common/basic/popup_menu_button.dart b/lib/widgets/common/basic/popup/menu_button.dart
similarity index 100%
rename from lib/widgets/common/basic/popup_menu_button.dart
rename to lib/widgets/common/basic/popup/menu_button.dart
diff --git a/lib/widgets/common/basic/popup/menu_row.dart b/lib/widgets/common/basic/popup/menu_row.dart
new file mode 100644
index 000000000..28442c841
--- /dev/null
+++ b/lib/widgets/common/basic/popup/menu_row.dart
@@ -0,0 +1,55 @@
+import 'package:flutter/material.dart';
+
+class MenuRow extends StatelessWidget {
+ final String text;
+ final Widget? icon;
+
+ const MenuRow({
+ super.key,
+ required this.text,
+ this.icon,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ return Row(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ if (icon != null)
+ Padding(
+ padding: const EdgeInsetsDirectional.only(end: 12),
+ child: IconTheme.merge(
+ data: IconThemeData(
+ color: ListTileTheme.of(context).iconColor,
+ ),
+ child: icon!,
+ ),
+ ),
+ Flexible(
+ child: Text(text),
+ ),
+ ],
+ );
+ }
+}
+
+// scale icons according to text scale
+class MenuIconTheme extends StatelessWidget {
+ final Widget child;
+
+ const MenuIconTheme({
+ super.key,
+ required this.child,
+ });
+
+ @override
+ Widget build(BuildContext context) {
+ final iconTheme = IconTheme.of(context);
+ return IconTheme(
+ data: iconTheme.copyWith(
+ size: iconTheme.size! * MediaQuery.textScaleFactorOf(context),
+ ),
+ child: child,
+ );
+ }
+}
diff --git a/lib/widgets/common/identity/aves_filter_chip.dart b/lib/widgets/common/identity/aves_filter_chip.dart
index f37f7ed5a..49062e520 100644
--- a/lib/widgets/common/identity/aves_filter_chip.dart
+++ b/lib/widgets/common/identity/aves_filter_chip.dart
@@ -14,7 +14,7 @@ import 'package:aves/theme/colors.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/collection/filter_bar.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
diff --git a/lib/widgets/debug/app_debug_page.dart b/lib/widgets/debug/app_debug_page.dart
index 63fbd4870..51d102076 100644
--- a/lib/widgets/debug/app_debug_page.dart
+++ b/lib/widgets/debug/app_debug_page.dart
@@ -8,7 +8,7 @@ import 'package:aves/model/source/collection_source.dart';
import 'package:aves/services/analysis_service.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/utils/android_file_utils.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/behaviour/pop/scope.dart';
import 'package:aves/widgets/common/behaviour/pop/tv_navigation.dart';
diff --git a/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart b/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart
index 331772cc2..5980f0993 100644
--- a/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart
+++ b/lib/widgets/dialogs/entry_editors/rename_entry_set_page.dart
@@ -7,7 +7,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/collection/collection_grid.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/grid/theme.dart';
diff --git a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart
index a391265e5..b36a59bcb 100644
--- a/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart
+++ b/lib/widgets/dialogs/pick_dialogs/album_pick_page.dart
@@ -13,7 +13,7 @@ import 'package:aves/model/vaults/details.dart';
import 'package:aves/model/vaults/vaults.dart';
import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
diff --git a/lib/widgets/filter_grids/common/app_bar.dart b/lib/widgets/filter_grids/common/app_bar.dart
index 8312628c4..1a1d7ffe6 100644
--- a/lib/widgets/filter_grids/common/app_bar.dart
+++ b/lib/widgets/filter_grids/common/app_bar.dart
@@ -11,7 +11,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/widgets/common/action_controls/togglers/title_search.dart';
import 'package:aves/widgets/common/app_bar/app_bar_subtitle.dart';
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/aves_app_bar.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
diff --git a/lib/widgets/map/map_page.dart b/lib/widgets/map/map_page.dart
index cb708fb97..be56ab1ed 100644
--- a/lib/widgets/map/map_page.dart
+++ b/lib/widgets/map/map_page.dart
@@ -18,7 +18,7 @@ import 'package:aves/utils/debouncer.dart';
import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/collection/entry_set_action_delegate.dart';
import 'package:aves/widgets/common/basic/insets.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/behaviour/routes.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
diff --git a/lib/widgets/settings/privacy/file_picker/file_picker_page.dart b/lib/widgets/settings/privacy/file_picker/file_picker_page.dart
index c20b29b25..c41580e78 100644
--- a/lib/widgets/settings/privacy/file_picker/file_picker_page.dart
+++ b/lib/widgets/settings/privacy/file_picker/file_picker_page.dart
@@ -6,7 +6,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/utils/constants.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/buttons/outlined_button.dart';
diff --git a/lib/widgets/settings/settings_page.dart b/lib/widgets/settings/settings_page.dart
index 166ee11ed..cdb23c642 100644
--- a/lib/widgets/settings/settings_page.dart
+++ b/lib/widgets/settings/settings_page.dart
@@ -12,7 +12,7 @@ import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/action_mixins/feedback.dart';
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
import 'package:aves/widgets/common/basic/insets.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/basic/scaffold.dart';
import 'package:aves/widgets/common/behaviour/pop/scope.dart';
import 'package:aves/widgets/common/behaviour/pop/tv_navigation.dart';
diff --git a/lib/widgets/viewer/info/info_app_bar.dart b/lib/widgets/viewer/info/info_app_bar.dart
index 03ccc2f30..1b2bb745e 100644
--- a/lib/widgets/viewer/info/info_app_bar.dart
+++ b/lib/widgets/viewer/info/info_app_bar.dart
@@ -6,7 +6,7 @@ import 'package:aves/theme/durations.dart';
import 'package:aves/theme/icons.dart';
import 'package:aves/widgets/common/app_bar/app_bar_title.dart';
import 'package:aves/widgets/common/app_bar/sliver_app_bar_title.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
import 'package:aves/widgets/viewer/info/info_search.dart';
diff --git a/lib/widgets/viewer/overlay/viewer_buttons.dart b/lib/widgets/viewer/overlay/viewer_buttons.dart
index a02bb9899..bd1342a86 100644
--- a/lib/widgets/viewer/overlay/viewer_buttons.dart
+++ b/lib/widgets/viewer/overlay/viewer_buttons.dart
@@ -11,8 +11,10 @@ import 'package:aves/widgets/common/action_controls/quick_choosers/tag_button.da
import 'package:aves/widgets/common/action_controls/togglers/favourite.dart';
import 'package:aves/widgets/common/action_controls/togglers/mute.dart';
import 'package:aves/widgets/common/action_controls/togglers/play.dart';
-import 'package:aves/widgets/common/basic/menu.dart';
-import 'package:aves/widgets/common/basic/popup_menu_button.dart';
+import 'package:aves/widgets/common/basic/popup/container.dart';
+import 'package:aves/widgets/common/basic/popup/expansion_panel.dart';
+import 'package:aves/widgets/common/basic/popup/menu_button.dart';
+import 'package:aves/widgets/common/basic/popup/menu_row.dart';
import 'package:aves/widgets/common/extensions/build_context.dart';
import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
import 'package:aves/widgets/common/identity/buttons/overlay_button.dart';
@@ -231,32 +233,26 @@ class ViewerButtonRowContent extends StatelessWidget {
if (pageEntry.canRotate || pageEntry.canFlip) _buildRotateAndFlipMenuItems(context),
...topLevelActions.map((action) => _buildPopupMenuItem(context, action, videoController)),
if (exportActions.isNotEmpty)
- PopupMenuItem(
- padding: EdgeInsets.zero,
- child: PopupMenuItemExpansionPanel(
- value: 'export',
- expandedNotifier: _popupExpandedNotifier,
- icon: AIcons.export,
- title: context.l10n.entryActionExport,
- items: [
- ...exportInternalActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(),
- if (exportInternalActions.isNotEmpty && exportExternalActions.isNotEmpty) const PopupMenuDivider(height: 0),
- ...exportExternalActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(),
- ],
- ),
+ PopupMenuExpansionPanel(
+ value: 'export',
+ expandedNotifier: _popupExpandedNotifier,
+ icon: AIcons.export,
+ title: context.l10n.entryActionExport,
+ items: [
+ ...exportInternalActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(),
+ if (exportInternalActions.isNotEmpty && exportExternalActions.isNotEmpty) const PopupMenuDivider(height: 0),
+ ...exportExternalActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(),
+ ],
),
if (videoActions.isNotEmpty)
- PopupMenuItem(
- padding: EdgeInsets.zero,
- child: PopupMenuItemExpansionPanel(
- value: 'video',
- expandedNotifier: _popupExpandedNotifier,
- icon: AIcons.video,
- title: context.l10n.settingsVideoSectionTitle,
- items: [
- ...videoActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(),
- ],
- ),
+ PopupMenuExpansionPanel(
+ value: 'video',
+ expandedNotifier: _popupExpandedNotifier,
+ icon: AIcons.video,
+ title: context.l10n.settingsVideoSectionTitle,
+ items: [
+ ...videoActions.map((action) => _buildPopupMenuItem(context, action, videoController)).toList(),
+ ],
),
if (!kReleaseMode) ...[
const PopupMenuDivider(),
@@ -357,7 +353,7 @@ class ViewerButtonRowContent extends StatelessWidget {
);
}
- PopupMenuItem _buildRotateAndFlipMenuItems(BuildContext context) {
+ PopupMenuEntry _buildRotateAndFlipMenuItems(BuildContext context) {
Widget buildDivider() => const SizedBox(
height: 16,
child: VerticalDivider(
@@ -383,29 +379,17 @@ class ViewerButtonRowContent extends StatelessWidget {
),
);
- return PopupMenuItem(
- padding: EdgeInsets.zero,
- child: IconTheme.merge(
- data: IconThemeData(
- color: ListTileTheme.of(context).iconColor,
- ),
- child: ColoredBox(
- color: PopupMenuTheme.of(context).color!,
- child: Padding(
- padding: const EdgeInsets.symmetric(horizontal: 16),
- child: Row(
- children: [
- buildDivider(),
- buildItem(EntryAction.rotateCCW),
- buildDivider(),
- buildItem(EntryAction.rotateCW),
- buildDivider(),
- buildItem(EntryAction.flip),
- buildDivider(),
- ],
- ),
- ),
- ),
+ return PopupMenuItemContainer(
+ child: Row(
+ children: [
+ buildDivider(),
+ buildItem(EntryAction.rotateCCW),
+ buildDivider(),
+ buildItem(EntryAction.rotateCW),
+ buildDivider(),
+ buildItem(EntryAction.flip),
+ buildDivider(),
+ ],
),
);
}