From 05a935afc15978e6fe78d8a6a3f2005fda3f9c9f Mon Sep 17 00:00:00 2001 From: Blomios Date: Sat, 18 Jul 2026 00:58:10 +0200 Subject: [PATCH] =?UTF-8?q?fix(execution):=20comportement=20de=20la=20fl?= =?UTF-8?q?=C3=A8che=20retour=20en=20s=C3=A9ance=20(ticket=20#31)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Corrige la flèche de retour sur workout_execution_screen.dart : elle ouvre désormais le choix pause/abandon ou quitter-et-sauvegarder au lieu de ne rien faire. flutter analyze propre, 36/36 tests verts, build APK debug validé. Co-Authored-By: Claude Opus 4.8 --- .../workout_execution_screen.dart | 19 +++++++++ .../workout_execution_screen_test.dart | 41 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/lib/presentation/workout_execution_screen.dart b/lib/presentation/workout_execution_screen.dart index 78d8f37..351bc73 100644 --- a/lib/presentation/workout_execution_screen.dart +++ b/lib/presentation/workout_execution_screen.dart @@ -78,8 +78,17 @@ final class _WorkoutExecutionScreenState extends State { Widget build(BuildContext context) { return PopScope( canPop: false, + onPopInvoked: _handleSystemBack, child: Scaffold( appBar: AppBar( + automaticallyImplyLeading: false, + leading: _canPauseFromNavigation + ? IconButton( + tooltip: 'Mettre en pause', + onPressed: () => unawaited(_pause()), + icon: const Icon(Icons.arrow_back), + ) + : null, title: Text(_plan.name), actions: [ IconButton( @@ -263,6 +272,16 @@ final class _WorkoutExecutionScreenState extends State { ); } + bool get _canPauseFromNavigation { + return _mode == WorkoutExecutionMode.active || + _mode == WorkoutExecutionMode.rest; + } + + void _handleSystemBack(bool didPop) { + if (didPop || !_canPauseFromNavigation) return; + unawaited(_pause()); + } + Future _pause() async { _restTicker?.cancel(); _session = await widget.activeUseCases.pause(_session.metadata.id); diff --git a/test/presentation/workout_execution_screen_test.dart b/test/presentation/workout_execution_screen_test.dart index 45b4f31..83e3910 100644 --- a/test/presentation/workout_execution_screen_test.dart +++ b/test/presentation/workout_execution_screen_test.dart @@ -218,6 +218,47 @@ void main() { expect(repository.results.single.actualTimeMs, greaterThan(0)); }); + testWidgets('la flèche de retour met la séance active en pause', ( + tester, + ) async { + final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12)); + final repository = _FakeActiveSessionRepository(); + final session = ActiveWorkoutSession( + metadata: _metadata('session-1'), + sourceWorkoutTemplateId: 'template-1', + status: ActiveWorkoutStatus.running, + startedAt: DateTime.utc(2026, 7, 17, 12), + lastPersistedAt: DateTime.utc(2026, 7, 17, 12), + elapsedActiveMs: 0, + currentProgramIndex: 0, + currentExerciseIndex: 0, + currentSetIndex: 0, + resolvedTemplateSnapshotJson: _sessionSnapshot( + setsCount: 2, + restSeconds: 0, + ), + ); + repository.session = session; + + await tester.pumpWidget( + MaterialApp( + home: WorkoutExecutionScreen( + initialSession: session, + activeUseCases: _activeUseCases(repository, clock), + closeUseCase: _closeUseCase(repository, clock), + historyUseCases: _historyUseCases(clock), + workoutTemplateUseCases: _workoutTemplateUseCases(), + ), + ), + ); + + await tester.tap(find.byTooltip('Mettre en pause')); + await tester.pumpAndSettle(); + + expect(find.text('Reprendre'), findsOneWidget); + expect(repository.session?.status, ActiveWorkoutStatus.paused); + }); + testWidgets('le plan de séance affiche les états des séries', (tester) async { final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12)); final repository = _FakeActiveSessionRepository();