search: added recent filters
This commit is contained in:
parent
2dcb2b6c7b
commit
206e30de30
13 changed files with 87 additions and 7 deletions
|
@ -87,6 +87,6 @@ class AlbumFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AlbumFilter{album=$album}';
|
||||
return '$runtimeType#${shortHash(this)}{album=$album}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/widgets/common/icons.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class LocationFilter extends CollectionFilter {
|
||||
|
@ -45,7 +46,7 @@ class LocationFilter extends CollectionFilter {
|
|||
// as of Flutter v1.22.0-12.1.pre emoji shadows are rendered as colorful duplicates,
|
||||
// not filled with the shadow color as expected, so we remove them
|
||||
if (flag != null) return Text(flag, style: TextStyle(fontSize: size, shadows: []));
|
||||
return Icon(AIcons.location, size: size);
|
||||
return Icon(_location.isEmpty ? AIcons.locationOff : AIcons.location, size: size);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -62,7 +63,7 @@ class LocationFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String toString() {
|
||||
return 'LocationFilter{level=$level, location=$_location}';
|
||||
return '$runtimeType#${shortHash(this)}{level=$level, location=$_location}';
|
||||
}
|
||||
|
||||
// U+0041 Latin Capital letter A
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/widgets/common/icons.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class MimeFilter extends CollectionFilter {
|
||||
|
@ -81,4 +82,9 @@ class MimeFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
int get hashCode => hashValues(type, mime);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '$runtimeType#${shortHash(this)}{mime=$mime}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,4 +69,9 @@ class QueryFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
int get hashCode => hashValues(type, query);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return '$runtimeType#${shortHash(this)}{query=$query}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:aves/model/filters/filters.dart';
|
||||
import 'package:aves/model/image_entry.dart';
|
||||
import 'package:aves/widgets/common/icons.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
|
||||
class TagFilter extends CollectionFilter {
|
||||
|
@ -32,7 +33,7 @@ class TagFilter extends CollectionFilter {
|
|||
String get label => tag.isEmpty ? emptyLabel : tag;
|
||||
|
||||
@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(tag.isEmpty ? AIcons.tagOff : AIcons.tag, size: size) : null;
|
||||
|
||||
@override
|
||||
String get typeKey => type;
|
||||
|
@ -48,6 +49,6 @@ class TagFilter extends CollectionFilter {
|
|||
|
||||
@override
|
||||
String toString() {
|
||||
return 'TagFilter{tag=$tag}';
|
||||
return '$runtimeType#${shortHash(this)}{tag=$tag}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,6 +55,10 @@ class Settings extends ChangeNotifier {
|
|||
// rendering
|
||||
static const svgBackgroundKey = 'svg_background';
|
||||
|
||||
// search
|
||||
static const saveSearchHistoryKey = 'save_search_history';
|
||||
static const searchHistoryKey = 'search_history';
|
||||
|
||||
Future<void> init() async {
|
||||
_prefs = await SharedPreferences.getInstance();
|
||||
}
|
||||
|
@ -179,6 +183,16 @@ class Settings extends ChangeNotifier {
|
|||
|
||||
set svgBackground(int newValue) => setAndNotify(svgBackgroundKey, newValue);
|
||||
|
||||
// search
|
||||
|
||||
bool get saveSearchHistory => getBoolOrDefault(saveSearchHistoryKey, true);
|
||||
|
||||
set saveSearchHistory(bool newValue) => setAndNotify(saveSearchHistoryKey, newValue);
|
||||
|
||||
List<CollectionFilter> get searchHistory => (_prefs.getStringList(searchHistoryKey) ?? []).map(CollectionFilter.fromJson).toList();
|
||||
|
||||
set searchHistory(List<CollectionFilter> newValue) => setAndNotify(searchHistoryKey, newValue.map((filter) => filter.toJson()).toList());
|
||||
|
||||
// utils
|
||||
|
||||
// `RoutePredicate`
|
||||
|
|
|
@ -160,6 +160,12 @@ class Constants {
|
|||
licenseUrl: 'https://github.com/MikeMitterer/dart-latlong/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/MikeMitterer/dart-latlong',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Material Design Icons Flutter',
|
||||
license: 'MIT',
|
||||
licenseUrl: 'https://github.com/ziofat/material_design_icons_flutter/blob/master/LICENSE',
|
||||
sourceUrl: 'https://github.com/ziofat/material_design_icons_flutter',
|
||||
),
|
||||
Dependency(
|
||||
name: 'Overlay Support',
|
||||
license: 'Apache 2.0',
|
||||
|
|
|
@ -316,6 +316,7 @@ class AppDebugPageState extends State<AppDebugPage> {
|
|||
'collectionTileExtent': '${settings.collectionTileExtent}',
|
||||
'infoMapZoom': '${settings.infoMapZoom}',
|
||||
'pinnedFilters': '${settings.pinnedFilters}',
|
||||
'searchHistory': '${settings.searchHistory}',
|
||||
}),
|
||||
],
|
||||
);
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:aves/utils/constants.dart';
|
|||
import 'package:aves/widgets/common/image_providers/app_icon_image_provider.dart';
|
||||
import 'package:decorated_icon/decorated_icon.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_design_icons_flutter/material_design_icons_flutter.dart';
|
||||
|
||||
class AIcons {
|
||||
static const IconData allCollection = Icons.collections_outlined;
|
||||
|
@ -20,15 +21,17 @@ class AIcons {
|
|||
static const IconData disc = Icons.fiber_manual_record;
|
||||
static const IconData error = Icons.error_outline;
|
||||
static const IconData location = Icons.place_outlined;
|
||||
static const IconData locationOff = Icons.location_off_outlined;
|
||||
static const IconData raw = Icons.camera_outlined;
|
||||
static const IconData shooting = Icons.camera_outlined;
|
||||
static const IconData removableStorage = Icons.sd_storage_outlined;
|
||||
static const IconData settings = Icons.settings_outlined;
|
||||
static const IconData text = Icons.format_quote_outlined;
|
||||
static const IconData tag = Icons.local_offer_outlined;
|
||||
static const IconData tagOff = MdiIcons.tagOffOutline;
|
||||
|
||||
// actions
|
||||
static const IconData addShortcut = Icons.bookmark_border;
|
||||
static const IconData addShortcut = Icons.add_to_home_screen_outlined;
|
||||
static const IconData clear = Icons.clear_outlined;
|
||||
static const IconData collapse = Icons.expand_less_outlined;
|
||||
static const IconData createAlbum = Icons.add_circle_outline;
|
||||
|
|
|
@ -25,6 +25,8 @@ class ImageSearchDelegate {
|
|||
final ValueNotifier<String> expandedSectionNotifier = ValueNotifier(null);
|
||||
final CollectionLens parentCollection;
|
||||
|
||||
static const searchHistoryCount = 10;
|
||||
|
||||
ImageSearchDelegate({@required this.source, this.parentCollection});
|
||||
|
||||
ThemeData appBarTheme(BuildContext context) {
|
||||
|
@ -67,7 +69,8 @@ class ImageSearchDelegate {
|
|||
child: ValueListenableBuilder<String>(
|
||||
valueListenable: expandedSectionNotifier,
|
||||
builder: (context, expandedSection, child) {
|
||||
var queryFilter = _buildQueryFilter(false);
|
||||
final queryFilter = _buildQueryFilter(false);
|
||||
final history = settings.searchHistory;
|
||||
return ListView(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
children: [
|
||||
|
@ -85,6 +88,12 @@ class ImageSearchDelegate {
|
|||
// but we also need to animate the query chip when it is selected by submitting the search query
|
||||
heroTypeBuilder: (filter) => filter == queryFilter ? HeroType.always : HeroType.onTap,
|
||||
),
|
||||
if (upQuery.isEmpty && history.isNotEmpty)
|
||||
_buildFilterRow(
|
||||
context: context,
|
||||
title: 'Recent',
|
||||
filters: history,
|
||||
),
|
||||
StreamBuilder(
|
||||
stream: source.eventBus.on<AlbumsChangedEvent>(),
|
||||
builder: (context, snapshot) {
|
||||
|
@ -170,6 +179,12 @@ class ImageSearchDelegate {
|
|||
}
|
||||
|
||||
void _select(BuildContext context, CollectionFilter filter) {
|
||||
if (settings.saveSearchHistory) {
|
||||
final history = settings.searchHistory
|
||||
..remove(filter)
|
||||
..insert(0, filter);
|
||||
settings.searchHistory = history.take(searchHistoryCount).toList();
|
||||
}
|
||||
if (parentCollection != null) {
|
||||
_applyToParentCollectionPage(context, filter);
|
||||
} else {
|
||||
|
|
|
@ -40,6 +40,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||
_buildDisplaySection(context),
|
||||
_buildThumbnailsSection(context),
|
||||
_buildViewerSection(context),
|
||||
_buildSearchSection(context),
|
||||
_buildPrivacySection(context),
|
||||
],
|
||||
),
|
||||
|
@ -171,6 +172,25 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget _buildSearchSection(BuildContext context) {
|
||||
return AvesExpansionTile(
|
||||
title: 'Search',
|
||||
expandedNotifier: _expandedNotifier,
|
||||
children: [
|
||||
SwitchListTile(
|
||||
value: settings.saveSearchHistory,
|
||||
onChanged: (v) {
|
||||
settings.saveSearchHistory = v;
|
||||
if (!v) {
|
||||
settings.searchHistory = [];
|
||||
}
|
||||
},
|
||||
title: Text('Save search history'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildPrivacySection(BuildContext context) {
|
||||
return AvesExpansionTile(
|
||||
title: 'Privacy',
|
||||
|
|
|
@ -480,6 +480,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.12.10-nullsafety.1"
|
||||
material_design_icons_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: material_design_icons_flutter
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "4.0.5755"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
|
|
@ -65,6 +65,7 @@ dependencies:
|
|||
google_maps_flutter:
|
||||
intl:
|
||||
latlong: # for flutter_map
|
||||
material_design_icons_flutter:
|
||||
overlay_support:
|
||||
package_info:
|
||||
palette_generator:
|
||||
|
|
Loading…
Reference in a new issue