added stats

This commit is contained in:
Thibault Deckers 2020-03-20 21:35:28 +09:00
parent 7f11d3702a
commit 76d9de9b1e
5 changed files with 166 additions and 9 deletions

View file

@ -4,6 +4,7 @@ import 'package:aves/widgets/album/search_delegate.dart';
import 'package:aves/widgets/album/thumbnail_collection.dart'; import 'package:aves/widgets/album/thumbnail_collection.dart';
import 'package:aves/widgets/common/menu_row.dart'; import 'package:aves/widgets/common/menu_row.dart';
import 'package:aves/widgets/debug_page.dart'; import 'package:aves/widgets/debug_page.dart';
import 'package:aves/widgets/stats.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:outline_material_icons/outline_material_icons.dart'; import 'package:outline_material_icons/outline_material_icons.dart';
import 'package:provider/provider.dart'; import 'package:provider/provider.dart';
@ -73,6 +74,10 @@ class _AllCollectionAppBar extends SliverAppBar {
), ),
const PopupMenuDivider(), const PopupMenuDivider(),
], ],
PopupMenuItem(
value: AlbumAction.stats,
child: MenuRow(text: 'Stats', icon: OMIcons.pieChart),
),
PopupMenuItem( PopupMenuItem(
value: AlbumAction.debug, value: AlbumAction.debug,
child: MenuRow(text: 'Debug', icon: OMIcons.whatshot), child: MenuRow(text: 'Debug', icon: OMIcons.whatshot),
@ -90,6 +95,9 @@ class _AllCollectionAppBar extends SliverAppBar {
case AlbumAction.debug: case AlbumAction.debug:
_goToDebug(context, collection); _goToDebug(context, collection);
break; break;
case AlbumAction.stats:
_goToStats(context, collection);
break;
case AlbumAction.groupByAlbum: case AlbumAction.groupByAlbum:
settings.collectionGroupFactor = GroupFactor.album; settings.collectionGroupFactor = GroupFactor.album;
collection.group(GroupFactor.album); collection.group(GroupFactor.album);
@ -127,6 +135,17 @@ class _AllCollectionAppBar extends SliverAppBar {
), ),
); );
} }
static Future _goToStats(BuildContext context, CollectionLens collection) {
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StatsPage(
collection: collection,
),
),
);
}
} }
enum AlbumAction { debug, groupByAlbum, groupByMonth, groupByDay, sortByDate, sortBySize, sortByName } enum AlbumAction { debug, stats, groupByAlbum, groupByMonth, groupByDay, sortByDate, sortBySize, sortByName }

View file

@ -44,10 +44,6 @@ class DebugPageState extends State<DebugPage> {
body: Column( body: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
const Text('Paths'),
Text('DCIM path: ${androidFileUtils.dcimPath}'),
Text('pictures path: ${androidFileUtils.picturesPath}'),
const Divider(),
const Text('Settings'), const Text('Settings'),
Text('collectionGroupFactor: ${settings.collectionGroupFactor}'), Text('collectionGroupFactor: ${settings.collectionGroupFactor}'),
Text('collectionSortFactor: ${settings.collectionSortFactor}'), Text('collectionSortFactor: ${settings.collectionSortFactor}'),

114
lib/widgets/stats.dart Normal file
View file

@ -0,0 +1,114 @@
import 'dart:math';
import 'package:aves/model/collection_lens.dart';
import 'package:aves/model/image_entry.dart';
import 'package:aves/utils/color_utils.dart';
import 'package:aves/widgets/common/providers/media_query_data_provider.dart';
import 'package:charts_flutter/flutter.dart' as charts;
import 'package:collection/collection.dart';
import 'package:flutter/material.dart';
class StatsPage extends StatelessWidget {
final CollectionLens collection;
const StatsPage({this.collection});
List<ImageEntry> get entries => collection.sortedEntries;
@override
Widget build(BuildContext context) {
final catalogued = entries.where((entry) => entry.isCatalogued);
final withGps = catalogued.where((entry) => entry.hasGps);
final located = withGps.where((entry) => entry.isLocated);
final Map<String, int> byMimeTypes = groupBy(entries, (entry) => entry.mimeType).map((k, v) => MapEntry(k, v.length));
return MediaQueryDataProvider(
child: Scaffold(
appBar: AppBar(
title: const Text('Stats'),
),
body: ListView(
children: [
_buildMimePie(context, 'images', Map.fromEntries(byMimeTypes.entries.where((kv) => kv.key.startsWith('image/')))),
_buildMimePie(context, 'videos', Map.fromEntries(byMimeTypes.entries.where((kv) => kv.key.startsWith('video/')))),
const Divider(),
Text('Catalogued: ${catalogued.length}'),
Text('With GPS: ${withGps.length}'),
Text('With address: ${located.length}'),
],
),
),
);
}
Widget _buildMimePie(BuildContext context, String label, Map<String, num> byMimeTypes) {
if (byMimeTypes.isEmpty) return const SizedBox.shrink();
final seriesData = byMimeTypes.entries.map((kv) => StringNumDatum(kv.key.replaceFirst(RegExp('.*/'), '').toUpperCase(), kv.value)).toList();
seriesData.sort((kv1, kv2) => kv2.value.compareTo(kv1.value));
final series = [
charts.Series<StringNumDatum, String>(
id: label,
colorFn: (d, i) => charts.ColorUtil.fromDartColor(stringToColor(d.key)),
domainFn: (d, i) => d.key,
measureFn: (d, i) => d.value,
data: seriesData,
labelAccessorFn: (d, _) => '${d.key}: ${d.value}',
),
];
final size = MediaQuery.of(context).size;
final circleDim = min(size.width, size.height) / 2;
return Row(
children: [
Container(
width: circleDim,
height: circleDim,
child: Stack(
children: [
charts.PieChart(
series,
defaultRenderer: charts.ArcRendererConfig(
arcWidth: 16,
),
),
Center(
child: Text(
'${byMimeTypes.values.fold(0, (prev, v) => prev + v)}\n$label',
textAlign: TextAlign.center,
),
),
],
),
),
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.start,
children: seriesData
.map((kv) => Row(
children: [
Icon(Icons.fiber_manual_record, color: stringToColor(kv.key)),
const SizedBox(width: 8),
Text(kv.key),
const SizedBox(width: 8),
Text('${kv.value}'),
],
))
.toList()),
],
);
}
}
class StringNumDatum {
final String key;
final num value;
const StringNumDatum(this.key, this.value);
@override
String toString() {
return '[$runtimeType#$hashCode: key=$key, value=$value]';
}
}

View file

@ -50,6 +50,20 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "1.1.2" version: "1.1.2"
charts_common:
dependency: transitive
description:
name: charts_common
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
charts_flutter:
dependency: "direct main"
description:
name: charts_flutter
url: "https://pub.dartlang.org"
source: hosted
version: "0.9.0"
collection: collection:
dependency: "direct main" dependency: "direct main"
description: description:
@ -90,9 +104,11 @@ packages:
flushbar: flushbar:
dependency: "direct main" dependency: "direct main"
description: description:
name: flushbar path: "."
url: "https://pub.dartlang.org" ref: "13c55a8"
source: hosted resolved-ref: "13c55a888c1693f1c8269ea30d55c614a1bfee16"
url: "https://github.com/AndreHaueisen/flushbar.git"
source: git
version: "1.9.1" version: "1.9.1"
flutter: flutter:
dependency: "direct main" dependency: "direct main"
@ -188,6 +204,13 @@ packages:
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.8.3" version: "0.8.3"
logging:
dependency: transitive
description:
name: logging
url: "https://pub.dartlang.org"
source: hosted
version: "0.11.4"
matcher: matcher:
dependency: transitive dependency: transitive
description: description:
@ -416,7 +439,7 @@ packages:
name: test_api name: test_api
url: "https://pub.dartlang.org" url: "https://pub.dartlang.org"
source: hosted source: hosted
version: "0.2.11" version: "0.2.15"
transparent_image: transparent_image:
dependency: "direct main" dependency: "direct main"
description: description:

View file

@ -17,12 +17,17 @@ dependencies:
flutter: flutter:
sdk: flutter sdk: flutter
after_init: after_init:
charts_flutter:
collection: collection:
draggable_scrollbar: draggable_scrollbar:
git: git:
url: git://github.com/deckerst/flutter-draggable-scrollbar.git url: git://github.com/deckerst/flutter-draggable-scrollbar.git
event_bus: event_bus:
flushbar: flushbar:
# flushbar-1.9.1 cannot be built with Flutter 1.15.17
git:
url: https://github.com/AndreHaueisen/flushbar.git
ref: 13c55a8
flutter_native_timezone: flutter_native_timezone:
flutter_staggered_grid_view: flutter_staggered_grid_view:
flutter_sticky_header: flutter_sticky_header: