Skip to content

Commit ca007d2

Browse files
committed
Move more usages to new exercise provider
1 parent 5ab04cb commit ca007d2

File tree

7 files changed

+146
-25
lines changed

7 files changed

+146
-25
lines changed

lib/providers/exercise_data.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
/*
2+
* This file is part of wger Workout Manager <https://github.com/wger-project>.
3+
* Copyright (C) 2020, 2025 wger Team
4+
*
5+
* wger Workout Manager is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
119
import 'package:drift/drift.dart';
220
import 'package:logging/logging.dart';
321
import 'package:riverpod_annotation/riverpod_annotation.dart';

lib/providers/exercise_state.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
/*
2+
* This file is part of wger Workout Manager <https://github.com/wger-project>.
3+
* Copyright (C) 2020, 2025 wger Team
4+
*
5+
* wger Workout Manager is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
119
import 'package:wger/models/exercises/category.dart';
220
import 'package:wger/models/exercises/equipment.dart';
321
import 'package:wger/models/exercises/exercise.dart';

lib/providers/exercise_state_notifier.dart

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,28 @@
1+
/*
2+
* This file is part of wger Workout Manager <https://github.com/wger-project>.
3+
* Copyright (C) 2020, 2025 wger Team
4+
*
5+
* wger Workout Manager is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
119
import 'package:logging/logging.dart';
220
import 'package:riverpod_annotation/riverpod_annotation.dart';
321
import 'package:wger/models/exercises/category.dart';
422
import 'package:wger/models/exercises/equipment.dart';
523
import 'package:wger/models/exercises/exercise.dart';
624
import 'package:wger/providers/exercise_data.dart';
725
import 'package:wger/providers/exercise_state.dart';
8-
import 'package:wger/providers/exercises.dart';
926

1027
part 'exercise_state_notifier.g.dart';
1128

@@ -130,4 +147,43 @@ final class ExerciseStateNotifier extends _$ExerciseStateNotifier {
130147
return null;
131148
}
132149
}
150+
151+
Future<List<Exercise>> searchExercise(
152+
String term, {
153+
bool useServer = false,
154+
String languageCode = 'en',
155+
bool searchEnglish = false,
156+
}) async {
157+
if (term.trim().length <= 1) {
158+
return [];
159+
}
160+
161+
// Local mode: search in the sqlite db
162+
if (!useServer) {
163+
final languages = [languageCode];
164+
if (searchEnglish && languageCode != 'en') {
165+
languages.add('en');
166+
}
167+
168+
final List<Exercise> out = [];
169+
170+
for (final e in state.exercises) {
171+
var matched = false;
172+
for (final lang in languages) {
173+
final title = (e.getTranslation(lang).name ?? '').toLowerCase();
174+
if (title.contains(term.toLowerCase())) {
175+
matched = true;
176+
break;
177+
}
178+
}
179+
if (matched) {
180+
out.add(e);
181+
}
182+
}
183+
return out;
184+
}
185+
186+
// Online mode, use server-side search API
187+
return [];
188+
}
133189
}

lib/screens/add_exercise_screen.dart

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
1+
/*
2+
* This file is part of wger Workout Manager <https://github.com/wger-project>.
3+
* Copyright (C) 2020, 2025 wger Team
4+
*
5+
* wger Workout Manager is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
119
import 'package:flutter/material.dart';
20+
import 'package:flutter_riverpod/flutter_riverpod.dart';
221
import 'package:provider/provider.dart';
322
import 'package:wger/exceptions/http_exception.dart';
423
import 'package:wger/helpers/consts.dart';
524
import 'package:wger/helpers/errors.dart';
625
import 'package:wger/l10n/generated/app_localizations.dart';
726
import 'package:wger/models/exercises/exercise.dart';
827
import 'package:wger/providers/add_exercise.dart';
9-
import 'package:wger/providers/exercises.dart';
28+
import 'package:wger/providers/exercise_state_notifier.dart';
1029
import 'package:wger/providers/user.dart';
1130
import 'package:wger/screens/exercise_screen.dart';
1231
import 'package:wger/widgets/add_exercise/steps/step_1_basics.dart';
@@ -33,7 +52,7 @@ class AddExerciseScreen extends StatelessWidget {
3352
}
3453
}
3554

36-
class AddExerciseStepper extends StatefulWidget {
55+
class AddExerciseStepper extends ConsumerStatefulWidget {
3756
const AddExerciseStepper({super.key});
3857

3958
static const STEPS_IN_FORM = 6;
@@ -42,7 +61,7 @@ class AddExerciseStepper extends StatefulWidget {
4261
_AddExerciseStepperState createState() => _AddExerciseStepperState();
4362
}
4463

45-
class _AddExerciseStepperState extends State<AddExerciseStepper> {
64+
class _AddExerciseStepperState extends ConsumerState<AddExerciseStepper> {
4665
int _currentStep = 0;
4766
int lastStepIndex = AddExerciseStepper.STEPS_IN_FORM - 1;
4867
bool _isLoading = false;
@@ -81,12 +100,11 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
81100
errorWidget = const SizedBox.shrink();
82101
});
83102
final addExerciseProvider = context.read<AddExerciseProvider>();
84-
final exerciseProvider = context.read<ExercisesProvider>();
85103

86104
Exercise? exercise;
87105
try {
88106
final exerciseId = await addExerciseProvider.postExerciseToServer();
89-
exercise = await exerciseProvider.fetchAndSetExercise(exerciseId);
107+
exercise = ref.read(exerciseStateProvider.notifier).getById(exerciseId);
90108
} on WgerHttpException catch (error) {
91109
if (context.mounted) {
92110
setState(() {

lib/widgets/add_exercise/steps/step_1_basics.dart

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,46 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_riverpod/flutter_riverpod.dart' hide Consumer;
23
import 'package:provider/provider.dart';
34
import 'package:wger/helpers/consts.dart';
45
import 'package:wger/helpers/exercises/validators.dart';
56
import 'package:wger/helpers/i18n.dart';
67
import 'package:wger/l10n/generated/app_localizations.dart';
78
import 'package:wger/models/exercises/category.dart';
89
import 'package:wger/models/exercises/equipment.dart';
10+
import 'package:wger/models/exercises/language.dart';
911
import 'package:wger/models/exercises/muscle.dart';
1012
import 'package:wger/providers/add_exercise.dart';
11-
import 'package:wger/providers/exercises.dart';
13+
import 'package:wger/providers/core_data.dart';
14+
import 'package:wger/providers/exercise_data.dart';
1215
import 'package:wger/providers/user.dart';
1316
import 'package:wger/widgets/add_exercise/add_exercise_multiselect_button.dart';
1417
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
1518
import 'package:wger/widgets/exercises/exercises.dart';
1619
import 'package:wger/widgets/exercises/forms.dart';
1720

18-
class Step1Basics extends StatelessWidget {
21+
class Step1Basics extends ConsumerWidget {
1922
final GlobalKey<FormState> formkey;
2023

2124
const Step1Basics({required this.formkey});
2225

2326
@override
24-
Widget build(BuildContext context) {
27+
Widget build(BuildContext context, WidgetRef ref) {
2528
final userProvider = context.read<UserProvider>();
2629
final addExerciseProvider = context.read<AddExerciseProvider>();
27-
final exerciseProvider = context.read<ExercisesProvider>();
28-
final categories = exerciseProvider.categories;
29-
final muscles = exerciseProvider.muscles;
30-
final equipment = exerciseProvider.equipment;
3130

32-
// There mus be a better way to ensure this...
33-
addExerciseProvider.languageEn = exerciseProvider.languages.firstWhere(
34-
(l) => l.shortName == LANGUAGE_SHORT_ENGLISH,
35-
);
31+
final languagesAsync = ref.watch(languageProvider);
32+
final categoriesAsync = ref.watch(exerciseCategoryProvider);
33+
final musclesAsync = ref.watch(exerciseMuscleProvider);
34+
final equipmentAsync = ref.watch(exerciseEquipmentProvider);
35+
36+
final categories = categoriesAsync.asData?.value ?? <ExerciseCategory>[];
37+
final muscles = musclesAsync.asData?.value ?? <Muscle>[];
38+
final equipment = equipmentAsync.asData?.value ?? <Equipment>[];
39+
final languages = languagesAsync.asData?.value ?? <Language>[];
40+
41+
// Doing it like this because the languages list is empty before the stream loads
42+
final matched = languages.where((l) => l.shortName == LANGUAGE_SHORT_ENGLISH);
43+
addExerciseProvider.languageEn = matched.isNotEmpty ? matched.first : null;
3644

3745
return Form(
3846
key: formkey,

lib/widgets/add_exercise/steps/step_4_translations.dart

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,33 @@
11
import 'package:flutter/material.dart';
2+
import 'package:flutter_riverpod/flutter_riverpod.dart' hide Consumer;
23
import 'package:provider/provider.dart';
34
import 'package:wger/helpers/exercises/validators.dart';
45
import 'package:wger/l10n/generated/app_localizations.dart';
56
import 'package:wger/models/exercises/language.dart';
67
import 'package:wger/providers/add_exercise.dart';
7-
import 'package:wger/providers/exercises.dart';
8+
import 'package:wger/providers/core_data.dart';
89
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
910
import 'package:wger/widgets/exercises/forms.dart';
1011

11-
class Step4Translation extends StatefulWidget {
12+
class Step4Translation extends ConsumerStatefulWidget {
1213
final GlobalKey<FormState> formkey;
1314

1415
const Step4Translation({required this.formkey});
1516

1617
@override
17-
State<Step4Translation> createState() => _Step4TranslationState();
18+
ConsumerState<Step4Translation> createState() => _Step4TranslationState();
1819
}
1920

20-
class _Step4TranslationState extends State<Step4Translation> {
21+
class _Step4TranslationState extends ConsumerState<Step4Translation> {
2122
bool translate = false;
2223

2324
@override
2425
Widget build(BuildContext context) {
2526
final i18n = AppLocalizations.of(context);
2627
final addExerciseProvider = context.read<AddExerciseProvider>();
27-
final exerciseProvider = context.read<ExercisesProvider>();
28-
final languages = exerciseProvider.languages;
28+
29+
final languagesAsync = ref.watch(languageProvider);
30+
final languages = languagesAsync.asData?.value ?? <Language>[];
2931

3032
return Form(
3133
key: widget.formkey,

lib/widgets/routines/gym_mode/gym_mode.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import 'package:logging/logging.dart';
2323
import 'package:provider/provider.dart' as provider;
2424
import 'package:wger/models/exercises/exercise.dart';
2525
import 'package:wger/models/workouts/day_data.dart';
26+
import 'package:wger/providers/exercise_state_notifier.dart';
2627
import 'package:wger/providers/exercises.dart';
2728
import 'package:wger/providers/gym_state.dart';
2829
import 'package:wger/providers/routines.dart';
@@ -131,7 +132,7 @@ class _GymModeState extends ConsumerState<GymMode> {
131132

132133
List<Widget> getContent() {
133134
final state = ref.watch(gymStateProvider);
134-
final exerciseProvider = context.read<ExercisesProvider>();
135+
final exercisesAsync = ref.watch(exerciseStateProvider.notifier);
135136
final routinesProvider = context.read<RoutinesProvider>();
136137
var currentElement = 1;
137138
final List<Widget> out = [];
@@ -140,7 +141,7 @@ class _GymModeState extends ConsumerState<GymMode> {
140141
var firstPage = true;
141142
for (final config in slotData.setConfigs) {
142143
final ratioCompleted = currentElement / _totalElements;
143-
final exercise = exerciseProvider.findExerciseById(config.exerciseId);
144+
final exercise = exercisesAsync.getById(config.exerciseId)!;
144145
currentElement++;
145146

146147
if (firstPage && state.showExercisePages) {

0 commit comments

Comments
 (0)