feat: add end workout button to 'jump to' section

This commit is contained in:
Arthur De Neyer
2025-10-13 23:32:39 +02:00
parent 93a11a16e4
commit 354a8c381c
8 changed files with 60 additions and 10 deletions

View File

@@ -1028,6 +1028,7 @@
"@indicatorAvg": { "@indicatorAvg": {
"description": "added for localization of Class Indicator's field text" "description": "added for localization of Class Indicator's field text"
}, },
"endWorkout": "End Workout",
"themeMode": "Theme mode", "themeMode": "Theme mode",
"darkMode": "Always dark mode", "darkMode": "Always dark mode",
"lightMode": "Always light mode", "lightMode": "Always light mode",

View File

@@ -25,12 +25,14 @@ class ExerciseOverview extends StatelessWidget {
final Exercise _exercise; final Exercise _exercise;
final double _ratioCompleted; final double _ratioCompleted;
final Map<Exercise, int> _exercisePages; final Map<Exercise, int> _exercisePages;
final int _totalPages;
const ExerciseOverview( const ExerciseOverview(
this._controller, this._controller,
this._exercise, this._exercise,
this._ratioCompleted, this._ratioCompleted,
this._exercisePages, this._exercisePages,
this._totalPages,
); );
@override @override
@@ -40,6 +42,7 @@ class ExerciseOverview extends StatelessWidget {
NavigationHeader( NavigationHeader(
_exercise.getTranslation(Localizations.localeOf(context).languageCode).name, _exercise.getTranslation(Localizations.localeOf(context).languageCode).name,
_controller, _controller,
_totalPages,
exercisePages: _exercisePages, exercisePages: _exercisePages,
), ),
Expanded( Expanded(

View File

@@ -46,6 +46,7 @@ class GymMode extends ConsumerStatefulWidget {
class _GymModeState extends ConsumerState<GymMode> { class _GymModeState extends ConsumerState<GymMode> {
var _totalElements = 1; var _totalElements = 1;
var _totalPages = 1;
late Future<int> _initData; late Future<int> _initData;
bool _initialPageJumped = false; bool _initialPageJumped = false;
@@ -103,6 +104,12 @@ class _GymModeState extends ConsumerState<GymMode> {
void _calculatePages() { void _calculatePages() {
for (final slot in widget._dayDataGym.slots) { for (final slot in widget._dayDataGym.slots) {
_totalElements += slot.setConfigs.length; _totalElements += slot.setConfigs.length;
// add 1 for each exercise
_totalPages += 1;
for (final config in slot.setConfigs) {
// add nrOfSets * 2, 1 for log page and 1 for timer
_totalPages += (config.nrOfSets! * 2).toInt();
}
} }
_exercisePages.clear(); _exercisePages.clear();
var currentPage = 1; var currentPage = 1;
@@ -128,7 +135,7 @@ class _GymModeState extends ConsumerState<GymMode> {
final routinesProvider = context.read<RoutinesProvider>(); final routinesProvider = context.read<RoutinesProvider>();
var currentElement = 1; var currentElement = 1;
final List<Widget> out = []; final List<Widget> out = [];
for (final slotData in widget._dayDataGym.slots) { for (final slotData in widget._dayDataGym.slots) {
var firstPage = true; var firstPage = true;
for (final config in slotData.setConfigs) { for (final config in slotData.setConfigs) {
@@ -143,10 +150,11 @@ class _GymModeState extends ConsumerState<GymMode> {
exercise, exercise,
ratioCompleted, ratioCompleted,
state.exercisePages, state.exercisePages,
_totalPages
), ),
); );
} }
out.add( out.add(
LogPage( LogPage(
_controller, _controller,
@@ -156,7 +164,8 @@ class _GymModeState extends ConsumerState<GymMode> {
routinesProvider.findById(widget._dayDataGym.day!.routineId), routinesProvider.findById(widget._dayDataGym.day!.routineId),
ratioCompleted, ratioCompleted,
state.exercisePages, state.exercisePages,
widget._iteration, _totalPages,
widget._iteration
), ),
); );
@@ -168,16 +177,16 @@ class _GymModeState extends ConsumerState<GymMode> {
config.restTime!.toInt(), config.restTime!.toInt(),
ratioCompleted, ratioCompleted,
state.exercisePages, state.exercisePages,
_totalPages
), ),
); );
} else { } else {
out.add(TimerWidget(_controller, ratioCompleted, state.exercisePages)); out.add(TimerWidget(_controller, ratioCompleted, state.exercisePages, _totalPages));
} }
firstPage = false; firstPage = false;
} }
} }
return out; return out;
} }
@@ -201,13 +210,14 @@ class _GymModeState extends ConsumerState<GymMode> {
}); });
final List<Widget> children = [ final List<Widget> children = [
StartPage(_controller, widget._dayDataDisplay, _exercisePages), StartPage(_controller, widget._dayDataDisplay, _exercisePages, _totalPages),
...getContent(), ...getContent(),
SessionPage( SessionPage(
context.read<RoutinesProvider>().findById(widget._dayDataGym.day!.routineId), context.read<RoutinesProvider>().findById(widget._dayDataGym.day!.routineId),
_controller, _controller,
ref.read(gymStateProvider).startTime, ref.read(gymStateProvider).startTime,
_exercisePages, _exercisePages,
_totalPages,
dayId: widget._dayDataGym.day!.id!, dayId: widget._dayDataGym.day!.id!,
), ),
]; ];

View File

@@ -48,6 +48,7 @@ class LogPage extends ConsumerStatefulWidget {
final double _ratioCompleted; final double _ratioCompleted;
final Map<Exercise, int> _exercisePages; final Map<Exercise, int> _exercisePages;
final Log _log; final Log _log;
final int _totalPages;
LogPage( LogPage(
this._controller, this._controller,
@@ -57,6 +58,7 @@ class LogPage extends ConsumerStatefulWidget {
this._workoutPlan, this._workoutPlan,
this._ratioCompleted, this._ratioCompleted,
this._exercisePages, this._exercisePages,
this._totalPages,
int? iteration, int? iteration,
) : _log = Log.fromSetConfigData(_configData) ) : _log = Log.fromSetConfigData(_configData)
..routineId = _workoutPlan.id! ..routineId = _workoutPlan.id!
@@ -266,6 +268,7 @@ class _LogPageState extends ConsumerState<LogPage> {
NavigationHeader( NavigationHeader(
widget._exercise.getTranslation(Localizations.localeOf(context).languageCode).name, widget._exercise.getTranslation(Localizations.localeOf(context).languageCode).name,
widget._controller, widget._controller,
widget._totalPages,
exercisePages: widget._exercisePages, exercisePages: widget._exercisePages,
), ),

View File

@@ -15,6 +15,7 @@
* You should have received a copy of the GNU Affero General Public License * You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:wger/helpers/consts.dart'; import 'package:wger/helpers/consts.dart';
import 'package:wger/l10n/generated/app_localizations.dart'; import 'package:wger/l10n/generated/app_localizations.dart';
@@ -78,14 +79,32 @@ class NavigationHeader extends StatelessWidget {
final PageController _controller; final PageController _controller;
final String _title; final String _title;
final Map<Exercise, int> exercisePages; final Map<Exercise, int> exercisePages;
final int _totalPages;
final bool hideEndWorkoutButton;
const NavigationHeader( const NavigationHeader(
this._title, this._title,
this._controller, { this._controller,
required this.exercisePages, this._totalPages, {
required this.exercisePages,
this.hideEndWorkoutButton = false
}); });
Widget getDialog(BuildContext context) { Widget getDialog(BuildContext context) {
final TextButton? endWorkoutButton = !hideEndWorkoutButton ?
TextButton(
child: Text(AppLocalizations.of(context).endWorkout),
onPressed: () {
_controller.animateToPage(
_totalPages,
duration: DEFAULT_ANIMATION_DURATION,
curve: DEFAULT_ANIMATION_CURVE,
);
Navigator.of(context).pop();
},
) : null;
return AlertDialog( return AlertDialog(
title: Text( title: Text(
AppLocalizations.of(context).jumpTo, AppLocalizations.of(context).jumpTo,
@@ -113,6 +132,7 @@ class NavigationHeader extends StatelessWidget {
), ),
), ),
actions: [ actions: [
?endWorkoutButton,
TextButton( TextButton(
child: Text(MaterialLocalizations.of(context).closeButtonLabel), child: Text(MaterialLocalizations.of(context).closeButtonLabel),
onPressed: () { onPressed: () {

View File

@@ -31,12 +31,14 @@ class SessionPage extends StatelessWidget {
final WorkoutSession _session; final WorkoutSession _session;
final PageController _controller; final PageController _controller;
final Map<Exercise, int> _exercisePages; final Map<Exercise, int> _exercisePages;
final int _totalElements;
SessionPage( SessionPage(
this._routine, this._routine,
this._controller, this._controller,
TimeOfDay start, TimeOfDay start,
this._exercisePages, { this._exercisePages,
this._totalElements, {
int? dayId, int? dayId,
}) : _session = _routine.sessions }) : _session = _routine.sessions
.map((sessionApi) => sessionApi.session) .map((sessionApi) => sessionApi.session)
@@ -59,7 +61,9 @@ class SessionPage extends StatelessWidget {
NavigationHeader( NavigationHeader(
AppLocalizations.of(context).workoutSession, AppLocalizations.of(context).workoutSession,
_controller, _controller,
_totalElements,
exercisePages: _exercisePages, exercisePages: _exercisePages,
hideEndWorkoutButton: true,
), ),
Expanded(child: Container()), Expanded(child: Container()),
Padding( Padding(

View File

@@ -9,8 +9,9 @@ class StartPage extends StatelessWidget {
final PageController _controller; final PageController _controller;
final DayData _dayData; final DayData _dayData;
final Map<Exercise, int> _exercisePages; final Map<Exercise, int> _exercisePages;
final int _totalPages;
const StartPage(this._controller, this._dayData, this._exercisePages); const StartPage(this._controller, this._dayData, this._exercisePages, this._totalPages);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@@ -19,7 +20,9 @@ class StartPage extends StatelessWidget {
NavigationHeader( NavigationHeader(
AppLocalizations.of(context).todaysWorkout, AppLocalizations.of(context).todaysWorkout,
_controller, _controller,
_totalPages,
exercisePages: _exercisePages, exercisePages: _exercisePages,
hideEndWorkoutButton: true,
), ),
Expanded( Expanded(
child: ListView( child: ListView(

View File

@@ -28,11 +28,13 @@ class TimerWidget extends StatefulWidget {
final PageController _controller; final PageController _controller;
final double _ratioCompleted; final double _ratioCompleted;
final Map<Exercise, int> _exercisePages; final Map<Exercise, int> _exercisePages;
final _totalPages;
const TimerWidget( const TimerWidget(
this._controller, this._controller,
this._ratioCompleted, this._ratioCompleted,
this._exercisePages, this._exercisePages,
this._totalPages
); );
@override @override
@@ -72,6 +74,7 @@ class _TimerWidgetState extends State<TimerWidget> {
NavigationHeader( NavigationHeader(
AppLocalizations.of(context).pause, AppLocalizations.of(context).pause,
widget._controller, widget._controller,
widget._totalPages,
exercisePages: widget._exercisePages, exercisePages: widget._exercisePages,
), ),
Expanded( Expanded(
@@ -93,12 +96,14 @@ class TimerCountdownWidget extends StatefulWidget {
final double _ratioCompleted; final double _ratioCompleted;
final int _seconds; final int _seconds;
final Map<Exercise, int> _exercisePages; final Map<Exercise, int> _exercisePages;
final int _totalPages;
const TimerCountdownWidget( const TimerCountdownWidget(
this._controller, this._controller,
this._seconds, this._seconds,
this._ratioCompleted, this._ratioCompleted,
this._exercisePages, this._exercisePages,
this._totalPages
); );
@override @override
@@ -137,6 +142,7 @@ class _TimerCountdownWidgetState extends State<TimerCountdownWidget> {
NavigationHeader( NavigationHeader(
AppLocalizations.of(context).pause, AppLocalizations.of(context).pause,
widget._controller, widget._controller,
widget._totalPages,
exercisePages: widget._exercisePages, exercisePages: widget._exercisePages,
), ),
Expanded( Expanded(