Aves_mio0.88/lib/widgets/activity/dialogs/activity_db_fields_dialog.dart
2026-10-03 12:51:15 +02:00

218 lines
6.8 KiB
Dart

// lib/widgets/activity/dialogs/activity_db_fields_dialog.dart
import 'package:aves/model/activity/activity_entry.dart';
import 'package:aves/widgets/activity/utils/activity_formatters.dart';
import 'package:flutter/material.dart';
Future<void> showActivityDbFieldsDialog({
required BuildContext context,
required ActivityEntry entry,
}) async {
final rows = _activityEntryDbRows(entry);
await showDialog<void>(
context: context,
builder: (context) {
return AlertDialog(
title: const Text('Dettagli DB attività'),
content: SizedBox(
width: double.maxFinite,
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: rows
.map(
(row) => _DbFieldLine(
label: row.$1,
value: row.$2,
),
)
.toList(),
),
),
),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: const Text('Chiudi'),
),
],
);
},
);
}
List<(String, String)> _activityEntryDbRows(ActivityEntry e) {
String v(Object? value) {
if (value == null) return '-';
if (value is String && value.isEmpty) return '-';
return '$value';
}
String millisDate(int? millis) {
if (millis == null) return '-';
final date = DateTime.fromMillisecondsSinceEpoch(millis).toLocal();
final day = date.day.toString().padLeft(2, '0');
final month = date.month.toString().padLeft(2, '0');
final year = date.year.toString().padLeft(4, '0');
final hour = date.hour.toString().padLeft(2, '0');
final minute = date.minute.toString().padLeft(2, '0');
final second = date.second.toString().padLeft(2, '0');
return '$day/$month/$year $hour:$minute:$second';
}
String millisValue(int? millis) {
if (millis == null) return '-';
return '$millis (${millisDate(millis)})';
}
String bytes(int? value) {
if (value == null) return '-';
if (value >= 1024 * 1024) {
return '${(value / (1024 * 1024)).toStringAsFixed(2)} MB ($value bytes)';
}
if (value >= 1024) {
return '${(value / 1024).toStringAsFixed(2)} KB ($value bytes)';
}
return '$value bytes';
}
String distance(double? meters) {
if (meters == null) return '-';
return '${(meters / 1000).toStringAsFixed(3)} km (${meters.toStringAsFixed(2)} m)';
}
String elevation(double? meters) {
if (meters == null) return '-';
return '${meters.toStringAsFixed(2)} m';
}
String speed(double? mps) {
if (mps == null) return '-';
final kmh = mps * 3.6;
return '${mps.toStringAsFixed(3)} m/s (${kmh.toStringAsFixed(2)} km/h)';
}
String pace(double? secPerKm) {
if (secPerKm == null) return '-';
final totalSeconds = secPerKm.round();
final minutes = totalSeconds ~/ 60;
final seconds = totalSeconds % 60;
return '${minutes}m ${seconds.toString().padLeft(2, '0')}s / km (${secPerKm.toStringAsFixed(2)} s/km)';
}
String coordinate(double? value) {
if (value == null) return '-';
return value.toStringAsFixed(7);
}
return [
('id', v(e.id)),
('origin', v(e.origin)),
('uri', v(e.uri)),
('relativePath', v(e.relativePath)),
('directoryName', v(e.directoryName)),
('fileName', v(e.fileName)),
('fileExtension', v(e.fileExtension)),
('format', v(e.format)),
('bestName', v(e.bestName)),
('displayName', v(e.displayName)),
('routeName', v(e.routeName)),
('title', v(e.title)),
('description', v(e.description)),
('notes', v(e.notes)),
('sport', v(e.sport)),
('activityType', v(e.activityType)),
('deviceManufacturer', v(e.deviceManufacturer)),
('deviceModel', v(e.deviceModel)),
('sourceApp', v(e.sourceApp)),
('startTimeMillis', millisValue(e.startTimeMillis)),
('endTimeMillis', millisValue(e.endTimeMillis)),
('durationMillis', v(e.durationMillis)),
('durationFormatted', ActivityFormatters.entryDuration(e.durationMillis)),
('distanceMeters', distance(e.distanceMeters)),
('elevationGainMeters', elevation(e.elevationGainMeters)),
('elevationLossMeters', elevation(e.elevationLossMeters)),
('minElevationMeters', elevation(e.minElevationMeters)),
('maxElevationMeters', elevation(e.maxElevationMeters)),
('fileDistanceMeters', distance(e.fileDistanceMeters)),
('fileElevationGainMeters', elevation(e.fileElevationGainMeters)),
('computedDistanceMeters', distance(e.computedDistanceMeters)),
('computedElevationGainMeters', elevation(e.computedElevationGainMeters)),
('averageSpeedMps', speed(e.averageSpeedMps)),
('maxSpeedMps', speed(e.maxSpeedMps)),
('averagePaceSecPerKm', pace(e.averagePaceSecPerKm)),
('averageHeartRate', v(e.averageHeartRate)),
('maxHeartRate', v(e.maxHeartRate)),
('averageCadence', v(e.averageCadence)),
('maxCadence', v(e.maxCadence)),
('calories', v(e.calories)),
('powerAvg', v(e.powerAvg)),
('powerMax', v(e.powerMax)),
('pointCount', v(e.pointCount)),
('segmentCount', v(e.segmentCount)),
('lapCount', v(e.lapCount)),
('minLatitude', coordinate(e.minLatitude)),
('maxLatitude', coordinate(e.maxLatitude)),
('minLongitude', coordinate(e.minLongitude)),
('maxLongitude', coordinate(e.maxLongitude)),
('centerLatitude', coordinate(e.centerLatitude)),
('centerLongitude', coordinate(e.centerLongitude)),
('sizeBytes', bytes(e.sizeBytes)),
('lastModifiedMillis', millisValue(e.lastModifiedMillis)),
('dateAddedMillis', millisValue(e.dateAddedMillis)),
('dateModifiedMillis', millisValue(e.dateModifiedMillis)),
('lastScanMillis', millisValue(e.lastScanMillis)),
('isFavorite', v(e.isFavorite)),
('isHidden', v(e.isHidden)),
('rating', v(e.rating)),
('tags', v(e.tags)),
('scanStatus', v(e.scanStatus)),
('scanError', v(e.scanError)),
('diagnostics', v(e.diagnostics)),
];
}
class _DbFieldLine extends StatelessWidget {
final String label;
final String value;
const _DbFieldLine({
required this.label,
required this.value,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Padding(
padding: const EdgeInsets.symmetric(vertical: 4),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
label,
style: theme.textTheme.labelMedium?.copyWith(
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 2),
SelectableText(
value,
style: theme.textTheme.bodySmall,
),
const Divider(height: 12),
],
),
);
}
}