#1370 dynamic albums: decompose action
This commit is contained in:
parent
43a42ad1dc
commit
9bdb3171d9
18 changed files with 123 additions and 79 deletions
|
@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
|
|||
|
||||
## <a id="unreleased"></a>[Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- dynamic album decompose action
|
||||
|
||||
## <a id="v1.12.0"></a>[v1.12.0] - 2024-12-19
|
||||
|
||||
### Added
|
||||
|
|
|
@ -92,6 +92,7 @@
|
|||
"chipActionGoToPlacePage": "Show in Places",
|
||||
"chipActionGoToTagPage": "Show in Tags",
|
||||
"chipActionGoToExplorerPage": "Show in Explorer",
|
||||
"chipActionDecompose": "Split",
|
||||
"chipActionFilterOut": "Filter out",
|
||||
"chipActionFilterIn": "Filter in",
|
||||
"chipActionHide": "Hide",
|
||||
|
|
|
@ -18,6 +18,8 @@ class SetAndFilter extends CollectionFilter {
|
|||
|
||||
CollectionFilter get _first => _filters.first;
|
||||
|
||||
Set<CollectionFilter> get innerFilters => _filters.toSet();
|
||||
|
||||
SetAndFilter(Set<CollectionFilter> filters, {super.reversed = false}) {
|
||||
_filters = filters.toList().sorted();
|
||||
_test = (entry) => _filters.every((v) => v.test(entry));
|
||||
|
|
|
@ -167,10 +167,12 @@ class CollectionLens with ChangeNotifier {
|
|||
}
|
||||
}
|
||||
|
||||
void addFilter(CollectionFilter filter) {
|
||||
if (filters.contains(filter)) return;
|
||||
void addFilters(Set<CollectionFilter> newFilters) {
|
||||
if (filters.containsAll(newFilters)) return;
|
||||
for (final filter in newFilters) {
|
||||
filters.removeWhere((other) => !filter.isCompatible(other));
|
||||
filters.add(filter);
|
||||
}
|
||||
filters.addAll(newFilters);
|
||||
_onFilterChanged();
|
||||
}
|
||||
|
||||
|
|
|
@ -145,6 +145,7 @@ class AIcons {
|
|||
static final showFullscreenArrows = MdiIcons.arrowExpand;
|
||||
static const showFullscreenCorners = Icons.fullscreen_outlined;
|
||||
static const slideshow = Icons.slideshow_outlined;
|
||||
static const split = Icons.call_split_outlined;
|
||||
static const stats = Icons.donut_small_outlined;
|
||||
static const vaultLock = Icons.lock_outlined;
|
||||
static const vaultAdd = Icons.enhanced_encryption_outlined;
|
||||
|
|
|
@ -16,6 +16,7 @@ extension ExtraChipActionView on ChipAction {
|
|||
ChipAction.ratingOrLower =>
|
||||
// different data depending on state
|
||||
toString(),
|
||||
ChipAction.decompose => l10n.chipActionDecompose,
|
||||
ChipAction.reverse =>
|
||||
// different data depending on state
|
||||
l10n.chipActionFilterOut,
|
||||
|
@ -33,6 +34,7 @@ extension ExtraChipActionView on ChipAction {
|
|||
ChipAction.goToTagPage => AIcons.tag,
|
||||
ChipAction.goToExplorerPage => AIcons.explorer,
|
||||
ChipAction.ratingOrGreater || ChipAction.ratingOrLower => AIcons.rating,
|
||||
ChipAction.decompose => AIcons.split,
|
||||
ChipAction.reverse => AIcons.reverse,
|
||||
ChipAction.hide => AIcons.hide,
|
||||
ChipAction.lockVault => AIcons.vaultLock,
|
||||
|
|
|
@ -3,8 +3,10 @@ import 'dart:math';
|
|||
|
||||
import 'package:aves/app_mode.dart';
|
||||
import 'package:aves/model/entry/entry.dart';
|
||||
import 'package:aves/model/filters/covered/dynamic_album.dart';
|
||||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/filters/query.dart';
|
||||
import 'package:aves/model/filters/set_and.dart';
|
||||
import 'package:aves/model/filters/trash.dart';
|
||||
import 'package:aves/model/query.dart';
|
||||
import 'package:aves/model/selection.dart';
|
||||
|
@ -33,8 +35,8 @@ import 'package:aves/widgets/common/identity/buttons/captioned_button.dart';
|
|||
import 'package:aves/widgets/common/search/route.dart';
|
||||
import 'package:aves/widgets/common/tile_extent_controller.dart';
|
||||
import 'package:aves/widgets/dialogs/tile_view_dialog.dart';
|
||||
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
|
||||
import 'package:aves/widgets/search/search_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/controls/notifications.dart';
|
||||
import 'package:aves_model/aves_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
@ -199,10 +201,22 @@ class _CollectionAppBarState extends State<CollectionAppBar> with SingleTickerPr
|
|||
),
|
||||
),
|
||||
if (showFilterBar)
|
||||
NotificationListener<FilterNotification>(
|
||||
NotificationListener(
|
||||
onNotification: (notification) {
|
||||
collection.addFilter(notification.filter);
|
||||
if (notification is SelectFilterNotification) {
|
||||
collection.addFilters({notification.filter});
|
||||
return true;
|
||||
} else if (notification is DecomposeFilterNotification) {
|
||||
final filter = notification.filter;
|
||||
if (filter is DynamicAlbumFilter) {
|
||||
final innerFilter = filter.filter;
|
||||
final newFilters = innerFilter is SetAndFilter ? innerFilter.innerFilters : {innerFilter};
|
||||
collection.addFilters(newFilters);
|
||||
collection.removeFilter(filter);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
child: FilterBar(
|
||||
filters: visibleFilters,
|
||||
|
|
|
@ -3,12 +3,8 @@ import 'dart:math';
|
|||
|
||||
import 'package:aves/app_mode.dart';
|
||||
import 'package:aves/model/covers.dart';
|
||||
import 'package:aves/model/filters/covered/stored_album.dart';
|
||||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/filters/covered/location.dart';
|
||||
import 'package:aves/model/filters/path.dart';
|
||||
import 'package:aves/model/filters/rating.dart';
|
||||
import 'package:aves/model/filters/covered/tag.dart';
|
||||
import 'package:aves/model/settings/enums/accessibility_animations.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/theme/colors.dart';
|
||||
|
@ -101,21 +97,6 @@ class AvesFilterChip extends StatefulWidget {
|
|||
|
||||
static Future<void> showDefaultLongPressMenu(BuildContext context, CollectionFilter filter, Offset tapPosition) async {
|
||||
if (context.read<ValueNotifier<AppMode>>().value.canNavigate) {
|
||||
final actions = <ChipAction>[
|
||||
if (filter is AlbumBaseFilter) ChipAction.goToAlbumPage,
|
||||
if (filter is StoredAlbumFilter || filter is PathFilter) ChipAction.goToExplorerPage,
|
||||
if ((filter is LocationFilter && filter.level == LocationLevel.country)) ChipAction.goToCountryPage,
|
||||
if ((filter is LocationFilter && filter.level == LocationLevel.place)) ChipAction.goToPlacePage,
|
||||
if (filter is TagFilter) ChipAction.goToTagPage,
|
||||
if (filter is RatingFilter && 1 < filter.rating && filter.rating < 5) ...[
|
||||
if (filter.op != RatingFilter.opOrGreater) ChipAction.ratingOrGreater,
|
||||
if (filter.op != RatingFilter.opOrLower) ChipAction.ratingOrLower,
|
||||
],
|
||||
ChipAction.reverse,
|
||||
ChipAction.hide,
|
||||
ChipAction.lockVault,
|
||||
];
|
||||
|
||||
// remove focus, if any, to prevent the keyboard from showing up
|
||||
// after the user is done with the popup menu
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
|
@ -132,7 +113,7 @@ class AvesFilterChip extends StatefulWidget {
|
|||
child: Text(filter.getLabel(context)),
|
||||
),
|
||||
const PopupMenuDivider(),
|
||||
...actions.where((action) => actionDelegate.isVisible(action, filter: filter)).map((action) {
|
||||
...ChipAction.values.where((action) => actionDelegate.isVisible(action, filter: filter)).map((action) {
|
||||
late String text;
|
||||
switch (action) {
|
||||
case ChipAction.reverse:
|
||||
|
|
|
@ -92,7 +92,7 @@ class _OverlayCoordinateFilterChipState extends State<OverlayCoordinateFilterChi
|
|||
useFilterColor: false,
|
||||
background: Themes.overlayBackgroundColor(brightness: theme.brightness, blurred: blurred),
|
||||
maxWidth: double.infinity,
|
||||
onTap: (filter) => FilterSelectedNotification(CoordinateFilter(bounds.sw, bounds.ne)).dispatch(context),
|
||||
onTap: (filter) => SelectFilterNotification(CoordinateFilter(bounds.sw, bounds.ne)).dispatch(context),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -97,7 +97,12 @@ class ExplorerActionDelegate with FeedbackMixin {
|
|||
}
|
||||
|
||||
void _hide(BuildContext context) {
|
||||
ChipActionDelegate().onActionSelected(context, _getPathFilter(), ChipAction.hide);
|
||||
final chipActionDelegate = ChipActionDelegate();
|
||||
const action = ChipAction.hide;
|
||||
final pathFilter = _getPathFilter();
|
||||
if (chipActionDelegate.isVisible(action, filter: pathFilter)) {
|
||||
chipActionDelegate.onActionSelected(context, pathFilter, action);
|
||||
}
|
||||
}
|
||||
|
||||
void _goToStats(BuildContext context) {
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
import 'package:aves/model/filters/covered/dynamic_album.dart';
|
||||
import 'package:aves/model/filters/covered/location.dart';
|
||||
import 'package:aves/model/filters/covered/stored_album.dart';
|
||||
import 'package:aves/model/filters/covered/tag.dart';
|
||||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/filters/path.dart';
|
||||
import 'package:aves/model/filters/rating.dart';
|
||||
|
@ -15,6 +18,7 @@ import 'package:aves/widgets/filter_grids/albums_page.dart';
|
|||
import 'package:aves/widgets/filter_grids/countries_page.dart';
|
||||
import 'package:aves/widgets/filter_grids/places_page.dart';
|
||||
import 'package:aves/widgets/filter_grids/tags_page.dart';
|
||||
import 'package:aves/widgets/viewer/controls/notifications.dart';
|
||||
import 'package:aves_model/aves_model.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
@ -26,12 +30,21 @@ class ChipActionDelegate with FeedbackMixin, VaultAwareMixin {
|
|||
}) {
|
||||
switch (action) {
|
||||
case ChipAction.goToAlbumPage:
|
||||
return filter is AlbumBaseFilter;
|
||||
case ChipAction.goToCountryPage:
|
||||
return filter is LocationFilter && filter.level == LocationLevel.country;
|
||||
case ChipAction.goToPlacePage:
|
||||
return filter is LocationFilter && filter.level == LocationLevel.place;
|
||||
case ChipAction.goToTagPage:
|
||||
return filter is TagFilter;
|
||||
case ChipAction.goToExplorerPage:
|
||||
return filter is StoredAlbumFilter || filter is PathFilter;
|
||||
case ChipAction.ratingOrGreater:
|
||||
return filter is RatingFilter && 1 < filter.rating && filter.rating < 5 && filter.op != RatingFilter.opOrGreater;
|
||||
case ChipAction.ratingOrLower:
|
||||
return filter is RatingFilter && 1 < filter.rating && filter.rating < 5 && filter.op != RatingFilter.opOrLower;
|
||||
case ChipAction.decompose:
|
||||
return filter is DynamicAlbumFilter;
|
||||
case ChipAction.reverse:
|
||||
return true;
|
||||
case ChipAction.hide:
|
||||
|
@ -69,11 +82,13 @@ class ChipActionDelegate with FeedbackMixin, VaultAwareMixin {
|
|||
);
|
||||
}
|
||||
case ChipAction.ratingOrGreater:
|
||||
FilterNotification((filter as RatingFilter).copyWith(RatingFilter.opOrGreater)).dispatch(context);
|
||||
SelectFilterNotification((filter as RatingFilter).copyWith(RatingFilter.opOrGreater)).dispatch(context);
|
||||
case ChipAction.ratingOrLower:
|
||||
FilterNotification((filter as RatingFilter).copyWith(RatingFilter.opOrLower)).dispatch(context);
|
||||
SelectFilterNotification((filter as RatingFilter).copyWith(RatingFilter.opOrLower)).dispatch(context);
|
||||
case ChipAction.decompose:
|
||||
DecomposeFilterNotification(filter).dispatch(context);
|
||||
case ChipAction.reverse:
|
||||
FilterNotification(filter.reverse()).dispatch(context);
|
||||
SelectFilterNotification(filter.reverse()).dispatch(context);
|
||||
case ChipAction.hide:
|
||||
_hide(context, filter);
|
||||
case ChipAction.lockVault:
|
||||
|
@ -119,10 +134,3 @@ class ChipActionDelegate with FeedbackMixin, VaultAwareMixin {
|
|||
settings.changeFilterVisibility({filter}, false);
|
||||
}
|
||||
}
|
||||
|
||||
@immutable
|
||||
class FilterNotification extends Notification {
|
||||
final CollectionFilter filter;
|
||||
|
||||
const FilterNotification(this.filter);
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import 'package:aves/app_mode.dart';
|
|||
import 'package:aves/model/entry/entry.dart';
|
||||
import 'package:aves/model/entry/extensions/location.dart';
|
||||
import 'package:aves/model/filters/coordinate.dart';
|
||||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/filters/covered/location.dart';
|
||||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/highlight.dart';
|
||||
import 'package:aves/model/media/geotiff.dart';
|
||||
import 'package:aves/model/settings/enums/accessibility_animations.dart';
|
||||
|
@ -31,7 +31,6 @@ import 'package:aves/widgets/common/map/map_action_delegate.dart';
|
|||
import 'package:aves/widgets/common/providers/highlight_info_provider.dart';
|
||||
import 'package:aves/widgets/common/providers/map_theme_provider.dart';
|
||||
import 'package:aves/widgets/dialogs/aves_dialog.dart';
|
||||
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
|
||||
import 'package:aves/widgets/map/scroller.dart';
|
||||
import 'package:aves/widgets/viewer/controls/notifications.dart';
|
||||
import 'package:aves/widgets/viewer/entry_viewer_page.dart';
|
||||
|
@ -203,9 +202,7 @@ class _ContentState extends State<_Content> with SingleTickerProviderStateMixin
|
|||
Widget build(BuildContext context) {
|
||||
return NotificationListener(
|
||||
onNotification: (notification) {
|
||||
if (notification is FilterSelectedNotification) {
|
||||
_goToCollection(notification.filter);
|
||||
} else if (notification is FilterNotification) {
|
||||
if (notification is SelectFilterNotification) {
|
||||
_goToCollection(notification.filter);
|
||||
} else if (notification is OpenMapAppNotification) {
|
||||
_openMapApp();
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import 'package:aves/model/dynamic_albums.dart';
|
||||
import 'package:aves/model/filters/covered/stored_album.dart';
|
||||
import 'package:aves/model/filters/aspect_ratio.dart';
|
||||
import 'package:aves/model/filters/covered/dynamic_album.dart';
|
||||
import 'package:aves/model/filters/covered/location.dart';
|
||||
import 'package:aves/model/filters/covered/stored_album.dart';
|
||||
import 'package:aves/model/filters/covered/tag.dart';
|
||||
import 'package:aves/model/filters/date.dart';
|
||||
import 'package:aves/model/filters/favourite.dart';
|
||||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/filters/covered/location.dart';
|
||||
import 'package:aves/model/filters/mime.dart';
|
||||
import 'package:aves/model/filters/missing.dart';
|
||||
import 'package:aves/model/filters/query.dart';
|
||||
import 'package:aves/model/filters/rating.dart';
|
||||
import 'package:aves/model/filters/recent.dart';
|
||||
import 'package:aves/model/filters/covered/tag.dart';
|
||||
import 'package:aves/model/filters/set_and.dart';
|
||||
import 'package:aves/model/filters/type.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/model/source/album.dart';
|
||||
|
@ -29,7 +31,7 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
|||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||
import 'package:aves/widgets/common/search/delegate.dart';
|
||||
import 'package:aves/widgets/common/search/page.dart';
|
||||
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
|
||||
import 'package:aves/widgets/viewer/controls/notifications.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
|
@ -91,10 +93,21 @@ class CollectionSearchDelegate extends AvesSearchDelegate with FeedbackMixin, Va
|
|||
final upQuery = query.trim().toUpperCase();
|
||||
bool containQuery(String s) => s.toUpperCase().contains(upQuery);
|
||||
return SafeArea(
|
||||
child: NotificationListener<FilterNotification>(
|
||||
child: NotificationListener(
|
||||
onNotification: (notification) {
|
||||
_select(context, notification.filter);
|
||||
if (notification is SelectFilterNotification) {
|
||||
_select(context, {notification.filter});
|
||||
return true;
|
||||
} else if (notification is DecomposeFilterNotification) {
|
||||
final filter = notification.filter;
|
||||
if (filter is DynamicAlbumFilter) {
|
||||
final innerFilter = filter.filter;
|
||||
final newFilters = innerFilter is SetAndFilter ? innerFilter.innerFilters : {innerFilter};
|
||||
_select(context, newFilters);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
child: ValueListenableBuilder<String?>(
|
||||
valueListenable: _expandedSectionNotifier,
|
||||
|
@ -159,7 +172,7 @@ class CollectionSearchDelegate extends AvesSearchDelegate with FeedbackMixin, Va
|
|||
required List<CollectionFilter> filters,
|
||||
HeroType Function(CollectionFilter filter)? heroTypeBuilder,
|
||||
}) {
|
||||
void onTap(filter) => _select(context, filter is QueryFilter ? QueryFilter(filter.query) : filter);
|
||||
void onTap(filter) => _select(context, {filter is QueryFilter ? QueryFilter(filter.query) : filter});
|
||||
const onLongPress = AvesFilterChip.showDefaultLongPressMenu;
|
||||
return title != null
|
||||
? TitledExpandableFilterRow(
|
||||
|
@ -303,7 +316,7 @@ class CollectionSearchDelegate extends AvesSearchDelegate with FeedbackMixin, Va
|
|||
// `buildResults` is called in the build phase,
|
||||
// so we post the call that will filter the collection
|
||||
// and possibly trigger a rebuild here
|
||||
_select(context, _buildQueryFilter(true));
|
||||
_select(context, {_buildQueryFilter(true)});
|
||||
});
|
||||
}
|
||||
return const SizedBox();
|
||||
|
@ -314,12 +327,14 @@ class CollectionSearchDelegate extends AvesSearchDelegate with FeedbackMixin, Va
|
|||
return cleanQuery.isNotEmpty ? QueryFilter(cleanQuery, colorful: colorful) : null;
|
||||
}
|
||||
|
||||
Future<void> _select(BuildContext context, CollectionFilter? filter) async {
|
||||
if (filter == null) {
|
||||
Future<void> _select(BuildContext context, Set<CollectionFilter?> filters) async {
|
||||
final newFilters = filters.nonNulls.toSet();
|
||||
if (newFilters.isEmpty) {
|
||||
goBack(context);
|
||||
return;
|
||||
}
|
||||
|
||||
for (final filter in newFilters) {
|
||||
if (!await unlockFilter(context, filter)) return;
|
||||
|
||||
if (settings.saveSearchHistory) {
|
||||
|
@ -328,15 +343,17 @@ class CollectionSearchDelegate extends AvesSearchDelegate with FeedbackMixin, Va
|
|||
..insert(0, filter);
|
||||
settings.searchHistory = history.take(searchHistoryCount).toList();
|
||||
}
|
||||
}
|
||||
|
||||
if (parentCollection != null) {
|
||||
_applyToParentCollectionPage(context, filter);
|
||||
_applyToParentCollectionPage(context, newFilters);
|
||||
} else {
|
||||
_jumpToCollectionPage(context, {filter});
|
||||
_jumpToCollectionPage(context, newFilters);
|
||||
}
|
||||
}
|
||||
|
||||
void _applyToParentCollectionPage(BuildContext context, CollectionFilter filter) {
|
||||
parentCollection!.addFilter(filter);
|
||||
void _applyToParentCollectionPage(BuildContext context, Set<CollectionFilter> filters) {
|
||||
parentCollection!.addFilters(filters);
|
||||
if (Navigator.canPop(context)) {
|
||||
// We delay closing the current page after applying the filter selection
|
||||
// so that hero animation target is ready in the `FilterBar`,
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:aves/model/entry/entry.dart';
|
||||
import 'package:aves/model/filters/covered/stored_album.dart';
|
||||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/filters/covered/location.dart';
|
||||
import 'package:aves/model/filters/rating.dart';
|
||||
import 'package:aves/model/filters/covered/stored_album.dart';
|
||||
import 'package:aves/model/filters/covered/tag.dart';
|
||||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/filters/rating.dart';
|
||||
import 'package:aves/model/settings/settings.dart';
|
||||
import 'package:aves/model/source/collection_lens.dart';
|
||||
import 'package:aves/model/source/collection_source.dart';
|
||||
|
@ -24,11 +24,11 @@ import 'package:aves/widgets/common/extensions/build_context.dart';
|
|||
import 'package:aves/widgets/common/extensions/media_query.dart';
|
||||
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
|
||||
import 'package:aves/widgets/common/identity/empty.dart';
|
||||
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
|
||||
import 'package:aves/widgets/stats/date/histogram.dart';
|
||||
import 'package:aves/widgets/stats/filter_table.dart';
|
||||
import 'package:aves/widgets/stats/mime_donut.dart';
|
||||
import 'package:aves/widgets/stats/percent_text.dart';
|
||||
import 'package:aves/widgets/viewer/controls/notifications.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/scheduler.dart';
|
||||
|
@ -172,7 +172,7 @@ class _StatsPageState extends State<StatsPage> with FeedbackMixin, VaultAwareMix
|
|||
],
|
||||
),
|
||||
);
|
||||
child = NotificationListener<FilterNotification>(
|
||||
child = NotificationListener<SelectFilterNotification>(
|
||||
onNotification: (notification) {
|
||||
_onFilterSelection(context, notification.filter);
|
||||
return true;
|
||||
|
@ -336,7 +336,7 @@ class _StatsPageState extends State<StatsPage> with FeedbackMixin, VaultAwareMix
|
|||
}
|
||||
|
||||
void _applyToParentCollectionPage(BuildContext context, CollectionFilter filter) {
|
||||
widget.parentCollection!.addFilter(filter);
|
||||
widget.parentCollection!.addFilters({filter});
|
||||
// We delay closing the current page after applying the filter selection
|
||||
// so that hero animation target is ready in the `FilterBar`,
|
||||
// even when the target is a child of an `AnimatedList`.
|
||||
|
@ -384,7 +384,7 @@ class StatsTopPage extends StatelessWidget {
|
|||
child: SafeArea(
|
||||
bottom: false,
|
||||
child: Builder(builder: (context) {
|
||||
return NotificationListener<FilterNotification>(
|
||||
return NotificationListener<SelectFilterNotification>(
|
||||
onNotification: (notification) {
|
||||
onFilterSelection(notification.filter);
|
||||
return true;
|
||||
|
|
|
@ -89,13 +89,23 @@ class CastNotification extends Notification with EquatableMixin {
|
|||
}
|
||||
|
||||
@immutable
|
||||
class FilterSelectedNotification extends Notification with EquatableMixin {
|
||||
class SelectFilterNotification extends Notification with EquatableMixin {
|
||||
final CollectionFilter filter;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [filter];
|
||||
|
||||
const FilterSelectedNotification(this.filter);
|
||||
const SelectFilterNotification(this.filter);
|
||||
}
|
||||
|
||||
@immutable
|
||||
class DecomposeFilterNotification extends Notification with EquatableMixin {
|
||||
final CollectionFilter filter;
|
||||
|
||||
@override
|
||||
List<Object?> get props => [filter];
|
||||
|
||||
const DecomposeFilterNotification(this.filter);
|
||||
}
|
||||
|
||||
@immutable
|
||||
|
|
|
@ -564,7 +564,7 @@ class _EntryViewerStackState extends State<EntryViewerStack> with EntryViewContr
|
|||
}
|
||||
|
||||
bool _handleNotification(dynamic notification) {
|
||||
if (notification is FilterSelectedNotification) {
|
||||
if (notification is SelectFilterNotification) {
|
||||
_goToCollection(notification.filter);
|
||||
} else if (notification is CastNotification) {
|
||||
_cast(notification.enabled);
|
||||
|
|
|
@ -10,7 +10,6 @@ import 'package:aves/theme/durations.dart';
|
|||
import 'package:aves/widgets/common/basic/insets.dart';
|
||||
import 'package:aves/widgets/common/basic/scaffold.dart';
|
||||
import 'package:aves/widgets/common/basic/tv_edge_focus.dart';
|
||||
import 'package:aves/widgets/filter_grids/common/action_delegates/chip.dart';
|
||||
import 'package:aves/widgets/viewer/action/entry_info_action_delegate.dart';
|
||||
import 'package:aves/widgets/viewer/controls/notifications.dart';
|
||||
import 'package:aves/widgets/viewer/info/basic_section.dart';
|
||||
|
@ -235,7 +234,7 @@ class _InfoPageContentState extends State<_InfoPageContent> {
|
|||
),
|
||||
);
|
||||
|
||||
return NotificationListener<FilterNotification>(
|
||||
return NotificationListener<SelectFilterNotification>(
|
||||
onNotification: (notification) {
|
||||
_onFilter(notification.filter);
|
||||
return true;
|
||||
|
@ -288,6 +287,6 @@ class _InfoPageContentState extends State<_InfoPageContent> {
|
|||
|
||||
void _onFilter(CollectionFilter filter) {
|
||||
if (!mounted) return;
|
||||
FilterSelectedNotification(filter).dispatch(context);
|
||||
SelectFilterNotification(filter).dispatch(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ enum ChipAction {
|
|||
goToExplorerPage,
|
||||
ratingOrGreater,
|
||||
ratingOrLower,
|
||||
decompose,
|
||||
reverse,
|
||||
hide,
|
||||
lockVault,
|
||||
|
|
Loading…
Reference in a new issue