#684 stats: added total size
This commit is contained in:
parent
157d2b2738
commit
7e51f7f5c8
1 changed files with 69 additions and 39 deletions
|
@ -13,6 +13,7 @@ import 'package:aves/model/source/collection_source.dart';
|
|||
import 'package:aves/theme/durations.dart';
|
||||
import 'package:aves/theme/icons.dart';
|
||||
import 'package:aves/theme/styles.dart';
|
||||
import 'package:aves/utils/file_utils.dart';
|
||||
import 'package:aves/widgets/collection/collection_page.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/feedback.dart';
|
||||
import 'package:aves/widgets/common/action_mixins/vault_aware.dart';
|
||||
|
@ -58,6 +59,7 @@ class _StatsPageState extends State<StatsPage> with FeedbackMixin, VaultAwareMix
|
|||
final Map<String, int> _entryCountPerTag = {}, _entryCountPerAlbum = {};
|
||||
final Map<int, int> _entryCountPerRating = Map.fromEntries(List.generate(7, (i) => MapEntry(5 - i, 0)));
|
||||
late final ValueNotifier<bool> _isPageAnimatingNotifier;
|
||||
int _totalSizeBytes = 0;
|
||||
|
||||
Set<AvesEntry> get entries => widget.entries;
|
||||
|
||||
|
@ -72,6 +74,8 @@ class _StatsPageState extends State<StatsPage> with FeedbackMixin, VaultAwareMix
|
|||
});
|
||||
|
||||
entries.forEach((entry) {
|
||||
_totalSizeBytes += entry.sizeBytes ?? 0;
|
||||
|
||||
if (entry.hasAddress) {
|
||||
final address = entry.addressDetails!;
|
||||
var country = address.countryName;
|
||||
|
@ -123,7 +127,6 @@ class _StatsPageState extends State<StatsPage> with FeedbackMixin, VaultAwareMix
|
|||
text: l10n.collectionEmptyImages,
|
||||
);
|
||||
} else {
|
||||
final theme = Theme.of(context);
|
||||
final chartAnimationDuration = context.read<DurationsData>().chartTransition;
|
||||
|
||||
final byMimeTypes = groupBy<AvesEntry, String>(entries, (entry) => entry.mimeType).map<String, int>((k, v) => MapEntry(k, v.length));
|
||||
|
@ -148,48 +151,21 @@ class _StatsPageState extends State<StatsPage> with FeedbackMixin, VaultAwareMix
|
|||
],
|
||||
);
|
||||
|
||||
final catalogued = entries.where((entry) => entry.isCatalogued);
|
||||
final withGps = catalogued.where((entry) => entry.hasGps);
|
||||
final withGpsCount = withGps.length;
|
||||
final withGpsPercent = withGpsCount / entries.length;
|
||||
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
||||
final lineHeight = 16 * textScaleFactor;
|
||||
final barRadius = Radius.circular(lineHeight / 2);
|
||||
final locationIndicator = Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
final showRatings = _entryCountPerRating.entries.any((kv) => kv.key != 0 && kv.value > 0);
|
||||
final source = widget.source;
|
||||
final sizeIndicator = Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(AIcons.location),
|
||||
const Icon(AIcons.size),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: LinearPercentIndicator(
|
||||
percent: withGpsPercent,
|
||||
lineHeight: lineHeight,
|
||||
backgroundColor: theme.colorScheme.onPrimary.withOpacity(.1),
|
||||
progressColor: theme.colorScheme.secondary,
|
||||
animation: context.select<Settings, bool>((v) => v.accessibilityAnimations.animate),
|
||||
isRTL: context.isRtl,
|
||||
barRadius: barRadius,
|
||||
center: LinearPercentIndicatorText(percent: withGpsPercent),
|
||||
padding: EdgeInsets.symmetric(horizontal: lineHeight),
|
||||
),
|
||||
),
|
||||
// end padding to match leading, so that inside label is aligned with outside label below
|
||||
const SizedBox(width: 24),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
l10n.statsWithGps(withGpsCount),
|
||||
textAlign: TextAlign.center,
|
||||
child: Text(formatFileSize(l10n.localeName, _totalSizeBytes)),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
final showRatings = _entryCountPerRating.entries.any((kv) => kv.key != 0 && kv.value > 0);
|
||||
final source = widget.source;
|
||||
child = NotificationListener<ReverseFilterNotification>(
|
||||
onNotification: (notification) {
|
||||
_onFilterSelection(context, notification.reversedFilter);
|
||||
|
@ -214,7 +190,10 @@ class _StatsPageState extends State<StatsPage> with FeedbackMixin, VaultAwareMix
|
|||
animationDuration: chartAnimationDuration,
|
||||
onFilterSelection: (filter) => _onFilterSelection(context, filter),
|
||||
),
|
||||
locationIndicator,
|
||||
const SizedBox(height: 16),
|
||||
sizeIndicator,
|
||||
const SizedBox(height: 16),
|
||||
_LocationIndicator(entries: entries),
|
||||
..._buildFilterSection<String>(context, l10n.statsTopCountriesSectionTitle, _entryCountPerCountry, (v) => LocationFilter(LocationLevel.country, v)),
|
||||
..._buildFilterSection<String>(context, l10n.statsTopStatesSectionTitle, _entryCountPerState, (v) => LocationFilter(LocationLevel.state, v)),
|
||||
..._buildFilterSection<String>(context, l10n.statsTopPlacesSectionTitle, _entryCountPerPlace, (v) => LocationFilter(LocationLevel.place, v)),
|
||||
|
@ -418,3 +397,54 @@ class StatsTopPage extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _LocationIndicator extends StatelessWidget {
|
||||
final Set<AvesEntry> entries;
|
||||
|
||||
const _LocationIndicator({required this.entries});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final catalogued = entries.where((entry) => entry.isCatalogued);
|
||||
final withGps = catalogued.where((entry) => entry.hasGps);
|
||||
final withGpsCount = withGps.length;
|
||||
final withGpsPercent = withGpsCount / entries.length;
|
||||
final textScaleFactor = MediaQuery.textScaleFactorOf(context);
|
||||
final lineHeight = 16 * textScaleFactor;
|
||||
final barRadius = Radius.circular(lineHeight / 2);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Icon(AIcons.location),
|
||||
Expanded(
|
||||
child: LinearPercentIndicator(
|
||||
percent: withGpsPercent,
|
||||
lineHeight: lineHeight,
|
||||
backgroundColor: theme.colorScheme.onPrimary.withOpacity(.1),
|
||||
progressColor: theme.colorScheme.secondary,
|
||||
animation: context.select<Settings, bool>((v) => v.accessibilityAnimations.animate),
|
||||
isRTL: context.isRtl,
|
||||
barRadius: barRadius,
|
||||
center: LinearPercentIndicatorText(percent: withGpsPercent),
|
||||
padding: EdgeInsets.symmetric(horizontal: lineHeight),
|
||||
),
|
||||
),
|
||||
// end padding to match leading, so that inside label is aligned with outside label below
|
||||
const SizedBox(width: 24),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
context.l10n.statsWithGps(withGpsCount),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue