stats: added ratings

This commit is contained in:
Thibault Deckers 2022-01-05 10:44:43 +09:00
parent b94097bda7
commit 1a17f9546c
2 changed files with 33 additions and 15 deletions

View file

@ -2,15 +2,16 @@ import 'package:aves/model/filters/filters.dart';
import 'package:aves/utils/color_utils.dart';
import 'package:aves/utils/constants.dart';
import 'package:aves/widgets/common/identity/aves_filter_chip.dart';
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:percent_indicator/linear_percent_indicator.dart';
class FilterTable extends StatelessWidget {
class FilterTable<T extends Comparable> extends StatelessWidget {
final int totalEntryCount;
final Map<String, int> entryCountMap;
final CollectionFilter Function(String key) filterBuilder;
final Map<T, int> entryCountMap;
final CollectionFilter Function(T key) filterBuilder;
final bool sortByCount;
final int? maxRowCount;
final FilterCallback onFilterSelection;
const FilterTable({
@ -18,6 +19,8 @@ class FilterTable extends StatelessWidget {
required this.totalEntryCount,
required this.entryCountMap,
required this.filterBuilder,
required this.sortByCount,
required this.maxRowCount,
required this.onFilterSelection,
}) : super(key: key);
@ -27,11 +30,13 @@ class FilterTable extends StatelessWidget {
@override
Widget build(BuildContext context) {
final sortedEntries = entryCountMap.entries.toList()
..sort((kv1, kv2) {
final sortedEntries = entryCountMap.entries.toList();
if (sortByCount) {
sortedEntries.sort((kv1, kv2) {
final c = kv2.value.compareTo(kv1.value);
return c != 0 ? c : compareAsciiUpperCase(kv1.key, kv2.key);
return c != 0 ? c : kv1.key.compareTo(kv2.key);
});
}
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
final lineHeight = 16 * textScaleFactor;
@ -41,8 +46,9 @@ class FilterTable extends StatelessWidget {
child: LayoutBuilder(
builder: (context, constraints) {
final showPercentIndicator = constraints.maxWidth - (chipWidth + countWidth) > percentIndicatorMinWidth;
final displayedEntries = maxRowCount != null ? sortedEntries.take(maxRowCount!) : sortedEntries;
return Table(
children: sortedEntries.take(5).map((kv) {
children: displayedEntries.map((kv) {
final filter = filterBuilder(kv.key);
final label = filter.getLabel(context);
final count = kv.value;

View file

@ -4,6 +4,7 @@ import 'package:aves/model/entry.dart';
import 'package:aves/model/filters/filters.dart';
import 'package:aves/model/filters/location.dart';
import 'package:aves/model/filters/mime.dart';
import 'package:aves/model/filters/rating.dart';
import 'package:aves/model/filters/tag.dart';
import 'package:aves/model/settings/accessibility_animations.dart';
import 'package:aves/model/settings/settings.dart';
@ -33,6 +34,7 @@ class StatsPage extends StatelessWidget {
final CollectionLens? parentCollection;
final Set<AvesEntry> entries;
final Map<String, int> entryCountPerCountry = {}, entryCountPerPlace = {}, entryCountPerTag = {};
final Map<int, int> entryCountPerRating = Map.fromEntries(List.generate(7, (i) => MapEntry(5 - i, 0)));
static const mimeDonutMinWidth = 124.0;
@ -55,9 +57,13 @@ class StatsPage extends StatelessWidget {
entryCountPerPlace[place] = (entryCountPerPlace[place] ?? 0) + 1;
}
}
entry.tags.forEach((tag) {
entryCountPerTag[tag] = (entryCountPerTag[tag] ?? 0) + 1;
});
final rating = entry.rating;
entryCountPerRating[rating] = (entryCountPerRating[rating] ?? 0) + 1;
});
}
@ -115,13 +121,15 @@ class StatsPage extends StatelessWidget {
],
),
);
final showRatings = entryCountPerRating.entries.any((kv) => kv.key != 0 && kv.value > 0);
child = ListView(
children: [
mimeDonuts,
locationIndicator,
..._buildTopFilters(context, context.l10n.statsTopCountries, entryCountPerCountry, (s) => LocationFilter(LocationLevel.country, s)),
..._buildTopFilters(context, context.l10n.statsTopPlaces, entryCountPerPlace, (s) => LocationFilter(LocationLevel.place, s)),
..._buildTopFilters(context, context.l10n.statsTopTags, entryCountPerTag, (s) => TagFilter(s)),
..._buildFilterSection<String>(context, context.l10n.statsTopCountries, entryCountPerCountry, (v) => LocationFilter(LocationLevel.country, v)),
..._buildFilterSection<String>(context, context.l10n.statsTopPlaces, entryCountPerPlace, (v) => LocationFilter(LocationLevel.place, v)),
..._buildFilterSection<String>(context, context.l10n.statsTopTags, entryCountPerTag, (v) => TagFilter(v)),
if (showRatings) ..._buildFilterSection<int>(context, context.l10n.searchSectionRating, entryCountPerRating, (v) => RatingFilter(v), sortByCount: false, maxRowCount: null),
],
);
}
@ -243,12 +251,14 @@ class StatsPage extends StatelessWidget {
});
}
List<Widget> _buildTopFilters(
List<Widget> _buildFilterSection<T extends Comparable>(
BuildContext context,
String title,
Map<String, int> entryCountMap,
CollectionFilter Function(String key) filterBuilder,
) {
Map<T, int> entryCountMap,
CollectionFilter Function(T key) filterBuilder, {
bool sortByCount = true,
int? maxRowCount = 5,
}) {
if (entryCountMap.isEmpty) return [];
return [
@ -263,6 +273,8 @@ class StatsPage extends StatelessWidget {
totalEntryCount: entries.length,
entryCountMap: entryCountMap,
filterBuilder: filterBuilder,
sortByCount: sortByCount,
maxRowCount: maxRowCount,
onFilterSelection: (filter) => _onFilterSelection(context, filter),
),
];