collection: apply filter change to selection
This commit is contained in:
parent
f4cca71f07
commit
690ebce80e
4 changed files with 33 additions and 20 deletions
|
@ -5,41 +5,45 @@ class Selection<T> extends ChangeNotifier {
|
|||
|
||||
bool get isSelecting => _isSelecting;
|
||||
|
||||
final Set<T> _selection = {};
|
||||
final Set<T> _selectedItems = {};
|
||||
|
||||
Set<T> get selection => _selection;
|
||||
Set<T> get selectedItems => _selectedItems;
|
||||
|
||||
void browse() {
|
||||
if (!_isSelecting) return;
|
||||
clearSelection();
|
||||
_isSelecting = false;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void select() {
|
||||
if (_isSelecting) return;
|
||||
_isSelecting = true;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
bool isSelected(Iterable<T> items) => items.every(selection.contains);
|
||||
bool isSelected(Iterable<T> items) => items.every(selectedItems.contains);
|
||||
|
||||
void addToSelection(Iterable<T> items) {
|
||||
_selection.addAll(items);
|
||||
if (items.isEmpty) return;
|
||||
_selectedItems.addAll(items);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void removeFromSelection(Iterable<T> items) {
|
||||
_selection.removeAll(items);
|
||||
if (items.isEmpty) return;
|
||||
_selectedItems.removeAll(items);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void clearSelection() {
|
||||
_selection.clear();
|
||||
_selectedItems.clear();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void toggleSelection(T item) {
|
||||
if (_selection.isEmpty) select();
|
||||
if (!_selection.remove(item)) _selection.add(item);
|
||||
if (_selectedItems.isEmpty) select();
|
||||
if (!_selectedItems.remove(item)) _selectedItems.add(item);
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
_isSelectingNotifier.addListener(_onActivityChange);
|
||||
_canAddShortcutsLoader = AppShortcutService.canPin();
|
||||
_registerWidget(widget);
|
||||
WidgetsBinding.instance!.addPostFrameCallback((_) => _updateHeight());
|
||||
WidgetsBinding.instance!.addPostFrameCallback((_) => _onFilterChanged());
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -84,11 +84,11 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
}
|
||||
|
||||
void _registerWidget(CollectionAppBar widget) {
|
||||
widget.collection.filterChangeNotifier.addListener(_updateHeight);
|
||||
widget.collection.filterChangeNotifier.addListener(_onFilterChanged);
|
||||
}
|
||||
|
||||
void _unregisterWidget(CollectionAppBar widget) {
|
||||
widget.collection.filterChangeNotifier.removeListener(_updateHeight);
|
||||
widget.collection.filterChangeNotifier.removeListener(_onFilterChanged);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -146,7 +146,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
Widget? _buildAppBarTitle(bool isSelecting) {
|
||||
if (isSelecting) {
|
||||
return Selector<Selection<AvesEntry>, int>(
|
||||
selector: (context, selection) => selection.selection.length,
|
||||
selector: (context, selection) => selection.selectedItems.length,
|
||||
builder: (context, count, child) => Text(context.l10n.collectionSelectionPageTitle(count)),
|
||||
);
|
||||
} else {
|
||||
|
@ -175,7 +175,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
),
|
||||
if (isSelecting)
|
||||
...EntryActions.selection.map((action) => Selector<Selection<AvesEntry>, bool>(
|
||||
selector: (context, selection) => selection.selection.isEmpty,
|
||||
selector: (context, selection) => selection.selectedItems.isEmpty,
|
||||
builder: (context, isEmpty, child) => IconButton(
|
||||
icon: Icon(action.getIcon()),
|
||||
onPressed: isEmpty ? null : () => _actionDelegate.onEntryActionSelected(context, action),
|
||||
|
@ -192,7 +192,7 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
final groupable = collection.sortFactor == EntrySortFactor.date;
|
||||
final selection = context.read<Selection<AvesEntry>>();
|
||||
final isSelecting = selection.isSelecting;
|
||||
final selectedItems = selection.selection;
|
||||
final selectedItems = selection.selectedItems;
|
||||
final hasSelection = selectedItems.isNotEmpty;
|
||||
final hasItems = !collection.isEmpty;
|
||||
final otherViewEnabled = (!isSelecting && hasItems) || (isSelecting && hasSelection);
|
||||
|
@ -272,8 +272,17 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
}
|
||||
}
|
||||
|
||||
void _updateHeight() {
|
||||
void _onFilterChanged() {
|
||||
widget.appBarHeightNotifier.value = kToolbarHeight + (hasFilters ? FilterBar.preferredHeight : 0);
|
||||
|
||||
if (hasFilters) {
|
||||
final filters = collection.filters;
|
||||
final selection = context.read<Selection<AvesEntry>>();
|
||||
if (selection.isSelecting) {
|
||||
final toRemove = selection.selectedItems.where((entry) => !filters.every((f) => f.test(entry))).toSet();
|
||||
selection.removeFromSelection(toRemove);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onCollectionActionSelected(CollectionAction action) async {
|
||||
|
|
|
@ -66,7 +66,7 @@ class EntrySetActionDelegate with FeedbackMixin, PermissionAwareMixin, SizeAware
|
|||
}
|
||||
|
||||
Set<AvesEntry> _getExpandedSelectedItems(Selection<AvesEntry> selection) {
|
||||
return selection.selection.expand((entry) => entry.burstEntries ?? {entry}).toSet();
|
||||
return selection.selectedItems.expand((entry) => entry.burstEntries ?? {entry}).toSet();
|
||||
}
|
||||
|
||||
void _share(BuildContext context) {
|
||||
|
|
|
@ -111,7 +111,7 @@ class _FilterGridAppBarState<T extends CollectionFilter> extends State<FilterGri
|
|||
Widget? _buildAppBarTitle(bool isSelecting) {
|
||||
if (isSelecting) {
|
||||
return Selector<Selection<FilterGridItem<T>>, int>(
|
||||
selector: (context, selection) => selection.selection.length,
|
||||
selector: (context, selection) => selection.selectedItems.length,
|
||||
builder: (context, count, child) => Text(context.l10n.collectionSelectionPageTitle(count)),
|
||||
);
|
||||
} else {
|
||||
|
@ -127,7 +127,7 @@ class _FilterGridAppBarState<T extends CollectionFilter> extends State<FilterGri
|
|||
}
|
||||
|
||||
List<Widget> _buildActions(AppMode appMode, Selection<FilterGridItem<T>> selection) {
|
||||
final selectedFilters = selection.selection.map((v) => v.filter).toSet();
|
||||
final selectedFilters = selection.selectedItems.map((v) => v.filter).toSet();
|
||||
|
||||
PopupMenuItem<ChipSetAction> toMenuItem(ChipSetAction action, {bool enabled = true}) {
|
||||
return PopupMenuItem(
|
||||
|
@ -152,7 +152,7 @@ class _FilterGridAppBarState<T extends CollectionFilter> extends State<FilterGri
|
|||
|
||||
final buttonActions = <Widget>[];
|
||||
if (isSelecting) {
|
||||
final selectedFilters = selection.selection.map((v) => v.filter).toSet();
|
||||
final selectedFilters = selection.selectedItems.map((v) => v.filter).toSet();
|
||||
final validActions = filterSelectionActions.where((action) => actionDelegate.isValid(selectedFilters, action)).toList();
|
||||
buttonActions.addAll(validActions.take(buttonActionCount).map(
|
||||
(action) {
|
||||
|
@ -174,7 +174,7 @@ class _FilterGridAppBarState<T extends CollectionFilter> extends State<FilterGri
|
|||
PopupMenuButton<ChipSetAction>(
|
||||
key: const Key('appbar-menu-button'),
|
||||
itemBuilder: (context) {
|
||||
final selectedItems = selection.selection;
|
||||
final selectedItems = selection.selectedItems;
|
||||
final hasSelection = selectedItems.isNotEmpty;
|
||||
final hasItems = !widget.isEmpty;
|
||||
final otherViewEnabled = (!isSelecting && hasItems) || (isSelecting && hasSelection);
|
||||
|
|
Loading…
Reference in a new issue