drawer: navigate by country
This commit is contained in:
parent
39185f5ba8
commit
2e5a2e7c91
4 changed files with 70 additions and 13 deletions
|
@ -24,6 +24,15 @@ class TagFilter extends CollectionFilter {
|
||||||
bool filter(ImageEntry entry) => entry.xmpSubjects.contains(tag);
|
bool filter(ImageEntry entry) => entry.xmpSubjects.contains(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CountryFilter extends CollectionFilter {
|
||||||
|
final String country;
|
||||||
|
|
||||||
|
const CountryFilter(this.country);
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool filter(ImageEntry entry) => entry.isLocated && entry.addressDetails.countryName == country;
|
||||||
|
}
|
||||||
|
|
||||||
class VideoFilter extends CollectionFilter {
|
class VideoFilter extends CollectionFilter {
|
||||||
@override
|
@override
|
||||||
bool filter(ImageEntry entry) => entry.isVideo;
|
bool filter(ImageEntry entry) => entry.isVideo;
|
||||||
|
|
|
@ -28,7 +28,7 @@ class CollectionLens with ChangeNotifier {
|
||||||
this.sortFactor = sortFactor ?? SortFactor.date {
|
this.sortFactor = sortFactor ?? SortFactor.date {
|
||||||
_subscriptions.add(source.eventBus.on<EntryAddedEvent>().listen((e) => onEntryAdded()));
|
_subscriptions.add(source.eventBus.on<EntryAddedEvent>().listen((e) => onEntryAdded()));
|
||||||
_subscriptions.add(source.eventBus.on<EntryRemovedEvent>().listen((e) => onEntryRemoved(e.entry)));
|
_subscriptions.add(source.eventBus.on<EntryRemovedEvent>().listen((e) => onEntryRemoved(e.entry)));
|
||||||
_subscriptions.add(source.eventBus.on<MetadataChangedEvent>().listen((e) => onMetadataChanged()));
|
_subscriptions.add(source.eventBus.on<CatalogMetadataChangedEvent>().listen((e) => onMetadataChanged()));
|
||||||
onEntryAdded();
|
onEntryAdded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ class CollectionSource {
|
||||||
|
|
||||||
List<String> sortedAlbums = List.unmodifiable(const Iterable.empty());
|
List<String> sortedAlbums = List.unmodifiable(const Iterable.empty());
|
||||||
List<String> sortedTags = List.unmodifiable(const Iterable.empty());
|
List<String> sortedTags = List.unmodifiable(const Iterable.empty());
|
||||||
|
List<String> sortedCountries = List.unmodifiable(const Iterable.empty());
|
||||||
|
|
||||||
List<ImageEntry> get entries => List.unmodifiable(_rawEntries);
|
List<ImageEntry> get entries => List.unmodifiable(_rawEntries);
|
||||||
|
|
||||||
|
@ -35,7 +36,7 @@ class CollectionSource {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
debugPrint('$runtimeType loadCatalogMetadata complete in ${stopwatch.elapsed.inMilliseconds}ms with ${saved.length} saved entries');
|
debugPrint('$runtimeType loadCatalogMetadata complete in ${stopwatch.elapsed.inMilliseconds}ms with ${saved.length} saved entries');
|
||||||
onMetadataChanged();
|
onCatalogMetadataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadAddresses() async {
|
Future<void> loadAddresses() async {
|
||||||
|
@ -48,6 +49,7 @@ class CollectionSource {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
debugPrint('$runtimeType loadAddresses complete in ${stopwatch.elapsed.inMilliseconds}ms with ${saved.length} saved entries');
|
debugPrint('$runtimeType loadAddresses complete in ${stopwatch.elapsed.inMilliseconds}ms with ${saved.length} saved entries');
|
||||||
|
onAddressMetadataChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> catalogEntries() async {
|
Future<void> catalogEntries() async {
|
||||||
|
@ -65,15 +67,10 @@ class CollectionSource {
|
||||||
if (newMetadata.isEmpty) return;
|
if (newMetadata.isEmpty) return;
|
||||||
|
|
||||||
await metadataDb.saveMetadata(List.unmodifiable(newMetadata));
|
await metadataDb.saveMetadata(List.unmodifiable(newMetadata));
|
||||||
onMetadataChanged();
|
onCatalogMetadataChanged();
|
||||||
debugPrint('$runtimeType catalogEntries complete in ${stopwatch.elapsed.inSeconds}s with ${newMetadata.length} new entries');
|
debugPrint('$runtimeType catalogEntries complete in ${stopwatch.elapsed.inSeconds}s with ${newMetadata.length} new entries');
|
||||||
}
|
}
|
||||||
|
|
||||||
void onMetadataChanged() {
|
|
||||||
updateTags();
|
|
||||||
eventBus.fire(MetadataChangedEvent());
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> locateEntries() async {
|
Future<void> locateEntries() async {
|
||||||
final stopwatch = Stopwatch()..start();
|
final stopwatch = Stopwatch()..start();
|
||||||
final unlocatedEntries = _rawEntries.where((entry) => entry.hasGps && !entry.isLocated).toList();
|
final unlocatedEntries = _rawEntries.where((entry) => entry.hasGps && !entry.isLocated).toList();
|
||||||
|
@ -89,9 +86,20 @@ class CollectionSource {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
await metadataDb.saveAddresses(List.unmodifiable(newAddresses));
|
await metadataDb.saveAddresses(List.unmodifiable(newAddresses));
|
||||||
|
onAddressMetadataChanged();
|
||||||
debugPrint('$runtimeType locateEntries complete in ${stopwatch.elapsed.inMilliseconds}ms');
|
debugPrint('$runtimeType locateEntries complete in ${stopwatch.elapsed.inMilliseconds}ms');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void onCatalogMetadataChanged() {
|
||||||
|
updateTags();
|
||||||
|
eventBus.fire(CatalogMetadataChangedEvent());
|
||||||
|
}
|
||||||
|
|
||||||
|
void onAddressMetadataChanged() {
|
||||||
|
updateLocations();
|
||||||
|
eventBus.fire(AddressMetadataChangedEvent());
|
||||||
|
}
|
||||||
|
|
||||||
void updateAlbums() {
|
void updateAlbums() {
|
||||||
final albums = _rawEntries.map((entry) => entry.directory).toSet();
|
final albums = _rawEntries.map((entry) => entry.directory).toSet();
|
||||||
final sorted = albums.toList()
|
final sorted = albums.toList()
|
||||||
|
@ -104,9 +112,14 @@ class CollectionSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateTags() {
|
void updateTags() {
|
||||||
final tags = _rawEntries.expand((entry) => entry.xmpSubjects).toSet();
|
final tags = _rawEntries.expand((entry) => entry.xmpSubjects).toSet().toList()..sort(compareAsciiUpperCase);
|
||||||
final sorted = tags.toList()..sort(compareAsciiUpperCase);
|
sortedTags = List.unmodifiable(tags);
|
||||||
sortedTags = List.unmodifiable(sorted);
|
}
|
||||||
|
|
||||||
|
void updateLocations() {
|
||||||
|
final locatedEntries = _rawEntries.where((entry) => entry.isLocated);
|
||||||
|
final countries = locatedEntries.map((entry) => entry.addressDetails.countryName).toSet().toList()..sort(compareAsciiUpperCase);
|
||||||
|
sortedCountries = List.unmodifiable(countries);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(ImageEntry entry) {
|
void add(ImageEntry entry) {
|
||||||
|
@ -140,7 +153,9 @@ class CollectionSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MetadataChangedEvent {}
|
class AddressMetadataChangedEvent {}
|
||||||
|
|
||||||
|
class CatalogMetadataChangedEvent {}
|
||||||
|
|
||||||
class EntryAddedEvent {
|
class EntryAddedEvent {
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
|
|
|
@ -20,7 +20,7 @@ class AllCollectionDrawer extends StatefulWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
||||||
bool _albumsExpanded = false, _tagsExpanded = false;
|
bool _albumsExpanded = false, _tagsExpanded = false, _countriesExpanded = false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -113,6 +113,16 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
||||||
dense: true,
|
dense: true,
|
||||||
filter: TagFilter(tag),
|
filter: TagFilter(tag),
|
||||||
);
|
);
|
||||||
|
final buildCountryEntry = (country) => _FilteredCollectionNavTile(
|
||||||
|
collection: collection,
|
||||||
|
leading: Icon(
|
||||||
|
OMIcons.place,
|
||||||
|
color: stringToColor(country),
|
||||||
|
),
|
||||||
|
title: country,
|
||||||
|
dense: true,
|
||||||
|
filter: CountryFilter(country),
|
||||||
|
);
|
||||||
|
|
||||||
final regularAlbums = [], appAlbums = [], specialAlbums = [];
|
final regularAlbums = [], appAlbums = [], specialAlbums = [];
|
||||||
for (var album in source.sortedAlbums) {
|
for (var album in source.sortedAlbums) {
|
||||||
|
@ -130,6 +140,7 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
||||||
}
|
}
|
||||||
|
|
||||||
final tags = source.sortedTags;
|
final tags = source.sortedTags;
|
||||||
|
final countries = source.sortedCountries;
|
||||||
final drawerItems = [
|
final drawerItems = [
|
||||||
header,
|
header,
|
||||||
gifEntry,
|
gifEntry,
|
||||||
|
@ -186,6 +197,28 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
||||||
children: tags.map(buildTagEntry).toList(),
|
children: tags.map(buildTagEntry).toList(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (countries.isNotEmpty)
|
||||||
|
SafeArea(
|
||||||
|
top: false,
|
||||||
|
bottom: false,
|
||||||
|
child: ExpansionTile(
|
||||||
|
leading: const Icon(OMIcons.place),
|
||||||
|
title: Row(
|
||||||
|
children: [
|
||||||
|
const Text('Countries'),
|
||||||
|
const Spacer(),
|
||||||
|
Text(
|
||||||
|
'${countries.length}',
|
||||||
|
style: TextStyle(
|
||||||
|
color: (_countriesExpanded ? Theme.of(context).accentColor : Colors.white).withOpacity(.6),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onExpansionChanged: (expanded) => setState(() => _countriesExpanded = expanded),
|
||||||
|
children: countries.map(buildCountryEntry).toList(),
|
||||||
|
),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
return Drawer(
|
return Drawer(
|
||||||
|
|
Loading…
Reference in a new issue