mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Reuse AddExerciseTextArea in the image form
This commit is contained in:
@@ -145,4 +145,4 @@ const String API_RESULTS_PAGE_SIZE = '100';
|
|||||||
const INTERPOLATION_MARKER = 123;
|
const INTERPOLATION_MARKER = 123;
|
||||||
|
|
||||||
/// Creative Commons license IDs
|
/// Creative Commons license IDs
|
||||||
const CC_BY_SA_4_ID = 4;
|
const CC_BY_SA_4_ID = 2;
|
||||||
|
|||||||
43
lib/helpers/exercises/validators.dart
Normal file
43
lib/helpers/exercises/validators.dart
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||||
|
|
||||||
|
/// The amount of characters an exercise description needs to have
|
||||||
|
const MIN_CHARS_DESCRIPTION = 40;
|
||||||
|
|
||||||
|
/// The amount of characters an exercise name needs to have
|
||||||
|
const MIN_CHARS_NAME = 5;
|
||||||
|
const MAX_CHARS_NAME = 40;
|
||||||
|
|
||||||
|
String? validateName(String? name, BuildContext context) {
|
||||||
|
if (name!.isEmpty) {
|
||||||
|
return AppLocalizations.of(context).enterValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.length < MIN_CHARS_NAME || name.length > MAX_CHARS_NAME) {
|
||||||
|
return AppLocalizations.of(
|
||||||
|
context,
|
||||||
|
).enterCharacters(MIN_CHARS_NAME.toString(), MAX_CHARS_NAME.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? validateAuthorName(String? name, BuildContext context) {
|
||||||
|
if (name!.isEmpty) {
|
||||||
|
return AppLocalizations.of(context).enterValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String? validateExerciseDescription(String? name, BuildContext context) {
|
||||||
|
if (name!.isEmpty) {
|
||||||
|
return AppLocalizations.of(context).enterValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (name.length < MIN_CHARS_DESCRIPTION) {
|
||||||
|
return AppLocalizations.of(context).enterMinCharacters(MIN_CHARS_DESCRIPTION.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
@@ -741,19 +741,19 @@
|
|||||||
"@imageDetailsLicenseTitleHint": {
|
"@imageDetailsLicenseTitleHint": {
|
||||||
"description": "Hint text for image title field"
|
"description": "Hint text for image title field"
|
||||||
},
|
},
|
||||||
"imageDetailsSourceLink": "Link to the source website, if available",
|
"imageDetailsSourceLink": "Link to the source website",
|
||||||
"@imageDetailsSourceLink": {
|
"@imageDetailsSourceLink": {
|
||||||
"description": "Label for source link field"
|
"description": "Label for source link field"
|
||||||
},
|
},
|
||||||
"imageDetailsAuthor": "Author(s)",
|
"author": "Author(s)",
|
||||||
"@imageDetailsAuthor": {
|
"@Author": {
|
||||||
"description": "Label for author field"
|
"description": "Label for author field"
|
||||||
},
|
},
|
||||||
"imageDetailsAuthorHint": "Enter author name",
|
"authorHint": "Enter author name",
|
||||||
"@imageDetailsAuthorHint": {
|
"@authorHint": {
|
||||||
"description": "Hint text for author field"
|
"description": "Hint text for author field"
|
||||||
},
|
},
|
||||||
"imageDetailsAuthorLink": "Link to author website or profile, if available",
|
"imageDetailsAuthorLink": "Link to author website or profile",
|
||||||
"@imageDetailsAuthorLink": {
|
"@imageDetailsAuthorLink": {
|
||||||
"description": "Label for author link field"
|
"description": "Label for author link field"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ ExerciseCategory _$ExerciseCategoryFromJson(Map<String, dynamic> json) {
|
|||||||
return ExerciseCategory(id: (json['id'] as num).toInt(), name: json['name'] as String);
|
return ExerciseCategory(id: (json['id'] as num).toInt(), name: json['name'] as String);
|
||||||
}
|
}
|
||||||
|
|
||||||
ap<String, dynamic> _$ExerciseCategoryToJson(ExerciseCategory instance) => <String, dynamic>{
|
Map<String, dynamic> _$ExerciseCategoryToJson(ExerciseCategory instance) => <String, dynamic>{
|
||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class AddExerciseProvider with ChangeNotifier {
|
|||||||
|
|
||||||
List<ExerciseSubmissionImage> get exerciseImages => [..._exerciseImages];
|
List<ExerciseSubmissionImage> get exerciseImages => [..._exerciseImages];
|
||||||
|
|
||||||
|
String author = '';
|
||||||
String? exerciseNameEn;
|
String? exerciseNameEn;
|
||||||
String? exerciseNameTrans;
|
String? exerciseNameTrans;
|
||||||
String? descriptionEn;
|
String? descriptionEn;
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AddExerciseTextArea extends StatelessWidget {
|
class AddExerciseTextArea extends StatelessWidget {
|
||||||
const AddExerciseTextArea({
|
AddExerciseTextArea({
|
||||||
super.key,
|
super.key,
|
||||||
required this.onChange,
|
|
||||||
required this.title,
|
required this.title,
|
||||||
|
ValueChanged<String>? onChange,
|
||||||
this.helperText = '',
|
this.helperText = '',
|
||||||
this.isRequired = true,
|
|
||||||
this.isMultiline = false,
|
this.isMultiline = false,
|
||||||
|
this.initialValue = '',
|
||||||
this.validator,
|
this.validator,
|
||||||
this.onSaved,
|
this.onSaved,
|
||||||
});
|
}) : onChange = onChange ?? ((String value) {});
|
||||||
|
|
||||||
final ValueChanged<String> onChange;
|
final ValueChanged<String> onChange;
|
||||||
final bool isRequired;
|
|
||||||
final bool isMultiline;
|
final bool isMultiline;
|
||||||
final String title;
|
final String title;
|
||||||
final String helperText;
|
final String helperText;
|
||||||
|
final String? initialValue;
|
||||||
final FormFieldValidator<String?>? validator;
|
final FormFieldValidator<String?>? validator;
|
||||||
final FormFieldSetter<String?>? onSaved;
|
final FormFieldSetter<String?>? onSaved;
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@ class AddExerciseTextArea extends StatelessWidget {
|
|||||||
return Padding(
|
return Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: TextFormField(
|
child: TextFormField(
|
||||||
|
initialValue: initialValue,
|
||||||
keyboardType: isMultiline ? TextInputType.multiline : TextInputType.text,
|
keyboardType: isMultiline ? TextInputType.multiline : TextInputType.text,
|
||||||
maxLines: isMultiline ? null : DEFAULT_LINES,
|
maxLines: isMultiline ? null : DEFAULT_LINES,
|
||||||
minLines: isMultiline ? MULTILINE_MIN_LINES : DEFAULT_LINES,
|
minLines: isMultiline ? MULTILINE_MIN_LINES : DEFAULT_LINES,
|
||||||
@@ -35,12 +36,11 @@ class AddExerciseTextArea extends StatelessWidget {
|
|||||||
onSaved: onSaved,
|
onSaved: onSaved,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
|
||||||
border: const OutlineInputBorder(
|
border: const OutlineInputBorder(borderRadius: BorderRadius.all(Radius.circular(10))),
|
||||||
borderRadius: BorderRadius.all(Radius.circular(10)),
|
|
||||||
),
|
|
||||||
labelText: title,
|
labelText: title,
|
||||||
alignLabelWithHint: true,
|
alignLabelWithHint: true,
|
||||||
helperText: helperText,
|
helperText: helperText,
|
||||||
|
helperMaxLines: 3,
|
||||||
),
|
),
|
||||||
onChanged: onChange,
|
onChanged: onChange,
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:wger/core/validators.dart';
|
||||||
|
import 'package:wger/helpers/exercises/validators.dart';
|
||||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||||
import 'package:wger/models/exercises/exercise_submission_images.dart';
|
import 'package:wger/models/exercises/exercise_submission_images.dart';
|
||||||
import 'package:wger/widgets/add_exercise/license_info_widget.dart';
|
import 'package:wger/widgets/add_exercise/license_info_widget.dart';
|
||||||
|
|
||||||
|
import 'add_exercise_text_area.dart';
|
||||||
|
|
||||||
/// Form for collecting CC BY-SA 4.0 license metadata for exercise images
|
/// Form for collecting CC BY-SA 4.0 license metadata for exercise images
|
||||||
///
|
///
|
||||||
/// This form is displayed after image selection in Step 5 of exercise creation.
|
/// This form is displayed after image selection in Step 5 of exercise creation.
|
||||||
@@ -50,6 +54,11 @@ class _ImageDetailsFormState extends State<ImageDetailsForm> {
|
|||||||
/// Currently selected image type
|
/// Currently selected image type
|
||||||
ImageType _selectedImageType = ImageType.photo;
|
ImageType _selectedImageType = ImageType.photo;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_titleController.dispose();
|
_titleController.dispose();
|
||||||
@@ -60,139 +69,78 @@ class _ImageDetailsFormState extends State<ImageDetailsForm> {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates URL format
|
|
||||||
///
|
|
||||||
/// Returns error message if URL is invalid, null if valid or empty
|
|
||||||
String? _validateUrl(String? value) {
|
|
||||||
if (value == null || value.trim().isEmpty) {
|
|
||||||
return null; // Empty is OK (optional field)
|
|
||||||
}
|
|
||||||
|
|
||||||
final trimmedValue = value.trim();
|
|
||||||
|
|
||||||
// Check if starts with http:// or https://
|
|
||||||
if (!trimmedValue.startsWith('http://') && !trimmedValue.startsWith('https://')) {
|
|
||||||
return AppLocalizations.of(context).invalidUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to parse as URI
|
|
||||||
try {
|
|
||||||
final uri = Uri.parse(trimmedValue);
|
|
||||||
if (!uri.hasScheme || !uri.hasAuthority) {
|
|
||||||
return AppLocalizations.of(context).invalidUrl;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
return AppLocalizations.of(context).invalidUrl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Maps UI image type selection to API 'style' field value
|
|
||||||
///
|
|
||||||
/// API expects numeric string:
|
|
||||||
/// - PHOTO = '1'
|
|
||||||
/// - 3D = '2'
|
|
||||||
/// - LINE = '3'
|
|
||||||
/// - LOW-POLY = '4'
|
|
||||||
/// - OTHER = '5'
|
|
||||||
String _getStyleValue() {
|
|
||||||
switch (_selectedImageType) {
|
|
||||||
case 'PHOTO':
|
|
||||||
return '1';
|
|
||||||
case '3D':
|
|
||||||
return '2';
|
|
||||||
case 'LINE':
|
|
||||||
return '3';
|
|
||||||
case 'LOW-POLY':
|
|
||||||
return '4';
|
|
||||||
case 'OTHER':
|
|
||||||
return '5';
|
|
||||||
default:
|
|
||||||
return '1'; // Default to PHOTO if unknown
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final i18n = AppLocalizations.of(context);
|
||||||
|
|
||||||
return SingleChildScrollView(
|
return SingleChildScrollView(
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Form(
|
child: Form(
|
||||||
key: _formKey,
|
key: _formKey,
|
||||||
child: Column(
|
child: Column(
|
||||||
|
spacing: 8,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
AppLocalizations.of(context).imageDetailsTitle,
|
AppLocalizations.of(context).imageDetailsTitle,
|
||||||
style: Theme.of(
|
style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
||||||
context,
|
|
||||||
).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
_buildImagePreview(),
|
_buildImagePreview(),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
// License title field - helps identify the image
|
|
||||||
_buildTextField(
|
|
||||||
controller: _titleController,
|
|
||||||
label: AppLocalizations.of(context).imageDetailsLicenseTitle,
|
|
||||||
hint: AppLocalizations.of(context).imageDetailsLicenseTitleHint,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Source URL - where the image was found (license_object_url in API)
|
|
||||||
_buildTextField(
|
|
||||||
controller: _sourceLinkController,
|
|
||||||
label: AppLocalizations.of(context).imageDetailsSourceLink,
|
|
||||||
hint: 'https://example.com',
|
|
||||||
keyboardType: TextInputType.url,
|
|
||||||
validator: _validateUrl,
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Author name - required for proper CC BY-SA attribution
|
// Author name - required for proper CC BY-SA attribution
|
||||||
_buildTextField(
|
AddExerciseTextArea(
|
||||||
controller: _authorController,
|
title: '${AppLocalizations.of(context).author}*',
|
||||||
label: AppLocalizations.of(context).imageDetailsAuthor,
|
initialValue: widget.submissionImage.author,
|
||||||
hint: AppLocalizations.of(context).imageDetailsAuthorHint,
|
onSaved: (value) => widget.submissionImage.author = value!,
|
||||||
|
validator: (name) => validateAuthorName(name, context),
|
||||||
|
),
|
||||||
|
|
||||||
|
// License title field - helps identify the image
|
||||||
|
AddExerciseTextArea(
|
||||||
|
title: AppLocalizations.of(context).imageDetailsLicenseTitle,
|
||||||
|
helperText: AppLocalizations.of(context).imageDetailsLicenseTitleHint,
|
||||||
|
initialValue: widget.submissionImage.title,
|
||||||
|
onSaved: (value) => widget.submissionImage.title = value,
|
||||||
|
),
|
||||||
|
|
||||||
|
// Source URL - where the image was found (license_object_url in API)
|
||||||
|
AddExerciseTextArea(
|
||||||
|
title: AppLocalizations.of(context).imageDetailsSourceLink,
|
||||||
|
initialValue: widget.submissionImage.sourceUrl,
|
||||||
|
onSaved: (value) => widget.submissionImage.sourceUrl = value,
|
||||||
|
validator: (value) => validateUrl(value, i18n, required: false),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Author's website/profile URL
|
// Author's website/profile URL
|
||||||
_buildTextField(
|
AddExerciseTextArea(
|
||||||
controller: _authorLinkController,
|
title: AppLocalizations.of(context).imageDetailsAuthorLink,
|
||||||
label: AppLocalizations.of(context).imageDetailsAuthorLink,
|
initialValue: widget.submissionImage.authorUrl,
|
||||||
hint: 'https://example.com/author',
|
onSaved: (value) => widget.submissionImage.authorUrl = value,
|
||||||
keyboardType: TextInputType.url,
|
validator: (value) => validateUrl(value, i18n, required: false),
|
||||||
validator: _validateUrl,
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Original source if this is a derivative work (modified from another image)
|
// Original source if this is a derivative work (modified from another image)
|
||||||
_buildTextField(
|
AddExerciseTextArea(
|
||||||
controller: _originalSourceController,
|
title: AppLocalizations.of(context).imageDetailsDerivativeSource,
|
||||||
label: AppLocalizations.of(context).imageDetailsDerivativeSource,
|
|
||||||
hint: 'https://example.com/original',
|
|
||||||
keyboardType: TextInputType.url,
|
|
||||||
helperText: AppLocalizations.of(context).imageDetailsDerivativeHelp,
|
helperText: AppLocalizations.of(context).imageDetailsDerivativeHelp,
|
||||||
validator: _validateUrl,
|
initialValue: widget.submissionImage.derivativeSourceUrl,
|
||||||
|
onSaved: (value) => widget.submissionImage.derivativeSourceUrl = value,
|
||||||
|
validator: (value) => validateUrl(value, i18n, required: false),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 24),
|
|
||||||
|
|
||||||
_buildImageTypeSelector(),
|
_buildImageTypeSelector(),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
// License info as separate widget for better optimization
|
// License info as separate widget for better optimization
|
||||||
const LicenseInfoWidget(),
|
const LicenseInfoWidget(),
|
||||||
const SizedBox(height: 24),
|
const SizedBox(height: 8),
|
||||||
|
|
||||||
_buildButtons(),
|
_buildButtons(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +240,9 @@ class _ImageDetailsFormState extends State<ImageDetailsForm> {
|
|||||||
type.label,
|
type.label,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: isSelected ? Colors.blue : Colors.grey.shade700,
|
color: isSelected
|
||||||
|
? theme.buttonTheme.colorScheme!.onPrimary
|
||||||
|
: theme.buttonTheme.colorScheme!.primary,
|
||||||
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
@@ -322,10 +272,6 @@ class _ImageDetailsFormState extends State<ImageDetailsForm> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build details map with API field names
|
|
||||||
// Style is always included, other fields only if non-empty
|
|
||||||
final details = <String, String>{'style': _getStyleValue()};
|
|
||||||
|
|
||||||
// Add optional fields only if user provided values
|
// Add optional fields only if user provided values
|
||||||
final title = _titleController.text.trim();
|
final title = _titleController.text.trim();
|
||||||
if (title.isNotEmpty) {
|
if (title.isNotEmpty) {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:wger/helpers/consts.dart';
|
import 'package:wger/helpers/consts.dart';
|
||||||
import 'package:wger/helpers/exercises/forms.dart';
|
import 'package:wger/helpers/exercises/validators.dart';
|
||||||
import 'package:wger/helpers/i18n.dart';
|
import 'package:wger/helpers/i18n.dart';
|
||||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||||
import 'package:wger/models/exercises/category.dart';
|
import 'package:wger/models/exercises/category.dart';
|
||||||
@@ -9,6 +9,7 @@ import 'package:wger/models/exercises/equipment.dart';
|
|||||||
import 'package:wger/models/exercises/muscle.dart';
|
import 'package:wger/models/exercises/muscle.dart';
|
||||||
import 'package:wger/providers/add_exercise.dart';
|
import 'package:wger/providers/add_exercise.dart';
|
||||||
import 'package:wger/providers/exercises.dart';
|
import 'package:wger/providers/exercises.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_multiselect_button.dart';
|
||||||
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
|
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
|
||||||
import 'package:wger/widgets/exercises/exercises.dart';
|
import 'package:wger/widgets/exercises/exercises.dart';
|
||||||
@@ -21,6 +22,7 @@ class Step1Basics extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final userProvider = context.read<UserProvider>();
|
||||||
final addExerciseProvider = context.read<AddExerciseProvider>();
|
final addExerciseProvider = context.read<AddExerciseProvider>();
|
||||||
final exerciseProvider = context.read<ExercisesProvider>();
|
final exerciseProvider = context.read<ExercisesProvider>();
|
||||||
final categories = exerciseProvider.categories;
|
final categories = exerciseProvider.categories;
|
||||||
@@ -38,21 +40,25 @@ class Step1Basics extends StatelessWidget {
|
|||||||
builder: (context, provider, child) => Column(
|
builder: (context, provider, child) => Column(
|
||||||
children: [
|
children: [
|
||||||
AddExerciseTextArea(
|
AddExerciseTextArea(
|
||||||
onChange: (value) => {},
|
|
||||||
title: '${AppLocalizations.of(context).name}*',
|
title: '${AppLocalizations.of(context).name}*',
|
||||||
helperText: AppLocalizations.of(context).baseNameEnglish,
|
helperText: AppLocalizations.of(context).baseNameEnglish,
|
||||||
isRequired: true,
|
|
||||||
validator: (name) => validateName(name, context),
|
validator: (name) => validateName(name, context),
|
||||||
onSaved: (String? name) => addExerciseProvider.exerciseNameEn = name!,
|
onSaved: (String? name) => addExerciseProvider.exerciseNameEn = name,
|
||||||
),
|
),
|
||||||
AddExerciseTextArea(
|
AddExerciseTextArea(
|
||||||
onChange: (value) => {},
|
|
||||||
title: AppLocalizations.of(context).alternativeNames,
|
title: AppLocalizations.of(context).alternativeNames,
|
||||||
isMultiline: true,
|
isMultiline: true,
|
||||||
helperText: AppLocalizations.of(context).oneNamePerLine,
|
helperText: AppLocalizations.of(context).oneNamePerLine,
|
||||||
onSaved: (String? alternateName) =>
|
onSaved: (String? alternateName) =>
|
||||||
addExerciseProvider.alternateNamesEn = alternateName!.split('\n'),
|
addExerciseProvider.alternateNamesEn = alternateName!.split('\n'),
|
||||||
),
|
),
|
||||||
|
AddExerciseTextArea(
|
||||||
|
title: '${AppLocalizations.of(context).author}*',
|
||||||
|
isMultiline: false,
|
||||||
|
validator: (name) => validateAuthorName(name, context),
|
||||||
|
initialValue: userProvider.profile!.username,
|
||||||
|
onSaved: (String? author) => addExerciseProvider.author = author!,
|
||||||
|
),
|
||||||
ExerciseCategoryInputWidget<ExerciseCategory>(
|
ExerciseCategoryInputWidget<ExerciseCategory>(
|
||||||
key: const Key('category-dropdown'),
|
key: const Key('category-dropdown'),
|
||||||
entries: categories,
|
entries: categories,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:wger/helpers/exercises/forms.dart';
|
import 'package:wger/helpers/exercises/validators.dart';
|
||||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||||
import 'package:wger/providers/add_exercise.dart';
|
import 'package:wger/providers/add_exercise.dart';
|
||||||
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
|
import 'package:wger/widgets/add_exercise/add_exercise_text_area.dart';
|
||||||
@@ -23,10 +23,9 @@ class Step3Description extends StatelessWidget {
|
|||||||
onChange: (value) => {},
|
onChange: (value) => {},
|
||||||
title: '${i18n.description}*',
|
title: '${i18n.description}*',
|
||||||
helperText: i18n.enterTextInLanguage,
|
helperText: i18n.enterTextInLanguage,
|
||||||
isRequired: true,
|
|
||||||
isMultiline: true,
|
isMultiline: true,
|
||||||
validator: (name) => validateExerciseDescription(name, context),
|
validator: (name) => validateExerciseDescription(name, context),
|
||||||
onSaved: (String? description) => addExerciseProvider.descriptionEn = description!,
|
onSaved: (String? description) => addExerciseProvider.descriptionEn = description,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:wger/helpers/exercises/forms.dart';
|
import 'package:wger/helpers/exercises/validators.dart';
|
||||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||||
import 'package:wger/models/exercises/language.dart';
|
import 'package:wger/models/exercises/language.dart';
|
||||||
import 'package:wger/providers/add_exercise.dart';
|
import 'package:wger/providers/add_exercise.dart';
|
||||||
@@ -59,14 +59,11 @@ class _Step4TranslationState extends State<Step4Translation> {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
AddExerciseTextArea(
|
AddExerciseTextArea(
|
||||||
onChange: (value) => {},
|
|
||||||
title: '${i18n.name}*',
|
title: '${i18n.name}*',
|
||||||
isRequired: true,
|
|
||||||
validator: (name) => validateName(name, context),
|
validator: (name) => validateName(name, context),
|
||||||
onSaved: (String? name) => addExerciseProvider.exerciseNameTrans = name!,
|
onSaved: (String? name) => addExerciseProvider.exerciseNameTrans = name!,
|
||||||
),
|
),
|
||||||
AddExerciseTextArea(
|
AddExerciseTextArea(
|
||||||
onChange: (value) => {},
|
|
||||||
title: i18n.alternativeNames,
|
title: i18n.alternativeNames,
|
||||||
isMultiline: true,
|
isMultiline: true,
|
||||||
helperText: i18n.oneNamePerLine,
|
helperText: i18n.oneNamePerLine,
|
||||||
@@ -93,7 +90,6 @@ class _Step4TranslationState extends State<Step4Translation> {
|
|||||||
onChange: (value) => {},
|
onChange: (value) => {},
|
||||||
title: '${i18n.description}*',
|
title: '${i18n.description}*',
|
||||||
helperText: i18n.enterTextInLanguage,
|
helperText: i18n.enterTextInLanguage,
|
||||||
isRequired: true,
|
|
||||||
isMultiline: true,
|
isMultiline: true,
|
||||||
validator: (name) => validateExerciseDescription(name, context),
|
validator: (name) => validateExerciseDescription(name, context),
|
||||||
onSaved: (String? description) =>
|
onSaved: (String? description) =>
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import 'package:provider/provider.dart';
|
|||||||
import 'package:wger/l10n/generated/app_localizations.dart';
|
import 'package:wger/l10n/generated/app_localizations.dart';
|
||||||
import 'package:wger/models/exercises/exercise_submission_images.dart';
|
import 'package:wger/models/exercises/exercise_submission_images.dart';
|
||||||
import 'package:wger/providers/add_exercise.dart';
|
import 'package:wger/providers/add_exercise.dart';
|
||||||
|
import 'package:wger/providers/user.dart';
|
||||||
import 'package:wger/widgets/add_exercise/image_details_form.dart';
|
import 'package:wger/widgets/add_exercise/image_details_form.dart';
|
||||||
import 'package:wger/widgets/add_exercise/mixins/image_picker_mixin.dart';
|
import 'package:wger/widgets/add_exercise/mixins/image_picker_mixin.dart';
|
||||||
import 'package:wger/widgets/add_exercise/preview_images.dart';
|
import 'package:wger/widgets/add_exercise/preview_images.dart';
|
||||||
@@ -33,7 +34,7 @@ class Step5Images extends StatefulWidget {
|
|||||||
class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin {
|
class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin {
|
||||||
/// Currently selected image waiting for metadata input
|
/// Currently selected image waiting for metadata input
|
||||||
/// When non-null, ImageDetailsForm is displayed instead of image picker
|
/// When non-null, ImageDetailsForm is displayed instead of image picker
|
||||||
ExerciseSubmissionImage? _currentImageToAddNew;
|
ExerciseSubmissionImage? _currentImageToAdd;
|
||||||
|
|
||||||
/// Show dialog to choose between Camera and Gallery
|
/// Show dialog to choose between Camera and Gallery
|
||||||
Future<void> _showImageSourceDialog(BuildContext context) async {
|
Future<void> _showImageSourceDialog(BuildContext context) async {
|
||||||
@@ -75,6 +76,7 @@ class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin
|
|||||||
///
|
///
|
||||||
/// [pickFromCamera] - If true, opens camera; otherwise opens gallery
|
/// [pickFromCamera] - If true, opens camera; otherwise opens gallery
|
||||||
void _pickAndShowImageDetails(BuildContext context, {bool pickFromCamera = false}) async {
|
void _pickAndShowImageDetails(BuildContext context, {bool pickFromCamera = false}) async {
|
||||||
|
final userProvider = context.read<UserProvider>();
|
||||||
final imagePicker = ImagePicker();
|
final imagePicker = ImagePicker();
|
||||||
|
|
||||||
XFile? selectedImage;
|
XFile? selectedImage;
|
||||||
@@ -114,7 +116,10 @@ class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin
|
|||||||
|
|
||||||
// Show metadata collection form for valid image
|
// Show metadata collection form for valid image
|
||||||
setState(() {
|
setState(() {
|
||||||
_currentImageToAddNew = ExerciseSubmissionImage(imageFile: imageFile);
|
_currentImageToAdd = ExerciseSubmissionImage(
|
||||||
|
imageFile: imageFile,
|
||||||
|
author: userProvider.profile?.username ?? '',
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,14 +140,14 @@ class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin
|
|||||||
|
|
||||||
// Reset form state - image is now visible in preview list
|
// Reset form state - image is now visible in preview list
|
||||||
setState(() {
|
setState(() {
|
||||||
_currentImageToAddNew = null;
|
_currentImageToAdd = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Cancel metadata input and return to image picker
|
/// Cancel metadata input and return to image picker
|
||||||
void _cancelImageAdd() {
|
void _cancelImageAdd() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_currentImageToAddNew = null;
|
_currentImageToAdd = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -153,7 +158,7 @@ class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
// License notice - shown when not entering metadata
|
// License notice - shown when not entering metadata
|
||||||
if (_currentImageToAddNew == null)
|
if (_currentImageToAdd == null)
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
padding: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
@@ -164,15 +169,15 @@ class _Step5ImagesState extends State<Step5Images> with ExerciseImagePickerMixin
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Metadata collection form - shown when image is selected
|
// Metadata collection form - shown when image is selected
|
||||||
if (_currentImageToAddNew != null)
|
if (_currentImageToAdd != null)
|
||||||
ImageDetailsForm(
|
ImageDetailsForm(
|
||||||
submissionImage: _currentImageToAddNew!,
|
submissionImage: _currentImageToAdd!,
|
||||||
onAdd: _addImageWithDetails,
|
onAdd: _addImageWithDetails,
|
||||||
onCancel: _cancelImageAdd,
|
onCancel: _cancelImageAdd,
|
||||||
),
|
),
|
||||||
|
|
||||||
// Image picker or preview - shown when not entering metadata
|
// Image picker or preview - shown when not entering metadata
|
||||||
if (_currentImageToAddNew == null)
|
if (_currentImageToAdd == null)
|
||||||
Consumer<AddExerciseProvider>(
|
Consumer<AddExerciseProvider>(
|
||||||
builder: (ctx, provider, __) {
|
builder: (ctx, provider, __) {
|
||||||
if (provider.exerciseImages.isNotEmpty) {
|
if (provider.exerciseImages.isNotEmpty) {
|
||||||
|
|||||||
@@ -11,13 +11,14 @@ class Step6Overview extends StatelessWidget {
|
|||||||
final i18n = AppLocalizations.of(context);
|
final i18n = AppLocalizations.of(context);
|
||||||
|
|
||||||
return Consumer<AddExerciseProvider>(
|
return Consumer<AddExerciseProvider>(
|
||||||
builder: (ctx, provider, __) => Column(
|
builder: (ctx, provider, _) => Column(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Text(i18n.baseData, style: Theme.of(context).textTheme.headlineSmall),
|
Text(i18n.baseData, style: Theme.of(context).textTheme.headlineSmall),
|
||||||
Table(
|
Table(
|
||||||
columnWidths: const {0: FlexColumnWidth(2), 1: FlexColumnWidth(3)},
|
columnWidths: const {0: FlexColumnWidth(2), 1: FlexColumnWidth(3)},
|
||||||
children: [
|
children: [
|
||||||
|
TableRow(children: [Text(i18n.author), Text(provider.author)]),
|
||||||
TableRow(children: [Text(i18n.name), Text(provider.exerciseNameEn ?? '...')]),
|
TableRow(children: [Text(i18n.name), Text(provider.exerciseNameEn ?? '...')]),
|
||||||
TableRow(
|
TableRow(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import 'dart:ui' as _i15;
|
|||||||
|
|
||||||
import 'package:http/http.dart' as _i5;
|
import 'package:http/http.dart' as _i5;
|
||||||
import 'package:mockito/mockito.dart' as _i1;
|
import 'package:mockito/mockito.dart' as _i1;
|
||||||
import 'package:mockito/src/dummies.dart' as _i11;
|
import 'package:mockito/src/dummies.dart' as _i8;
|
||||||
import 'package:wger/models/exercises/category.dart' as _i13;
|
import 'package:wger/models/exercises/category.dart' as _i13;
|
||||||
import 'package:wger/models/exercises/equipment.dart' as _i8;
|
import 'package:wger/models/exercises/equipment.dart' as _i9;
|
||||||
import 'package:wger/models/exercises/exercise_submission.dart' as _i10;
|
import 'package:wger/models/exercises/exercise_submission.dart' as _i11;
|
||||||
import 'package:wger/models/exercises/exercise_submission_images.dart' as _i7;
|
import 'package:wger/models/exercises/exercise_submission_images.dart' as _i7;
|
||||||
import 'package:wger/models/exercises/language.dart' as _i12;
|
import 'package:wger/models/exercises/language.dart' as _i12;
|
||||||
import 'package:wger/models/exercises/muscle.dart' as _i9;
|
import 'package:wger/models/exercises/muscle.dart' as _i10;
|
||||||
import 'package:wger/models/exercises/variation.dart' as _i3;
|
import 'package:wger/models/exercises/variation.dart' as _i3;
|
||||||
import 'package:wger/providers/add_exercise.dart' as _i6;
|
import 'package:wger/providers/add_exercise.dart' as _i6;
|
||||||
import 'package:wger/providers/auth.dart' as _i4;
|
import 'package:wger/providers/auth.dart' as _i4;
|
||||||
@@ -84,6 +84,14 @@ class MockAddExerciseProvider extends _i1.Mock implements _i6.AddExerciseProvide
|
|||||||
)
|
)
|
||||||
as List<_i7.ExerciseSubmissionImage>);
|
as List<_i7.ExerciseSubmissionImage>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get author =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.getter(#author),
|
||||||
|
returnValue: _i8.dummyValue<String>(this, Invocation.getter(#author)),
|
||||||
|
)
|
||||||
|
as String);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> get alternateNamesEn =>
|
List<String> get alternateNamesEn =>
|
||||||
(super.noSuchMethod(Invocation.getter(#alternateNamesEn), returnValue: <String>[])
|
(super.noSuchMethod(Invocation.getter(#alternateNamesEn), returnValue: <String>[])
|
||||||
@@ -95,9 +103,9 @@ class MockAddExerciseProvider extends _i1.Mock implements _i6.AddExerciseProvide
|
|||||||
as List<String>);
|
as List<String>);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<_i8.Equipment> get equipment =>
|
List<_i9.Equipment> get equipment =>
|
||||||
(super.noSuchMethod(Invocation.getter(#equipment), returnValue: <_i8.Equipment>[])
|
(super.noSuchMethod(Invocation.getter(#equipment), returnValue: <_i9.Equipment>[])
|
||||||
as List<_i8.Equipment>);
|
as List<_i9.Equipment>);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool get newVariation =>
|
bool get newVariation =>
|
||||||
@@ -112,25 +120,29 @@ class MockAddExerciseProvider extends _i1.Mock implements _i6.AddExerciseProvide
|
|||||||
as _i3.Variation);
|
as _i3.Variation);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<_i9.Muscle> get primaryMuscles =>
|
List<_i10.Muscle> get primaryMuscles =>
|
||||||
(super.noSuchMethod(Invocation.getter(#primaryMuscles), returnValue: <_i9.Muscle>[])
|
(super.noSuchMethod(Invocation.getter(#primaryMuscles), returnValue: <_i10.Muscle>[])
|
||||||
as List<_i9.Muscle>);
|
as List<_i10.Muscle>);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<_i9.Muscle> get secondaryMuscles =>
|
List<_i10.Muscle> get secondaryMuscles =>
|
||||||
(super.noSuchMethod(Invocation.getter(#secondaryMuscles), returnValue: <_i9.Muscle>[])
|
(super.noSuchMethod(Invocation.getter(#secondaryMuscles), returnValue: <_i10.Muscle>[])
|
||||||
as List<_i9.Muscle>);
|
as List<_i10.Muscle>);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_i10.ExerciseSubmissionApi get exerciseApiObject =>
|
_i11.ExerciseSubmissionApi get exerciseApiObject =>
|
||||||
(super.noSuchMethod(
|
(super.noSuchMethod(
|
||||||
Invocation.getter(#exerciseApiObject),
|
Invocation.getter(#exerciseApiObject),
|
||||||
returnValue: _i11.dummyValue<_i10.ExerciseSubmissionApi>(
|
returnValue: _i8.dummyValue<_i11.ExerciseSubmissionApi>(
|
||||||
this,
|
this,
|
||||||
Invocation.getter(#exerciseApiObject),
|
Invocation.getter(#exerciseApiObject),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
as _i10.ExerciseSubmissionApi);
|
as _i11.ExerciseSubmissionApi);
|
||||||
|
|
||||||
|
@override
|
||||||
|
set author(String? value) =>
|
||||||
|
super.noSuchMethod(Invocation.setter(#author, value), returnValueForMissingStub: null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set exerciseNameEn(String? value) => super.noSuchMethod(
|
set exerciseNameEn(String? value) => super.noSuchMethod(
|
||||||
@@ -181,7 +193,7 @@ class MockAddExerciseProvider extends _i1.Mock implements _i6.AddExerciseProvide
|
|||||||
super.noSuchMethod(Invocation.setter(#category, value), returnValueForMissingStub: null);
|
super.noSuchMethod(Invocation.setter(#category, value), returnValueForMissingStub: null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set equipment(List<_i8.Equipment>? equipment) =>
|
set equipment(List<_i9.Equipment>? equipment) =>
|
||||||
super.noSuchMethod(Invocation.setter(#equipment, equipment), returnValueForMissingStub: null);
|
super.noSuchMethod(Invocation.setter(#equipment, equipment), returnValueForMissingStub: null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -197,13 +209,13 @@ class MockAddExerciseProvider extends _i1.Mock implements _i6.AddExerciseProvide
|
|||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set primaryMuscles(List<_i9.Muscle>? muscles) => super.noSuchMethod(
|
set primaryMuscles(List<_i10.Muscle>? muscles) => super.noSuchMethod(
|
||||||
Invocation.setter(#primaryMuscles, muscles),
|
Invocation.setter(#primaryMuscles, muscles),
|
||||||
returnValueForMissingStub: null,
|
returnValueForMissingStub: null,
|
||||||
);
|
);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set secondaryMuscles(List<_i9.Muscle>? muscles) => super.noSuchMethod(
|
set secondaryMuscles(List<_i10.Muscle>? muscles) => super.noSuchMethod(
|
||||||
Invocation.setter(#secondaryMuscles, muscles),
|
Invocation.setter(#secondaryMuscles, muscles),
|
||||||
returnValueForMissingStub: null,
|
returnValueForMissingStub: null,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import 'dart:ui' as _i16;
|
|||||||
|
|
||||||
import 'package:flutter/material.dart' as _i18;
|
import 'package:flutter/material.dart' as _i18;
|
||||||
import 'package:mockito/mockito.dart' as _i1;
|
import 'package:mockito/mockito.dart' as _i1;
|
||||||
import 'package:mockito/src/dummies.dart' as _i14;
|
import 'package:mockito/src/dummies.dart' as _i13;
|
||||||
import 'package:shared_preferences/shared_preferences.dart' as _i4;
|
import 'package:shared_preferences/shared_preferences.dart' as _i4;
|
||||||
import 'package:wger/database/exercises/exercise_database.dart' as _i5;
|
import 'package:wger/database/exercises/exercise_database.dart' as _i5;
|
||||||
import 'package:wger/models/exercises/category.dart' as _i7;
|
import 'package:wger/models/exercises/category.dart' as _i7;
|
||||||
import 'package:wger/models/exercises/equipment.dart' as _i8;
|
import 'package:wger/models/exercises/equipment.dart' as _i8;
|
||||||
import 'package:wger/models/exercises/exercise.dart' as _i6;
|
import 'package:wger/models/exercises/exercise.dart' as _i6;
|
||||||
import 'package:wger/models/exercises/exercise_submission.dart' as _i13;
|
import 'package:wger/models/exercises/exercise_submission.dart' as _i14;
|
||||||
import 'package:wger/models/exercises/exercise_submission_images.dart' as _i12;
|
import 'package:wger/models/exercises/exercise_submission_images.dart' as _i12;
|
||||||
import 'package:wger/models/exercises/language.dart' as _i10;
|
import 'package:wger/models/exercises/language.dart' as _i10;
|
||||||
import 'package:wger/models/exercises/muscle.dart' as _i9;
|
import 'package:wger/models/exercises/muscle.dart' as _i9;
|
||||||
@@ -104,6 +104,14 @@ class MockAddExerciseProvider extends _i1.Mock implements _i11.AddExerciseProvid
|
|||||||
)
|
)
|
||||||
as List<_i12.ExerciseSubmissionImage>);
|
as List<_i12.ExerciseSubmissionImage>);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get author =>
|
||||||
|
(super.noSuchMethod(
|
||||||
|
Invocation.getter(#author),
|
||||||
|
returnValue: _i13.dummyValue<String>(this, Invocation.getter(#author)),
|
||||||
|
)
|
||||||
|
as String);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<String> get alternateNamesEn =>
|
List<String> get alternateNamesEn =>
|
||||||
(super.noSuchMethod(Invocation.getter(#alternateNamesEn), returnValue: <String>[])
|
(super.noSuchMethod(Invocation.getter(#alternateNamesEn), returnValue: <String>[])
|
||||||
@@ -142,15 +150,19 @@ class MockAddExerciseProvider extends _i1.Mock implements _i11.AddExerciseProvid
|
|||||||
as List<_i9.Muscle>);
|
as List<_i9.Muscle>);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
_i13.ExerciseSubmissionApi get exerciseApiObject =>
|
_i14.ExerciseSubmissionApi get exerciseApiObject =>
|
||||||
(super.noSuchMethod(
|
(super.noSuchMethod(
|
||||||
Invocation.getter(#exerciseApiObject),
|
Invocation.getter(#exerciseApiObject),
|
||||||
returnValue: _i14.dummyValue<_i13.ExerciseSubmissionApi>(
|
returnValue: _i13.dummyValue<_i14.ExerciseSubmissionApi>(
|
||||||
this,
|
this,
|
||||||
Invocation.getter(#exerciseApiObject),
|
Invocation.getter(#exerciseApiObject),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
as _i13.ExerciseSubmissionApi);
|
as _i14.ExerciseSubmissionApi);
|
||||||
|
|
||||||
|
@override
|
||||||
|
set author(String? value) =>
|
||||||
|
super.noSuchMethod(Invocation.setter(#author, value), returnValueForMissingStub: null);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
set exerciseNameEn(String? value) => super.noSuchMethod(
|
set exerciseNameEn(String? value) => super.noSuchMethod(
|
||||||
|
|||||||
Reference in New Issue
Block a user