collection: apply filter change to selection

This commit is contained in:
Thibault Deckers 2021-08-11 10:44:07 +09:00
parent f4cca71f07
commit 690ebce80e
4 changed files with 33 additions and 20 deletions

View file

@ -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();
}
}

View file

@ -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 {

View file

@ -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) {

View file

@ -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);