feat(exercice): état d'exécution Chrono suivant prêt (ticket #78)
Ajoute l'état "Chrono suivant prêt" sur workout_execution_screen.dart pour l'auto-enchaînement des chronos d'étapes. Corrige _startCurrentStepTimerIfNeeded() qui forçait à tort startTimer() : il se contente maintenant de rafraîchir le ticker d'affichage, laissant le backend (#76) seul décisionnaire du démarrage automatique ou de l'attente du chrono suivant. flutter pub get OK, dart format appliqué (aucun changement), analyze propre (mêmes infos préexistantes), 153/153 tests verts (dont le test de non-régression pour l'enchaînement automatique activé par défaut), build APK debug validé. Dernier ticket de développement du chantier "auto-enchaînement des chronos d'étapes" (#73) — il ne reste que la QA finale (#79). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -740,16 +740,9 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _startCurrentStepTimerIfNeeded() async {
|
||||
final view = _stepProgress;
|
||||
final step = view?.currentStep;
|
||||
if (view == null ||
|
||||
step == null ||
|
||||
step.type != ExerciseStepType.time ||
|
||||
view.state.status == ActiveExerciseStepProgressStatus.runningTimer) {
|
||||
return;
|
||||
}
|
||||
await _startCurrentStepTimer();
|
||||
Future<void> _startCurrentStepTimerIfNeeded() {
|
||||
_refreshStepTicker();
|
||||
return Future<void>.value();
|
||||
}
|
||||
|
||||
Future<void> _completeCurrentStep() async {
|
||||
@ -1537,6 +1530,7 @@ final class _StepSequencePanel extends StatelessWidget {
|
||||
running:
|
||||
view.state.status ==
|
||||
ActiveExerciseStepProgressStatus.runningTimer,
|
||||
readyToStart: _isNextTimedStepReady(view),
|
||||
onStartTimer: onStartTimer,
|
||||
)
|
||||
else
|
||||
@ -1590,12 +1584,14 @@ final class _TimedStepBody extends StatelessWidget {
|
||||
required this.step,
|
||||
required this.remainingLabel,
|
||||
required this.running,
|
||||
required this.readyToStart,
|
||||
required this.onStartTimer,
|
||||
});
|
||||
|
||||
final ExerciseStep step;
|
||||
final String remainingLabel;
|
||||
final bool running;
|
||||
final bool readyToStart;
|
||||
final VoidCallback onStartTimer;
|
||||
|
||||
@override
|
||||
@ -1615,10 +1611,22 @@ final class _TimedStepBody extends StatelessWidget {
|
||||
),
|
||||
if (!running) ...[
|
||||
const SizedBox(height: 12),
|
||||
if (readyToStart) ...[
|
||||
Text(
|
||||
'Chrono suivant prêt',
|
||||
textAlign: TextAlign.center,
|
||||
style: Theme.of(context).textTheme.titleMedium?.copyWith(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
],
|
||||
FilledButton.icon(
|
||||
onPressed: onStartTimer,
|
||||
icon: const Icon(Icons.play_arrow),
|
||||
label: const Text('Démarrer la séquence'),
|
||||
label: Text(
|
||||
readyToStart ? 'Démarrer le chrono' : 'Démarrer la séquence',
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
@ -1626,6 +1634,22 @@ final class _TimedStepBody extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
bool _isNextTimedStepReady(ActiveExerciseStepProgressView view) {
|
||||
final step = view.currentStep;
|
||||
if (step == null ||
|
||||
step.type != ExerciseStepType.time ||
|
||||
view.state.status != ActiveExerciseStepProgressStatus.stoppedTimer) {
|
||||
return false;
|
||||
}
|
||||
return view.results.any((result) {
|
||||
if (result.passageIndex < view.state.currentPassageIndex) {
|
||||
return true;
|
||||
}
|
||||
return result.passageIndex == view.state.currentPassageIndex &&
|
||||
result.stepIndex < view.state.currentStepIndex;
|
||||
});
|
||||
}
|
||||
|
||||
final class _RepsStepBody extends StatelessWidget {
|
||||
const _RepsStepBody({required this.step, required this.onCompleteStep});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user