Add a Settings option to reorder the selection action bar's actions

NooSelectionBar's fixed inline slots (3 mobile / 4 desktop, the rest
behind "More") previously just took the first N actions in whatever
order each screen happened to build them in. Give bulk actions a
stable SelectionActionKind identity (independent of their dynamic
icon/label, e.g. favorite vs. unfavorite) so Settings can offer a
drag-to-reorder list - mirroring the existing Tabs section, minus the
pin/hide concept, which doesn't apply here - and each screen applies
that saved priority order via orderSelectionActions before handing
its action list to the bar.
This commit is contained in:
2026-09-28 12:21:36 -04:00
parent 800e8ebf44
commit 254db255a7
10 changed files with 347 additions and 27 deletions
+41
View File
@@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../models/app_tab.dart';
import '../models/selection_action.dart';
import '../theme/app_theme.dart';
/// What swiping a Files list-view item left/right does, user-configurable
@@ -24,6 +25,7 @@ class SettingsController extends ChangeNotifier {
static const _prefUseDynamicColor = 'ui_use_dynamic_color';
static const _prefSeedColor = 'ui_seed_color';
static const _prefTabOrder = 'ui_tab_order';
static const _prefSelectionActionOrder = 'ui_selection_action_order';
static const _prefHiddenTabs = 'ui_hidden_tabs';
static const _prefDefaultTab = 'ui_default_tab';
static const _prefSwipeLeftAction = 'ui_swipe_left_action';
@@ -47,6 +49,9 @@ class SettingsController extends ChangeNotifier {
Set<AppTab> _hiddenTabs = {};
AppTab _defaultTab = AppTab.files;
List<SelectionActionKind> _selectionActionOrder = SelectionActionKind.values
.toList();
SwipeAction _swipeLeftAction = SwipeAction.delete;
SwipeAction _swipeRightAction = SwipeAction.favorite;
@@ -86,6 +91,12 @@ class SettingsController extends ChangeNotifier {
Set<AppTab> get hiddenTabs => _hiddenTabs;
AppTab get defaultTab => _defaultTab;
/// The priority order bulk actions (favorite, share, download, ...) show
/// in on the multi-select action bar - see [orderSelectionActions]. Every
/// [SelectionActionKind] is always present here (nothing is hidden, only
/// reordered), so [NooSelectionBar]'s fixed inline slots are always full.
List<SelectionActionKind> get selectionActionOrder => _selectionActionOrder;
/// The tabs the bottom nav bar should actually show, in order.
List<AppTab> get visibleTabs =>
_tabOrder.where((t) => !_hiddenTabs.contains(t)).toList();
@@ -134,6 +145,25 @@ class SettingsController extends ChangeNotifier {
_tabOrder = order;
}
final savedActionOrderNames = prefs.getStringList(
_prefSelectionActionOrder,
);
if (savedActionOrderNames != null) {
final order = <SelectionActionKind>[];
for (final name in savedActionOrderNames) {
final match = SelectionActionKind.values
.where((k) => k.name == name)
.firstOrNull;
if (match != null) order.add(match);
}
// Forward-compat: a kind added in a later app update won't be in an
// older saved order yet, so append anything missing.
for (final kind in SelectionActionKind.values) {
if (!order.contains(kind)) order.add(kind);
}
_selectionActionOrder = order;
}
final savedHiddenNames = prefs.getStringList(_prefHiddenTabs);
if (savedHiddenNames != null) {
_hiddenTabs = savedHiddenNames
@@ -234,6 +264,17 @@ class SettingsController extends ChangeNotifier {
);
}
void setSelectionActionOrder(List<SelectionActionKind> order) {
_selectionActionOrder = order;
notifyListeners();
_prefsFuture.then(
(p) => p.setStringList(
_prefSelectionActionOrder,
order.map((k) => k.name).toList(),
),
);
}
/// Shows or hides a tab in the bottom nav bar. Refuses to hide the last
/// remaining visible tab. If the tab being hidden is the current default,
/// the default falls back to the next visible tab.