diff --git a/lib/widgets/routines/day.dart b/lib/widgets/routines/day.dart index 5b5463d2..b7cfa0c5 100644 --- a/lib/widgets/routines/day.dart +++ b/lib/widgets/routines/day.dart @@ -145,6 +145,7 @@ class DayHeader extends StatelessWidget { style: Theme.of(context).textTheme.headlineSmall, overflow: TextOverflow.ellipsis, ), + subtitle: Text(_dayData.day!.description), leading: _viewMode ? null : const Icon(Icons.play_arrow), trailing: _dayData.date.isSameDayAs(DateTime.now()) ? const Icon(Icons.today) : null, minLeadingWidth: 8, diff --git a/lib/widgets/routines/gym_mode.dart b/lib/widgets/routines/gym_mode.dart index c8b93095..69463606 100644 --- a/lib/widgets/routines/gym_mode.dart +++ b/lib/widgets/routines/gym_mode.dart @@ -167,7 +167,19 @@ class _GymModeState extends ConsumerState { state.exercisePages, widget._iteration, )); - out.add(TimerWidget(_controller, ratioCompleted, state.exercisePages)); + + // If there is a rest time, add a countdown timer + if (config.restTime != null) { + out.add(TimerCountdownWidget( + _controller, + config.restTime!.toInt(), + ratioCompleted, + state.exercisePages, + )); + } else { + out.add(TimerWidget(_controller, ratioCompleted, state.exercisePages)); + } + firstPage = false; } } @@ -1026,22 +1038,16 @@ class _TimerWidgetState extends State { DateTime today = DateTime(2000, 1, 1, 0, 0, 0); void startTimer() { - setState(() { - _seconds = 0; - }); + setState(() => _seconds = 0); _timer?.cancel(); const oneSecond = Duration(seconds: 1); _timer = Timer.periodic(oneSecond, (Timer timer) { if (_seconds == _maxSeconds) { - setState(() { - timer.cancel(); - }); + setState(() => timer.cancel()); } else { - setState(() { - _seconds++; - }); + setState(() => _seconds++); } }); } @@ -1081,6 +1087,79 @@ class _TimerWidgetState extends State { } } +class TimerCountdownWidget extends StatefulWidget { + final PageController _controller; + final double _ratioCompleted; + final int _seconds; + final Map _exercisePages; + + const TimerCountdownWidget( + this._controller, + this._seconds, + this._ratioCompleted, + this._exercisePages, + ); + + @override + _TimerCountdownWidgetState createState() => _TimerCountdownWidgetState(); +} + +class _TimerCountdownWidgetState extends State { + // See https://stackoverflow.com/questions/54610121/flutter-countdown-timer + + Timer? _timer; + late int _seconds; + DateTime today = DateTime(2000, 1, 1, 0, 0, 0); + + void startTimer() { + _timer?.cancel(); + + const oneSecond = Duration(seconds: 1); + _timer = Timer.periodic(oneSecond, (Timer timer) { + if (_seconds == 0) { + setState(() => timer.cancel()); + } else { + setState(() => _seconds--); + } + }); + } + + @override + void dispose() { + _timer?.cancel(); + super.dispose(); + } + + @override + void initState() { + super.initState(); + _seconds = widget._seconds; + startTimer(); + } + + @override + Widget build(BuildContext context) { + return Column( + children: [ + NavigationHeader( + AppLocalizations.of(context).pause, + widget._controller, + exercisePages: widget._exercisePages, + ), + Expanded( + child: Center( + child: Text( + DateFormat('m:ss').format(today.add(Duration(seconds: _seconds))), + style: Theme.of(context).textTheme.displayLarge!.copyWith(color: wgerPrimaryColor), + ), + ), + ), + NavigationFooter(widget._controller, widget._ratioCompleted), + ], + ); + } +} + class NavigationFooter extends StatelessWidget { final PageController _controller; final double _ratioCompleted; diff --git a/test/workout/gym_mode_screen_test.dart b/test/workout/gym_mode_screen_test.dart index d8c355f6..e4997e59 100644 --- a/test/workout/gym_mode_screen_test.dart +++ b/test/workout/gym_mode_screen_test.dart @@ -148,7 +148,7 @@ void main() { // Bench press - pause // expect(find.text('Pause'), findsOneWidget); - expect(find.byType(TimerWidget), findsOneWidget); + expect(find.byType(TimerCountdownWidget), findsOneWidget); expect(find.byIcon(Icons.close), findsOneWidget); expect(find.byIcon(Icons.toc), findsOneWidget); expect(find.byIcon(Icons.chevron_left), findsOneWidget); @@ -169,7 +169,7 @@ void main() { // Pause // expect(find.text('Pause'), findsOneWidget); - expect(find.byType(TimerWidget), findsOneWidget); + expect(find.byType(TimerCountdownWidget), findsOneWidget); expect(find.byIcon(Icons.chevron_left), findsOneWidget); expect(find.byIcon(Icons.close), findsOneWidget); expect(find.byIcon(Icons.chevron_right), findsOneWidget); @@ -189,7 +189,7 @@ void main() { // Pause // expect(find.text('Pause'), findsOneWidget); - expect(find.byType(TimerWidget), findsOneWidget); + expect(find.byType(TimerCountdownWidget), findsOneWidget); await tester.tap(find.byIcon(Icons.chevron_right)); await tester.pumpAndSettle(); diff --git a/test/workout/routine_screen_test.dart b/test/workout/routine_screen_test.dart index 9709ac61..93c3b24e 100644 --- a/test/workout/routine_screen_test.dart +++ b/test/workout/routine_screen_test.dart @@ -65,9 +65,7 @@ void main() { ), child: const SizedBox(), ), - routes: { - RoutineScreen.routeName: (ctx) => const RoutineScreen(), - }, + routes: {RoutineScreen.routeName: (ctx) => const RoutineScreen()}, ), ); } @@ -83,6 +81,7 @@ void main() { expect(find.text('3 day workout'), findsOneWidget); expect(find.text('first day'), findsOneWidget); + debugDumpApp(); expect(find.text('chest, shoulders'), findsOneWidget); expect(find.text('second day'), findsOneWidget); diff --git a/test/workout/slot_entry_form_test.dart b/test/workout/slot_entry_form_test.dart index 02f44ba7..9b4167fa 100644 --- a/test/workout/slot_entry_form_test.dart +++ b/test/workout/slot_entry_form_test.dart @@ -56,7 +56,7 @@ void main() { localizationsDelegates: AppLocalizations.localizationsDelegates, supportedLocales: AppLocalizations.supportedLocales, navigatorKey: key, - home: Scaffold(body: SlotEntryForm(slotEntry, simpleMode: simpleMode)), + home: Scaffold(body: SlotEntryForm(slotEntry, 1, simpleMode: simpleMode)), ), ); } @@ -89,7 +89,7 @@ void main() { await tester.tap(find.byKey(const Key(SUBMIT_BUTTON_KEY_NAME))); await tester.pumpAndSettle(); - verify(mockRoutinesProvider.editSlotEntry(any)).called(1); + verify(mockRoutinesProvider.editSlotEntry(any, any)).called(1); verify(mockRoutinesProvider.handleConfig(any, any, any)).called(8); }); } diff --git a/test_data/routines.dart b/test_data/routines.dart index 9a49c810..6885ce64 100644 --- a/test_data/routines.dart +++ b/test_data/routines.dart @@ -296,7 +296,7 @@ Routine getTestRoutine({List? exercises}) { repetitionsUnit: testRepetitionUnit1, weight: 10, weightUnit: testWeightUnit1, - restTime: 60, + restTime: null, rir: '', rpe: '', textRepr: '12x10kg', @@ -310,7 +310,7 @@ Routine getTestRoutine({List? exercises}) { repetitionsUnit: testRepetitionUnit1, weight: 10, weightUnit: testWeightUnit1, - restTime: 60, + restTime: null, rir: '', rpe: '', textRepr: '12x10kg', @@ -324,7 +324,7 @@ Routine getTestRoutine({List? exercises}) { repetitionsUnit: testRepetitionUnit1, weight: 10, weightUnit: testWeightUnit1, - restTime: 60, + restTime: null, rir: '', rpe: '', textRepr: '12x10kg',