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);
|
||||
}
|
||||
|
||||
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 {
|
||||
@override
|
||||
bool filter(ImageEntry entry) => entry.isVideo;
|
||||
|
|
|
@ -28,7 +28,7 @@ class CollectionLens with ChangeNotifier {
|
|||
this.sortFactor = sortFactor ?? SortFactor.date {
|
||||
_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<MetadataChangedEvent>().listen((e) => onMetadataChanged()));
|
||||
_subscriptions.add(source.eventBus.on<CatalogMetadataChangedEvent>().listen((e) => onMetadataChanged()));
|
||||
onEntryAdded();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ class CollectionSource {
|
|||
|
||||
List<String> sortedAlbums = 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);
|
||||
|
||||
|
@ -35,7 +36,7 @@ class CollectionSource {
|
|||
}
|
||||
});
|
||||
debugPrint('$runtimeType loadCatalogMetadata complete in ${stopwatch.elapsed.inMilliseconds}ms with ${saved.length} saved entries');
|
||||
onMetadataChanged();
|
||||
onCatalogMetadataChanged();
|
||||
}
|
||||
|
||||
Future<void> loadAddresses() async {
|
||||
|
@ -48,6 +49,7 @@ class CollectionSource {
|
|||
}
|
||||
});
|
||||
debugPrint('$runtimeType loadAddresses complete in ${stopwatch.elapsed.inMilliseconds}ms with ${saved.length} saved entries');
|
||||
onAddressMetadataChanged();
|
||||
}
|
||||
|
||||
Future<void> catalogEntries() async {
|
||||
|
@ -65,15 +67,10 @@ class CollectionSource {
|
|||
if (newMetadata.isEmpty) return;
|
||||
|
||||
await metadataDb.saveMetadata(List.unmodifiable(newMetadata));
|
||||
onMetadataChanged();
|
||||
onCatalogMetadataChanged();
|
||||
debugPrint('$runtimeType catalogEntries complete in ${stopwatch.elapsed.inSeconds}s with ${newMetadata.length} new entries');
|
||||
}
|
||||
|
||||
void onMetadataChanged() {
|
||||
updateTags();
|
||||
eventBus.fire(MetadataChangedEvent());
|
||||
}
|
||||
|
||||
Future<void> locateEntries() async {
|
||||
final stopwatch = Stopwatch()..start();
|
||||
final unlocatedEntries = _rawEntries.where((entry) => entry.hasGps && !entry.isLocated).toList();
|
||||
|
@ -89,9 +86,20 @@ class CollectionSource {
|
|||
}
|
||||
});
|
||||
await metadataDb.saveAddresses(List.unmodifiable(newAddresses));
|
||||
onAddressMetadataChanged();
|
||||
debugPrint('$runtimeType locateEntries complete in ${stopwatch.elapsed.inMilliseconds}ms');
|
||||
}
|
||||
|
||||
void onCatalogMetadataChanged() {
|
||||
updateTags();
|
||||
eventBus.fire(CatalogMetadataChangedEvent());
|
||||
}
|
||||
|
||||
void onAddressMetadataChanged() {
|
||||
updateLocations();
|
||||
eventBus.fire(AddressMetadataChangedEvent());
|
||||
}
|
||||
|
||||
void updateAlbums() {
|
||||
final albums = _rawEntries.map((entry) => entry.directory).toSet();
|
||||
final sorted = albums.toList()
|
||||
|
@ -104,9 +112,14 @@ class CollectionSource {
|
|||
}
|
||||
|
||||
void updateTags() {
|
||||
final tags = _rawEntries.expand((entry) => entry.xmpSubjects).toSet();
|
||||
final sorted = tags.toList()..sort(compareAsciiUpperCase);
|
||||
sortedTags = List.unmodifiable(sorted);
|
||||
final tags = _rawEntries.expand((entry) => entry.xmpSubjects).toSet().toList()..sort(compareAsciiUpperCase);
|
||||
sortedTags = List.unmodifiable(tags);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -140,7 +153,9 @@ class CollectionSource {
|
|||
}
|
||||
}
|
||||
|
||||
class MetadataChangedEvent {}
|
||||
class AddressMetadataChangedEvent {}
|
||||
|
||||
class CatalogMetadataChangedEvent {}
|
||||
|
||||
class EntryAddedEvent {
|
||||
final ImageEntry entry;
|
||||
|
|
|
@ -20,7 +20,7 @@ class AllCollectionDrawer extends StatefulWidget {
|
|||
}
|
||||
|
||||
class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
||||
bool _albumsExpanded = false, _tagsExpanded = false;
|
||||
bool _albumsExpanded = false, _tagsExpanded = false, _countriesExpanded = false;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -113,6 +113,16 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
|||
dense: true,
|
||||
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 = [];
|
||||
for (var album in source.sortedAlbums) {
|
||||
|
@ -130,6 +140,7 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
|||
}
|
||||
|
||||
final tags = source.sortedTags;
|
||||
final countries = source.sortedCountries;
|
||||
final drawerItems = [
|
||||
header,
|
||||
gifEntry,
|
||||
|
@ -186,6 +197,28 @@ class _AllCollectionDrawerState extends State<AllCollectionDrawer> {
|
|||
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(
|
||||
|
|
Loading…
Reference in a new issue