fix(execution): corrige la reprise de seance affichant a tort Seance Terminee (#192)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -12,7 +12,7 @@ import 'exercise_step_audio.dart';
|
||||
import 'history_screen.dart';
|
||||
import 'theme.dart';
|
||||
|
||||
enum WorkoutExecutionMode { active, rest, paused, finished }
|
||||
enum WorkoutExecutionMode { active, rest, paused, finished, resumingSavedExit }
|
||||
|
||||
typedef VideoMediaBuilder =
|
||||
Widget Function(BuildContext context, MediaAsset asset);
|
||||
@ -117,9 +117,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
(widget.stepUseCases == null
|
||||
? const NoOpExerciseStepAudioCuePlayer()
|
||||
: AudioplayersExerciseStepAudioCuePlayer());
|
||||
_mode = _session.status == ActiveWorkoutStatus.running
|
||||
? WorkoutExecutionMode.active
|
||||
: WorkoutExecutionMode.paused;
|
||||
_mode = _modeForSessionStatus(_session.status);
|
||||
_reps = _initialRepsFor(_exercise);
|
||||
_performanceReference = _loadPerformanceReference();
|
||||
_ticker = Timer.periodic(const Duration(seconds: 1), (_) {
|
||||
@ -136,11 +134,16 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
}
|
||||
setState(() => _sensorState = state);
|
||||
});
|
||||
unawaited(_loadSetTimer());
|
||||
unawaited(_loadScoreStopwatch());
|
||||
unawaited(_syncManualScoreInput(force: true));
|
||||
unawaited(_loadStepProgress());
|
||||
unawaited(_restoreActiveRest());
|
||||
final resumingSavedExit = _session.status == ActiveWorkoutStatus.savedExit;
|
||||
if (resumingSavedExit) {
|
||||
unawaited(_resumeSavedExitSession());
|
||||
} else {
|
||||
unawaited(_loadSetTimer());
|
||||
unawaited(_loadScoreStopwatch());
|
||||
unawaited(_syncManualScoreInput(force: true));
|
||||
unawaited(_loadStepProgress());
|
||||
unawaited(_restoreActiveRest());
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
@ -225,7 +228,8 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
onPressed: _openWorkoutPlan,
|
||||
icon: const Icon(Icons.list_alt),
|
||||
),
|
||||
TextButton(onPressed: _pause, child: const Text('Pause')),
|
||||
if (_canPauseFromNavigation)
|
||||
TextButton(onPressed: _pause, child: const Text('Pause')),
|
||||
],
|
||||
),
|
||||
bottomNavigationBar: _mode == WorkoutExecutionMode.active
|
||||
@ -243,6 +247,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
WorkoutExecutionMode.rest => _buildRest(),
|
||||
WorkoutExecutionMode.paused => _buildPaused(),
|
||||
WorkoutExecutionMode.finished => _buildFinished(),
|
||||
WorkoutExecutionMode.resumingSavedExit => _buildResumingSavedExit(),
|
||||
},
|
||||
),
|
||||
);
|
||||
@ -510,6 +515,22 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildResumingSavedExit() {
|
||||
return const Center(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(24),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
SizedBox(height: 16),
|
||||
Text('Reprise de la séance...'),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFinished() {
|
||||
final elapsed = Duration(
|
||||
milliseconds: widget.activeUseCases.elapsedActiveMilliseconds(_session),
|
||||
@ -1221,7 +1242,9 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
}
|
||||
|
||||
Future<void> _syncExternalSessionChanges() async {
|
||||
if (_externalSyncInFlight || !mounted) {
|
||||
if (_externalSyncInFlight ||
|
||||
!mounted ||
|
||||
_mode == WorkoutExecutionMode.resumingSavedExit) {
|
||||
return;
|
||||
}
|
||||
_externalSyncInFlight = true;
|
||||
@ -1250,16 +1273,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_mode = switch (session.status) {
|
||||
ActiveWorkoutStatus.running =>
|
||||
_activeRestStateId == null
|
||||
? WorkoutExecutionMode.active
|
||||
: WorkoutExecutionMode.rest,
|
||||
ActiveWorkoutStatus.paused => WorkoutExecutionMode.paused,
|
||||
ActiveWorkoutStatus.completed ||
|
||||
ActiveWorkoutStatus.abandoned ||
|
||||
ActiveWorkoutStatus.savedExit => WorkoutExecutionMode.finished,
|
||||
};
|
||||
_mode = _modeForSessionStatus(session.status);
|
||||
});
|
||||
_refreshScoreStopwatchTicker();
|
||||
_refreshStepTicker();
|
||||
@ -1400,6 +1414,19 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
_mode == WorkoutExecutionMode.rest;
|
||||
}
|
||||
|
||||
WorkoutExecutionMode _modeForSessionStatus(ActiveWorkoutStatus status) {
|
||||
return switch (status) {
|
||||
ActiveWorkoutStatus.running =>
|
||||
_activeRestStateId == null
|
||||
? WorkoutExecutionMode.active
|
||||
: WorkoutExecutionMode.rest,
|
||||
ActiveWorkoutStatus.paused => WorkoutExecutionMode.paused,
|
||||
ActiveWorkoutStatus.savedExit => WorkoutExecutionMode.resumingSavedExit,
|
||||
ActiveWorkoutStatus.completed ||
|
||||
ActiveWorkoutStatus.abandoned => WorkoutExecutionMode.finished,
|
||||
};
|
||||
}
|
||||
|
||||
void _handleSystemBack(bool didPop, Object? result) {
|
||||
if (didPop || !_canPauseFromNavigation) return;
|
||||
unawaited(_pause());
|
||||
@ -1443,6 +1470,13 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
_refreshStepTicker();
|
||||
}
|
||||
|
||||
Future<void> _resumeSavedExitSession() async {
|
||||
if (!mounted || _mode != WorkoutExecutionMode.resumingSavedExit) {
|
||||
return;
|
||||
}
|
||||
await _resume();
|
||||
}
|
||||
|
||||
Future<void> _quitAndSave() async {
|
||||
await widget.activeUseCases.quitAndSave(_session.metadata.id);
|
||||
if (!mounted) return;
|
||||
@ -2777,6 +2811,8 @@ final class _CurrentStepPane extends StatelessWidget {
|
||||
step.type == ExerciseStepType.time &&
|
||||
step.hasScore &&
|
||||
step.scoreInputMode == ScoreInputMode.manual;
|
||||
final useCompactRepsActions =
|
||||
step.type == ExerciseStepType.reps && constraints.maxHeight < 180;
|
||||
if (hasRepsWithStopwatchScore || hasTimedWithManualScore) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
@ -2900,7 +2936,8 @@ final class _CurrentStepPane extends StatelessWidget {
|
||||
),
|
||||
],
|
||||
const SizedBox(height: 4),
|
||||
if (step.type == ExerciseStepType.reps) ...[
|
||||
if (step.type == ExerciseStepType.reps &&
|
||||
!useCompactRepsActions) ...[
|
||||
FilledButton.icon(
|
||||
onPressed: onCompleteStep,
|
||||
style: FilledButton.styleFrom(
|
||||
@ -2922,6 +2959,19 @@ final class _CurrentStepPane extends StatelessWidget {
|
||||
child: const Text('Passer l’étape'),
|
||||
),
|
||||
),
|
||||
if (useCompactRepsActions) ...[
|
||||
const SizedBox(width: 8),
|
||||
Expanded(
|
||||
child: FilledButton.icon(
|
||||
onPressed: onCompleteStep,
|
||||
style: FilledButton.styleFrom(
|
||||
minimumSize: const Size.fromHeight(44),
|
||||
),
|
||||
icon: const Icon(Icons.check),
|
||||
label: const Text('Étape suivante'),
|
||||
),
|
||||
),
|
||||
],
|
||||
const SizedBox(width: 8),
|
||||
PopupMenuButton<_StepSkipAction>(
|
||||
tooltip: 'Plus d’actions',
|
||||
|
||||
Reference in New Issue
Block a user