From d926d943fddc14be70aab26fd101b46e2bfff9f5 Mon Sep 17 00:00:00 2001 From: Thibault Deckers Date: Tue, 6 Sep 2022 12:04:32 +0200 Subject: [PATCH] search: undated, untitled filters --- CHANGELOG.md | 1 + lib/l10n/app_de.arb | 6 +- lib/l10n/app_el.arb | 6 +- lib/l10n/app_en.arb | 9 ++- lib/l10n/app_es.arb | 6 +- lib/l10n/app_fr.arb | 9 ++- lib/l10n/app_id.arb | 6 +- lib/l10n/app_it.arb | 6 +- lib/l10n/app_ja.arb | 6 +- lib/l10n/app_ko.arb | 9 ++- lib/l10n/app_nl.arb | 6 +- lib/l10n/app_pt.arb | 6 +- lib/l10n/app_ru.arb | 6 +- lib/l10n/app_tr.arb | 6 +- lib/l10n/app_zh.arb | 6 +- lib/model/filters/filters.dart | 5 ++ lib/model/filters/location.dart | 2 +- lib/model/filters/missing.dart | 73 +++++++++++++++++++ lib/model/filters/rating.dart | 2 +- lib/model/filters/recent.dart | 2 +- lib/model/filters/tag.dart | 2 +- lib/theme/icons.dart | 4 +- .../entry_editors/edit_rating_dialog.dart | 2 +- .../entry_editors/edit_tags_dialog.dart | 2 +- lib/widgets/search/search_delegate.dart | 35 +++++---- test/model/filters_test.dart | 4 + untranslated.json | 45 ++++++++++-- 27 files changed, 202 insertions(+), 70 deletions(-) create mode 100644 lib/model/filters/missing.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index 7191c0a11..bcd801fb6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - Collection / Info: edit title via IPTC / XMP - Albums / Countries / Tags: size displayed in list view details, sort by size +- Search: `undated` and `untitled` filters - Greek translation (thanks Emmanouil Papavergis) ### Changed diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index aaecf0c35..ae65698f6 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -94,11 +94,11 @@ "filterBinLabel": "Papierkorb", "filterFavouriteLabel": "Favorit", - "filterLocationEmptyLabel": "Ungeortet", - "filterTagEmptyLabel": "Unmarkiert", + "filterNoLocationLabel": "Ungeortet", + "filterNoRatingLabel": "Nicht bewertet", + "filterNoTagLabel": "Unmarkiert", "filterOnThisDayLabel": "Am heutigen Tag", "filterRecentlyAddedLabel": "Kürzlich hinzugefügt", - "filterRatingUnratedLabel": "Nicht bewertet", "filterRatingRejectedLabel": "Verworfen", "filterTypeAnimatedLabel": "Animationen", "filterTypeMotionPhotoLabel": "Bewegtes Foto", diff --git a/lib/l10n/app_el.arb b/lib/l10n/app_el.arb index 44881d0ca..f634da885 100644 --- a/lib/l10n/app_el.arb +++ b/lib/l10n/app_el.arb @@ -94,11 +94,11 @@ "filterBinLabel": "Κάδος ανακύκλωσης", "filterFavouriteLabel": "Αγαπημένα", - "filterLocationEmptyLabel": "Χωρίς τοποθεσία", - "filterTagEmptyLabel": "Χωρίς ετικέτα", + "filterNoLocationLabel": "Χωρίς τοποθεσία", + "filterNoRatingLabel": "Χωρίς βαθμολογία", + "filterNoTagLabel": "Χωρίς ετικέτα", "filterOnThisDayLabel": "Αυτή τη μέρα", "filterRecentlyAddedLabel": "Προστέθηκαν πρόσφατα", - "filterRatingUnratedLabel": "Χωρίς βαθμολογία", "filterRatingRejectedLabel": "Απορριφθέντα", "filterTypeAnimatedLabel": "Κινούμενα", "filterTypeMotionPhotoLabel": "Φωτογραφίες με κίνηση", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 408073802..de316fb95 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -123,11 +123,13 @@ "filterBinLabel": "Recycle bin", "filterFavouriteLabel": "Favorite", - "filterLocationEmptyLabel": "Unlocated", - "filterTagEmptyLabel": "Untagged", + "filterNoDateLabel": "Undated", + "filterNoLocationLabel": "Unlocated", + "filterNoRatingLabel": "Unrated", + "filterNoTagLabel": "Untagged", + "filterNoTitleLabel": "Untitled", "filterOnThisDayLabel": "On this day", "filterRecentlyAddedLabel": "Recently added", - "filterRatingUnratedLabel": "Unrated", "filterRatingRejectedLabel": "Rejected", "filterTypeAnimatedLabel": "Animated", "filterTypeMotionPhotoLabel": "Motion Photo", @@ -605,6 +607,7 @@ "searchPlacesSectionTitle": "Places", "searchTagsSectionTitle": "Tags", "searchRatingSectionTitle": "Ratings", + "searchMetadataSectionTitle": "Metadata", "settingsPageTitle": "Settings", "settingsSystemDefault": "System", diff --git a/lib/l10n/app_es.arb b/lib/l10n/app_es.arb index 8e9a662eb..e2e6d5ee9 100644 --- a/lib/l10n/app_es.arb +++ b/lib/l10n/app_es.arb @@ -94,10 +94,10 @@ "filterBinLabel": "Cesto de basura", "filterFavouriteLabel": "Favorito", - "filterLocationEmptyLabel": "No localizado", - "filterTagEmptyLabel": "Sin etiquetar", + "filterNoLocationLabel": "No localizado", + "filterNoRatingLabel": "Sin clasificar", + "filterNoTagLabel": "Sin etiquetar", "filterOnThisDayLabel": "De este día", - "filterRatingUnratedLabel": "Sin clasificar", "filterRatingRejectedLabel": "Rechazado", "filterTypeAnimatedLabel": "Animado", "filterTypeMotionPhotoLabel": "Foto en movimiento", diff --git a/lib/l10n/app_fr.arb b/lib/l10n/app_fr.arb index 7c7414d17..3167b8a57 100644 --- a/lib/l10n/app_fr.arb +++ b/lib/l10n/app_fr.arb @@ -95,11 +95,13 @@ "filterBinLabel": "Corbeille", "filterFavouriteLabel": "Favori", - "filterLocationEmptyLabel": "Sans lieu", - "filterTagEmptyLabel": "Sans libellé", + "filterNoDateLabel": "Sans date", + "filterNoLocationLabel": "Sans lieu", + "filterNoRatingLabel": "Sans notation", + "filterNoTagLabel": "Sans libellé", + "filterNoTitleLabel": "Sans titre", "filterOnThisDayLabel": "Ce jour-là", "filterRecentlyAddedLabel": "Ajouté récemment", - "filterRatingUnratedLabel": "Sans notation", "filterRatingRejectedLabel": "Rejeté", "filterTypeAnimatedLabel": "Animation", "filterTypeMotionPhotoLabel": "Photo animée", @@ -425,6 +427,7 @@ "searchPlacesSectionTitle": "Lieux", "searchTagsSectionTitle": "Libellés", "searchRatingSectionTitle": "Notations", + "searchMetadataSectionTitle": "Métadonnées", "settingsPageTitle": "Réglages", "settingsSystemDefault": "Système", diff --git a/lib/l10n/app_id.arb b/lib/l10n/app_id.arb index beb9b1df0..92261fe93 100644 --- a/lib/l10n/app_id.arb +++ b/lib/l10n/app_id.arb @@ -94,10 +94,10 @@ "filterBinLabel": "Tong sampah", "filterFavouriteLabel": "Favorit", - "filterLocationEmptyLabel": "Lokasi yang tidak ditemukan", - "filterTagEmptyLabel": "Tidak dilabel", + "filterNoLocationLabel": "Lokasi yang tidak ditemukan", + "filterNoRatingLabel": "Belum diberi nilai", + "filterNoTagLabel": "Tidak dilabel", "filterOnThisDayLabel": "Di hari ini", - "filterRatingUnratedLabel": "Belum diberi nilai", "filterRatingRejectedLabel": "Ditolak", "filterTypeAnimatedLabel": "Teranimasi", "filterTypeMotionPhotoLabel": "Foto bergerak", diff --git a/lib/l10n/app_it.arb b/lib/l10n/app_it.arb index 6e534b460..0b60071a7 100644 --- a/lib/l10n/app_it.arb +++ b/lib/l10n/app_it.arb @@ -94,11 +94,11 @@ "filterBinLabel": "Cestino", "filterFavouriteLabel": "Preferiti", - "filterLocationEmptyLabel": "Senza posizione", - "filterTagEmptyLabel": "Senza etichetta", + "filterNoLocationLabel": "Senza posizione", + "filterNoRatingLabel": "Non valutato", + "filterNoTagLabel": "Senza etichetta", "filterOnThisDayLabel": "In questo giorno", "filterRecentlyAddedLabel": "Aggiunto di recente", - "filterRatingUnratedLabel": "Non valutato", "filterRatingRejectedLabel": "Rifiutato", "filterTypeAnimatedLabel": "Animato", "filterTypeMotionPhotoLabel": "Foto in movimento", diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index 25c97a0a0..cf36d0569 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -94,10 +94,10 @@ "filterBinLabel": "ごみ箱", "filterFavouriteLabel": "お気に入り", - "filterLocationEmptyLabel": "位置情報なし", - "filterTagEmptyLabel": "タグ情報なし", + "filterNoLocationLabel": "位置情報なし", + "filterNoRatingLabel": "評価情報なし", + "filterNoTagLabel": "タグ情報なし", "filterOnThisDayLabel": "過去のこの日", - "filterRatingUnratedLabel": "評価情報なし", "filterRatingRejectedLabel": "拒否", "filterTypeAnimatedLabel": "アニメーション", "filterTypeMotionPhotoLabel": "モーションフォト", diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index aca6034aa..c98afdad5 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -95,11 +95,13 @@ "filterBinLabel": "휴지통", "filterFavouriteLabel": "즐겨찾기", - "filterLocationEmptyLabel": "장소 없음", - "filterTagEmptyLabel": "태그 없음", + "filterNoDateLabel": "날짜 없음", + "filterNoLocationLabel": "장소 없음", + "filterNoRatingLabel": "별점 없음", + "filterNoTagLabel": "태그 없음", + "filterNoTitleLabel": "제목 없음", "filterOnThisDayLabel": "이 날", "filterRecentlyAddedLabel": "최근 추가된", - "filterRatingUnratedLabel": "별점 없음", "filterRatingRejectedLabel": "거부됨", "filterTypeAnimatedLabel": "애니메이션", "filterTypeMotionPhotoLabel": "모션 사진", @@ -425,6 +427,7 @@ "searchPlacesSectionTitle": "장소", "searchTagsSectionTitle": "태그", "searchRatingSectionTitle": "별점", + "searchMetadataSectionTitle": "메타데이터", "settingsPageTitle": "설정", "settingsSystemDefault": "시스템", diff --git a/lib/l10n/app_nl.arb b/lib/l10n/app_nl.arb index f32d80358..668d17141 100644 --- a/lib/l10n/app_nl.arb +++ b/lib/l10n/app_nl.arb @@ -94,11 +94,11 @@ "filterBinLabel": "Prullenbak", "filterFavouriteLabel": "Favorieten", - "filterLocationEmptyLabel": "Geen locatie", - "filterTagEmptyLabel": "Geen label", + "filterNoLocationLabel": "Geen locatie", + "filterNoRatingLabel": "Geen rating", + "filterNoTagLabel": "Geen label", "filterOnThisDayLabel": "Op deze dag", "filterRecentlyAddedLabel": "Recent toegevoegd", - "filterRatingUnratedLabel": "Geen rating", "filterRatingRejectedLabel": "Afgekeurd", "filterTypeAnimatedLabel": "Geanimeerd", "filterTypeMotionPhotoLabel": "Bewegende Foto", diff --git a/lib/l10n/app_pt.arb b/lib/l10n/app_pt.arb index f3f9f7cf0..4ec03a9a4 100644 --- a/lib/l10n/app_pt.arb +++ b/lib/l10n/app_pt.arb @@ -94,11 +94,11 @@ "filterBinLabel": "Lixeira", "filterFavouriteLabel": "Favorito", - "filterLocationEmptyLabel": "Não localizado", - "filterTagEmptyLabel": "Sem etiqueta", + "filterNoLocationLabel": "Não localizado", + "filterNoRatingLabel": "Sem classificação", + "filterNoTagLabel": "Sem etiqueta", "filterOnThisDayLabel": "Neste dia", "filterRecentlyAddedLabel": "Adicionado recentemente", - "filterRatingUnratedLabel": "Sem classificação", "filterRatingRejectedLabel": "Rejeitado", "filterTypeAnimatedLabel": "Animado", "filterTypeMotionPhotoLabel": "Foto em movimento", diff --git a/lib/l10n/app_ru.arb b/lib/l10n/app_ru.arb index ceb54e7a9..02857f957 100644 --- a/lib/l10n/app_ru.arb +++ b/lib/l10n/app_ru.arb @@ -94,9 +94,9 @@ "filterBinLabel": "Корзина", "filterFavouriteLabel": "Избранное", - "filterLocationEmptyLabel": "Без местоположения", - "filterTagEmptyLabel": "Без тегов", - "filterRatingUnratedLabel": "Без рейтинга", + "filterNoLocationLabel": "Без местоположения", + "filterNoRatingLabel": "Без рейтинга", + "filterNoTagLabel": "Без тегов", "filterRatingRejectedLabel": "Отклонённое", "filterTypeAnimatedLabel": "GIF", "filterTypeMotionPhotoLabel": "Живое фото", diff --git a/lib/l10n/app_tr.arb b/lib/l10n/app_tr.arb index 1b29050f2..fd68ac636 100644 --- a/lib/l10n/app_tr.arb +++ b/lib/l10n/app_tr.arb @@ -91,9 +91,9 @@ "filterBinLabel": "Geri dönüşüm kutusu", "filterFavouriteLabel": "Favori", - "filterLocationEmptyLabel": "Konumsuz", - "filterTagEmptyLabel": "Etiketsiz", - "filterRatingUnratedLabel": "Derecelendirilmemiş", + "filterNoLocationLabel": "Konumsuz", + "filterNoRatingLabel": "Derecelendirilmemiş", + "filterNoTagLabel": "Etiketsiz", "filterRatingRejectedLabel": "Reddedilmiş", "filterTypeAnimatedLabel": "Hareketli", "filterTypeMotionPhotoLabel": "Hareketli Fotoğraf", diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 88b4a4cce..2fe141f99 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -94,11 +94,11 @@ "filterBinLabel": "回收站", "filterFavouriteLabel": "收藏夹", - "filterLocationEmptyLabel": "未定位", - "filterTagEmptyLabel": "无标签", + "filterNoLocationLabel": "未定位", + "filterNoRatingLabel": "未评分", + "filterNoTagLabel": "无标签", "filterOnThisDayLabel": "选择日期", "filterRecentlyAddedLabel": "最近添加", - "filterRatingUnratedLabel": "未评分", "filterRatingRejectedLabel": "拒绝", "filterTypeAnimatedLabel": "动画", "filterTypeMotionPhotoLabel": "动态照片", diff --git a/lib/model/filters/filters.dart b/lib/model/filters/filters.dart index 1c0b7a300..a57b0cce7 100644 --- a/lib/model/filters/filters.dart +++ b/lib/model/filters/filters.dart @@ -8,6 +8,7 @@ import 'package:aves/model/filters/date.dart'; import 'package:aves/model/filters/favourite.dart'; import 'package:aves/model/filters/location.dart'; import 'package:aves/model/filters/mime.dart'; +import 'package:aves/model/filters/missing.dart'; import 'package:aves/model/filters/path.dart'; import 'package:aves/model/filters/query.dart'; import 'package:aves/model/filters/rating.dart'; @@ -30,12 +31,14 @@ abstract class CollectionFilter extends Equatable implements Comparable _location; @override - String getLabel(BuildContext context) => _location.isEmpty ? context.l10n.filterLocationEmptyLabel : _location; + String getLabel(BuildContext context) => _location.isEmpty ? context.l10n.filterNoLocationLabel : _location; @override Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) { diff --git a/lib/model/filters/missing.dart b/lib/model/filters/missing.dart new file mode 100644 index 000000000..119355e3e --- /dev/null +++ b/lib/model/filters/missing.dart @@ -0,0 +1,73 @@ +import 'package:aves/model/filters/filters.dart'; +import 'package:aves/theme/icons.dart'; +import 'package:aves/widgets/common/extensions/build_context.dart'; +import 'package:flutter/widgets.dart'; + +class MissingFilter extends CollectionFilter { + static const type = 'missing'; + + static const _date = 'date'; + static const _title = 'title'; + + final String metadataType; + late final EntryFilter _test; + late final IconData _icon; + + static final date = MissingFilter._private(_date); + static final title = MissingFilter._private(_title); + + @override + List get props => [metadataType]; + + MissingFilter._private(this.metadataType) { + switch (metadataType) { + case _date: + _test = (entry) => (entry.catalogMetadata?.dateMillis ?? 0) == 0; + _icon = AIcons.dateUndated; + break; + case _title: + _test = (entry) => (entry.catalogMetadata?.xmpTitle ?? '').isEmpty; + _icon = AIcons.descriptionUntitled; + break; + } + } + + factory MissingFilter.fromMap(Map json) { + return MissingFilter._private( + json['metadataType'], + ); + } + + @override + Map toMap() => { + 'type': type, + 'metadataType': metadataType, + }; + + @override + EntryFilter get test => _test; + + @override + String get universalLabel => metadataType; + + @override + String getLabel(BuildContext context) { + switch (metadataType) { + case _date: + return context.l10n.filterNoDateLabel; + case _title: + return context.l10n.filterNoTitleLabel; + default: + return metadataType; + } + } + + @override + Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(_icon, size: size); + + @override + String get category => type; + + @override + String get key => '$type-$metadataType'; +} diff --git a/lib/model/filters/rating.dart b/lib/model/filters/rating.dart index 7eadd4e8c..ad516aa5e 100644 --- a/lib/model/filters/rating.dart +++ b/lib/model/filters/rating.dart @@ -57,7 +57,7 @@ class RatingFilter extends CollectionFilter { case -1: return context.l10n.filterRatingRejectedLabel; case 0: - return context.l10n.filterRatingUnratedLabel; + return context.l10n.filterNoRatingLabel; default: return '\u2B50' * rating; } diff --git a/lib/model/filters/recent.dart b/lib/model/filters/recent.dart index 3d8e8ae92..f6ffb1a0b 100644 --- a/lib/model/filters/recent.dart +++ b/lib/model/filters/recent.dart @@ -38,7 +38,7 @@ class RecentlyAddedFilter extends CollectionFilter { String getLabel(BuildContext context) => context.l10n.filterRecentlyAddedLabel; @override - Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.recent, size: size); + Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.dateRecent, size: size); @override String get category => type; diff --git a/lib/model/filters/tag.dart b/lib/model/filters/tag.dart index 8c57586ab..b72624da1 100644 --- a/lib/model/filters/tag.dart +++ b/lib/model/filters/tag.dart @@ -44,7 +44,7 @@ class TagFilter extends CoveredCollectionFilter { String get universalLabel => tag; @override - String getLabel(BuildContext context) => tag.isEmpty ? context.l10n.filterTagEmptyLabel : tag; + String getLabel(BuildContext context) => tag.isEmpty ? context.l10n.filterNoTagLabel : tag; @override Widget? iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => showGenericIcon ? Icon(tag.isEmpty ? AIcons.tagUntagged : AIcons.tag, size: size) : null; diff --git a/lib/theme/icons.dart b/lib/theme/icons.dart index 9ab8ba74e..af817ffde 100644 --- a/lib/theme/icons.dart +++ b/lib/theme/icons.dart @@ -16,7 +16,10 @@ class AIcons { static const IconData checked = Icons.done_outlined; static const IconData counter = Icons.plus_one_outlined; static const IconData date = Icons.calendar_today_outlined; + static const IconData dateRecent = Icons.today_outlined; + static const IconData dateUndated = Icons.event_busy_outlined; static const IconData description = Icons.description_outlined; + static const IconData descriptionUntitled = Icons.comments_disabled_outlined; static const IconData disc = Icons.fiber_manual_record; static const IconData display = Icons.light_mode_outlined; static const IconData error = Icons.error_outline; @@ -35,7 +38,6 @@ class AIcons { static const IconData ratingRejected = MdiIcons.starMinusOutline; static const IconData ratingUnrated = MdiIcons.starOffOutline; static const IconData raw = Icons.raw_on_outlined; - static const IconData recent = Icons.today_outlined; static const IconData shooting = Icons.camera_outlined; static const IconData removableStorage = Icons.sd_storage_outlined; static const IconData sensorControlEnabled = Icons.explore_outlined; diff --git a/lib/widgets/dialogs/entry_editors/edit_rating_dialog.dart b/lib/widgets/dialogs/entry_editors/edit_rating_dialog.dart index 49c848423..2e07e0751 100644 --- a/lib/widgets/dialogs/entry_editors/edit_rating_dialog.dart +++ b/lib/widgets/dialogs/entry_editors/edit_rating_dialog.dart @@ -95,7 +95,7 @@ class _EditEntryRatingDialogState extends State { _action = v!; _rating = 0; }), - title: Text(l10n.filterRatingUnratedLabel), + title: Text(l10n.filterNoRatingLabel), ), ], actions: [ diff --git a/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart b/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart index 3fb6d620a..7ce92e34c 100644 --- a/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart +++ b/lib/widgets/dialogs/entry_editors/edit_tags_dialog.dart @@ -125,7 +125,7 @@ class _TagEditorPageState extends State { const Icon(AIcons.tagUntagged, color: untaggedColor), const SizedBox(width: 8), Text( - l10n.filterTagEmptyLabel, + l10n.filterNoTagLabel, style: const TextStyle(color: untaggedColor), ), ], diff --git a/lib/widgets/search/search_delegate.dart b/lib/widgets/search/search_delegate.dart index 08c31ce53..0b23308ab 100644 --- a/lib/widgets/search/search_delegate.dart +++ b/lib/widgets/search/search_delegate.dart @@ -4,6 +4,7 @@ import 'package:aves/model/filters/favourite.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/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'; @@ -105,6 +106,7 @@ class CollectionSearchDelegate extends AvesSearchDelegate { _buildPlaceFilters(containQuery), _buildTagFilters(containQuery), _buildRatingFilters(context, containQuery), + _buildMetadataFilters(context, containQuery), ], ); }); @@ -166,11 +168,10 @@ class CollectionSearchDelegate extends AvesSearchDelegate { return StreamBuilder( stream: source.eventBus.on(), builder: (context, snapshot) { - final filters = source.sortedCountries.where(containQuery).map((s) => LocationFilter(LocationLevel.country, s)).toList(); return _buildFilterRow( context: context, title: context.l10n.searchCountriesSectionTitle, - filters: filters, + filters: source.sortedCountries.where(containQuery).map((s) => LocationFilter(LocationLevel.country, s)).toList(), ); }, ); @@ -180,15 +181,10 @@ class CollectionSearchDelegate extends AvesSearchDelegate { return StreamBuilder( stream: source.eventBus.on(), builder: (context, snapshot) { - final filters = source.sortedPlaces.where(containQuery).map((s) => LocationFilter(LocationLevel.place, s)); - final noFilter = LocationFilter(LocationLevel.place, ''); return _buildFilterRow( context: context, title: context.l10n.searchPlacesSectionTitle, - filters: [ - if (containQuery(noFilter.getLabel(context))) noFilter, - ...filters, - ], + filters: source.sortedPlaces.where(containQuery).map((s) => LocationFilter(LocationLevel.place, s)).toList(), ); }, ); @@ -198,15 +194,10 @@ class CollectionSearchDelegate extends AvesSearchDelegate { return StreamBuilder( stream: source.eventBus.on(), builder: (context, snapshot) { - final filters = source.sortedTags.where(containQuery).map(TagFilter.new); - final noFilter = TagFilter(''); return _buildFilterRow( context: context, title: context.l10n.searchTagsSectionTitle, - filters: [ - if (containQuery(noFilter.getLabel(context))) noFilter, - ...filters, - ], + filters: source.sortedTags.where(containQuery).map(TagFilter.new).toList(), ); }, ); @@ -216,7 +207,21 @@ class CollectionSearchDelegate extends AvesSearchDelegate { return _buildFilterRow( context: context, title: context.l10n.searchRatingSectionTitle, - filters: [0, 5, 4, 3, 2, 1, -1].map(RatingFilter.new).where((f) => containQuery(f.getLabel(context))).toList(), + filters: [5, 4, 3, 2, 1, -1].map(RatingFilter.new).where((f) => containQuery(f.getLabel(context))).toList(), + ); + } + + Widget _buildMetadataFilters(BuildContext context, _ContainQuery containQuery) { + return _buildFilterRow( + context: context, + title: context.l10n.searchMetadataSectionTitle, + filters: [ + MissingFilter.date, + LocationFilter(LocationLevel.place, ''), + TagFilter(''), + const RatingFilter(0), + MissingFilter.title, + ].where((f) => containQuery(f.getLabel(context))).toList(), ); } diff --git a/test/model/filters_test.dart b/test/model/filters_test.dart index f6d7059d8..39e6f582f 100644 --- a/test/model/filters_test.dart +++ b/test/model/filters_test.dart @@ -5,6 +5,7 @@ import 'package:aves/model/filters/favourite.dart'; import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/location.dart'; import 'package:aves/model/filters/mime.dart'; +import 'package:aves/model/filters/missing.dart'; import 'package:aves/model/filters/path.dart'; import 'package:aves/model/filters/query.dart'; import 'package:aves/model/filters/rating.dart'; @@ -53,6 +54,9 @@ void main() { final mime = MimeFilter.video; expect(mime, jsonRoundTrip(mime)); + final missing = MissingFilter.title; + expect(missing, jsonRoundTrip(missing)); + final path = PathFilter('/some/path/'); expect(path, jsonRoundTrip(path)); diff --git a/untranslated.json b/untranslated.json index 9b8fc4af3..2083a68b3 100644 --- a/untranslated.json +++ b/untranslated.json @@ -1,51 +1,78 @@ { "de": [ - "entryInfoActionEditTitleDescription" + "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", + "searchMetadataSectionTitle" ], "el": [ - "entryInfoActionEditTitleDescription" + "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", + "searchMetadataSectionTitle" ], "es": [ "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", "filterRecentlyAddedLabel", + "searchMetadataSectionTitle", "settingsConfirmationAfterMoveToBinItems", "viewerInfoLabelDescription" ], "id": [ "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", "filterRecentlyAddedLabel", + "searchMetadataSectionTitle", "settingsConfirmationAfterMoveToBinItems", "settingsViewerGestureSideTapNext", "viewerInfoLabelDescription" ], "it": [ - "entryInfoActionEditTitleDescription" + "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", + "searchMetadataSectionTitle" ], "ja": [ "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", "filterRecentlyAddedLabel", + "searchMetadataSectionTitle", "settingsConfirmationAfterMoveToBinItems", "settingsViewerGestureSideTapNext", "viewerInfoLabelDescription" ], "nl": [ - "entryInfoActionEditTitleDescription" + "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", + "searchMetadataSectionTitle" ], "pt": [ - "entryInfoActionEditTitleDescription" + "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", + "searchMetadataSectionTitle" ], "ru": [ "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", "filterOnThisDayLabel", "filterRecentlyAddedLabel", + "searchMetadataSectionTitle", "settingsConfirmationAfterMoveToBinItems", "settingsViewerGestureSideTapNext", "settingsSlideshowFillScreen", @@ -58,6 +85,8 @@ "slideshowActionResume", "slideshowActionShowInCollection", "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", "filterOnThisDayLabel", "filterRecentlyAddedLabel", "slideshowVideoPlaybackSkip", @@ -71,6 +100,7 @@ "wallpaperTargetLock", "wallpaperTargetHomeLock", "menuActionSlideshow", + "searchMetadataSectionTitle", "settingsConfirmationAfterMoveToBinItems", "settingsViewerGestureSideTapNext", "settingsViewerSlideshowTile", @@ -91,6 +121,9 @@ ], "zh": [ - "entryInfoActionEditTitleDescription" + "entryInfoActionEditTitleDescription", + "filterNoDateLabel", + "filterNoTitleLabel", + "searchMetadataSectionTitle" ] }