feat(watch): fréquence cardiaque live montre/téléphone (ticket #155)

Met en conformité l'implémentation avec le cadrage produit acté
(#155, #144, #142) : diffusion de la FC live depuis la montre vers le
téléphone via le bridge, affichage sur l'écran de séance montre
(watch_session_screen) en plus de l'écran Stats existant.

Validé : bridge fonctionnel bout-en-bout, tests watch_session_screen OK.
Artefact canonique d'installation montre confirmé :
watch_app/build/app/outputs/flutter-apk/app-release.apk
(package com.gametime.app) ; ne pas utiliser l'artefact résiduel
watch_app/build/watch_app/app/outputs/flutter-apk/app-release.apk.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-28 13:03:40 +02:00
parent 8bb74df763
commit 592796915f
6 changed files with 246 additions and 89 deletions

View File

@ -620,6 +620,33 @@ final class _StatusLine extends StatelessWidget {
}
}
final class _MainHeartRateLine extends StatelessWidget {
const _MainHeartRateLine({required this.sample});
final WatchSensorSample? sample;
@override
Widget build(BuildContext context) {
final label = _heartRateLabel(sample);
if (label == null) {
return const SizedBox.shrink();
}
return Padding(
padding: const EdgeInsets.only(top: 2),
child: Text(
'FC $label',
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.bodySmall?.copyWith(
color: const Color(0xFFA7ADBA),
fontSize: 11,
),
),
);
}
}
final class _ScaledContent extends StatelessWidget {
const _ScaledContent({required this.child});
@ -679,6 +706,7 @@ final class _ActiveContent extends StatelessWidget {
_SmallLabel(dominantLabel),
const SizedBox(height: 2),
_DominantValue(dominantValue),
_MainHeartRateLine(sample: state.sensorSample),
if (timer != null) ...[
const SizedBox(height: 3),
_TimerToggleButton(
@ -792,6 +820,7 @@ final class _ManualScoreContent extends StatelessWidget {
? const _PendingDot()
: const SizedBox.shrink(),
),
_MainHeartRateLine(sample: state.sensorSample),
const SizedBox(height: 5),
if (timer != null)
_CompactTimerLine(
@ -950,6 +979,7 @@ final class _RestContent extends StatelessWidget {
const _SmallLabel('REPOS'),
const SizedBox(height: 2),
_DominantValue(timer == null ? '--:--' : _timerText(timer)),
_MainHeartRateLine(sample: state.sensorSample),
if (timer != null) ...[
const SizedBox(height: 3),
_TimerToggleButton(