Move more usages to new exercise provider

This commit is contained in:
Roland Geider
2025-10-25 02:08:34 +02:00
parent 5ab04cb6df
commit ca007d2335
7 changed files with 146 additions and 25 deletions

View File

@@ -1,3 +1,21 @@
/*
* This file is part of wger Workout Manager <https://github.com/wger-project>.
* Copyright (C) 2020, 2025 wger Team
*
* wger Workout Manager is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
*/
import 'package:drift/drift.dart';
import 'package:logging/logging.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';

View File

@@ -1,3 +1,21 @@
/*
* This file is part of wger Workout Manager <https://github.com/wger-project>.
* Copyright (C) 2020, 2025 wger Team
*
* wger Workout Manager is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
*/
import 'package:wger/models/exercises/category.dart';
import 'package:wger/models/exercises/equipment.dart';
import 'package:wger/models/exercises/exercise.dart';

View File

@@ -1,3 +1,21 @@
/*
* This file is part of wger Workout Manager <https://github.com/wger-project>.
* Copyright (C) 2020, 2025 wger Team
*
* wger Workout Manager is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
*/
import 'package:logging/logging.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:wger/models/exercises/category.dart';
@@ -5,7 +23,6 @@ import 'package:wger/models/exercises/equipment.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/providers/exercise_data.dart';
import 'package:wger/providers/exercise_state.dart';
import 'package:wger/providers/exercises.dart';
part 'exercise_state_notifier.g.dart';
@@ -130,4 +147,43 @@ final class ExerciseStateNotifier extends _$ExerciseStateNotifier {
return null;
}
}
Future<List<Exercise>> searchExercise(
String term, {
bool useServer = false,
String languageCode = 'en',
bool searchEnglish = false,
}) async {
if (term.trim().length <= 1) {
return [];
}
// Local mode: search in the sqlite db
if (!useServer) {
final languages = [languageCode];
if (searchEnglish && languageCode != 'en') {
languages.add('en');
}
final List<Exercise> out = [];
for (final e in state.exercises) {
var matched = false;
for (final lang in languages) {
final title = (e.getTranslation(lang).name ?? '').toLowerCase();
if (title.contains(term.toLowerCase())) {
matched = true;
break;
}
}
if (matched) {
out.add(e);
}
}
return out;
}
// Online mode, use server-side search API
return [];
}
}

View File

@@ -1,4 +1,23 @@
/*
* This file is part of wger Workout Manager <https://github.com/wger-project>.
* Copyright (C) 2020, 2025 wger Team
*
* wger Workout Manager is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* 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/>.
*/
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:provider/provider.dart';
import 'package:wger/exceptions/http_exception.dart';
import 'package:wger/helpers/consts.dart';
@@ -6,7 +25,7 @@ import 'package:wger/helpers/errors.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/exercise_state_notifier.dart';
import 'package:wger/providers/user.dart';
import 'package:wger/screens/exercise_screen.dart';
import 'package:wger/widgets/add_exercise/steps/step_1_basics.dart';
@@ -33,7 +52,7 @@ class AddExerciseScreen extends StatelessWidget {
}
}
class AddExerciseStepper extends StatefulWidget {
class AddExerciseStepper extends ConsumerStatefulWidget {
const AddExerciseStepper({super.key});
static const STEPS_IN_FORM = 6;
@@ -42,7 +61,7 @@ class AddExerciseStepper extends StatefulWidget {
_AddExerciseStepperState createState() => _AddExerciseStepperState();
}
class _AddExerciseStepperState extends State<AddExerciseStepper> {
class _AddExerciseStepperState extends ConsumerState<AddExerciseStepper> {
int _currentStep = 0;
int lastStepIndex = AddExerciseStepper.STEPS_IN_FORM - 1;
bool _isLoading = false;
@@ -81,12 +100,11 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
errorWidget = const SizedBox.shrink();
});
final addExerciseProvider = context.read<AddExerciseProvider>();
final exerciseProvider = context.read<ExercisesProvider>();
Exercise? exercise;
try {
final exerciseId = await addExerciseProvider.postExerciseToServer();
exercise = await exerciseProvider.fetchAndSetExercise(exerciseId);
exercise = ref.read(exerciseStateProvider.notifier).getById(exerciseId);
} on WgerHttpException catch (error) {
if (context.mounted) {
setState(() {

View File

@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart' hide Consumer;
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/exercises/validators.dart';
@@ -6,33 +7,40 @@ import 'package:wger/helpers/i18n.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/category.dart';
import 'package:wger/models/exercises/equipment.dart';
import 'package:wger/models/exercises/language.dart';
import 'package:wger/models/exercises/muscle.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/core_data.dart';
import 'package:wger/providers/exercise_data.dart';
import 'package:wger/providers/user.dart';
import 'package:wger/widgets/add_exercise/add_exercise_multiselect_button.dart';
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
import 'package:wger/widgets/exercises/exercises.dart';
import 'package:wger/widgets/exercises/forms.dart';
class Step1Basics extends StatelessWidget {
class Step1Basics extends ConsumerWidget {
final GlobalKey<FormState> formkey;
const Step1Basics({required this.formkey});
@override
Widget build(BuildContext context) {
Widget build(BuildContext context, WidgetRef ref) {
final userProvider = context.read<UserProvider>();
final addExerciseProvider = context.read<AddExerciseProvider>();
final exerciseProvider = context.read<ExercisesProvider>();
final categories = exerciseProvider.categories;
final muscles = exerciseProvider.muscles;
final equipment = exerciseProvider.equipment;
// There mus be a better way to ensure this...
addExerciseProvider.languageEn = exerciseProvider.languages.firstWhere(
(l) => l.shortName == LANGUAGE_SHORT_ENGLISH,
);
final languagesAsync = ref.watch(languageProvider);
final categoriesAsync = ref.watch(exerciseCategoryProvider);
final musclesAsync = ref.watch(exerciseMuscleProvider);
final equipmentAsync = ref.watch(exerciseEquipmentProvider);
final categories = categoriesAsync.asData?.value ?? <ExerciseCategory>[];
final muscles = musclesAsync.asData?.value ?? <Muscle>[];
final equipment = equipmentAsync.asData?.value ?? <Equipment>[];
final languages = languagesAsync.asData?.value ?? <Language>[];
// Doing it like this because the languages list is empty before the stream loads
final matched = languages.where((l) => l.shortName == LANGUAGE_SHORT_ENGLISH);
addExerciseProvider.languageEn = matched.isNotEmpty ? matched.first : null;
return Form(
key: formkey,

View File

@@ -1,31 +1,33 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart' hide Consumer;
import 'package:provider/provider.dart';
import 'package:wger/helpers/exercises/validators.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/models/exercises/language.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/core_data.dart';
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
import 'package:wger/widgets/exercises/forms.dart';
class Step4Translation extends StatefulWidget {
class Step4Translation extends ConsumerStatefulWidget {
final GlobalKey<FormState> formkey;
const Step4Translation({required this.formkey});
@override
State<Step4Translation> createState() => _Step4TranslationState();
ConsumerState<Step4Translation> createState() => _Step4TranslationState();
}
class _Step4TranslationState extends State<Step4Translation> {
class _Step4TranslationState extends ConsumerState<Step4Translation> {
bool translate = false;
@override
Widget build(BuildContext context) {
final i18n = AppLocalizations.of(context);
final addExerciseProvider = context.read<AddExerciseProvider>();
final exerciseProvider = context.read<ExercisesProvider>();
final languages = exerciseProvider.languages;
final languagesAsync = ref.watch(languageProvider);
final languages = languagesAsync.asData?.value ?? <Language>[];
return Form(
key: widget.formkey,

View File

@@ -23,6 +23,7 @@ import 'package:logging/logging.dart';
import 'package:provider/provider.dart' as provider;
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/workouts/day_data.dart';
import 'package:wger/providers/exercise_state_notifier.dart';
import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/gym_state.dart';
import 'package:wger/providers/routines.dart';
@@ -131,7 +132,7 @@ class _GymModeState extends ConsumerState<GymMode> {
List<Widget> getContent() {
final state = ref.watch(gymStateProvider);
final exerciseProvider = context.read<ExercisesProvider>();
final exercisesAsync = ref.watch(exerciseStateProvider.notifier);
final routinesProvider = context.read<RoutinesProvider>();
var currentElement = 1;
final List<Widget> out = [];
@@ -140,7 +141,7 @@ class _GymModeState extends ConsumerState<GymMode> {
var firstPage = true;
for (final config in slotData.setConfigs) {
final ratioCompleted = currentElement / _totalElements;
final exercise = exerciseProvider.findExerciseById(config.exerciseId);
final exercise = exercisesAsync.getById(config.exerciseId)!;
currentElement++;
if (firstPage && state.showExercisePages) {