feat(watch): renforce la vibration de fin de chrono et consolide la remontee des donnees stats montre

Cote montre pour #180 (vibration timerFinished plus longue et plus forte) et #179 (contrat/collecte des donnees stats vers le telephone).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 14:55:52 +02:00
parent 36691643d7
commit b4503d6b5f
8 changed files with 170 additions and 29 deletions

View File

@ -1296,20 +1296,24 @@ final class _StatsView extends StatelessWidget {
Widget build(BuildContext context) {
final sample = state.sensorSample;
final metrics = [
if (_heartRateLabel(sample) case final value?)
_StatsMetric(icon: Icons.favorite, label: 'FC', value: value),
if (_distanceLabel(sample) case final value?)
_StatsMetric(
icon: Icons.directions_run,
label: 'Distance',
value: value,
),
if (_caloriesLabel(sample) case final value?)
_StatsMetric(
icon: Icons.local_fire_department,
label: 'Calories',
value: value,
),
_StatsMetric(
icon: Icons.favorite,
label: 'FC',
value: _heartRateMetricLabel(sample),
available: _heartRateLabel(sample) != null,
),
_StatsMetric(
icon: Icons.directions_run,
label: 'Distance',
value: _distanceMetricLabel(sample),
available: _distanceLabel(sample) != null,
),
_StatsMetric(
icon: Icons.local_fire_department,
label: 'Calories',
value: _caloriesMetricLabel(sample),
available: _caloriesLabel(sample) != null,
),
];
return Stack(
children: [
@ -1356,11 +1360,13 @@ final class _StatsMetric extends StatelessWidget {
required this.icon,
required this.label,
required this.value,
required this.available,
});
final IconData icon;
final String label;
final String value;
final bool available;
@override
Widget build(BuildContext context) {
@ -1384,13 +1390,18 @@ final class _StatsMetric extends StatelessWidget {
style: Theme.of(context).textTheme.bodySmall,
),
),
Text(
value,
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontSize: 14,
color: const Color(0xFFC9A24A),
Flexible(
child: Text(
value,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.end,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
fontSize: available ? 14 : 11,
color: available
? const Color(0xFFC9A24A)
: const Color(0xFFA7ADBA),
),
),
),
],
@ -1777,6 +1788,28 @@ String? _heartRateLabel(WatchSensorSample? sample) {
return '$bpm bpm';
}
String _heartRateMetricLabel(WatchSensorSample? sample) {
return _heartRateLabel(sample) ?? _sensorUnavailableLabel(sample);
}
String _distanceMetricLabel(WatchSensorSample? sample) {
return _distanceLabel(sample) ?? _sensorUnavailableLabel(sample);
}
String _caloriesMetricLabel(WatchSensorSample? sample) {
return _caloriesLabel(sample) ?? _sensorUnavailableLabel(sample);
}
String _sensorUnavailableLabel(WatchSensorSample? sample) {
if (sample?.sensorCollectionStatus == 'authorizationRequired') {
return 'Autorisation requise';
}
if (sample == null) {
return 'Mesure en attente';
}
return 'Donnée indisponible';
}
String? _distanceLabel(WatchSensorSample? sample) {
final meters = sample?.distanceMeters;
if (meters == null || meters < 0) {