added album grid page

This commit is contained in:
Thibault Deckers 2020-05-24 16:19:02 +09:00
parent 2bc16bd373
commit 00d3c9a86e
11 changed files with 69 additions and 62 deletions

View file

@ -2,6 +2,7 @@ import 'package:aves/model/collection_lens.dart';
import 'package:aves/model/image_entry.dart';
import 'package:aves/model/image_metadata.dart';
import 'package:aves/model/metadata_db.dart';
import 'package:aves/utils/android_file_utils.dart';
import 'package:collection/collection.dart';
import 'package:event_bus/event_bus.dart';
import 'package:flutter/foundation.dart';
@ -164,6 +165,28 @@ class CollectionSource {
sortFactor: SortFactor.date,
).sortedEntries;
Map<String, ImageEntry> getAlbumEntries() {
final entries = _sortedEntriesForFilterList;
final regularAlbums = <String>[], appAlbums = <String>[], specialAlbums = <String>[];
for (var album in sortedAlbums) {
switch (androidFileUtils.getAlbumType(album)) {
case AlbumType.regular:
regularAlbums.add(album);
break;
case AlbumType.app:
appAlbums.add(album);
break;
default:
specialAlbums.add(album);
break;
}
}
return Map.fromEntries([...specialAlbums, ...appAlbums, ...regularAlbums].map((tag) => MapEntry(
tag,
entries.firstWhere((entry) => entry.directory == tag, orElse: () => null),
)));
}
Map<String, ImageEntry> getCountryEntries() {
final locatedEntries = _sortedEntriesForFilterList.where((entry) => entry.isLocated);
return Map.fromEntries(sortedCountries.map((countryNameAndCode) {

View file

@ -14,7 +14,6 @@ class AlbumFilter extends CollectionFilter {
static final Map<String, Color> _appColors = {};
final String album;
final String uniqueName;
const AlbumFilter(this.album, this.uniqueName);
@ -29,8 +28,8 @@ class AlbumFilter extends CollectionFilter {
String get tooltip => album;
@override
Widget iconBuilder(context, size) {
return IconUtils.getAlbumIcon(context: context, album: album, size: size) ?? Icon(AIcons.album, size: size);
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) {
return IconUtils.getAlbumIcon(context: context, album: album, size: size) ?? (showGenericIcon ? Icon(AIcons.album, size: size) : null);
}
@override

View file

@ -14,7 +14,7 @@ class FavouriteFilter extends CollectionFilter {
String get label => 'Favourite';
@override
Widget iconBuilder(context, size) => Icon(AIcons.favourite, size: size);
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.favourite, size: size);
@override
String get typeKey => type;

View file

@ -30,7 +30,7 @@ abstract class CollectionFilter implements Comparable<CollectionFilter> {
String get tooltip => label;
Widget iconBuilder(BuildContext context, double size);
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true});
Future<Color> color(BuildContext context) => SynchronousFuture(stringToColor(label));

View file

@ -23,7 +23,7 @@ class LocationFilter extends CollectionFilter {
String get label => _location;
@override
Widget iconBuilder(context, size) {
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) {
final flag = countryCodeToFlag(_countryCode);
if (flag != null) return Text(flag, style: TextStyle(fontSize: size));
return Icon(AIcons.location, size: size);

View file

@ -49,7 +49,7 @@ class MimeFilter extends CollectionFilter {
String get label => _label;
@override
Widget iconBuilder(context, size) => Icon(_icon, size: size);
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(_icon, size: size);
@override
String get typeKey => type;

View file

@ -42,7 +42,7 @@ class QueryFilter extends CollectionFilter {
String get label => '${query}';
@override
Widget iconBuilder(context, size) => Icon(AIcons.text, size: size);
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => Icon(AIcons.text, size: size);
@override
Future<Color> color(BuildContext context) => colorful ? super.color(context) : SynchronousFuture(Colors.white);

View file

@ -20,7 +20,7 @@ class TagFilter extends CollectionFilter {
String get label => tag;
@override
Widget iconBuilder(context, size) => Icon(AIcons.tag, size: size);
Widget iconBuilder(BuildContext context, double size, {bool showGenericIcon = true}) => showGenericIcon ? Icon(AIcons.tag, size: size) : null;
@override
String get typeKey => type;

View file

@ -31,8 +31,6 @@ class AppDrawer extends StatefulWidget {
}
class _AppDrawerState extends State<AppDrawer> {
bool _albumsExpanded = false;
CollectionSource get source => widget.source;
@override
@ -184,49 +182,25 @@ class _AppDrawerState extends State<AppDrawer> {
}
Widget _buildRegularAlbumSection() {
return StreamBuilder(
stream: source.eventBus.on<AlbumsChangedEvent>(),
builder: (context, snapshot) {
final regularAlbums = <String>[], appAlbums = <String>[];
for (var album in source.sortedAlbums) {
switch (androidFileUtils.getAlbumType(album)) {
case AlbumType.regular:
regularAlbums.add(album);
break;
case AlbumType.app:
appAlbums.add(album);
break;
default:
break;
}
}
if (appAlbums.isEmpty && regularAlbums.isEmpty) return const SizedBox.shrink();
return SafeArea(
top: false,
bottom: false,
child: ExpansionTile(
leading: const Icon(AIcons.album),
title: Row(
children: [
const Text('Albums'),
const Spacer(),
Text(
'${appAlbums.length + regularAlbums.length}',
style: TextStyle(
color: (_albumsExpanded ? Theme.of(context).accentColor : Colors.white).withOpacity(.6),
),
),
],
),
onExpansionChanged: (expanded) => setState(() => _albumsExpanded = expanded),
children: [
...appAlbums.map(_buildAlbumEntry),
if (appAlbums.isNotEmpty && regularAlbums.isNotEmpty) const Divider(),
...regularAlbums.map(_buildAlbumEntry),
],
),
);
});
return SafeArea(
top: false,
bottom: false,
child: ListTile(
leading: const Icon(AIcons.album),
title: const Text('Albums'),
trailing: StreamBuilder(
stream: source.eventBus.on<AlbumsChangedEvent>(),
builder: (context, snapshot) {
return Text(
'${source.sortedAlbums.length}',
style: TextStyle(
color: Colors.white.withOpacity(.6),
),
);
}),
onTap: () => _goToAlbums(context),
),
);
}
Widget _buildCountrySection() {
@ -273,6 +247,21 @@ class _AppDrawerState extends State<AppDrawer> {
);
}
void _goToAlbums(BuildContext context) {
Navigator.pop(context);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => FilterGridPage(
source: source,
title: 'Albums',
filterEntries: source.getAlbumEntries(),
filterBuilder: (s) => AlbumFilter(s, source.getUniqueAlbumName(s)),
),
),
);
}
void _goToCountries(BuildContext context) {
Navigator.pop(context);
Navigator.push(
@ -283,7 +272,6 @@ class _AppDrawerState extends State<AppDrawer> {
title: 'Countries',
filterEntries: source.getCountryEntries(),
filterBuilder: (s) => LocationFilter(LocationLevel.country, s),
showFilterIcon: true,
),
),
);
@ -299,7 +287,6 @@ class _AppDrawerState extends State<AppDrawer> {
title: 'Tags',
filterEntries: source.getTagEntries(),
filterBuilder: (s) => TagFilter(s),
showFilterIcon: false,
),
),
);

View file

@ -7,7 +7,7 @@ typedef FilterCallback = void Function(CollectionFilter filter);
class AvesFilterChip extends StatefulWidget {
final CollectionFilter filter;
final bool removable;
final bool showLeading;
final bool showGenericIcon;
final Decoration decoration;
final FilterCallback onPressed;
@ -22,7 +22,7 @@ class AvesFilterChip extends StatefulWidget {
Key key,
this.filter,
this.removable = false,
this.showLeading = true,
this.showGenericIcon = true,
this.decoration,
@required this.onPressed,
}) : super(key: key);
@ -54,7 +54,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
@override
Widget build(BuildContext context) {
final leading = widget.showLeading ? filter.iconBuilder(context, AvesFilterChip.iconSize) : null;
final leading = filter.iconBuilder(context, AvesFilterChip.iconSize, showGenericIcon: widget.showGenericIcon);
final trailing = widget.removable ? const Icon(AIcons.clear, size: AvesFilterChip.iconSize) : null;
Widget content = Padding(

View file

@ -17,14 +17,12 @@ class FilterGridPage extends StatelessWidget {
final String title;
final Map<String, ImageEntry> filterEntries;
final CollectionFilter Function(String key) filterBuilder;
final bool showFilterIcon;
const FilterGridPage({
@required this.source,
@required this.title,
@required this.filterEntries,
@required this.filterBuilder,
@required this.showFilterIcon,
});
List<String> get filterKeys => filterEntries.keys.toList();
@ -62,7 +60,7 @@ class FilterGridPage extends StatelessWidget {
}
return AvesFilterChip(
filter: filterBuilder(key),
showLeading: showFilterIcon,
showGenericIcon: false,
decoration: decoration,
onPressed: (filter) => Navigator.pushAndRemoveUntil(
context,