stats: tap on donut legend to filter by mime type

This commit is contained in:
Thibault Deckers 2020-08-27 21:57:46 +09:00
parent 789f195306
commit c2022a6ee6
2 changed files with 56 additions and 39 deletions

View file

@ -1,6 +1,5 @@
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/mime_types.dart';
import 'package:aves/widgets/common/icons.dart'; import 'package:aves/widgets/common/icons.dart';
import 'package:flutter/widgets.dart'; import 'package:flutter/widgets.dart';
@ -34,14 +33,15 @@ class MimeFilter extends CollectionFilter {
_label ??= lowMime.split('/')[0].toUpperCase(); _label ??= lowMime.split('/')[0].toUpperCase();
} else { } else {
_filter = (entry) => entry.mimeType == lowMime; _filter = (entry) => entry.mimeType == lowMime;
if (lowMime == MimeTypes.svg) { _label = displayType(lowMime);
_label = 'SVG';
}
_label ??= lowMime.split('/')[1].toUpperCase();
} }
_icon ??= AIcons.vector; _icon ??= AIcons.vector;
} }
static String displayType(String mime) {
return mime.toUpperCase().replaceFirst(RegExp('.*/(X-)?'), '').replaceFirst('+XML', '').replaceFirst('VND.', '');
}
@override @override
bool filter(ImageEntry entry) => _filter(entry); bool filter(ImageEntry entry) => _filter(entry);

View file

@ -2,11 +2,13 @@ import 'dart:math';
import 'package:aves/model/filters/filters.dart'; import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/filters/location.dart'; import 'package:aves/model/filters/location.dart';
import 'package:aves/model/filters/mime.dart';
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/image_entry.dart';
import 'package:aves/model/source/collection_lens.dart'; import 'package:aves/model/source/collection_lens.dart';
import 'package:aves/utils/color_utils.dart'; import 'package:aves/utils/color_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/empty.dart'; import 'package:aves/widgets/album/empty.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/icons.dart';
@ -112,30 +114,25 @@ class StatsPage extends StatelessWidget {
); );
} }
String _cleanMime(String mime) {
mime = mime.toUpperCase().replaceFirst(RegExp('.*/(X-)?'), '').replaceFirst('+XML', '').replaceFirst('VND.', '');
return mime;
}
Widget _buildMimeDonut(BuildContext context, String Function(num) label, Map<String, num> byMimeTypes) { Widget _buildMimeDonut(BuildContext context, String Function(num) label, Map<String, num> byMimeTypes) {
if (byMimeTypes.isEmpty) return SizedBox.shrink(); if (byMimeTypes.isEmpty) return SizedBox.shrink();
final sum = byMimeTypes.values.fold<int>(0, (prev, v) => prev + v); final sum = byMimeTypes.values.fold<int>(0, (prev, v) => prev + v);
final seriesData = byMimeTypes.entries.map((kv) => StringNumDatum(_cleanMime(kv.key), kv.value)).toList(); final seriesData = byMimeTypes.entries.map((kv) => EntryByMimeDatum(mimeType: kv.key, entryCount: kv.value)).toList();
seriesData.sort((kv1, kv2) { seriesData.sort((d1, d2) {
final c = kv2.value.compareTo(kv1.value); final c = d2.entryCount.compareTo(d1.entryCount);
return c != 0 ? c : compareAsciiUpperCase(kv1.key, kv2.key); return c != 0 ? c : compareAsciiUpperCase(d1.displayText, d2.displayText);
}); });
final series = [ final series = [
charts.Series<StringNumDatum, String>( charts.Series<EntryByMimeDatum, String>(
id: 'mime', id: 'mime',
colorFn: (d, i) => charts.ColorUtil.fromDartColor(stringToColor(d.key)), colorFn: (d, i) => charts.ColorUtil.fromDartColor(d.color),
domainFn: (d, i) => d.key, domainFn: (d, i) => d.displayText,
measureFn: (d, i) => d.value, measureFn: (d, i) => d.entryCount,
data: seriesData, data: seriesData,
labelAccessorFn: (d, _) => '${d.key}: ${d.value}', labelAccessorFn: (d, _) => '${d.displayText}: ${d.entryCount}',
), ),
]; ];
@ -171,23 +168,26 @@ class StatsPage extends StatelessWidget {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: seriesData children: seriesData
.map((kv) => Text.rich( .map((d) => GestureDetector(
TextSpan( onTap: () => _goToCollection(context, MimeFilter(d.mimeType)),
children: [ child: Text.rich(
WidgetSpan( TextSpan(
alignment: PlaceholderAlignment.middle, children: [
child: Padding( WidgetSpan(
padding: EdgeInsetsDirectional.only(end: 8), alignment: PlaceholderAlignment.middle,
child: Icon(AIcons.disc, color: stringToColor(kv.key)), child: Padding(
padding: EdgeInsetsDirectional.only(end: 8),
child: Icon(AIcons.disc, color: d.color),
),
), ),
), TextSpan(text: '${d.displayText} '),
TextSpan(text: '${kv.key} '), TextSpan(text: '${d.entryCount}', style: TextStyle(color: Colors.white70)),
TextSpan(text: '${kv.value}', style: TextStyle(color: Colors.white70)), ],
], ),
overflow: TextOverflow.fade,
softWrap: false,
maxLines: 1,
), ),
overflow: TextOverflow.fade,
softWrap: false,
maxLines: 1,
)) ))
.toList(), .toList(),
), ),
@ -230,16 +230,33 @@ class StatsPage extends StatelessWidget {
), ),
]; ];
} }
void _goToCollection(BuildContext context, CollectionFilter filter) {
if (collection == null) return;
Navigator.pushAndRemoveUntil(
context,
MaterialPageRoute(
builder: (context) => CollectionPage(collection.derive(filter)),
),
(route) => false,
);
}
} }
class StringNumDatum { class EntryByMimeDatum {
final String key; final String mimeType;
final num value; final String displayText;
final int entryCount;
const StringNumDatum(this.key, this.value); EntryByMimeDatum({
@required this.mimeType,
@required this.entryCount,
}) : displayText = MimeFilter.displayType(mimeType);
Color get color => stringToColor(displayText);
@override @override
String toString() { String toString() {
return '[$runtimeType#$hashCode: key=$key, value=$value]'; return '[$runtimeType#$hashCode: mimeType=$mimeType, displayText=$displayText, entryCount=$entryCount]';
} }
} }