feat(exercice): modèle et migration pour l'auto-enchaînement des chronos d'étapes (ticket #75)

Étend le modèle Drift (migration schemaVersion 13→14, ADD COLUMN) et
la couche application (entités, use cases, repositories) pour
supporter l'auto-enchaînement des chronos d'étapes. flutter pub get
OK, build_runner OK, analyze propre (mêmes infos préexistantes),
141/141 tests verts, build APK debug validé. Premier ticket du
chantier "auto-enchaînement des chronos d'étapes" (#73).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 13:42:46 +02:00
parent f510053d55
commit e61365277b
8 changed files with 704 additions and 4 deletions

View File

@ -592,6 +592,10 @@ final class ShareUseCases {
exerciseStepsSnapshot: _exerciseStepsFromSnapshot(
map['exerciseStepsSnapshot'],
),
autoStartNextTimedStepSnapshot:
map['autoStartNextTimedStepSnapshot'] as bool? ?? true,
autoStartNextTimedStepOverride:
map['autoStartNextTimedStepOverride'] as bool?,
exerciseArchivedSnapshot: map['exerciseArchivedSnapshot'] == true,
availableTimeSnapshot: map['availableTimeSnapshot'] == true,
availableRepsSnapshot: map['availableRepsSnapshot'] == true,
@ -733,6 +737,8 @@ final class ShareUseCases {
targetRepsOverride: map['targetRepsOverride'] as int?,
targetScoreOverride: (map['targetScoreOverride'] as num?)?.toDouble(),
targetScoreTimeMsOverride: map['targetScoreTimeMsOverride'] as int?,
autoStartNextTimedStepOverride:
map['autoStartNextTimedStepOverride'] as bool?,
),
);
}
@ -772,6 +778,7 @@ final class ExerciseUseCases {
int? defaultTargetReps,
double? defaultTargetScore,
int? defaultTargetScoreTimeMs,
bool autoStartNextTimedStep = true,
List<ExerciseStep> steps = const [],
}) async {
_validateExerciseSteps(steps);
@ -803,6 +810,7 @@ final class ExerciseUseCases {
defaultTargetReps: defaultTargetReps,
defaultTargetScore: defaultTargetScore,
defaultTargetScoreTimeMs: defaultTargetScoreTimeMs,
autoStartNextTimedStep: autoStartNextTimedStep,
steps: steps,
);
await repository.save(exercise);
@ -835,6 +843,7 @@ final class ExerciseUseCases {
Object? defaultTargetReps = _useCaseUnchanged,
Object? defaultTargetScore = _useCaseUnchanged,
Object? defaultTargetScoreTimeMs = _useCaseUnchanged,
bool? autoStartNextTimedStep,
Object? steps = _useCaseUnchanged,
}) async {
final exercise = await repository.findById(id);
@ -895,6 +904,7 @@ final class ExerciseUseCases {
defaultTargetReps: resolvedDefaultTargetReps,
defaultTargetScore: resolvedDefaultTargetScore,
defaultTargetScoreTimeMs: resolvedDefaultTargetScoreTimeMs,
autoStartNextTimedStep: autoStartNextTimedStep,
steps: resolvedSteps,
);
await repository.save(updated);
@ -1204,6 +1214,10 @@ final class ProgramUseCases {
exerciseImageMediaIdsSnapshot: input.exerciseImageMediaIdsSnapshot,
exerciseVideoMediaIdSnapshot: input.exerciseVideoMediaIdSnapshot,
exerciseStepsSnapshot: input.exerciseStepsSnapshot,
autoStartNextTimedStepSnapshot:
input.autoStartNextTimedStepSnapshot,
autoStartNextTimedStepOverride:
input.autoStartNextTimedStepOverride,
exerciseArchivedSnapshot: input.exerciseArchivedSnapshot,
availableTimeSnapshot: input.availableTimeSnapshot,
availableRepsSnapshot: input.availableRepsSnapshot,
@ -1322,6 +1336,8 @@ final class ProgramExerciseConfig {
this.exerciseImageMediaIdsSnapshot = const [],
this.exerciseVideoMediaIdSnapshot,
this.exerciseStepsSnapshot = const [],
this.autoStartNextTimedStepSnapshot = true,
this.autoStartNextTimedStepOverride,
this.exerciseArchivedSnapshot = false,
required this.availableTimeSnapshot,
required this.availableRepsSnapshot,
@ -1346,6 +1362,8 @@ final class ProgramExerciseConfig {
final List<String> exerciseImageMediaIdsSnapshot;
final String? exerciseVideoMediaIdSnapshot;
final List<ExerciseStep> exerciseStepsSnapshot;
final bool autoStartNextTimedStepSnapshot;
final bool? autoStartNextTimedStepOverride;
final bool exerciseArchivedSnapshot;
final bool availableTimeSnapshot;
final bool availableRepsSnapshot;
@ -1460,6 +1478,8 @@ final class WorkoutTemplateUseCases {
targetRepsOverride: input.targetRepsOverride,
targetScoreOverride: input.targetScoreOverride,
targetScoreTimeMsOverride: input.targetScoreTimeMsOverride,
autoStartNextTimedStepOverride:
input.autoStartNextTimedStepOverride,
),
);
}
@ -1502,6 +1522,7 @@ final class WorkoutTemplateUseCases {
int? targetRepsOverride,
double? targetScoreOverride,
int? targetScoreTimeMsOverride,
bool? autoStartNextTimedStepOverride,
Set<WorkoutMeasure>? attemptedMeasureOverride,
}) async {
if (attemptedMeasureOverride != null) {
@ -1519,6 +1540,7 @@ final class WorkoutTemplateUseCases {
targetRepsOverride: targetRepsOverride,
targetScoreOverride: targetScoreOverride,
targetScoreTimeMsOverride: targetScoreTimeMsOverride,
autoStartNextTimedStepOverride: autoStartNextTimedStepOverride,
);
await templateRepository.saveOverride(override);
return override;
@ -1568,6 +1590,7 @@ final class WorkoutTemplateExerciseOverrideConfig {
this.targetRepsOverride,
this.targetScoreOverride,
this.targetScoreTimeMsOverride,
this.autoStartNextTimedStepOverride,
});
final EntityMetadata? existingMetadata;
@ -1578,6 +1601,7 @@ final class WorkoutTemplateExerciseOverrideConfig {
final int? targetRepsOverride;
final double? targetScoreOverride;
final int? targetScoreTimeMsOverride;
final bool? autoStartNextTimedStepOverride;
}
final class ActiveWorkoutSessionUseCases {
@ -1635,6 +1659,8 @@ final class ActiveWorkoutSessionUseCases {
'targetRepsOverride': override.targetRepsOverride,
'targetScoreOverride': override.targetScoreOverride,
'targetScoreTimeMsOverride': override.targetScoreTimeMsOverride,
'autoStartNextTimedStepOverride':
override.autoStartNextTimedStepOverride,
},
)
.toList(),
@ -3185,6 +3211,8 @@ Map<String, Object?> _workoutTemplateSharePayload(WorkoutTemplate template) => {
'targetRepsOverride': override.targetRepsOverride,
'targetScoreOverride': override.targetScoreOverride,
'targetScoreTimeMsOverride': override.targetScoreTimeMsOverride,
'autoStartNextTimedStepOverride':
override.autoStartNextTimedStepOverride,
},
)
.toList(),