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

@ -1,4 +1,4 @@
const int watchBridgeSchemaVersion = 6;
const int watchBridgeSchemaVersion = 7;
enum WatchCommandType {
startCurrentExercise,
@ -300,6 +300,7 @@ final class WatchSessionProjection {
this.manualScoreTargetLabel,
this.manualScoreRepsTargetValue,
this.manualScoreScope,
this.healthServicesExerciseTypeStrategy = const [],
});
factory WatchSessionProjection.fromJson(Map<String, Object?> json) {
@ -362,6 +363,9 @@ final class WatchSessionProjection {
json['manualScoreScope'],
WatchManualScoreScope.values,
),
healthServicesExerciseTypeStrategy: _stringListFromJson(
json['healthServicesExerciseTypeStrategy'],
),
);
}
@ -398,6 +402,7 @@ final class WatchSessionProjection {
final String? manualScoreTargetLabel;
final int? manualScoreRepsTargetValue;
final WatchManualScoreScope? manualScoreScope;
final List<String> healthServicesExerciseTypeStrategy;
Map<String, Object?> toJson() {
return {
@ -438,6 +443,7 @@ final class WatchSessionProjection {
'manualScoreTargetLabel': manualScoreTargetLabel,
'manualScoreRepsTargetValue': manualScoreRepsTargetValue,
'manualScoreScope': manualScoreScope?.name,
'healthServicesExerciseTypeStrategy': healthServicesExerciseTypeStrategy,
};
}
@ -477,7 +483,11 @@ final class WatchSessionProjection {
manualScoreTargetValue == other.manualScoreTargetValue &&
manualScoreTargetLabel == other.manualScoreTargetLabel &&
manualScoreRepsTargetValue == other.manualScoreRepsTargetValue &&
manualScoreScope == other.manualScoreScope;
manualScoreScope == other.manualScoreScope &&
_listEquals(
healthServicesExerciseTypeStrategy,
other.healthServicesExerciseTypeStrategy,
);
}
@override
@ -516,6 +526,7 @@ final class WatchSessionProjection {
manualScoreTargetLabel,
manualScoreRepsTargetValue,
manualScoreScope,
Object.hashAll(healthServicesExerciseTypeStrategy),
]);
}
}
@ -886,6 +897,13 @@ String? _nullableStringFromJson(Object? value) {
return value is String ? value : null;
}
List<String> _stringListFromJson(Object? value) {
if (value is! List) {
return const [];
}
return value.whereType<String>().toList(growable: false);
}
int _intFromJson(Object? value, int fallback) {
return value is int ? value : fallback;
}