chip grid: added count and storage indicator for albums
This commit is contained in:
parent
97e3fe62c0
commit
b9bf51ff83
3 changed files with 93 additions and 33 deletions
|
@ -1,4 +1,5 @@
|
||||||
import 'package:aves/model/collection_lens.dart';
|
import 'package:aves/model/collection_lens.dart';
|
||||||
|
import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/image_metadata.dart';
|
import 'package:aves/model/image_metadata.dart';
|
||||||
import 'package:aves/model/metadata_db.dart';
|
import 'package:aves/model/metadata_db.dart';
|
||||||
|
@ -13,10 +14,10 @@ class CollectionSource {
|
||||||
final Set<String> _folderPaths = {};
|
final Set<String> _folderPaths = {};
|
||||||
final EventBus _eventBus = EventBus();
|
final EventBus _eventBus = EventBus();
|
||||||
|
|
||||||
List<String> sortedAlbums = List.unmodifiable(const Iterable.empty());
|
List<String> sortedAlbums = List.unmodifiable([]);
|
||||||
List<String> sortedCountries = List.unmodifiable(const Iterable.empty());
|
List<String> sortedCountries = List.unmodifiable([]);
|
||||||
List<String> sortedPlaces = List.unmodifiable(const Iterable.empty());
|
List<String> sortedPlaces = List.unmodifiable([]);
|
||||||
List<String> sortedTags = List.unmodifiable(const Iterable.empty());
|
List<String> sortedTags = List.unmodifiable([]);
|
||||||
|
|
||||||
List<ImageEntry> get entries => List.unmodifiable(_rawEntries);
|
List<ImageEntry> get entries => List.unmodifiable(_rawEntries);
|
||||||
|
|
||||||
|
@ -223,6 +224,11 @@ class CollectionSource {
|
||||||
entries.firstWhere((entry) => entry.xmpSubjects.contains(tag), orElse: () => null),
|
entries.firstWhere((entry) => entry.xmpSubjects.contains(tag), orElse: () => null),
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO TLAD cache counts, invalidate them on any add/remove
|
||||||
|
int count(CollectionFilter filter) {
|
||||||
|
return _rawEntries.where((entry) => filter.filter(entry)).length;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AddressMetadataChangedEvent {}
|
class AddressMetadataChangedEvent {}
|
||||||
|
|
|
@ -9,6 +9,7 @@ class AvesFilterChip extends StatefulWidget {
|
||||||
final bool removable;
|
final bool removable;
|
||||||
final bool showGenericIcon;
|
final bool showGenericIcon;
|
||||||
final Decoration decoration;
|
final Decoration decoration;
|
||||||
|
final Widget details;
|
||||||
final FilterCallback onPressed;
|
final FilterCallback onPressed;
|
||||||
|
|
||||||
static final BorderRadius borderRadius = BorderRadius.circular(32);
|
static final BorderRadius borderRadius = BorderRadius.circular(32);
|
||||||
|
@ -24,6 +25,7 @@ class AvesFilterChip extends StatefulWidget {
|
||||||
this.removable = false,
|
this.removable = false,
|
||||||
this.showGenericIcon = true,
|
this.showGenericIcon = true,
|
||||||
this.decoration,
|
this.decoration,
|
||||||
|
this.details,
|
||||||
@required this.onPressed,
|
@required this.onPressed,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@ -57,9 +59,7 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
final leading = filter.iconBuilder(context, AvesFilterChip.iconSize, showGenericIcon: widget.showGenericIcon);
|
final leading = filter.iconBuilder(context, AvesFilterChip.iconSize, showGenericIcon: widget.showGenericIcon);
|
||||||
final trailing = widget.removable ? const Icon(AIcons.clear, size: AvesFilterChip.iconSize) : null;
|
final trailing = widget.removable ? const Icon(AIcons.clear, size: AvesFilterChip.iconSize) : null;
|
||||||
|
|
||||||
Widget content = Padding(
|
Widget content = Row(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.padding * 2),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: widget.decoration != null ? MainAxisSize.max : MainAxisSize.min,
|
mainAxisSize: widget.decoration != null ? MainAxisSize.max : MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
|
@ -80,14 +80,39 @@ class _AvesFilterChipState extends State<AvesFilterChip> {
|
||||||
trailing,
|
trailing,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
);
|
||||||
|
|
||||||
|
if (widget.details != null) {
|
||||||
|
content = Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
content,
|
||||||
|
widget.details,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
content = Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: AvesFilterChip.padding * 2, vertical: 2),
|
||||||
|
child: content,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (widget.decoration != null) {
|
if (widget.decoration != null) {
|
||||||
content = Container(
|
content = Center(
|
||||||
constraints: BoxConstraints(minHeight: DefaultTextStyle.of(context).style.fontSize * 2),
|
child: ColoredBox(
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
|
child: DefaultTextStyle(
|
||||||
|
style: Theme.of(context).textTheme.bodyText2.copyWith(
|
||||||
|
shadows: const [
|
||||||
|
Shadow(
|
||||||
|
color: Colors.black87,
|
||||||
|
offset: Offset(0.5, 1.0),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
child: content,
|
child: content,
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
import 'package:aves/model/collection_lens.dart';
|
import 'package:aves/model/collection_lens.dart';
|
||||||
import 'package:aves/model/collection_source.dart';
|
import 'package:aves/model/collection_source.dart';
|
||||||
|
import 'package:aves/model/filters/album.dart';
|
||||||
import 'package:aves/model/filters/filters.dart';
|
import 'package:aves/model/filters/filters.dart';
|
||||||
import 'package:aves/model/image_entry.dart';
|
import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/settings.dart';
|
import 'package:aves/model/settings.dart';
|
||||||
|
import 'package:aves/utils/android_file_utils.dart';
|
||||||
import 'package:aves/utils/constants.dart';
|
import 'package:aves/utils/constants.dart';
|
||||||
import 'package:aves/widgets/album/collection_page.dart';
|
import 'package:aves/widgets/album/collection_page.dart';
|
||||||
import 'package:aves/widgets/app_drawer.dart';
|
import 'package:aves/widgets/app_drawer.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/icons.dart';
|
||||||
import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart';
|
import 'package:aves/widgets/common/image_providers/thumbnail_provider.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
@ -68,6 +71,8 @@ class FilterGridPage extends StatelessWidget {
|
||||||
|
|
||||||
List<String> get filterKeys => filterEntries.keys.toList();
|
List<String> get filterKeys => filterEntries.keys.toList();
|
||||||
|
|
||||||
|
static const Color detailColor = Color(0xFFE0E0E0);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MediaQueryDataProvider(
|
return MediaQueryDataProvider(
|
||||||
|
@ -77,13 +82,14 @@ class FilterGridPage extends StatelessWidget {
|
||||||
slivers: [
|
slivers: [
|
||||||
appBar,
|
appBar,
|
||||||
SliverPadding(
|
SliverPadding(
|
||||||
padding: EdgeInsets.all(AvesFilterChip.buttonBorderWidth),
|
padding: const EdgeInsets.all(AvesFilterChip.buttonBorderWidth),
|
||||||
sliver: SliverGrid(
|
sliver: SliverGrid(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate(
|
||||||
(context, i) {
|
(context, i) {
|
||||||
final key = filterKeys[i];
|
final key = filterKeys[i];
|
||||||
final entry = filterEntries[key];
|
final entry = filterEntries[key];
|
||||||
Decoration decoration;
|
Decoration decoration;
|
||||||
|
// TODO TLAD add decoration for SVG
|
||||||
if (entry != null && !entry.isSvg) {
|
if (entry != null && !entry.isSvg) {
|
||||||
decoration = BoxDecoration(
|
decoration = BoxDecoration(
|
||||||
image: DecorationImage(
|
image: DecorationImage(
|
||||||
|
@ -96,10 +102,12 @@ class FilterGridPage extends StatelessWidget {
|
||||||
borderRadius: AvesFilterChip.borderRadius,
|
borderRadius: AvesFilterChip.borderRadius,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
final filter = filterBuilder(key);
|
||||||
return AvesFilterChip(
|
return AvesFilterChip(
|
||||||
filter: filterBuilder(key),
|
filter: filter,
|
||||||
showGenericIcon: false,
|
showGenericIcon: false,
|
||||||
decoration: decoration,
|
decoration: decoration,
|
||||||
|
details: _buildDetails(filter),
|
||||||
onPressed: onPressed,
|
onPressed: onPressed,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -130,4 +138,25 @@ class FilterGridPage extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _buildDetails(CollectionFilter filter) {
|
||||||
|
final count = Text(
|
||||||
|
'${source.count(filter)}',
|
||||||
|
style: const TextStyle(color: FilterGridPage.detailColor),
|
||||||
|
);
|
||||||
|
return filter is AlbumFilter && androidFileUtils.isOnRemovableStorage(filter.album)
|
||||||
|
? Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
AIcons.removableStorage,
|
||||||
|
size: 16,
|
||||||
|
color: FilterGridPage.detailColor,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
count,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: count;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue