Add image upload methods

We use the "manual" way as it was before, since there were some problems
making this work and most of the errors were happening during the exercise
creation itself.
This commit is contained in:
Roland Geider
2025-09-19 22:27:04 +02:00
parent 9ea8362d20
commit ba34570a3d
7 changed files with 349 additions and 318 deletions

View File

@@ -50,7 +50,6 @@ abstract mixin class $ExerciseAliasSubmissionApiCopyWith<$Res> {
factory $ExerciseAliasSubmissionApiCopyWith(
ExerciseAliasSubmissionApi value, $Res Function(ExerciseAliasSubmissionApi) _then) =
_$ExerciseAliasSubmissionApiCopyWithImpl;
@useResult
$Res call({String alias});
}
@@ -236,7 +235,6 @@ extension ExerciseAliasSubmissionApiPatterns on ExerciseAliasSubmissionApi {
@JsonSerializable()
class _ExerciseAliasSubmissionApi implements ExerciseAliasSubmissionApi {
const _ExerciseAliasSubmissionApi({required this.alias});
factory _ExerciseAliasSubmissionApi.fromJson(Map<String, dynamic> json) =>
_$ExerciseAliasSubmissionApiFromJson(json);
@@ -282,7 +280,6 @@ abstract mixin class _$ExerciseAliasSubmissionApiCopyWith<$Res>
factory _$ExerciseAliasSubmissionApiCopyWith(
_ExerciseAliasSubmissionApi value, $Res Function(_ExerciseAliasSubmissionApi) _then) =
__$ExerciseAliasSubmissionApiCopyWithImpl;
@override
@useResult
$Res call({String alias});
@@ -350,7 +347,6 @@ abstract mixin class $ExerciseCommentSubmissionApiCopyWith<$Res> {
factory $ExerciseCommentSubmissionApiCopyWith(
ExerciseCommentSubmissionApi value, $Res Function(ExerciseCommentSubmissionApi) _then) =
_$ExerciseCommentSubmissionApiCopyWithImpl;
@useResult
$Res call({String alias});
}
@@ -536,7 +532,6 @@ extension ExerciseCommentSubmissionApiPatterns on ExerciseCommentSubmissionApi {
@JsonSerializable()
class _ExerciseCommentSubmissionApi implements ExerciseCommentSubmissionApi {
const _ExerciseCommentSubmissionApi({required this.alias});
factory _ExerciseCommentSubmissionApi.fromJson(Map<String, dynamic> json) =>
_$ExerciseCommentSubmissionApiFromJson(json);
@@ -582,7 +577,6 @@ abstract mixin class _$ExerciseCommentSubmissionApiCopyWith<$Res>
factory _$ExerciseCommentSubmissionApiCopyWith(
_ExerciseCommentSubmissionApi value, $Res Function(_ExerciseCommentSubmissionApi) _then) =
__$ExerciseCommentSubmissionApiCopyWithImpl;
@override
@useResult
$Res call({String alias});
@@ -615,16 +609,11 @@ class __$ExerciseCommentSubmissionApiCopyWithImpl<$Res>
/// @nodoc
mixin _$ExerciseTranslationSubmissionApi {
String get name;
String get description;
int get language;
@JsonKey(name: 'license_author')
String get author;
List<ExerciseAliasSubmissionApi> get aliases;
List<ExerciseCommentSubmissionApi> get comments;
/// Create a copy of ExerciseTranslationSubmissionApi
@@ -667,7 +656,6 @@ abstract mixin class $ExerciseTranslationSubmissionApiCopyWith<$Res> {
factory $ExerciseTranslationSubmissionApiCopyWith(ExerciseTranslationSubmissionApi value,
$Res Function(ExerciseTranslationSubmissionApi) _then) =
_$ExerciseTranslationSubmissionApiCopyWithImpl;
@useResult
$Res call(
{String name,
@@ -916,7 +904,6 @@ class _ExerciseTranslationSubmissionApi implements ExerciseTranslationSubmission
final List<ExerciseCommentSubmissionApi> comments = const []})
: _aliases = aliases,
_comments = comments;
factory _ExerciseTranslationSubmissionApi.fromJson(Map<String, dynamic> json) =>
_$ExerciseTranslationSubmissionApiFromJson(json);
@@ -930,7 +917,6 @@ class _ExerciseTranslationSubmissionApi implements ExerciseTranslationSubmission
@JsonKey(name: 'license_author')
final String author;
final List<ExerciseAliasSubmissionApi> _aliases;
@override
@JsonKey()
List<ExerciseAliasSubmissionApi> get aliases {
@@ -940,7 +926,6 @@ class _ExerciseTranslationSubmissionApi implements ExerciseTranslationSubmission
}
final List<ExerciseCommentSubmissionApi> _comments;
@override
@JsonKey()
List<ExerciseCommentSubmissionApi> get comments {
@@ -1001,7 +986,6 @@ abstract mixin class _$ExerciseTranslationSubmissionApiCopyWith<$Res>
factory _$ExerciseTranslationSubmissionApiCopyWith(_ExerciseTranslationSubmissionApi value,
$Res Function(_ExerciseTranslationSubmissionApi) _then) =
__$ExerciseTranslationSubmissionApiCopyWithImpl;
@override
@useResult
$Res call(
@@ -1065,20 +1049,14 @@ class __$ExerciseTranslationSubmissionApiCopyWithImpl<$Res>
/// @nodoc
mixin _$ExerciseSubmissionApi {
int get category;
List<int> get muscles;
@JsonKey(name: 'muscles_secondary')
List<int> get musclesSecondary;
List<int> get equipment;
@JsonKey(name: 'license_author')
String get author;
@JsonKey(includeToJson: false)
int? get variation;
List<ExerciseTranslationSubmissionApi> get translations;
/// Create a copy of ExerciseSubmissionApi
@@ -1129,7 +1107,6 @@ abstract mixin class $ExerciseSubmissionApiCopyWith<$Res> {
factory $ExerciseSubmissionApiCopyWith(
ExerciseSubmissionApi value, $Res Function(ExerciseSubmissionApi) _then) =
_$ExerciseSubmissionApiCopyWithImpl;
@useResult
$Res call(
{int category,
@@ -1389,14 +1366,12 @@ class _ExerciseSubmissionApi implements ExerciseSubmissionApi {
_musclesSecondary = musclesSecondary,
_equipment = equipment,
_translations = translations;
factory _ExerciseSubmissionApi.fromJson(Map<String, dynamic> json) =>
_$ExerciseSubmissionApiFromJson(json);
@override
final int category;
final List<int> _muscles;
@override
List<int> get muscles {
if (_muscles is EqualUnmodifiableListView) return _muscles;
@@ -1405,7 +1380,6 @@ class _ExerciseSubmissionApi implements ExerciseSubmissionApi {
}
final List<int> _musclesSecondary;
@override
@JsonKey(name: 'muscles_secondary')
List<int> get musclesSecondary {
@@ -1415,7 +1389,6 @@ class _ExerciseSubmissionApi implements ExerciseSubmissionApi {
}
final List<int> _equipment;
@override
List<int> get equipment {
if (_equipment is EqualUnmodifiableListView) return _equipment;
@@ -1430,7 +1403,6 @@ class _ExerciseSubmissionApi implements ExerciseSubmissionApi {
@JsonKey(includeToJson: false)
final int? variation;
final List<ExerciseTranslationSubmissionApi> _translations;
@override
List<ExerciseTranslationSubmissionApi> get translations {
if (_translations is EqualUnmodifiableListView) return _translations;
@@ -1491,7 +1463,6 @@ abstract mixin class _$ExerciseSubmissionApiCopyWith<$Res>
factory _$ExerciseSubmissionApiCopyWith(
_ExerciseSubmissionApi value, $Res Function(_ExerciseSubmissionApi) _then) =
__$ExerciseSubmissionApiCopyWithImpl;
@override
@useResult
$Res call(

View File

@@ -2,6 +2,8 @@ import 'dart:developer';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:http/http.dart' as http;
import 'package:wger/helpers/consts.dart';
import 'package:wger/models/exercises/category.dart';
import 'package:wger/models/exercises/equipment.dart';
import 'package:wger/models/exercises/exercise.dart';
@@ -36,6 +38,7 @@ class AddExerciseProvider with ChangeNotifier {
List<Muscle> _secondaryMuscles = [];
static const _exerciseSubmissionUrlPath = 'exercise-submission';
static const _imagesUrlPath = 'exerciseimage';
static const _checkLanguageUrlPath = 'check-language';
void clear() {
@@ -190,6 +193,21 @@ class AddExerciseProvider with ChangeNotifier {
return result['id'];
}
Future<void> addImages(int exerciseId) async {
for (final image in _exerciseImages) {
final request = http.MultipartRequest('POST', baseProvider.makeUrl(_imagesUrlPath));
request.headers.addAll(baseProvider.getDefaultHeaders(includeAuth: true));
request.files.add(await http.MultipartFile.fromPath('image', image.path));
request.fields['exercise'] = exerciseId.toString();
request.fields['style'] = EXERCISE_IMAGE_ART_STYLE.PHOTO.index.toString();
await request.send();
}
notifyListeners();
}
Future<bool> validateLanguage(String input, String languageCode) async {
final Map<String, dynamic> result = await baseProvider.post(
{'input': input, 'language_code': languageCode},

View File

@@ -86,21 +86,24 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
Exercise? exercise;
try {
final exerciseId = await addExerciseProvider.addExercise();
await addExerciseProvider.addImages(exerciseId);
exercise = await exerciseProvider.fetchAndSetExercise(exerciseId);
addExerciseProvider.clear();
} on WgerHttpException catch (error) {
if (context.mounted) {
setState(() {
errorWidget = FormHttpErrorsWidget(error);
});
}
}
if (exercise == null) {
} finally {
if (mounted) {
setState(() {
_isLoading = false;
});
}
}
if (exercise == null || !context.mounted) {
return;
}
@@ -108,16 +111,6 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
.getTranslation(Localizations.localeOf(context).languageCode)
.name;
if (mounted) {
setState(() {
_isLoading = false;
});
}
if (!context.mounted) {
return;
}
return showDialog(
context: context,
builder: (BuildContext context) {

View File

@@ -7,9 +7,11 @@ import 'package:wger/providers/add_exercise.dart';
import 'mixins/image_picker_mixin.dart';
class PreviewExerciseImages extends StatelessWidget with ExerciseImagePickerMixin {
const PreviewExerciseImages({super.key, required this.selectedImages});
final List<File> selectedImages;
final bool allowEdit;
const PreviewExerciseImages({super.key, required this.selectedImages, this.allowEdit = true});
@override
Widget build(BuildContext context) {
return SizedBox(
@@ -23,46 +25,48 @@ class PreviewExerciseImages extends StatelessWidget with ExerciseImagePickerMixi
child: Stack(
children: [
Image.file(file),
Positioned(
bottom: 0,
right: 0,
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Container(
decoration: BoxDecoration(
color: Colors.grey.withValues(alpha: 0.5),
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
child: IconButton(
iconSize: 20,
onPressed: () =>
context.read<AddExerciseProvider>().removeExercise(file.path),
color: Colors.white,
icon: const Icon(Icons.delete),
if (allowEdit)
Positioned(
bottom: 0,
right: 0,
child: Padding(
padding: const EdgeInsets.all(3.0),
child: Container(
decoration: BoxDecoration(
color: Colors.grey.withValues(alpha: 0.5),
borderRadius: const BorderRadius.all(Radius.circular(20)),
),
child: IconButton(
iconSize: 20,
onPressed: () =>
context.read<AddExerciseProvider>().removeExercise(file.path),
color: Colors.white,
icon: const Icon(Icons.delete),
),
),
),
),
),
],
),
),
),
),
const SizedBox(width: 10),
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.grey,
height: 200,
width: 100,
child: Center(
child: IconButton(
icon: const Icon(Icons.add),
onPressed: () => pickImages(context),
if (allowEdit)
Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
color: Colors.grey,
height: 200,
width: 100,
child: Center(
child: IconButton(
icon: const Icon(Icons.add),
onPressed: () => pickImages(context),
),
),
),
),
),
]),
);
}

View File

@@ -34,89 +34,89 @@ class Step1Basics extends StatelessWidget {
return Form(
key: formkey,
child: Column(
children: [
AddExerciseTextArea(
onChange: (value) => {},
title: '${AppLocalizations.of(context).name}*',
helperText: AppLocalizations.of(context).baseNameEnglish,
isRequired: true,
validator: (name) => validateName(name, context),
onSaved: (String? name) => addExerciseProvider.exerciseNameEn = name!,
),
AddExerciseTextArea(
onChange: (value) => {},
title: AppLocalizations.of(context).alternativeNames,
isMultiline: true,
helperText: AppLocalizations.of(context).oneNamePerLine,
onSaved: (String? alternateName) =>
addExerciseProvider.alternateNamesEn = alternateName!.split('\n'),
),
ExerciseCategoryInputWidget<ExerciseCategory>(
key: const Key('category-dropdown'),
entries: categories,
title: '${AppLocalizations.of(context).category}*',
callback: (ExerciseCategory newValue) {
addExerciseProvider.category = newValue;
},
validator: (ExerciseCategory? category) {
if (category == null) {
return AppLocalizations.of(context).selectEntry;
}
},
displayName: (ExerciseCategory c) => getTranslation(c.name, context),
),
AddExerciseMultiselectButton<Equipment>(
key: const Key('equipment-multiselect'),
title: AppLocalizations.of(context).equipment,
items: equipment,
initialItems: addExerciseProvider.equipment,
onChange: (dynamic entries) {
addExerciseProvider.equipment = entries.cast<Equipment>();
},
onSaved: (dynamic entries) {
addExerciseProvider.equipment = entries.cast<Equipment>();
},
displayName: (Equipment e) => getTranslation(e.name, context),
),
AddExerciseMultiselectButton<Muscle>(
key: const Key('primary-muscles-multiselect'),
title: AppLocalizations.of(context).muscles,
items: muscles,
initialItems: addExerciseProvider.primaryMuscles,
onChange: (dynamic muscles) {
addExerciseProvider.primaryMuscles = muscles.cast<Muscle>();
},
onSaved: (dynamic muscles) {
addExerciseProvider.primaryMuscles = muscles.cast<Muscle>();
},
displayName: (Muscle e) =>
e.name + (e.nameEn.isNotEmpty ? '\n(${getTranslation(e.nameEn, context)})' : ''),
),
AddExerciseMultiselectButton<Muscle>(
key: const Key('secondary-muscles-multiselect'),
title: AppLocalizations.of(context).musclesSecondary,
items: muscles,
initialItems: addExerciseProvider.secondaryMuscles,
onChange: (dynamic muscles) {
addExerciseProvider.secondaryMuscles = muscles.cast<Muscle>();
},
onSaved: (dynamic muscles) {
addExerciseProvider.secondaryMuscles = muscles.cast<Muscle>();
},
displayName: (Muscle e) =>
e.name + (e.nameEn.isNotEmpty ? '\n(${getTranslation(e.nameEn, context)})' : ''),
),
Consumer<AddExerciseProvider>(
builder: (context, value, child) => MuscleRowWidget(
muscles: value.primaryMuscles,
musclesSecondary: value.secondaryMuscles,
child: Consumer<AddExerciseProvider>(
builder: (context, provider, child) => Column(
children: [
AddExerciseTextArea(
onChange: (value) => {},
title: '${AppLocalizations.of(context).name}*',
helperText: AppLocalizations.of(context).baseNameEnglish,
isRequired: true,
validator: (name) => validateName(name, context),
onSaved: (String? name) => addExerciseProvider.exerciseNameEn = name!,
),
),
const MuscleColorHelper(main: true),
const SizedBox(height: 5),
const MuscleColorHelper(main: false),
],
AddExerciseTextArea(
onChange: (value) => {},
title: AppLocalizations.of(context).alternativeNames,
isMultiline: true,
helperText: AppLocalizations.of(context).oneNamePerLine,
onSaved: (String? alternateName) =>
addExerciseProvider.alternateNamesEn = alternateName!.split('\n'),
),
ExerciseCategoryInputWidget<ExerciseCategory>(
key: const Key('category-dropdown'),
entries: categories,
title: '${AppLocalizations.of(context).category}*',
callback: (ExerciseCategory newValue) {
addExerciseProvider.category = newValue;
},
validator: (ExerciseCategory? category) {
if (category == null) {
return AppLocalizations.of(context).selectEntry;
}
},
displayName: (ExerciseCategory c) => getTranslation(c.name, context),
),
AddExerciseMultiselectButton<Equipment>(
key: const Key('equipment-multiselect'),
title: AppLocalizations.of(context).equipment,
items: equipment,
initialItems: addExerciseProvider.equipment,
onChange: (dynamic entries) {
addExerciseProvider.equipment = entries.cast<Equipment>();
},
onSaved: (dynamic entries) {
addExerciseProvider.equipment = entries.cast<Equipment>();
},
displayName: (Equipment e) => getTranslation(e.name, context),
),
AddExerciseMultiselectButton<Muscle>(
key: const Key('primary-muscles-multiselect'),
title: AppLocalizations.of(context).muscles,
items: muscles,
initialItems: addExerciseProvider.primaryMuscles,
onChange: (dynamic muscles) {
addExerciseProvider.primaryMuscles = muscles.cast<Muscle>();
},
onSaved: (dynamic muscles) {
addExerciseProvider.primaryMuscles = muscles.cast<Muscle>();
},
displayName: (Muscle e) =>
e.name + (e.nameEn.isNotEmpty ? '\n(${getTranslation(e.nameEn, context)})' : ''),
),
AddExerciseMultiselectButton<Muscle>(
key: const Key('secondary-muscles-multiselect'),
title: AppLocalizations.of(context).musclesSecondary,
items: muscles,
initialItems: addExerciseProvider.secondaryMuscles,
onChange: (dynamic muscles) {
addExerciseProvider.secondaryMuscles = muscles.cast<Muscle>();
},
onSaved: (dynamic muscles) {
addExerciseProvider.secondaryMuscles = muscles.cast<Muscle>();
},
displayName: (Muscle e) =>
e.name + (e.nameEn.isNotEmpty ? '\n(${getTranslation(e.nameEn, context)})' : ''),
),
MuscleRowWidget(
muscles: provider.primaryMuscles,
musclesSecondary: provider.secondaryMuscles,
),
const MuscleColorHelper(main: true),
const SizedBox(height: 5),
const MuscleColorHelper(main: false),
],
),
),
);
}

View File

@@ -2,129 +2,136 @@ import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wger/l10n/generated/app_localizations.dart';
import 'package:wger/providers/add_exercise.dart';
import 'package:wger/widgets/add_exercise/preview_images.dart';
import 'package:wger/widgets/core/cards.dart';
class Step6Overview extends StatelessWidget {
@override
Widget build(BuildContext context) {
final i18n = AppLocalizations.of(context);
final addExerciseProvider = context.read<AddExerciseProvider>();
return Column(
spacing: 8,
children: [
Text(
i18n.baseData,
style: Theme.of(context).textTheme.headlineSmall,
),
Table(
columnWidths: const {
0: FlexColumnWidth(2),
1: FlexColumnWidth(3),
},
children: [
TableRow(
children: [
Text(i18n.name),
Text(addExerciseProvider.exerciseNameEn ?? '...'),
],
return Consumer<AddExerciseProvider>(
builder: (ctx, provider, __) => Column(
spacing: 8,
children: [
Text(
i18n.baseData,
style: Theme.of(context).textTheme.headlineSmall,
),
Table(
columnWidths: const {
0: FlexColumnWidth(2),
1: FlexColumnWidth(3),
},
children: [
TableRow(
children: [
Text(i18n.name),
Text(provider.exerciseNameEn ?? '...'),
],
),
TableRow(
children: [
Text(i18n.alternativeNames),
Text(
provider.alternateNamesEn.isNotEmpty
? provider.alternateNamesEn.join('\n')
: '...',
),
],
),
TableRow(
children: [
Text(i18n.description),
Text(provider.descriptionEn ?? '...'),
],
),
TableRow(
children: [
Text(i18n.category),
Text(provider.category?.name ?? '...'),
],
),
TableRow(
children: [
Text(i18n.muscles),
Text(
provider.primaryMuscles.isNotEmpty
? provider.primaryMuscles.map((m) => m.name).join('\n')
: '...',
),
],
),
TableRow(
children: [
Text(i18n.musclesSecondary),
Text(
provider.secondaryMuscles.isNotEmpty
? provider.secondaryMuscles.map((m) => m.name).join('\n')
: '...',
),
],
),
TableRow(
children: [
Text(i18n.equipment),
Text(
provider.equipment.isNotEmpty
? provider.equipment.map((m) => m.name).join('\n')
: '...',
),
],
),
],
),
Text(
i18n.translation,
style: Theme.of(context).textTheme.headlineSmall,
),
Table(
columnWidths: const {
0: FlexColumnWidth(2),
1: FlexColumnWidth(3),
},
children: [
TableRow(
children: [
Text(i18n.name),
Text(provider.exerciseNameTrans ?? '...'),
],
),
TableRow(
children: [
Text(i18n.alternativeNames),
Text(
provider.alternateNamesTrans.isNotEmpty
? provider.alternateNamesTrans.join('\n')
: '...',
),
],
),
TableRow(
children: [
Text(i18n.description),
Text(provider.descriptionTrans ?? '...'),
],
),
TableRow(
children: [
Text(i18n.language),
Text(provider.languageTranslation?.fullName ?? '...'),
],
),
],
),
if (provider.exerciseImages.isNotEmpty)
PreviewExerciseImages(
selectedImages: provider.exerciseImages,
allowEdit: false,
),
TableRow(
children: [
Text(i18n.alternativeNames),
Text(
addExerciseProvider.alternateNamesEn.isNotEmpty
? addExerciseProvider.alternateNamesEn.join('\n')
: '...',
),
],
),
TableRow(
children: [
Text(i18n.description),
Text(addExerciseProvider.descriptionEn ?? '...'),
],
),
TableRow(
children: [
Text(i18n.category),
Text(addExerciseProvider.category?.name ?? '...'),
],
),
TableRow(
children: [
Text(i18n.muscles),
Text(
addExerciseProvider.primaryMuscles.isNotEmpty
? addExerciseProvider.primaryMuscles.map((m) => m.name).join('\n')
: '...',
),
],
),
TableRow(
children: [
Text(i18n.musclesSecondary),
Text(
addExerciseProvider.secondaryMuscles.isNotEmpty
? addExerciseProvider.secondaryMuscles.map((m) => m.name).join('\n')
: '...',
),
],
),
TableRow(
children: [
Text(i18n.equipment),
Text(
addExerciseProvider.equipment.isNotEmpty
? addExerciseProvider.equipment.map((m) => m.name).join('\n')
: '...',
),
],
),
],
),
Text(
i18n.translation,
style: Theme.of(context).textTheme.headlineSmall,
),
Table(
columnWidths: const {
0: FlexColumnWidth(2),
1: FlexColumnWidth(3),
},
children: [
TableRow(
children: [
Text(i18n.name),
Text(addExerciseProvider.exerciseNameTrans ?? '...'),
],
),
TableRow(
children: [
Text(i18n.alternativeNames),
Text(
addExerciseProvider.alternateNamesTrans.isNotEmpty
? addExerciseProvider.alternateNamesTrans.join('\n')
: '...',
),
],
),
TableRow(
children: [
Text(i18n.description),
Text(addExerciseProvider.descriptionTrans ?? '...'),
],
),
TableRow(
children: [
Text(i18n.language),
Text(addExerciseProvider.languageTranslation?.fullName ?? '...'),
],
),
],
),
InfoCard(text: i18n.checkInformationBeforeSubmitting)
],
InfoCard(text: i18n.checkInformationBeforeSubmitting)
],
),
);
}
}

View File

@@ -153,6 +153,18 @@ class MockAddExerciseProvider extends _i1.Mock implements _i11.AddExerciseProvid
returnValue: <_i12.File>[],
) as List<_i12.File>);
@override
List<String> get alternateNamesEn => (super.noSuchMethod(
Invocation.getter(#alternateNamesEn),
returnValue: <String>[],
) as List<String>);
@override
List<String> get alternateNamesTrans => (super.noSuchMethod(
Invocation.getter(#alternateNamesTrans),
returnValue: <String>[],
) as List<String>);
@override
List<_i8.Equipment> get equipment => (super.noSuchMethod(
Invocation.getter(#equipment),
@@ -195,6 +207,42 @@ class MockAddExerciseProvider extends _i1.Mock implements _i11.AddExerciseProvid
),
) as _i13.ExerciseSubmissionApi);
@override
set exerciseNameEn(String? value) => super.noSuchMethod(
Invocation.setter(
#exerciseNameEn,
value,
),
returnValueForMissingStub: null,
);
@override
set exerciseNameTrans(String? value) => super.noSuchMethod(
Invocation.setter(
#exerciseNameTrans,
value,
),
returnValueForMissingStub: null,
);
@override
set descriptionEn(String? value) => super.noSuchMethod(
Invocation.setter(
#descriptionEn,
value,
),
returnValueForMissingStub: null,
);
@override
set descriptionTrans(String? value) => super.noSuchMethod(
Invocation.setter(
#descriptionTrans,
value,
),
returnValueForMissingStub: null,
);
@override
set languageEn(_i10.Language? value) => super.noSuchMethod(
Invocation.setter(
@@ -214,64 +262,28 @@ class MockAddExerciseProvider extends _i1.Mock implements _i11.AddExerciseProvid
);
@override
set category(_i7.ExerciseCategory? value) => super.noSuchMethod(
set alternateNamesEn(List<String>? value) => super.noSuchMethod(
Invocation.setter(
#category,
#alternateNamesEn,
value,
),
returnValueForMissingStub: null,
);
@override
set exerciseNameEn(String? name) => super.noSuchMethod(
Invocation.setter(
#exerciseNameEn,
name,
),
returnValueForMissingStub: null,
);
@override
set exerciseNameTrans(String? name) => super.noSuchMethod(
Invocation.setter(
#exerciseNameTrans,
name,
),
returnValueForMissingStub: null,
);
@override
set descriptionEn(String? description) => super.noSuchMethod(
Invocation.setter(
#descriptionEn,
description,
),
returnValueForMissingStub: null,
);
@override
set descriptionTrans(String? description) => super.noSuchMethod(
Invocation.setter(
#descriptionTrans,
description,
),
returnValueForMissingStub: null,
);
@override
set alternateNamesEn(List<String>? names) => super.noSuchMethod(
Invocation.setter(
#alternateNamesEn,
names,
),
returnValueForMissingStub: null,
);
@override
set alternateNamesTrans(List<String>? names) => super.noSuchMethod(
set alternateNamesTrans(List<String>? value) => super.noSuchMethod(
Invocation.setter(
#alternateNamesTrans,
names,
value,
),
returnValueForMissingStub: null,
);
@override
set category(_i7.ExerciseCategory? value) => super.noSuchMethod(
Invocation.setter(
#category,
value,
),
returnValueForMissingStub: null,
);
@@ -381,6 +393,32 @@ class MockAddExerciseProvider extends _i1.Mock implements _i11.AddExerciseProvid
returnValue: _i15.Future<int>.value(0),
) as _i15.Future<int>);
@override
_i15.Future<void> addImages(int? exerciseId) => (super.noSuchMethod(
Invocation.method(
#addImages,
[exerciseId],
),
returnValue: _i15.Future<void>.value(),
returnValueForMissingStub: _i15.Future<void>.value(),
) as _i15.Future<void>);
@override
_i15.Future<bool> validateLanguage(
String? input,
String? languageCode,
) =>
(super.noSuchMethod(
Invocation.method(
#validateLanguage,
[
input,
languageCode,
],
),
returnValue: _i15.Future<bool>.value(false),
) as _i15.Future<bool>);
@override
void addListener(_i16.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(