#935 hidden items can be toggled

This commit is contained in:
Thibault Deckers 2024-03-23 22:26:52 +01:00
parent b5dbac1e2b
commit 55c96ad1c1
7 changed files with 118 additions and 58 deletions

View file

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

View file

@ -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<CollectionFilter> newValue) => set(SettingKeys.pinnedFiltersKey, newValue.map((filter) => filter.toJson()).toList());
Set<CollectionFilter> get hiddenFilters => (getStringList(SettingKeys.hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
set hiddenFilters(Set<CollectionFilter> newValue) => set(SettingKeys.hiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList());
void changeFilterVisibility(Set<CollectionFilter> 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);

View file

@ -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<CollectionFilter> get hiddenFilters => (getStringList(SettingKeys.hiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
set hiddenFilters(Set<CollectionFilter> newValue) => set(SettingKeys.hiddenFiltersKey, newValue.map((filter) => filter.toJson()).toList());
void changeFilterVisibility(Set<CollectionFilter> 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<CollectionFilter> get deactivatedHiddenFilters => (getStringList(SettingKeys.deactivatedHiddenFiltersKey) ?? []).map(CollectionFilter.fromJson).whereNotNull().toSet();
set deactivatedHiddenFilters(Set<CollectionFilter> 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);
}
}

View file

@ -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<StreamSubscription> _subscriptions = [];
final EventChannel _platformSettingsChangeChannel = const OptionalEventChannel('deckers.thibault/aves/settings_change');
final StreamController<SettingsChangedEvent> _updateStreamController = StreamController.broadcast();

View file

@ -69,6 +69,7 @@ class _DebugSettingsSectionState extends State<DebugSettingsSection> 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),

View file

@ -58,50 +58,77 @@ class _HiddenFilters extends StatelessWidget {
@override
Widget build(BuildContext context) {
bool filterPredicate(CollectionFilter v) => v is! PathFilter;
return Selector<Settings, Set<CollectionFilter>>(
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<Settings, Set<CollectionFilter>>(
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<Settings, Set<PathFilter>>(
selector: (context, s) => settings.hiddenFilters.whereType<PathFilter>().toSet(),
selector: (context, s) => {
...settings.hiddenFilters,
...settings.deactivatedHiddenFilters,
}.whereType<PathFilter>().toSet(),
builder: (context, hiddenPaths, child) {
final pathList = hiddenPaths.toList()..sort();
return Column(

View file

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