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(), + ], ), ); }