feat(core): consolide le chainage type metier d'exercice -> strategie Health Services -> payload montre -> consommation Kotlin

Finalise #183 : modele/persistance des types metier d'exercice, mapping vers la strategie Health Services, propagation du payload dans le contrat watch bridge et consommation cote Kotlin montre. Perimetre complet QA vert.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 16:17:31 +02:00
parent 30e657a67f
commit 2ae716206a
10 changed files with 444 additions and 22 deletions

View File

@ -3542,7 +3542,11 @@ bool _hasSameWatchCommandRevisionState(
left.manualScoreTargetValue == right.manualScoreTargetValue &&
left.manualScoreTargetLabel == right.manualScoreTargetLabel &&
left.manualScoreRepsTargetValue == right.manualScoreRepsTargetValue &&
left.manualScoreScope == right.manualScoreScope;
left.manualScoreScope == right.manualScoreScope &&
_listEquals(
left.healthServicesExerciseTypeStrategy,
right.healthServicesExerciseTypeStrategy,
);
}
bool _hasSameWatchCommandRevisionTimerListState(
@ -4216,6 +4220,8 @@ final class WatchSessionProjectionProjector {
manualScoreTargetLabel: manualScoreProjection?.targetLabel,
manualScoreRepsTargetValue: manualScoreProjection?.repsTargetValue,
manualScoreScope: manualScoreProjection?.scope,
healthServicesExerciseTypeStrategy:
snapshot.healthServicesExerciseTypeStrategy,
);
}
@ -7052,6 +7058,13 @@ ScoreInputMode _scoreInputModeFromSnapshot(Object? value) {
};
}
List<String> _stringListFromSnapshot(Object? value) {
if (value is! List) {
return const [];
}
return value.whereType<String>().toList(growable: false);
}
_SetPositionSnapshot? _findSetSnapshot({
required String resolvedTemplateSnapshotJson,
required int programIndex,
@ -7203,6 +7216,9 @@ _ResolvedExerciseSnapshot? _findExerciseSnapshot({
scoreUnitSnapshot: exercise['scoreUnitSnapshot'] as String?,
setsCount: exercise['setsCount'] as int? ?? 0,
restSeconds: exercise['restSecondsOverride'] as int? ?? 0,
healthServicesExerciseTypeStrategy: _stringListFromSnapshot(
exercise['healthServicesExerciseTypeStrategy'],
),
steps: _exerciseStepsFromSnapshot(exercise['exerciseStepsSnapshot']),
autoStartNextTimedStepEffective: autoStartNextTimedStepEffective,
);
@ -7423,6 +7439,9 @@ Map<String, _ResolvedExerciseSnapshot> _exerciseSnapshotsById(
scoreUnitSnapshot: exercise['scoreUnitSnapshot'] as String?,
setsCount: exercise['setsCount'] as int? ?? 0,
restSeconds: exercise['restSecondsOverride'] as int? ?? 0,
healthServicesExerciseTypeStrategy: _stringListFromSnapshot(
exercise['healthServicesExerciseTypeStrategy'],
),
steps: _exerciseStepsFromSnapshot(exercise['exerciseStepsSnapshot']),
autoStartNextTimedStepEffective:
(exercise['autoStartNextTimedStepOverride'] as bool?) ??
@ -7453,6 +7472,7 @@ final class _ResolvedExerciseSnapshot {
this.scoreUnitSnapshot,
required this.setsCount,
required this.restSeconds,
this.healthServicesExerciseTypeStrategy = const [],
this.steps = const [],
this.autoStartNextTimedStepEffective = true,
});
@ -7474,6 +7494,7 @@ final class _ResolvedExerciseSnapshot {
final String? scoreUnitSnapshot;
final int setsCount;
final int restSeconds;
final List<String> healthServicesExerciseTypeStrategy;
final List<ExerciseStep> steps;
final bool autoStartNextTimedStepEffective;
}