diff --git a/CHANGELOG.md b/CHANGELOG.md
index 76754fc1e..a5edbeb38 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
## [Unreleased]
+### Added
+
+- Collection: `select all` available as quick action
+
## [v1.11.0] - 2024-05-01
### Added
diff --git a/lib/model/selection.dart b/lib/model/selection.dart
index f26d0c4d9..b49ffdc0d 100644
--- a/lib/model/selection.dart
+++ b/lib/model/selection.dart
@@ -28,12 +28,15 @@ class Selection extends ChangeNotifier {
void addToSelection(Iterable items) {
if (items.isEmpty) return;
+
+ select();
_selectedItems.addAll(items);
notifyListeners();
}
void removeFromSelection(Iterable items) {
if (items.isEmpty) return;
+
_selectedItems.removeAll(items);
notifyListeners();
}
diff --git a/lib/widgets/collection/app_bar.dart b/lib/widgets/collection/app_bar.dart
index 20aa7c3d8..30b19b9d4 100644
--- a/lib/widgets/collection/app_bar.dart
+++ b/lib/widgets/collection/app_bar.dart
@@ -379,7 +379,8 @@ class _CollectionAppBarState extends State with SingleTickerPr
final browsingQuickActions = settings.collectionBrowsingQuickActions;
final selectionQuickActions = isTrash ? [EntrySetAction.delete, EntrySetAction.restore] : settings.collectionSelectionQuickActions;
- final quickActionButtons = (isSelecting ? selectionQuickActions : browsingQuickActions).where(isVisible).map(
+ final quickActions = isSelecting ? selectionQuickActions : browsingQuickActions;
+ final quickActionButtons = quickActions.where(isVisible).map(
(action) => _buildButtonIcon(context, action, enabled: canApply(action), selection: selection),
);
@@ -390,13 +391,13 @@ class _CollectionAppBarState extends State with SingleTickerPr
// key is expected by test driver
key: const Key('appbar-menu-button'),
itemBuilder: (context) {
- final generalMenuItems = EntrySetActions.general.where(isVisible).map(
+ bool _isValidForMenu(EntrySetAction? v) => v == null || (!quickActions.contains(v) && isVisible(v));
+ final generalMenuItems = EntrySetActions.general.where(_isValidForMenu).map(
(action) => _toMenuItem(action, enabled: canApply(action), selection: selection),
);
- final browsingMenuActions = EntrySetActions.pageBrowsing.where((v) => !browsingQuickActions.contains(v));
- final selectionMenuActions = EntrySetActions.pageSelection.where((v) => !selectionQuickActions.contains(v));
- final contextualMenuActions = (isSelecting ? selectionMenuActions : browsingMenuActions).where((v) => v == null || isVisible(v)).fold([], (prev, v) {
+ final allContextualActions = isSelecting ? EntrySetActions.pageSelection: EntrySetActions.pageBrowsing;
+ final contextualMenuActions = allContextualActions.where(_isValidForMenu).fold([], (prev, v) {
if (v == null && (prev.isEmpty || prev.last == null)) return prev;
return [...prev, v];
});
diff --git a/lib/widgets/collection/entry_set_action_delegate.dart b/lib/widgets/collection/entry_set_action_delegate.dart
index 3abf41f8c..23f444808 100644
--- a/lib/widgets/collection/entry_set_action_delegate.dart
+++ b/lib/widgets/collection/entry_set_action_delegate.dart
@@ -66,7 +66,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
case EntrySetAction.select:
return appMode.canSelectMedia && !isSelecting;
case EntrySetAction.selectAll:
- return isSelecting && selectedItemCount < itemCount;
+ return (isSelecting && selectedItemCount < itemCount) || (!isSelecting && settings.collectionBrowsingQuickActions.contains(action));
case EntrySetAction.selectNone:
return isSelecting && selectedItemCount == itemCount;
// browsing
@@ -127,7 +127,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
case EntrySetAction.select:
return hasItems;
case EntrySetAction.selectAll:
- return selectedItemCount < itemCount;
+ return selectedItemCount < itemCount || (!isSelecting && settings.collectionBrowsingQuickActions.contains(action));
case EntrySetAction.selectNone:
return hasSelection;
case EntrySetAction.searchCollection:
diff --git a/lib/widgets/settings/privacy/hidden_items_page.dart b/lib/widgets/settings/privacy/hidden_items_page.dart
index 5006f979c..2d88c27d3 100644
--- a/lib/widgets/settings/privacy/hidden_items_page.dart
+++ b/lib/widgets/settings/privacy/hidden_items_page.dart
@@ -102,7 +102,6 @@ class _HiddenFilters extends StatelessWidget {
children: [
Expanded(
child: LayoutBuilder(builder: (context, constraints) {
- debugPrint('TLAD constraints=$constraints');
return Row(
children: [
AvesFilterChip(
diff --git a/lib/widgets/settings/thumbnails/collection_actions_editor_page.dart b/lib/widgets/settings/thumbnails/collection_actions_editor_page.dart
index c16762cd7..0741b39c5 100644
--- a/lib/widgets/settings/thumbnails/collection_actions_editor_page.dart
+++ b/lib/widgets/settings/thumbnails/collection_actions_editor_page.dart
@@ -19,7 +19,9 @@ class CollectionActionEditorPage extends StatelessWidget {
Tab(text: l10n.settingsCollectionQuickActionTabBrowsing),
QuickActionEditorBody(
bannerText: context.l10n.settingsCollectionBrowsingQuickActionEditorBanner,
- allAvailableActions: const [EntrySetActions.collectionEditorBrowsing],
+ allAvailableActions: const [
+ EntrySetActions.collectionEditorBrowsing,
+ ],
actionIcon: (action) => action.getIcon(),
actionText: (context, action) => action.getText(context),
load: () => settings.collectionBrowsingQuickActions,
diff --git a/plugins/aves_model/lib/src/actions/entry_set.dart b/plugins/aves_model/lib/src/actions/entry_set.dart
index 0cf289223..171497d6a 100644
--- a/plugins/aves_model/lib/src/actions/entry_set.dart
+++ b/plugins/aves_model/lib/src/actions/entry_set.dart
@@ -65,6 +65,8 @@ class EntrySetActions {
EntrySetAction.map,
EntrySetAction.slideshow,
EntrySetAction.stats,
+ // only available as a quick action
+ EntrySetAction.selectAll,
];
// `null` items are converted to dividers
@@ -98,6 +100,7 @@ class EntrySetActions {
EntrySetAction.map,
EntrySetAction.slideshow,
EntrySetAction.stats,
+ EntrySetAction.selectAll,
// editing actions are in their subsection
];