albums/countries/tags: sort by entry count
This commit is contained in:
parent
2236be7d60
commit
ae2f8d3ae7
6 changed files with 90 additions and 62 deletions
|
@ -1,6 +1,6 @@
|
||||||
enum Activity { browse, select }
|
enum Activity { browse, select }
|
||||||
|
|
||||||
enum ChipSortFactor { date, name }
|
enum ChipSortFactor { date, name, count }
|
||||||
|
|
||||||
enum EntrySortFactor { date, size, name }
|
enum EntrySortFactor { date, size, name }
|
||||||
|
|
||||||
|
|
|
@ -62,42 +62,56 @@ class AlbumListPage extends StatelessWidget {
|
||||||
final pinned = settings.pinnedFilters.whereType<AlbumFilter>().map((f) => f.album);
|
final pinned = settings.pinnedFilters.whereType<AlbumFilter>().map((f) => f.album);
|
||||||
final entriesByDate = source.sortedEntriesForFilterList;
|
final entriesByDate = source.sortedEntriesForFilterList;
|
||||||
|
|
||||||
switch (settings.albumSortFactor) {
|
// albums are initially sorted by name at the source level
|
||||||
case ChipSortFactor.date:
|
var sortedAlbums = source.sortedAlbums;
|
||||||
final allAlbumMapEntries = source.sortedAlbums.map((album) => MapEntry(
|
|
||||||
album,
|
if (settings.albumSortFactor == ChipSortFactor.name) {
|
||||||
entriesByDate.firstWhere((entry) => entry.directory == album, orElse: () => null),
|
final pinnedAlbums = <String>[], regularAlbums = <String>[], appAlbums = <String>[], specialAlbums = <String>[];
|
||||||
));
|
for (var album in sortedAlbums) {
|
||||||
final byPin = groupBy<MapEntry<String, ImageEntry>, bool>(allAlbumMapEntries, (e) => pinned.contains(e.key));
|
if (pinned.contains(album)) {
|
||||||
final pinnedMapEntries = (byPin[true] ?? [])..sort(FilterNavigationPage.compareChipsByDate);
|
pinnedAlbums.add(album);
|
||||||
final unpinnedMapEntries = (byPin[false] ?? [])..sort(FilterNavigationPage.compareChipsByDate);
|
} else {
|
||||||
return Map.fromEntries([...pinnedMapEntries, ...unpinnedMapEntries]);
|
switch (androidFileUtils.getAlbumType(album)) {
|
||||||
case ChipSortFactor.name:
|
case AlbumType.regular:
|
||||||
default:
|
regularAlbums.add(album);
|
||||||
final pinnedAlbums = <String>[], regularAlbums = <String>[], appAlbums = <String>[], specialAlbums = <String>[];
|
break;
|
||||||
for (var album in source.sortedAlbums) {
|
case AlbumType.app:
|
||||||
if (pinned.contains(album)) {
|
appAlbums.add(album);
|
||||||
pinnedAlbums.add(album);
|
break;
|
||||||
} else {
|
default:
|
||||||
switch (androidFileUtils.getAlbumType(album)) {
|
specialAlbums.add(album);
|
||||||
case AlbumType.regular:
|
break;
|
||||||
regularAlbums.add(album);
|
|
||||||
break;
|
|
||||||
case AlbumType.app:
|
|
||||||
appAlbums.add(album);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
specialAlbums.add(album);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Map.fromEntries([...pinnedAlbums, ...specialAlbums, ...appAlbums, ...regularAlbums].map((album) {
|
}
|
||||||
return MapEntry(
|
return Map.fromEntries([...pinnedAlbums, ...specialAlbums, ...appAlbums, ...regularAlbums].map((album) {
|
||||||
album,
|
return MapEntry(
|
||||||
entriesByDate.firstWhere((entry) => entry.directory == album, orElse: () => null),
|
album,
|
||||||
);
|
entriesByDate.firstWhere((entry) => entry.directory == album, orElse: () => null),
|
||||||
}));
|
);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (settings.albumSortFactor == ChipSortFactor.count) {
|
||||||
|
CollectionFilter _buildFilter(String album) => AlbumFilter(album, source.getUniqueAlbumName(album));
|
||||||
|
var filtersWithCount = List.of(sortedAlbums.map((s) => MapEntry(s, source.count(_buildFilter(s)))));
|
||||||
|
filtersWithCount.sort(FilterNavigationPage.compareChipsByEntryCount);
|
||||||
|
sortedAlbums = filtersWithCount.map((kv) => kv.key).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final allMapEntries = sortedAlbums.map((album) => MapEntry(
|
||||||
|
album,
|
||||||
|
entriesByDate.firstWhere((entry) => entry.directory == album, orElse: () => null),
|
||||||
|
));
|
||||||
|
final byPin = groupBy<MapEntry<String, ImageEntry>, bool>(allMapEntries, (e) => pinned.contains(e.key));
|
||||||
|
final pinnedMapEntries = (byPin[true] ?? []);
|
||||||
|
final unpinnedMapEntries = (byPin[false] ?? []);
|
||||||
|
|
||||||
|
if (settings.albumSortFactor == ChipSortFactor.date) {
|
||||||
|
pinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
||||||
|
unpinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Map.fromEntries([...pinnedMapEntries, ...unpinnedMapEntries]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,6 +46,7 @@ abstract class ChipSetActionDelegate {
|
||||||
options: {
|
options: {
|
||||||
ChipSortFactor.date: 'By date',
|
ChipSortFactor.date: 'By date',
|
||||||
ChipSortFactor.name: 'By name',
|
ChipSortFactor.name: 'By name',
|
||||||
|
ChipSortFactor.count: 'By entry count',
|
||||||
},
|
},
|
||||||
title: 'Sort',
|
title: 'Sort',
|
||||||
),
|
),
|
||||||
|
|
|
@ -153,6 +153,11 @@ class FilterNavigationPage extends StatelessWidget {
|
||||||
final c = b.value.bestDate?.compareTo(a.value.bestDate) ?? -1;
|
final c = b.value.bestDate?.compareTo(a.value.bestDate) ?? -1;
|
||||||
return c != 0 ? c : compareAsciiUpperCase(a.key, b.key);
|
return c != 0 ? c : compareAsciiUpperCase(a.key, b.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compareChipsByEntryCount(MapEntry<String, num> a, MapEntry<String, num> b) {
|
||||||
|
final c = b.value.compareTo(a.value) ?? -1;
|
||||||
|
return c != 0 ? c : compareAsciiUpperCase(a.key, b.key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FilterGridPage extends StatelessWidget {
|
class FilterGridPage extends StatelessWidget {
|
||||||
|
|
|
@ -39,7 +39,7 @@ class CountryListPage extends StatelessWidget {
|
||||||
settings.pinnedFilters.contains(filter) ? ChipAction.unpin : ChipAction.pin,
|
settings.pinnedFilters.contains(filter) ? ChipAction.unpin : ChipAction.pin,
|
||||||
],
|
],
|
||||||
filterEntries: _getCountryEntries(),
|
filterEntries: _getCountryEntries(),
|
||||||
filterBuilder: (s) => LocationFilter(LocationLevel.country, s),
|
filterBuilder: _buildFilter,
|
||||||
emptyBuilder: () => EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.location,
|
icon: AIcons.location,
|
||||||
text: 'No countries',
|
text: 'No countries',
|
||||||
|
@ -50,12 +50,22 @@ class CountryListPage extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CollectionFilter _buildFilter(String location) => LocationFilter(LocationLevel.country, location);
|
||||||
|
|
||||||
Map<String, ImageEntry> _getCountryEntries() {
|
Map<String, ImageEntry> _getCountryEntries() {
|
||||||
final pinned = settings.pinnedFilters.whereType<LocationFilter>().map((f) => f.countryNameAndCode);
|
final pinned = settings.pinnedFilters.whereType<LocationFilter>().map((f) => f.countryNameAndCode);
|
||||||
|
|
||||||
final entriesByDate = source.sortedEntriesForFilterList;
|
final entriesByDate = source.sortedEntriesForFilterList;
|
||||||
|
// countries are initially sorted by name at the source level
|
||||||
|
var sortedCountries = source.sortedCountries;
|
||||||
|
if (settings.countrySortFactor == ChipSortFactor.count) {
|
||||||
|
var filtersWithCount = List.of(sortedCountries.map((s) => MapEntry(s, source.count(_buildFilter(s)))));
|
||||||
|
filtersWithCount.sort(FilterNavigationPage.compareChipsByEntryCount);
|
||||||
|
sortedCountries = filtersWithCount.map((kv) => kv.key).toList();
|
||||||
|
}
|
||||||
|
|
||||||
final locatedEntries = entriesByDate.where((entry) => entry.isLocated);
|
final locatedEntries = entriesByDate.where((entry) => entry.isLocated);
|
||||||
final allMapEntries = source.sortedCountries.map((countryNameAndCode) {
|
final allMapEntries = sortedCountries.map((countryNameAndCode) {
|
||||||
final split = countryNameAndCode.split(LocationFilter.locationSeparator);
|
final split = countryNameAndCode.split(LocationFilter.locationSeparator);
|
||||||
ImageEntry entry;
|
ImageEntry entry;
|
||||||
if (split.length > 1) {
|
if (split.length > 1) {
|
||||||
|
@ -63,21 +73,16 @@ class CountryListPage extends StatelessWidget {
|
||||||
entry = locatedEntries.firstWhere((entry) => entry.addressDetails.countryCode == countryCode, orElse: () => null);
|
entry = locatedEntries.firstWhere((entry) => entry.addressDetails.countryCode == countryCode, orElse: () => null);
|
||||||
}
|
}
|
||||||
return MapEntry(countryNameAndCode, entry);
|
return MapEntry(countryNameAndCode, entry);
|
||||||
}).toList();
|
});
|
||||||
|
|
||||||
final byPin = groupBy<MapEntry<String, ImageEntry>, bool>(allMapEntries, (e) => pinned.contains(e.key));
|
final byPin = groupBy<MapEntry<String, ImageEntry>, bool>(allMapEntries, (e) => pinned.contains(e.key));
|
||||||
final pinnedMapEntries = (byPin[true] ?? []);
|
final pinnedMapEntries = (byPin[true] ?? []);
|
||||||
final unpinnedMapEntries = (byPin[false] ?? []);
|
final unpinnedMapEntries = (byPin[false] ?? []);
|
||||||
|
|
||||||
switch (settings.countrySortFactor) {
|
if (settings.countrySortFactor == ChipSortFactor.date) {
|
||||||
case ChipSortFactor.date:
|
pinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
||||||
pinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
unpinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
||||||
unpinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
|
||||||
break;
|
|
||||||
case ChipSortFactor.name:
|
|
||||||
// already sorted by name at the source level
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Map.fromEntries([...pinnedMapEntries, ...unpinnedMapEntries]);
|
return Map.fromEntries([...pinnedMapEntries, ...unpinnedMapEntries]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,7 +39,7 @@ class TagListPage extends StatelessWidget {
|
||||||
settings.pinnedFilters.contains(filter) ? ChipAction.unpin : ChipAction.pin,
|
settings.pinnedFilters.contains(filter) ? ChipAction.unpin : ChipAction.pin,
|
||||||
],
|
],
|
||||||
filterEntries: _getTagEntries(),
|
filterEntries: _getTagEntries(),
|
||||||
filterBuilder: (s) => TagFilter(s),
|
filterBuilder: _buildFilter,
|
||||||
emptyBuilder: () => EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.tag,
|
icon: AIcons.tag,
|
||||||
text: 'No tags',
|
text: 'No tags',
|
||||||
|
@ -50,30 +50,33 @@ class TagListPage extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CollectionFilter _buildFilter(String tag) => TagFilter(tag);
|
||||||
|
|
||||||
Map<String, ImageEntry> _getTagEntries() {
|
Map<String, ImageEntry> _getTagEntries() {
|
||||||
final pinned = settings.pinnedFilters.whereType<TagFilter>().map((f) => f.tag);
|
final pinned = settings.pinnedFilters.whereType<TagFilter>().map((f) => f.tag);
|
||||||
|
|
||||||
final entriesByDate = source.sortedEntriesForFilterList;
|
final entriesByDate = source.sortedEntriesForFilterList;
|
||||||
final allMapEntries = source.sortedTags
|
// tags are initially sorted by name at the source level
|
||||||
.map((tag) => MapEntry(
|
var sortedTags = source.sortedTags;
|
||||||
tag,
|
if (settings.tagSortFactor == ChipSortFactor.count) {
|
||||||
entriesByDate.firstWhere((entry) => entry.xmpSubjects.contains(tag), orElse: () => null),
|
var filtersWithCount = List.of(sortedTags.map((s) => MapEntry(s, source.count(_buildFilter(s)))));
|
||||||
))
|
filtersWithCount.sort(FilterNavigationPage.compareChipsByEntryCount);
|
||||||
.toList();
|
sortedTags = filtersWithCount.map((kv) => kv.key).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final allMapEntries = sortedTags.map((tag) => MapEntry(
|
||||||
|
tag,
|
||||||
|
entriesByDate.firstWhere((entry) => entry.xmpSubjects.contains(tag), orElse: () => null),
|
||||||
|
));
|
||||||
final byPin = groupBy<MapEntry<String, ImageEntry>, bool>(allMapEntries, (e) => pinned.contains(e.key));
|
final byPin = groupBy<MapEntry<String, ImageEntry>, bool>(allMapEntries, (e) => pinned.contains(e.key));
|
||||||
final pinnedMapEntries = (byPin[true] ?? []);
|
final pinnedMapEntries = (byPin[true] ?? []);
|
||||||
final unpinnedMapEntries = (byPin[false] ?? []);
|
final unpinnedMapEntries = (byPin[false] ?? []);
|
||||||
|
|
||||||
switch (settings.tagSortFactor) {
|
if (settings.tagSortFactor == ChipSortFactor.date) {
|
||||||
case ChipSortFactor.date:
|
pinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
||||||
pinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
unpinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
||||||
unpinnedMapEntries.sort(FilterNavigationPage.compareChipsByDate);
|
|
||||||
break;
|
|
||||||
case ChipSortFactor.name:
|
|
||||||
// already sorted by name at the source level
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Map.fromEntries([...pinnedMapEntries, ...unpinnedMapEntries]);
|
return Map.fromEntries([...pinnedMapEntries, ...unpinnedMapEntries]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue