search: added filters for entries without location, without tags

This commit is contained in:
Thibault Deckers 2020-11-01 09:21:35 +09:00
parent b83986e01a
commit 2dcb2b6c7b
9 changed files with 32 additions and 18 deletions

View file

@ -5,6 +5,7 @@ import 'package:flutter/widgets.dart';
class LocationFilter extends CollectionFilter { class LocationFilter extends CollectionFilter {
static const type = 'location'; static const type = 'location';
static const emptyLabel = 'unlocated';
static const locationSeparator = ';'; static const locationSeparator = ';';
final LocationLevel level; final LocationLevel level;
@ -33,10 +34,10 @@ class LocationFilter extends CollectionFilter {
String get countryNameAndCode => '$_location$locationSeparator$_countryCode'; String get countryNameAndCode => '$_location$locationSeparator$_countryCode';
@override @override
bool filter(ImageEntry entry) => entry.isLocated && ((level == LocationLevel.country && entry.addressDetails.countryCode == _countryCode) || (level == LocationLevel.place && entry.addressDetails.place == _location)); bool filter(ImageEntry entry) => _location.isEmpty ? !entry.isLocated : entry.isLocated && ((level == LocationLevel.country && entry.addressDetails.countryCode == _countryCode) || (level == LocationLevel.place && entry.addressDetails.place == _location));
@override @override
String get label => _location; String get label => _location.isEmpty ? emptyLabel : _location;
@override @override
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true, bool embossed = false}) { Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true, bool embossed = false}) {

View file

@ -5,6 +5,7 @@ import 'package:flutter/widgets.dart';
class TagFilter extends CollectionFilter { class TagFilter extends CollectionFilter {
static const type = 'tag'; static const type = 'tag';
static const emptyLabel = 'untagged';
final String tag; final String tag;
@ -22,13 +23,13 @@ class TagFilter extends CollectionFilter {
}; };
@override @override
bool filter(ImageEntry entry) => entry.xmpSubjects.contains(tag); bool filter(ImageEntry entry) => tag.isEmpty ? entry.xmpSubjects.isEmpty : entry.xmpSubjects.contains(tag);
@override @override
bool get isUnique => false; bool get isUnique => false;
@override @override
String get label => tag; String get label => tag.isEmpty ? emptyLabel : tag;
@override @override
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true, bool embossed = false}) => showGenericIcon ? Icon(AIcons.tag, size: size) : null; Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true, bool embossed = false}) => showGenericIcon ? Icon(AIcons.tag, size: size) : null;

View file

@ -9,7 +9,6 @@ import 'package:aves/services/app_shortcut_service.dart';
import 'package:aves/utils/durations.dart'; import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/collection/collection_actions.dart'; import 'package:aves/widgets/collection/collection_actions.dart';
import 'package:aves/widgets/collection/filter_bar.dart'; import 'package:aves/widgets/collection/filter_bar.dart';
import 'package:aves/widgets/collection/search/search_delegate.dart';
import 'package:aves/widgets/common/action_delegates/add_shortcut_dialog.dart'; import 'package:aves/widgets/common/action_delegates/add_shortcut_dialog.dart';
import 'package:aves/widgets/common/action_delegates/selection_action_delegate.dart'; import 'package:aves/widgets/common/action_delegates/selection_action_delegate.dart';
import 'package:aves/widgets/common/app_bar_subtitle.dart'; import 'package:aves/widgets/common/app_bar_subtitle.dart';
@ -19,7 +18,8 @@ import 'package:aves/widgets/common/data_providers/media_store_collection_provid
import 'package:aves/widgets/common/entry_actions.dart'; import 'package:aves/widgets/common/entry_actions.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:aves/widgets/common/menu_row.dart'; import 'package:aves/widgets/common/menu_row.dart';
import 'package:aves/widgets/common/search_button.dart'; import 'package:aves/widgets/search/search_button.dart';
import 'package:aves/widgets/search/search_delegate.dart';
import 'package:aves/widgets/stats/stats.dart'; import 'package:aves/widgets/stats/stats.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';

View file

@ -8,7 +8,6 @@ import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/model/source/collection_source.dart'; import 'package:aves/model/source/collection_source.dart';
import 'package:aves/utils/durations.dart'; import 'package:aves/utils/durations.dart';
import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/collection/search/search_delegate.dart';
import 'package:aves/widgets/common/app_bar_subtitle.dart'; import 'package:aves/widgets/common/app_bar_subtitle.dart';
import 'package:aves/widgets/common/app_bar_title.dart'; import 'package:aves/widgets/common/app_bar_title.dart';
import 'package:aves/widgets/common/aves_filter_chip.dart'; import 'package:aves/widgets/common/aves_filter_chip.dart';
@ -17,12 +16,13 @@ import 'package:aves/widgets/common/double_back_pop.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:aves/widgets/common/menu_row.dart'; import 'package:aves/widgets/common/menu_row.dart';
import 'package:aves/widgets/common/scroll_thumb.dart'; import 'package:aves/widgets/common/scroll_thumb.dart';
import 'package:aves/widgets/common/search_button.dart';
import 'package:aves/widgets/drawer/app_drawer.dart'; import 'package:aves/widgets/drawer/app_drawer.dart';
import 'package:aves/widgets/filter_grids/common/chip_action_delegate.dart'; import 'package:aves/widgets/filter_grids/common/chip_action_delegate.dart';
import 'package:aves/widgets/filter_grids/common/chip_actions.dart'; import 'package:aves/widgets/filter_grids/common/chip_actions.dart';
import 'package:aves/widgets/filter_grids/common/chip_set_action_delegate.dart'; import 'package:aves/widgets/filter_grids/common/chip_set_action_delegate.dart';
import 'package:aves/widgets/filter_grids/common/decorated_filter_chip.dart'; import 'package:aves/widgets/filter_grids/common/decorated_filter_chip.dart';
import 'package:aves/widgets/search/search_button.dart';
import 'package:aves/widgets/search/search_delegate.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:draggable_scrollbar/draggable_scrollbar.dart'; import 'package:draggable_scrollbar/draggable_scrollbar.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';

View file

@ -9,12 +9,12 @@ import 'package:aves/services/image_file_service.dart';
import 'package:aves/services/viewer_service.dart'; import 'package:aves/services/viewer_service.dart';
import 'package:aves/utils/android_file_utils.dart'; import 'package:aves/utils/android_file_utils.dart';
import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/collection/search/search_delegate.dart';
import 'package:aves/widgets/collection/search_page.dart';
import 'package:aves/widgets/common/data_providers/media_store_collection_provider.dart'; import 'package:aves/widgets/common/data_providers/media_store_collection_provider.dart';
import 'package:aves/widgets/common/routes.dart'; import 'package:aves/widgets/common/routes.dart';
import 'package:aves/widgets/filter_grids/albums_page.dart'; import 'package:aves/widgets/filter_grids/albums_page.dart';
import 'package:aves/widgets/fullscreen/fullscreen_page.dart'; import 'package:aves/widgets/fullscreen/fullscreen_page.dart';
import 'package:aves/widgets/search/search_delegate.dart';
import 'package:aves/widgets/search/search_page.dart';
import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';

View file

@ -1,7 +1,7 @@
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/model/source/collection_source.dart'; import 'package:aves/model/source/collection_source.dart';
import 'package:aves/widgets/collection/search/search_delegate.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:aves/widgets/search/search_delegate.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class SearchButton extends StatelessWidget { class SearchButton extends StatelessWidget {

View file

@ -13,10 +13,10 @@ import 'package:aves/model/source/collection_source.dart';
import 'package:aves/model/source/location.dart'; import 'package:aves/model/source/location.dart';
import 'package:aves/model/source/tag.dart'; import 'package:aves/model/source/tag.dart';
import 'package:aves/widgets/collection/collection_page.dart'; import 'package:aves/widgets/collection/collection_page.dart';
import 'package:aves/widgets/collection/search/expandable_filter_row.dart';
import 'package:aves/widgets/collection/search_page.dart';
import 'package:aves/widgets/common/aves_filter_chip.dart'; import 'package:aves/widgets/common/aves_filter_chip.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:aves/widgets/search/expandable_filter_row.dart';
import 'package:aves/widgets/search/search_page.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
@ -88,37 +88,49 @@ class ImageSearchDelegate {
StreamBuilder( StreamBuilder(
stream: source.eventBus.on<AlbumsChangedEvent>(), stream: source.eventBus.on<AlbumsChangedEvent>(),
builder: (context, snapshot) { builder: (context, snapshot) {
final filters = source.sortedAlbums.where(containQuery).map((s) => AlbumFilter(s, source.getUniqueAlbumName(s))).where((f) => containQuery(f.uniqueName));
return _buildFilterRow( return _buildFilterRow(
context: context, context: context,
title: 'Albums', title: 'Albums',
filters: source.sortedAlbums.where(containQuery).map((s) => AlbumFilter(s, source.getUniqueAlbumName(s))).where((f) => containQuery(f.uniqueName)), filters: filters,
); );
}), }),
StreamBuilder( StreamBuilder(
stream: source.eventBus.on<LocationsChangedEvent>(), stream: source.eventBus.on<LocationsChangedEvent>(),
builder: (context, snapshot) { builder: (context, snapshot) {
final filters = source.sortedCountries.where(containQuery).map((s) => LocationFilter(LocationLevel.country, s));
return _buildFilterRow( return _buildFilterRow(
context: context, context: context,
title: 'Countries', title: 'Countries',
filters: source.sortedCountries.where(containQuery).map((s) => LocationFilter(LocationLevel.country, s)), filters: filters,
); );
}), }),
StreamBuilder( StreamBuilder(
stream: source.eventBus.on<LocationsChangedEvent>(), stream: source.eventBus.on<LocationsChangedEvent>(),
builder: (context, snapshot) { builder: (context, snapshot) {
final filters = source.sortedPlaces.where(containQuery).map((s) => LocationFilter(LocationLevel.place, s));
final noFilter = LocationFilter(LocationLevel.place, '');
return _buildFilterRow( return _buildFilterRow(
context: context, context: context,
title: 'Places', title: 'Places',
filters: source.sortedPlaces.where(containQuery).map((s) => LocationFilter(LocationLevel.place, s)), filters: [
if (containQuery(LocationFilter.emptyLabel)) noFilter,
...filters,
],
); );
}), }),
StreamBuilder( StreamBuilder(
stream: source.eventBus.on<TagsChangedEvent>(), stream: source.eventBus.on<TagsChangedEvent>(),
builder: (context, snapshot) { builder: (context, snapshot) {
final filters = source.sortedTags.where(containQuery).map((s) => TagFilter(s));
final noFilter = TagFilter('');
return _buildFilterRow( return _buildFilterRow(
context: context, context: context,
title: 'Tags', title: 'Tags',
filters: source.sortedTags.where(containQuery).map((s) => TagFilter(s)), filters: [
if (containQuery(TagFilter.emptyLabel)) noFilter,
...filters,
],
); );
}), }),
], ],

View file

@ -1,4 +1,4 @@
import 'package:aves/widgets/collection/search/search_delegate.dart'; import 'package:aves/widgets/search/search_delegate.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';