sort chips on countries/tags pages
This commit is contained in:
parent
78ba136a21
commit
7e530aed74
7 changed files with 193 additions and 100 deletions
|
@ -29,6 +29,8 @@ class Settings extends ChangeNotifier {
|
||||||
|
|
||||||
// filter grids
|
// filter grids
|
||||||
static const albumSortFactorKey = 'album_sort_factor';
|
static const albumSortFactorKey = 'album_sort_factor';
|
||||||
|
static const countrySortFactorKey = 'country_sort_factor';
|
||||||
|
static const tagSortFactorKey = 'tag_sort_factor';
|
||||||
|
|
||||||
// info
|
// info
|
||||||
static const infoMapStyleKey = 'info_map_style';
|
static const infoMapStyleKey = 'info_map_style';
|
||||||
|
@ -84,6 +86,14 @@ class Settings extends ChangeNotifier {
|
||||||
|
|
||||||
set albumSortFactor(ChipSortFactor newValue) => setAndNotify(albumSortFactorKey, newValue.toString());
|
set albumSortFactor(ChipSortFactor newValue) => setAndNotify(albumSortFactorKey, newValue.toString());
|
||||||
|
|
||||||
|
ChipSortFactor get countrySortFactor => getEnumOrDefault(countrySortFactorKey, ChipSortFactor.name, ChipSortFactor.values);
|
||||||
|
|
||||||
|
set countrySortFactor(ChipSortFactor newValue) => setAndNotify(countrySortFactorKey, newValue.toString());
|
||||||
|
|
||||||
|
ChipSortFactor get tagSortFactor => getEnumOrDefault(tagSortFactorKey, ChipSortFactor.name, ChipSortFactor.values);
|
||||||
|
|
||||||
|
set tagSortFactor(ChipSortFactor newValue) => setAndNotify(tagSortFactorKey, newValue.toString());
|
||||||
|
|
||||||
// info
|
// info
|
||||||
|
|
||||||
EntryMapStyle get infoMapStyle => getEnumOrDefault(infoMapStyleKey, EntryMapStyle.stamenWatercolor, EntryMapStyle.values);
|
EntryMapStyle get infoMapStyle => getEnumOrDefault(infoMapStyleKey, EntryMapStyle.stamenWatercolor, EntryMapStyle.values);
|
||||||
|
|
|
@ -83,19 +83,6 @@ mixin LocationMixin on SourceBase {
|
||||||
invalidateFilterEntryCounts();
|
invalidateFilterEntryCounts();
|
||||||
eventBus.fire(LocationsChangedEvent());
|
eventBus.fire(LocationsChangedEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, ImageEntry> getCountryEntries() {
|
|
||||||
final locatedEntries = sortedEntriesForFilterList.where((entry) => entry.isLocated);
|
|
||||||
return Map.fromEntries(sortedCountries.map((countryNameAndCode) {
|
|
||||||
final split = countryNameAndCode.split(LocationFilter.locationSeparator);
|
|
||||||
ImageEntry entry;
|
|
||||||
if (split.length > 1) {
|
|
||||||
final countryCode = split[1];
|
|
||||||
entry = locatedEntries.firstWhere((entry) => entry.addressDetails.countryCode == countryCode, orElse: () => null);
|
|
||||||
}
|
|
||||||
return MapEntry(countryNameAndCode, entry);
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddressMetadataChangedEvent {}
|
class AddressMetadataChangedEvent {}
|
||||||
|
|
|
@ -59,14 +59,6 @@ mixin TagMixin on SourceBase {
|
||||||
invalidateFilterEntryCounts();
|
invalidateFilterEntryCounts();
|
||||||
eventBus.fire(TagsChangedEvent());
|
eventBus.fire(TagsChangedEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, ImageEntry> getTagEntries() {
|
|
||||||
final entries = sortedEntriesForFilterList;
|
|
||||||
return Map.fromEntries(sortedTags.map((tag) => MapEntry(
|
|
||||||
tag,
|
|
||||||
entries.firstWhere((entry) => entry.xmpSubjects.contains(tag), orElse: () => null),
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CatalogMetadataChangedEvent {}
|
class CatalogMetadataChangedEvent {}
|
||||||
|
|
|
@ -5,15 +5,11 @@ import 'package:aves/model/source/album.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
import 'package:aves/model/source/enums.dart';
|
import 'package:aves/model/source/enums.dart';
|
||||||
import 'package:aves/utils/android_file_utils.dart';
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/utils/durations.dart';
|
|
||||||
import 'package:aves/widgets/collection/empty.dart';
|
import 'package:aves/widgets/collection/empty.dart';
|
||||||
import 'package:aves/widgets/common/aves_selection_dialog.dart';
|
import 'package:aves/widgets/common/aves_selection_dialog.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/filter_grids/filter_grid_page.dart';
|
import 'package:aves/widgets/filter_grids/filter_grid_page.dart';
|
||||||
import 'package:collection/collection.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/scheduler.dart';
|
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class AlbumListPage extends StatelessWidget {
|
class AlbumListPage extends StatelessWidget {
|
||||||
|
@ -27,51 +23,29 @@ class AlbumListPage extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Selector<Settings, ChipSortFactor>(
|
return Selector<Settings, ChipSortFactor>(
|
||||||
selector: (context, s) => s.albumSortFactor,
|
selector: (context, s) => s.albumSortFactor,
|
||||||
builder: (context, albumSortFactor, child) {
|
builder: (context, sortFactor, child) {
|
||||||
return AnimatedBuilder(
|
return AnimatedBuilder(
|
||||||
animation: androidFileUtils.appNameChangeNotifier,
|
animation: androidFileUtils.appNameChangeNotifier,
|
||||||
builder: (context, child) => StreamBuilder(
|
builder: (context, child) => StreamBuilder(
|
||||||
stream: source.eventBus.on<AlbumsChangedEvent>(),
|
stream: source.eventBus.on<AlbumsChangedEvent>(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) => FilterNavigationPage(
|
||||||
return FilterNavigationPage(
|
|
||||||
source: source,
|
source: source,
|
||||||
title: 'Albums',
|
title: 'Albums',
|
||||||
actions: _buildActions(context),
|
onChipActionSelected: _onChipActionSelected,
|
||||||
filterEntries: getAlbumEntries(source),
|
filterEntries: getAlbumEntries(source),
|
||||||
filterBuilder: (s) => AlbumFilter(s, source.getUniqueAlbumName(s)),
|
filterBuilder: (s) => AlbumFilter(s, source.getUniqueAlbumName(s)),
|
||||||
emptyBuilder: () => EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.album,
|
icon: AIcons.album,
|
||||||
text: 'No albums',
|
text: 'No albums',
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
},
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Widget> _buildActions(BuildContext context) {
|
|
||||||
return [
|
|
||||||
PopupMenuButton<ChipAction>(
|
|
||||||
key: Key('appbar-menu-button'),
|
|
||||||
itemBuilder: (context) {
|
|
||||||
return [
|
|
||||||
PopupMenuItem(
|
|
||||||
key: Key('menu-sort'),
|
|
||||||
value: ChipAction.sort,
|
|
||||||
child: MenuRow(text: 'Sort...', icon: AIcons.sort),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
},
|
|
||||||
onSelected: (action) => _onChipActionSelected(context, action),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onChipActionSelected(BuildContext context, ChipAction action) async {
|
void _onChipActionSelected(BuildContext context, ChipAction action) async {
|
||||||
// wait for the popup menu to hide before proceeding with the action
|
|
||||||
await Future.delayed(Durations.popupMenuAnimation * timeDilation);
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case ChipAction.sort:
|
case ChipAction.sort:
|
||||||
final factor = await showDialog<ChipSortFactor>(
|
final factor = await showDialog<ChipSortFactor>(
|
||||||
|
@ -96,20 +70,17 @@ class AlbumListPage extends StatelessWidget {
|
||||||
|
|
||||||
static Map<String, ImageEntry> getAlbumEntries(CollectionSource source) {
|
static Map<String, ImageEntry> getAlbumEntries(CollectionSource source) {
|
||||||
final entriesByDate = source.sortedEntriesForFilterList;
|
final entriesByDate = source.sortedEntriesForFilterList;
|
||||||
final albumEntries = source.sortedAlbums.map((album) {
|
final albums = source.sortedAlbums
|
||||||
return MapEntry(
|
.map((album) => MapEntry(
|
||||||
album,
|
album,
|
||||||
entriesByDate.firstWhere((entry) => entry.directory == album, orElse: () => null),
|
entriesByDate.firstWhere((entry) => entry.directory == album, orElse: () => null),
|
||||||
);
|
))
|
||||||
}).toList();
|
.toList();
|
||||||
|
|
||||||
switch (settings.albumSortFactor) {
|
switch (settings.albumSortFactor) {
|
||||||
case ChipSortFactor.date:
|
case ChipSortFactor.date:
|
||||||
albumEntries.sort((a, b) {
|
albums.sort(FilterNavigationPage.compareChipByDate);
|
||||||
final c = b.value.bestDate?.compareTo(a.value.bestDate) ?? -1;
|
return Map.fromEntries(albums);
|
||||||
return c != 0 ? c : compareAsciiUpperCase(a.key, b.key);
|
|
||||||
});
|
|
||||||
return Map.fromEntries(albumEntries);
|
|
||||||
case ChipSortFactor.name:
|
case ChipSortFactor.name:
|
||||||
default:
|
default:
|
||||||
final regularAlbums = <String>[], appAlbums = <String>[], specialAlbums = <String>[];
|
final regularAlbums = <String>[], appAlbums = <String>[], specialAlbums = <String>[];
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
import 'package:aves/model/filters/location.dart';
|
import 'package:aves/model/filters/location.dart';
|
||||||
|
import 'package:aves/model/image_entry.dart';
|
||||||
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
import 'package:aves/model/source/enums.dart';
|
||||||
import 'package:aves/model/source/location.dart';
|
import 'package:aves/model/source/location.dart';
|
||||||
import 'package:aves/widgets/collection/empty.dart';
|
import 'package:aves/widgets/collection/empty.dart';
|
||||||
|
import 'package:aves/widgets/common/aves_selection_dialog.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
import 'package:aves/widgets/filter_grids/filter_grid_page.dart';
|
import 'package:aves/widgets/filter_grids/filter_grid_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class CountryListPage extends StatelessWidget {
|
class CountryListPage extends StatelessWidget {
|
||||||
static const routeName = '/countries';
|
static const routeName = '/countries';
|
||||||
|
@ -15,12 +20,16 @@ class CountryListPage extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return Selector<Settings, ChipSortFactor>(
|
||||||
|
selector: (context, s) => s.countrySortFactor,
|
||||||
|
builder: (context, sortFactor, child) {
|
||||||
return StreamBuilder(
|
return StreamBuilder(
|
||||||
stream: source.eventBus.on<LocationsChangedEvent>(),
|
stream: source.eventBus.on<LocationsChangedEvent>(),
|
||||||
builder: (context, snapshot) => FilterNavigationPage(
|
builder: (context, snapshot) => FilterNavigationPage(
|
||||||
source: source,
|
source: source,
|
||||||
title: 'Countries',
|
title: 'Countries',
|
||||||
filterEntries: source.getCountryEntries(),
|
onChipActionSelected: _onChipActionSelected,
|
||||||
|
filterEntries: _getCountryEntries(),
|
||||||
filterBuilder: (s) => LocationFilter(LocationLevel.country, s),
|
filterBuilder: (s) => LocationFilter(LocationLevel.country, s),
|
||||||
emptyBuilder: () => EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.location,
|
icon: AIcons.location,
|
||||||
|
@ -28,5 +37,50 @@ class CountryListPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChipActionSelected(BuildContext context, ChipAction action) async {
|
||||||
|
switch (action) {
|
||||||
|
case ChipAction.sort:
|
||||||
|
final factor = await showDialog<ChipSortFactor>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AvesSelectionDialog<ChipSortFactor>(
|
||||||
|
initialValue: settings.countrySortFactor,
|
||||||
|
options: {
|
||||||
|
ChipSortFactor.date: 'By date',
|
||||||
|
ChipSortFactor.name: 'By name',
|
||||||
|
},
|
||||||
|
title: 'Sort',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (factor != null) {
|
||||||
|
settings.countrySortFactor = factor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, ImageEntry> _getCountryEntries() {
|
||||||
|
final entriesByDate = source.sortedEntriesForFilterList;
|
||||||
|
final locatedEntries = entriesByDate.where((entry) => entry.isLocated);
|
||||||
|
final countries = source.sortedCountries.map((countryNameAndCode) {
|
||||||
|
final split = countryNameAndCode.split(LocationFilter.locationSeparator);
|
||||||
|
ImageEntry entry;
|
||||||
|
if (split.length > 1) {
|
||||||
|
final countryCode = split[1];
|
||||||
|
entry = locatedEntries.firstWhere((entry) => entry.addressDetails.countryCode == countryCode, orElse: () => null);
|
||||||
|
}
|
||||||
|
return MapEntry(countryNameAndCode, entry);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
switch (settings.countrySortFactor) {
|
||||||
|
case ChipSortFactor.date:
|
||||||
|
countries.sort(FilterNavigationPage.compareChipByDate);
|
||||||
|
break;
|
||||||
|
case ChipSortFactor.name:
|
||||||
|
}
|
||||||
|
return Map.fromEntries(countries);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,17 +13,21 @@ 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';
|
||||||
import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart';
|
import 'package:aves/widgets/common/data_providers/media_query_data_provider.dart';
|
||||||
import 'package:aves/widgets/common/double_back_pop.dart';
|
import 'package:aves/widgets/common/double_back_pop.dart';
|
||||||
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
|
import 'package:aves/widgets/common/menu_row.dart';
|
||||||
import 'package:aves/widgets/drawer/app_drawer.dart';
|
import 'package:aves/widgets/drawer/app_drawer.dart';
|
||||||
import 'package:aves/widgets/filter_grids/decorated_filter_chip.dart';
|
import 'package:aves/widgets/filter_grids/decorated_filter_chip.dart';
|
||||||
import 'package:aves/widgets/filter_grids/search_button.dart';
|
import 'package:aves/widgets/filter_grids/search_button.dart';
|
||||||
|
import 'package:collection/collection.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/scheduler.dart';
|
||||||
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
import 'package:flutter_staggered_animations/flutter_staggered_animations.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class FilterNavigationPage extends StatelessWidget {
|
class FilterNavigationPage extends StatelessWidget {
|
||||||
final CollectionSource source;
|
final CollectionSource source;
|
||||||
final String title;
|
final String title;
|
||||||
final List<Widget> actions;
|
final void Function(BuildContext context, ChipAction action) onChipActionSelected;
|
||||||
final Map<String, ImageEntry> filterEntries;
|
final Map<String, ImageEntry> filterEntries;
|
||||||
final CollectionFilter Function(String key) filterBuilder;
|
final CollectionFilter Function(String key) filterBuilder;
|
||||||
final Widget Function() emptyBuilder;
|
final Widget Function() emptyBuilder;
|
||||||
|
@ -31,7 +35,7 @@ class FilterNavigationPage extends StatelessWidget {
|
||||||
const FilterNavigationPage({
|
const FilterNavigationPage({
|
||||||
@required this.source,
|
@required this.source,
|
||||||
@required this.title,
|
@required this.title,
|
||||||
this.actions,
|
@required this.onChipActionSelected,
|
||||||
@required this.filterEntries,
|
@required this.filterEntries,
|
||||||
@required this.filterBuilder,
|
@required this.filterBuilder,
|
||||||
@required this.emptyBuilder,
|
@required this.emptyBuilder,
|
||||||
|
@ -49,10 +53,7 @@ class FilterNavigationPage extends StatelessWidget {
|
||||||
source: source,
|
source: source,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: _buildActions(context),
|
||||||
SearchButton(source),
|
|
||||||
...(actions ?? []),
|
|
||||||
],
|
|
||||||
titleSpacing: 0,
|
titleSpacing: 0,
|
||||||
floating: true,
|
floating: true,
|
||||||
),
|
),
|
||||||
|
@ -80,6 +81,29 @@ class FilterNavigationPage extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<Widget> _buildActions(BuildContext context) {
|
||||||
|
return [
|
||||||
|
SearchButton(source),
|
||||||
|
PopupMenuButton<ChipAction>(
|
||||||
|
key: Key('appbar-menu-button'),
|
||||||
|
itemBuilder: (context) {
|
||||||
|
return [
|
||||||
|
PopupMenuItem(
|
||||||
|
key: Key('menu-sort'),
|
||||||
|
value: ChipAction.sort,
|
||||||
|
child: MenuRow(text: 'Sort...', icon: AIcons.sort),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
onSelected: (action) async {
|
||||||
|
// wait for the popup menu to hide before proceeding with the action
|
||||||
|
await Future.delayed(Durations.popupMenuAnimation * timeDilation);
|
||||||
|
onChipActionSelected(context, action);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
void _goToSearch(BuildContext context) {
|
void _goToSearch(BuildContext context) {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
|
@ -89,6 +113,11 @@ class FilterNavigationPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int compareChipByDate(MapEntry<String, ImageEntry> a, MapEntry<String, ImageEntry> b) {
|
||||||
|
final c = b.value.bestDate?.compareTo(a.value.bestDate) ?? -1;
|
||||||
|
return c != 0 ? c : compareAsciiUpperCase(a.key, b.key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FilterGridPage extends StatelessWidget {
|
class FilterGridPage extends StatelessWidget {
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
import 'package:aves/model/filters/tag.dart';
|
import 'package:aves/model/filters/tag.dart';
|
||||||
|
import 'package:aves/model/image_entry.dart';
|
||||||
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_source.dart';
|
import 'package:aves/model/source/collection_source.dart';
|
||||||
|
import 'package:aves/model/source/enums.dart';
|
||||||
import 'package:aves/model/source/tag.dart';
|
import 'package:aves/model/source/tag.dart';
|
||||||
import 'package:aves/widgets/collection/empty.dart';
|
import 'package:aves/widgets/collection/empty.dart';
|
||||||
|
import 'package:aves/widgets/common/aves_selection_dialog.dart';
|
||||||
import 'package:aves/widgets/common/icons.dart';
|
import 'package:aves/widgets/common/icons.dart';
|
||||||
import 'package:aves/widgets/filter_grids/filter_grid_page.dart';
|
import 'package:aves/widgets/filter_grids/filter_grid_page.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class TagListPage extends StatelessWidget {
|
class TagListPage extends StatelessWidget {
|
||||||
static const routeName = '/tags';
|
static const routeName = '/tags';
|
||||||
|
@ -15,12 +20,16 @@ class TagListPage extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
return Selector<Settings, ChipSortFactor>(
|
||||||
|
selector: (context, s) => s.tagSortFactor,
|
||||||
|
builder: (context, sortFactor, child) {
|
||||||
return StreamBuilder(
|
return StreamBuilder(
|
||||||
stream: source.eventBus.on<TagsChangedEvent>(),
|
stream: source.eventBus.on<TagsChangedEvent>(),
|
||||||
builder: (context, snapshot) => FilterNavigationPage(
|
builder: (context, snapshot) => FilterNavigationPage(
|
||||||
source: source,
|
source: source,
|
||||||
title: 'Tags',
|
title: 'Tags',
|
||||||
filterEntries: source.getTagEntries(),
|
onChipActionSelected: _onChipActionSelected,
|
||||||
|
filterEntries: _getTagEntries(),
|
||||||
filterBuilder: (s) => TagFilter(s),
|
filterBuilder: (s) => TagFilter(s),
|
||||||
emptyBuilder: () => EmptyContent(
|
emptyBuilder: () => EmptyContent(
|
||||||
icon: AIcons.tag,
|
icon: AIcons.tag,
|
||||||
|
@ -28,5 +37,46 @@ class TagListPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onChipActionSelected(BuildContext context, ChipAction action) async {
|
||||||
|
switch (action) {
|
||||||
|
case ChipAction.sort:
|
||||||
|
final factor = await showDialog<ChipSortFactor>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AvesSelectionDialog<ChipSortFactor>(
|
||||||
|
initialValue: settings.tagSortFactor,
|
||||||
|
options: {
|
||||||
|
ChipSortFactor.date: 'By date',
|
||||||
|
ChipSortFactor.name: 'By name',
|
||||||
|
},
|
||||||
|
title: 'Sort',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (factor != null) {
|
||||||
|
settings.tagSortFactor = factor;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, ImageEntry> _getTagEntries() {
|
||||||
|
final entriesByDate = source.sortedEntriesForFilterList;
|
||||||
|
final tags = source.sortedTags
|
||||||
|
.map((tag) => MapEntry(
|
||||||
|
tag,
|
||||||
|
entriesByDate.firstWhere((entry) => entry.xmpSubjects.contains(tag), orElse: () => null),
|
||||||
|
))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
switch (settings.tagSortFactor) {
|
||||||
|
case ChipSortFactor.date:
|
||||||
|
tags.sort(FilterNavigationPage.compareChipByDate);
|
||||||
|
break;
|
||||||
|
case ChipSortFactor.name:
|
||||||
|
}
|
||||||
|
return Map.fromEntries(tags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue