From 55c96ad1c11bd74e3c4a22fcb265e243f779b54d Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Sat, 23 Mar 2024 22:26:52 +0100 Subject: [PATCH] #935 hidden items can be toggled --- CHANGELOG.md | 1 + lib/model/settings/modules/filter_grids.dart | 18 +-- lib/model/settings/modules/privacy.dart | 42 +++++++ lib/model/settings/settings.dart | 3 +- lib/widgets/debug/settings.dart | 1 + .../settings/privacy/hidden_items_page.dart | 110 +++++++++++------- plugins/aves_model/lib/src/settings/keys.dart | 1 + 7 files changed, 118 insertions(+), 58 deletions(-) create mode 100644 lib/model/settings/modules/privacy.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 103ad0125..03c1fbd7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. ### Added - Collection: support for Fairphone burst pattern +- Settings: hidden items can be toggled ### Changed diff --git a/lib/model/settings/modules/filter_grids.dart b/lib/model/settings/modules/filter_grids.dart index 4476349a2..4fa6482c5 100644 --- a/lib/model/settings/modules/filter_grids.dart +++ b/lib/model/settings/modules/filter_grids.dart @@ -1,10 +1,9 @@ import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/settings/defaults.dart'; -import 'package:aves/model/settings/modules/search.dart'; import 'package:aves_model/aves_model.dart'; import 'package:collection/collection.dart'; -mixin FilterGridsSettings on SettingsAccess, SearchSettings { +mixin FilterGridsSettings on SettingsAccess { AlbumChipGroupFactor get albumGroupFactor => getEnumOrDefault(SettingKeys.albumGroupFactorKey, SettingsDefaults.albumGroupFactor, AlbumChipGroupFactor.values); set albumGroupFactor(AlbumChipGroupFactor newValue) => set(SettingKeys.albumGroupFactorKey, newValue.toString()); @@ -53,21 +52,6 @@ mixin FilterGridsSettings on SettingsAccess, SearchSettings { set pinnedFilters(Set newValue) => set(SettingKeys.pinnedFiltersKey, newValue.map((filter) => filter.toJson()).toList()); - Set get hiddenFilters => (getStringList(SettingKeys.hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); - - set hiddenFilters(Set newValue) => set(SettingKeys.hiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList()); - - void changeFilterVisibility(Set filters, bool visible) { - final _hiddenFilters = hiddenFilters; - if (visible) { - _hiddenFilters.removeAll(filters); - } else { - _hiddenFilters.addAll(filters); - searchHistory = searchHistory..removeWhere(filters.contains); - } - hiddenFilters = _hiddenFilters; - } - bool get showAlbumPickQuery => getBool(SettingKeys.showAlbumPickQueryKey) ?? false; set showAlbumPickQuery(bool newValue) => set(SettingKeys.showAlbumPickQueryKey, newValue); diff --git a/lib/model/settings/modules/privacy.dart b/lib/model/settings/modules/privacy.dart new file mode 100644 index 000000000..90a4b6a97 --- /dev/null +++ b/lib/model/settings/modules/privacy.dart @@ -0,0 +1,42 @@ +import 'package:aves/model/filters/filters.dart'; +import 'package:aves/model/settings/modules/search.dart'; +import 'package:aves_model/aves_model.dart'; +import 'package:collection/collection.dart'; + +mixin PrivacySettings on SettingsAccess, SearchSettings { + Set get hiddenFilters => (getStringList(SettingKeys.hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); + + set hiddenFilters(Set newValue) => set(SettingKeys.hiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList()); + + void changeFilterVisibility(Set filters, bool visible) { + final _hiddenFilters = hiddenFilters; + if (visible) { + _hiddenFilters.removeAll(filters); + } else { + _hiddenFilters.addAll(filters); + searchHistory = searchHistory..removeWhere(filters.contains); + + final _deactivatedHiddenFilters = deactivatedHiddenFilters; + _deactivatedHiddenFilters.removeAll(filters); + deactivatedHiddenFilters = _deactivatedHiddenFilters; + } + hiddenFilters = _hiddenFilters; + } + + Set get deactivatedHiddenFilters => (getStringList(SettingKeys.deactivatedHiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet(); + + set deactivatedHiddenFilters(Set newValue) => set(SettingKeys.deactivatedHiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList()); + + void activateHiddenFilter(CollectionFilter filter, bool active) { + final _deactivatedHiddenFilters = deactivatedHiddenFilters; + if (active) { + _deactivatedHiddenFilters.remove(filter); + } else { + _deactivatedHiddenFilters.add(filter); + } + deactivatedHiddenFilters = _deactivatedHiddenFilters; + + final visible = !active; + changeFilterVisibility({filter}, visible); + } +} diff --git a/lib/model/settings/settings.dart b/lib/model/settings/settings.dart index 51a19966f..a8a96a74b 100644 --- a/lib/model/settings/settings.dart +++ b/lib/model/settings/settings.dart @@ -15,6 +15,7 @@ import 'package:aves/model/settings/modules/display.dart'; import 'package:aves/model/settings/modules/filter_grids.dart'; import 'package:aves/model/settings/modules/info.dart'; import 'package:aves/model/settings/modules/navigation.dart'; +import 'package:aves/model/settings/modules/privacy.dart'; import 'package:aves/model/settings/modules/search.dart'; import 'package:aves/model/settings/modules/viewer.dart'; import 'package:aves/ref/bursts.dart'; @@ -37,7 +38,7 @@ import 'package:latlong2/latlong.dart'; final Settings settings = Settings._private(); -class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings, NavigationSettings, SearchSettings, CollectionSettings, FilterGridsSettings, ViewerSettings, VideoSettings, SubtitlesSettings, InfoSettings { +class Settings with ChangeNotifier, SettingsAccess, AppSettings, DisplaySettings, NavigationSettings, SearchSettings, CollectionSettings, FilterGridsSettings, PrivacySettings, ViewerSettings, VideoSettings, SubtitlesSettings, InfoSettings { final List _subscriptions = []; final EventChannel _platformSettingsChangeChannel = const OptionalEventChannel('deckers.thibault/aves/settings_change'); final StreamController _updateStreamController = StreamController.broadcast(); diff --git a/lib/widgets/debug/settings.dart b/lib/widgets/debug/settings.dart index 99dbf7913..262b89a22 100644 --- a/lib/widgets/debug/settings.dart +++ b/lib/widgets/debug/settings.dart @@ -69,6 +69,7 @@ class _DebugSettingsSectionState extends State with Automa 'drawerPageBookmarks': toMultiline(settings.drawerPageBookmarks), 'pinnedFilters': toMultiline(settings.pinnedFilters), 'hiddenFilters': toMultiline(settings.hiddenFilters), + 'deactivatedHiddenFilters': toMultiline(settings.deactivatedHiddenFilters), 'searchHistory': toMultiline(settings.searchHistory), 'recentDestinationAlbums': toMultiline(settings.recentDestinationAlbums), 'recentTags': toMultiline(settings.recentTags), diff --git a/lib/widgets/settings/privacy/hidden_items_page.dart b/lib/widgets/settings/privacy/hidden_items_page.dart index bd5f602da..5006f979c 100644 --- a/lib/widgets/settings/privacy/hidden_items_page.dart +++ b/lib/widgets/settings/privacy/hidden_items_page.dart @@ -58,50 +58,77 @@ class _HiddenFilters extends StatelessWidget { @override Widget build(BuildContext context) { + bool filterPredicate(CollectionFilter v) => v is! PathFilter; return Selector>( - selector: (context, s) => settings.hiddenFilters.where((v) => v is! PathFilter).toSet(), - builder: (context, hiddenFilters, child) { - if (hiddenFilters.isEmpty) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - _Banner(bannerText: context.l10n.settingsHiddenFiltersBanner), - const Divider(height: 0), - Expanded( - child: Padding( - padding: const EdgeInsets.all(8), - child: EmptyContent( - icon: AIcons.hide, - text: context.l10n.settingsHiddenFiltersEmpty, + selector: (context, s) => settings.hiddenFilters.where(filterPredicate).toSet(), + builder: (context, activatedHiddenFilters, child) { + return Selector>( + selector: (context, s) => settings.deactivatedHiddenFilters.where(filterPredicate).toSet(), + builder: (context, deactivatedHiddenFilters, child) { + final allHiddenFilters = { + ...activatedHiddenFilters, + ...deactivatedHiddenFilters, + }; + if (allHiddenFilters.isEmpty) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _Banner(bannerText: context.l10n.settingsHiddenFiltersBanner), + const Divider(height: 0), + Expanded( + child: Padding( + padding: const EdgeInsets.all(8), + child: EmptyContent( + icon: AIcons.hide, + text: context.l10n.settingsHiddenFiltersEmpty, + ), + ), ), - ), - ), - ], - ); - } + ], + ); + } - final filterList = hiddenFilters.toList()..sort(); - return ListView( - children: [ - _Banner(bannerText: context.l10n.settingsHiddenFiltersBanner), - const Divider(height: 0), - Padding( - padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 8), - child: Wrap( - spacing: 8, - runSpacing: 8, - children: filterList.map((filter) { + final filterList = allHiddenFilters.toList()..sort(); + return ListView( + children: [ + _Banner(bannerText: context.l10n.settingsHiddenFiltersBanner), + const Divider(height: 0), + const SizedBox(height: 8), + ...filterList.map((filter) { void onRemove(CollectionFilter filter) => settings.changeFilterVisibility({filter}, true); - return AvesFilterChip( - filter: filter, - onTap: onRemove, - onRemove: onRemove, - onLongPress: null, + return Padding( + padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8), + child: Row( + children: [ + Expanded( + child: LayoutBuilder(builder: (context, constraints) { + debugPrint('TLAD constraints=$constraints'); + return Row( + children: [ + AvesFilterChip( + filter: filter, + maxWidth: constraints.maxWidth, + onTap: onRemove, + onRemove: onRemove, + onLongPress: null, + ), + const Spacer(), + ], + ); + }), + ), + const SizedBox(width: 8), + Switch( + value: activatedHiddenFilters.contains(filter), + onChanged: (v) => settings.activateHiddenFilter(filter, v), + ), + ], + ), ); - }).toList(), - ), - ), - ], + }), + ], + ); + }, ); }, ); @@ -114,7 +141,10 @@ class _HiddenPaths extends StatelessWidget { @override Widget build(BuildContext context) { return Selector>( - selector: (context, s) => settings.hiddenFilters.whereType().toSet(), + selector: (context, s) => { + ...settings.hiddenFilters, + ...settings.deactivatedHiddenFilters, + }.whereType().toSet(), builder: (context, hiddenPaths, child) { final pathList = hiddenPaths.toList()..sort(); return Column( diff --git a/plugins/aves_model/lib/src/settings/keys.dart b/plugins/aves_model/lib/src/settings/keys.dart index 071a017a1..e3a7b42c1 100644 --- a/plugins/aves_model/lib/src/settings/keys.dart +++ b/plugins/aves_model/lib/src/settings/keys.dart @@ -83,6 +83,7 @@ class SettingKeys { static const tagSortReverseKey = 'tag_sort_reverse'; static const pinnedFiltersKey = 'pinned_filters'; static const hiddenFiltersKey = 'hidden_filters'; + static const deactivatedHiddenFiltersKey = 'deactivated_hidden_filters'; static const showAlbumPickQueryKey = 'show_album_pick_query'; // viewer