Fixes for flutter typeahead 5.1.0

Also, add some models for the API response from the search
This commit is contained in:
Roland Geider
2024-01-29 12:07:26 +01:00
parent 3764c2e3c7
commit faf1018f2a
28 changed files with 1485 additions and 172 deletions

View File

@@ -15,7 +15,7 @@ import '../test_data/workouts.dart';
Widget createGymModeScreen({locale = 'en'}) {
final key = GlobalKey<NavigatorState>();
final bases = getTestExerciseBases();
final bases = getTestExercises();
final workout = getWorkout(exercises: getScreenshotExercises());
final mockExerciseProvider = MockExercisesProvider();

View File

@@ -48,3 +48,44 @@ class ExerciseApiData with _$ExerciseApiData {
factory ExerciseApiData.fromJson(Map<String, dynamic> json) => _$ExerciseApiDataFromJson(json);
}
/// Model for the search results returned from the /api/v2/exercise/search endpoint
///
@freezed
class ExerciseSearchDetails with _$ExerciseSearchDetails {
factory ExerciseSearchDetails({
// ignore: invalid_annotation_target
@JsonKey(name: 'id') required int translationId,
// ignore: invalid_annotation_target
@JsonKey(name: 'base_id') required int exerciseId,
required String name,
required String category,
required String? image,
// ignore: invalid_annotation_target
@JsonKey(name: 'image_thumbnail') required String? imageThumbnail,
}) = _ExerciseSearchDetails;
factory ExerciseSearchDetails.fromJson(Map<String, dynamic> json) =>
_$ExerciseSearchDetailsFromJson(json);
}
@freezed
class ExerciseSearchEntry with _$ExerciseSearchEntry {
factory ExerciseSearchEntry({
required String value,
required ExerciseSearchDetails data,
}) = _ExerciseSearchEntry;
factory ExerciseSearchEntry.fromJson(Map<String, dynamic> json) =>
_$ExerciseSearchEntryFromJson(json);
}
@freezed
class ExerciseApiSearch with _$ExerciseApiSearch {
factory ExerciseApiSearch({
required List<ExerciseSearchEntry> suggestions,
}) = _ExerciseApiSearch;
factory ExerciseApiSearch.fromJson(Map<String, dynamic> json) =>
_$ExerciseApiSearchFromJson(json);
}

View File

@@ -545,3 +545,567 @@ abstract class _ExerciseBaseData implements ExerciseApiData {
_$$ExerciseBaseDataImplCopyWith<_$ExerciseBaseDataImpl> get copyWith =>
throw _privateConstructorUsedError;
}
ExerciseSearchDetails _$ExerciseSearchDetailsFromJson(Map<String, dynamic> json) {
return _ExerciseSearchDetails.fromJson(json);
}
/// @nodoc
mixin _$ExerciseSearchDetails {
// ignore: invalid_annotation_target
@JsonKey(name: 'id')
int get translationId => throw _privateConstructorUsedError; // ignore: invalid_annotation_target
@JsonKey(name: 'base_id')
int get exerciseId => throw _privateConstructorUsedError;
String get name => throw _privateConstructorUsedError;
String get category => throw _privateConstructorUsedError;
String? get image => throw _privateConstructorUsedError; // ignore: invalid_annotation_target
@JsonKey(name: 'image_thumbnail')
String? get imageThumbnail => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ExerciseSearchDetailsCopyWith<ExerciseSearchDetails> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ExerciseSearchDetailsCopyWith<$Res> {
factory $ExerciseSearchDetailsCopyWith(
ExerciseSearchDetails value, $Res Function(ExerciseSearchDetails) then) =
_$ExerciseSearchDetailsCopyWithImpl<$Res, ExerciseSearchDetails>;
@useResult
$Res call(
{@JsonKey(name: 'id') int translationId,
@JsonKey(name: 'base_id') int exerciseId,
String name,
String category,
String? image,
@JsonKey(name: 'image_thumbnail') String? imageThumbnail});
}
/// @nodoc
class _$ExerciseSearchDetailsCopyWithImpl<$Res, $Val extends ExerciseSearchDetails>
implements $ExerciseSearchDetailsCopyWith<$Res> {
_$ExerciseSearchDetailsCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? translationId = null,
Object? exerciseId = null,
Object? name = null,
Object? category = null,
Object? image = freezed,
Object? imageThumbnail = freezed,
}) {
return _then(_value.copyWith(
translationId: null == translationId
? _value.translationId
: translationId // ignore: cast_nullable_to_non_nullable
as int,
exerciseId: null == exerciseId
? _value.exerciseId
: exerciseId // ignore: cast_nullable_to_non_nullable
as int,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
category: null == category
? _value.category
: category // ignore: cast_nullable_to_non_nullable
as String,
image: freezed == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as String?,
imageThumbnail: freezed == imageThumbnail
? _value.imageThumbnail
: imageThumbnail // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
/// @nodoc
abstract class _$$ExerciseSearchDetailsImplCopyWith<$Res>
implements $ExerciseSearchDetailsCopyWith<$Res> {
factory _$$ExerciseSearchDetailsImplCopyWith(
_$ExerciseSearchDetailsImpl value, $Res Function(_$ExerciseSearchDetailsImpl) then) =
__$$ExerciseSearchDetailsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{@JsonKey(name: 'id') int translationId,
@JsonKey(name: 'base_id') int exerciseId,
String name,
String category,
String? image,
@JsonKey(name: 'image_thumbnail') String? imageThumbnail});
}
/// @nodoc
class __$$ExerciseSearchDetailsImplCopyWithImpl<$Res>
extends _$ExerciseSearchDetailsCopyWithImpl<$Res, _$ExerciseSearchDetailsImpl>
implements _$$ExerciseSearchDetailsImplCopyWith<$Res> {
__$$ExerciseSearchDetailsImplCopyWithImpl(
_$ExerciseSearchDetailsImpl _value, $Res Function(_$ExerciseSearchDetailsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? translationId = null,
Object? exerciseId = null,
Object? name = null,
Object? category = null,
Object? image = freezed,
Object? imageThumbnail = freezed,
}) {
return _then(_$ExerciseSearchDetailsImpl(
translationId: null == translationId
? _value.translationId
: translationId // ignore: cast_nullable_to_non_nullable
as int,
exerciseId: null == exerciseId
? _value.exerciseId
: exerciseId // ignore: cast_nullable_to_non_nullable
as int,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
category: null == category
? _value.category
: category // ignore: cast_nullable_to_non_nullable
as String,
image: freezed == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as String?,
imageThumbnail: freezed == imageThumbnail
? _value.imageThumbnail
: imageThumbnail // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ExerciseSearchDetailsImpl implements _ExerciseSearchDetails {
_$ExerciseSearchDetailsImpl(
{@JsonKey(name: 'id') required this.translationId,
@JsonKey(name: 'base_id') required this.exerciseId,
required this.name,
required this.category,
required this.image,
@JsonKey(name: 'image_thumbnail') required this.imageThumbnail});
factory _$ExerciseSearchDetailsImpl.fromJson(Map<String, dynamic> json) =>
_$$ExerciseSearchDetailsImplFromJson(json);
// ignore: invalid_annotation_target
@override
@JsonKey(name: 'id')
final int translationId;
// ignore: invalid_annotation_target
@override
@JsonKey(name: 'base_id')
final int exerciseId;
@override
final String name;
@override
final String category;
@override
final String? image;
// ignore: invalid_annotation_target
@override
@JsonKey(name: 'image_thumbnail')
final String? imageThumbnail;
@override
String toString() {
return 'ExerciseSearchDetails(translationId: $translationId, exerciseId: $exerciseId, name: $name, category: $category, image: $image, imageThumbnail: $imageThumbnail)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ExerciseSearchDetailsImpl &&
(identical(other.translationId, translationId) ||
other.translationId == translationId) &&
(identical(other.exerciseId, exerciseId) || other.exerciseId == exerciseId) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.category, category) || other.category == category) &&
(identical(other.image, image) || other.image == image) &&
(identical(other.imageThumbnail, imageThumbnail) ||
other.imageThumbnail == imageThumbnail));
}
@JsonKey(ignore: true)
@override
int get hashCode =>
Object.hash(runtimeType, translationId, exerciseId, name, category, image, imageThumbnail);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ExerciseSearchDetailsImplCopyWith<_$ExerciseSearchDetailsImpl> get copyWith =>
__$$ExerciseSearchDetailsImplCopyWithImpl<_$ExerciseSearchDetailsImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ExerciseSearchDetailsImplToJson(
this,
);
}
}
abstract class _ExerciseSearchDetails implements ExerciseSearchDetails {
factory _ExerciseSearchDetails(
{@JsonKey(name: 'id') required final int translationId,
@JsonKey(name: 'base_id') required final int exerciseId,
required final String name,
required final String category,
required final String? image,
@JsonKey(name: 'image_thumbnail') required final String? imageThumbnail}) =
_$ExerciseSearchDetailsImpl;
factory _ExerciseSearchDetails.fromJson(Map<String, dynamic> json) =
_$ExerciseSearchDetailsImpl.fromJson;
@override // ignore: invalid_annotation_target
@JsonKey(name: 'id')
int get translationId;
@override // ignore: invalid_annotation_target
@JsonKey(name: 'base_id')
int get exerciseId;
@override
String get name;
@override
String get category;
@override
String? get image;
@override // ignore: invalid_annotation_target
@JsonKey(name: 'image_thumbnail')
String? get imageThumbnail;
@override
@JsonKey(ignore: true)
_$$ExerciseSearchDetailsImplCopyWith<_$ExerciseSearchDetailsImpl> get copyWith =>
throw _privateConstructorUsedError;
}
ExerciseSearchEntry _$ExerciseSearchEntryFromJson(Map<String, dynamic> json) {
return _ExerciseSearchEntry.fromJson(json);
}
/// @nodoc
mixin _$ExerciseSearchEntry {
String get value => throw _privateConstructorUsedError;
ExerciseSearchDetails get data => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ExerciseSearchEntryCopyWith<ExerciseSearchEntry> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ExerciseSearchEntryCopyWith<$Res> {
factory $ExerciseSearchEntryCopyWith(
ExerciseSearchEntry value, $Res Function(ExerciseSearchEntry) then) =
_$ExerciseSearchEntryCopyWithImpl<$Res, ExerciseSearchEntry>;
@useResult
$Res call({String value, ExerciseSearchDetails data});
$ExerciseSearchDetailsCopyWith<$Res> get data;
}
/// @nodoc
class _$ExerciseSearchEntryCopyWithImpl<$Res, $Val extends ExerciseSearchEntry>
implements $ExerciseSearchEntryCopyWith<$Res> {
_$ExerciseSearchEntryCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? value = null,
Object? data = null,
}) {
return _then(_value.copyWith(
value: null == value
? _value.value
: value // ignore: cast_nullable_to_non_nullable
as String,
data: null == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as ExerciseSearchDetails,
) as $Val);
}
@override
@pragma('vm:prefer-inline')
$ExerciseSearchDetailsCopyWith<$Res> get data {
return $ExerciseSearchDetailsCopyWith<$Res>(_value.data, (value) {
return _then(_value.copyWith(data: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$ExerciseSearchEntryImplCopyWith<$Res>
implements $ExerciseSearchEntryCopyWith<$Res> {
factory _$$ExerciseSearchEntryImplCopyWith(
_$ExerciseSearchEntryImpl value, $Res Function(_$ExerciseSearchEntryImpl) then) =
__$$ExerciseSearchEntryImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String value, ExerciseSearchDetails data});
@override
$ExerciseSearchDetailsCopyWith<$Res> get data;
}
/// @nodoc
class __$$ExerciseSearchEntryImplCopyWithImpl<$Res>
extends _$ExerciseSearchEntryCopyWithImpl<$Res, _$ExerciseSearchEntryImpl>
implements _$$ExerciseSearchEntryImplCopyWith<$Res> {
__$$ExerciseSearchEntryImplCopyWithImpl(
_$ExerciseSearchEntryImpl _value, $Res Function(_$ExerciseSearchEntryImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? value = null,
Object? data = null,
}) {
return _then(_$ExerciseSearchEntryImpl(
value: null == value
? _value.value
: value // ignore: cast_nullable_to_non_nullable
as String,
data: null == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as ExerciseSearchDetails,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ExerciseSearchEntryImpl implements _ExerciseSearchEntry {
_$ExerciseSearchEntryImpl({required this.value, required this.data});
factory _$ExerciseSearchEntryImpl.fromJson(Map<String, dynamic> json) =>
_$$ExerciseSearchEntryImplFromJson(json);
@override
final String value;
@override
final ExerciseSearchDetails data;
@override
String toString() {
return 'ExerciseSearchEntry(value: $value, data: $data)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ExerciseSearchEntryImpl &&
(identical(other.value, value) || other.value == value) &&
(identical(other.data, data) || other.data == data));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, value, data);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ExerciseSearchEntryImplCopyWith<_$ExerciseSearchEntryImpl> get copyWith =>
__$$ExerciseSearchEntryImplCopyWithImpl<_$ExerciseSearchEntryImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ExerciseSearchEntryImplToJson(
this,
);
}
}
abstract class _ExerciseSearchEntry implements ExerciseSearchEntry {
factory _ExerciseSearchEntry(
{required final String value,
required final ExerciseSearchDetails data}) = _$ExerciseSearchEntryImpl;
factory _ExerciseSearchEntry.fromJson(Map<String, dynamic> json) =
_$ExerciseSearchEntryImpl.fromJson;
@override
String get value;
@override
ExerciseSearchDetails get data;
@override
@JsonKey(ignore: true)
_$$ExerciseSearchEntryImplCopyWith<_$ExerciseSearchEntryImpl> get copyWith =>
throw _privateConstructorUsedError;
}
ExerciseApiSearch _$ExerciseApiSearchFromJson(Map<String, dynamic> json) {
return _ExerciseApiSearch.fromJson(json);
}
/// @nodoc
mixin _$ExerciseApiSearch {
List<ExerciseSearchEntry> get suggestions => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ExerciseApiSearchCopyWith<ExerciseApiSearch> get copyWith => throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ExerciseApiSearchCopyWith<$Res> {
factory $ExerciseApiSearchCopyWith(
ExerciseApiSearch value, $Res Function(ExerciseApiSearch) then) =
_$ExerciseApiSearchCopyWithImpl<$Res, ExerciseApiSearch>;
@useResult
$Res call({List<ExerciseSearchEntry> suggestions});
}
/// @nodoc
class _$ExerciseApiSearchCopyWithImpl<$Res, $Val extends ExerciseApiSearch>
implements $ExerciseApiSearchCopyWith<$Res> {
_$ExerciseApiSearchCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? suggestions = null,
}) {
return _then(_value.copyWith(
suggestions: null == suggestions
? _value.suggestions
: suggestions // ignore: cast_nullable_to_non_nullable
as List<ExerciseSearchEntry>,
) as $Val);
}
}
/// @nodoc
abstract class _$$ExerciseApiSearchImplCopyWith<$Res> implements $ExerciseApiSearchCopyWith<$Res> {
factory _$$ExerciseApiSearchImplCopyWith(
_$ExerciseApiSearchImpl value, $Res Function(_$ExerciseApiSearchImpl) then) =
__$$ExerciseApiSearchImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({List<ExerciseSearchEntry> suggestions});
}
/// @nodoc
class __$$ExerciseApiSearchImplCopyWithImpl<$Res>
extends _$ExerciseApiSearchCopyWithImpl<$Res, _$ExerciseApiSearchImpl>
implements _$$ExerciseApiSearchImplCopyWith<$Res> {
__$$ExerciseApiSearchImplCopyWithImpl(
_$ExerciseApiSearchImpl _value, $Res Function(_$ExerciseApiSearchImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? suggestions = null,
}) {
return _then(_$ExerciseApiSearchImpl(
suggestions: null == suggestions
? _value._suggestions
: suggestions // ignore: cast_nullable_to_non_nullable
as List<ExerciseSearchEntry>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ExerciseApiSearchImpl implements _ExerciseApiSearch {
_$ExerciseApiSearchImpl({required final List<ExerciseSearchEntry> suggestions})
: _suggestions = suggestions;
factory _$ExerciseApiSearchImpl.fromJson(Map<String, dynamic> json) =>
_$$ExerciseApiSearchImplFromJson(json);
final List<ExerciseSearchEntry> _suggestions;
@override
List<ExerciseSearchEntry> get suggestions {
if (_suggestions is EqualUnmodifiableListView) return _suggestions;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_suggestions);
}
@override
String toString() {
return 'ExerciseApiSearch(suggestions: $suggestions)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ExerciseApiSearchImpl &&
const DeepCollectionEquality().equals(other._suggestions, _suggestions));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_suggestions));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ExerciseApiSearchImplCopyWith<_$ExerciseApiSearchImpl> get copyWith =>
__$$ExerciseApiSearchImplCopyWithImpl<_$ExerciseApiSearchImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ExerciseApiSearchImplToJson(
this,
);
}
}
abstract class _ExerciseApiSearch implements ExerciseApiSearch {
factory _ExerciseApiSearch({required final List<ExerciseSearchEntry> suggestions}) =
_$ExerciseApiSearchImpl;
factory _ExerciseApiSearch.fromJson(Map<String, dynamic> json) = _$ExerciseApiSearchImpl.fromJson;
@override
List<ExerciseSearchEntry> get suggestions;
@override
@JsonKey(ignore: true)
_$$ExerciseApiSearchImplCopyWith<_$ExerciseApiSearchImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -56,3 +56,47 @@ Map<String, dynamic> _$$ExerciseBaseDataImplToJson(_$ExerciseBaseDataImpl instan
'author_history': instance.authors,
'total_authors_history': instance.authorsGlobal,
};
_$ExerciseSearchDetailsImpl _$$ExerciseSearchDetailsImplFromJson(Map<String, dynamic> json) =>
_$ExerciseSearchDetailsImpl(
translationId: json['id'] as int,
exerciseId: json['base_id'] as int,
name: json['name'] as String,
category: json['category'] as String,
image: json['image'] as String?,
imageThumbnail: json['image_thumbnail'] as String?,
);
Map<String, dynamic> _$$ExerciseSearchDetailsImplToJson(_$ExerciseSearchDetailsImpl instance) =>
<String, dynamic>{
'id': instance.translationId,
'base_id': instance.exerciseId,
'name': instance.name,
'category': instance.category,
'image': instance.image,
'image_thumbnail': instance.imageThumbnail,
};
_$ExerciseSearchEntryImpl _$$ExerciseSearchEntryImplFromJson(Map<String, dynamic> json) =>
_$ExerciseSearchEntryImpl(
value: json['value'] as String,
data: ExerciseSearchDetails.fromJson(json['data'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$ExerciseSearchEntryImplToJson(_$ExerciseSearchEntryImpl instance) =>
<String, dynamic>{
'value': instance.value,
'data': instance.data,
};
_$ExerciseApiSearchImpl _$$ExerciseApiSearchImplFromJson(Map<String, dynamic> json) =>
_$ExerciseApiSearchImpl(
suggestions: (json['suggestions'] as List<dynamic>)
.map((e) => ExerciseSearchEntry.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$ExerciseApiSearchImplToJson(_$ExerciseApiSearchImpl instance) =>
<String, dynamic>{
'suggestions': instance.suggestions,
};

View File

@@ -0,0 +1,40 @@
import 'package:freezed_annotation/freezed_annotation.dart';
part 'ingredient_api.freezed.dart';
part 'ingredient_api.g.dart';
/// Model for the search results returned from the /api/v2/ingredient/search endpoint
@freezed
class IngredientApiSearchDetails with _$IngredientApiSearchDetails {
factory IngredientApiSearchDetails({
required int id,
required String name,
required String? image,
// ignore: invalid_annotation_target
@JsonKey(name: 'image_thumbnail') required String? imageThumbnail,
}) = _IngredientApiSearchDetails;
factory IngredientApiSearchDetails.fromJson(Map<String, dynamic> json) =>
_$IngredientApiSearchDetailsFromJson(json);
}
@freezed
class IngredientApiSearchEntry with _$IngredientApiSearchEntry {
factory IngredientApiSearchEntry({
required String value,
required IngredientApiSearchDetails data,
}) = _IngredientApiSearchEntry;
factory IngredientApiSearchEntry.fromJson(Map<String, dynamic> json) =>
_$IngredientApiSearchEntryFromJson(json);
}
@freezed
class IngredientApiSearch with _$IngredientApiSearch {
factory IngredientApiSearch({
required List<IngredientApiSearchEntry> suggestions,
}) = _IngredientApiSearch;
factory IngredientApiSearch.fromJson(Map<String, dynamic> json) =>
_$IngredientApiSearchFromJson(json);
}

View File

@@ -0,0 +1,533 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'ingredient_api.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
IngredientApiSearchDetails _$IngredientApiSearchDetailsFromJson(Map<String, dynamic> json) {
return _IngredientApiSearchDetails.fromJson(json);
}
/// @nodoc
mixin _$IngredientApiSearchDetails {
int get id => throw _privateConstructorUsedError;
String get name => throw _privateConstructorUsedError;
String? get image => throw _privateConstructorUsedError; // ignore: invalid_annotation_target
@JsonKey(name: 'image_thumbnail')
String? get imageThumbnail => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$IngredientApiSearchDetailsCopyWith<IngredientApiSearchDetails> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $IngredientApiSearchDetailsCopyWith<$Res> {
factory $IngredientApiSearchDetailsCopyWith(
IngredientApiSearchDetails value, $Res Function(IngredientApiSearchDetails) then) =
_$IngredientApiSearchDetailsCopyWithImpl<$Res, IngredientApiSearchDetails>;
@useResult
$Res call(
{int id,
String name,
String? image,
@JsonKey(name: 'image_thumbnail') String? imageThumbnail});
}
/// @nodoc
class _$IngredientApiSearchDetailsCopyWithImpl<$Res, $Val extends IngredientApiSearchDetails>
implements $IngredientApiSearchDetailsCopyWith<$Res> {
_$IngredientApiSearchDetailsCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? name = null,
Object? image = freezed,
Object? imageThumbnail = freezed,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
image: freezed == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as String?,
imageThumbnail: freezed == imageThumbnail
? _value.imageThumbnail
: imageThumbnail // ignore: cast_nullable_to_non_nullable
as String?,
) as $Val);
}
}
/// @nodoc
abstract class _$$IngredientApiSearchDetailsImplCopyWith<$Res>
implements $IngredientApiSearchDetailsCopyWith<$Res> {
factory _$$IngredientApiSearchDetailsImplCopyWith(_$IngredientApiSearchDetailsImpl value,
$Res Function(_$IngredientApiSearchDetailsImpl) then) =
__$$IngredientApiSearchDetailsImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
String name,
String? image,
@JsonKey(name: 'image_thumbnail') String? imageThumbnail});
}
/// @nodoc
class __$$IngredientApiSearchDetailsImplCopyWithImpl<$Res>
extends _$IngredientApiSearchDetailsCopyWithImpl<$Res, _$IngredientApiSearchDetailsImpl>
implements _$$IngredientApiSearchDetailsImplCopyWith<$Res> {
__$$IngredientApiSearchDetailsImplCopyWithImpl(_$IngredientApiSearchDetailsImpl _value,
$Res Function(_$IngredientApiSearchDetailsImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? name = null,
Object? image = freezed,
Object? imageThumbnail = freezed,
}) {
return _then(_$IngredientApiSearchDetailsImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
image: freezed == image
? _value.image
: image // ignore: cast_nullable_to_non_nullable
as String?,
imageThumbnail: freezed == imageThumbnail
? _value.imageThumbnail
: imageThumbnail // ignore: cast_nullable_to_non_nullable
as String?,
));
}
}
/// @nodoc
@JsonSerializable()
class _$IngredientApiSearchDetailsImpl implements _IngredientApiSearchDetails {
_$IngredientApiSearchDetailsImpl(
{required this.id,
required this.name,
required this.image,
@JsonKey(name: 'image_thumbnail') required this.imageThumbnail});
factory _$IngredientApiSearchDetailsImpl.fromJson(Map<String, dynamic> json) =>
_$$IngredientApiSearchDetailsImplFromJson(json);
@override
final int id;
@override
final String name;
@override
final String? image;
// ignore: invalid_annotation_target
@override
@JsonKey(name: 'image_thumbnail')
final String? imageThumbnail;
@override
String toString() {
return 'IngredientApiSearchDetails(id: $id, name: $name, image: $image, imageThumbnail: $imageThumbnail)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$IngredientApiSearchDetailsImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.name, name) || other.name == name) &&
(identical(other.image, image) || other.image == image) &&
(identical(other.imageThumbnail, imageThumbnail) ||
other.imageThumbnail == imageThumbnail));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, id, name, image, imageThumbnail);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$IngredientApiSearchDetailsImplCopyWith<_$IngredientApiSearchDetailsImpl> get copyWith =>
__$$IngredientApiSearchDetailsImplCopyWithImpl<_$IngredientApiSearchDetailsImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$IngredientApiSearchDetailsImplToJson(
this,
);
}
}
abstract class _IngredientApiSearchDetails implements IngredientApiSearchDetails {
factory _IngredientApiSearchDetails(
{required final int id,
required final String name,
required final String? image,
@JsonKey(name: 'image_thumbnail') required final String? imageThumbnail}) =
_$IngredientApiSearchDetailsImpl;
factory _IngredientApiSearchDetails.fromJson(Map<String, dynamic> json) =
_$IngredientApiSearchDetailsImpl.fromJson;
@override
int get id;
@override
String get name;
@override
String? get image;
@override // ignore: invalid_annotation_target
@JsonKey(name: 'image_thumbnail')
String? get imageThumbnail;
@override
@JsonKey(ignore: true)
_$$IngredientApiSearchDetailsImplCopyWith<_$IngredientApiSearchDetailsImpl> get copyWith =>
throw _privateConstructorUsedError;
}
IngredientApiSearchEntry _$IngredientApiSearchEntryFromJson(Map<String, dynamic> json) {
return _IngredientApiSearchEntry.fromJson(json);
}
/// @nodoc
mixin _$IngredientApiSearchEntry {
String get value => throw _privateConstructorUsedError;
IngredientApiSearchDetails get data => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$IngredientApiSearchEntryCopyWith<IngredientApiSearchEntry> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $IngredientApiSearchEntryCopyWith<$Res> {
factory $IngredientApiSearchEntryCopyWith(
IngredientApiSearchEntry value, $Res Function(IngredientApiSearchEntry) then) =
_$IngredientApiSearchEntryCopyWithImpl<$Res, IngredientApiSearchEntry>;
@useResult
$Res call({String value, IngredientApiSearchDetails data});
$IngredientApiSearchDetailsCopyWith<$Res> get data;
}
/// @nodoc
class _$IngredientApiSearchEntryCopyWithImpl<$Res, $Val extends IngredientApiSearchEntry>
implements $IngredientApiSearchEntryCopyWith<$Res> {
_$IngredientApiSearchEntryCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? value = null,
Object? data = null,
}) {
return _then(_value.copyWith(
value: null == value
? _value.value
: value // ignore: cast_nullable_to_non_nullable
as String,
data: null == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as IngredientApiSearchDetails,
) as $Val);
}
@override
@pragma('vm:prefer-inline')
$IngredientApiSearchDetailsCopyWith<$Res> get data {
return $IngredientApiSearchDetailsCopyWith<$Res>(_value.data, (value) {
return _then(_value.copyWith(data: value) as $Val);
});
}
}
/// @nodoc
abstract class _$$IngredientApiSearchEntryImplCopyWith<$Res>
implements $IngredientApiSearchEntryCopyWith<$Res> {
factory _$$IngredientApiSearchEntryImplCopyWith(_$IngredientApiSearchEntryImpl value,
$Res Function(_$IngredientApiSearchEntryImpl) then) =
__$$IngredientApiSearchEntryImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({String value, IngredientApiSearchDetails data});
@override
$IngredientApiSearchDetailsCopyWith<$Res> get data;
}
/// @nodoc
class __$$IngredientApiSearchEntryImplCopyWithImpl<$Res>
extends _$IngredientApiSearchEntryCopyWithImpl<$Res, _$IngredientApiSearchEntryImpl>
implements _$$IngredientApiSearchEntryImplCopyWith<$Res> {
__$$IngredientApiSearchEntryImplCopyWithImpl(
_$IngredientApiSearchEntryImpl _value, $Res Function(_$IngredientApiSearchEntryImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? value = null,
Object? data = null,
}) {
return _then(_$IngredientApiSearchEntryImpl(
value: null == value
? _value.value
: value // ignore: cast_nullable_to_non_nullable
as String,
data: null == data
? _value.data
: data // ignore: cast_nullable_to_non_nullable
as IngredientApiSearchDetails,
));
}
}
/// @nodoc
@JsonSerializable()
class _$IngredientApiSearchEntryImpl implements _IngredientApiSearchEntry {
_$IngredientApiSearchEntryImpl({required this.value, required this.data});
factory _$IngredientApiSearchEntryImpl.fromJson(Map<String, dynamic> json) =>
_$$IngredientApiSearchEntryImplFromJson(json);
@override
final String value;
@override
final IngredientApiSearchDetails data;
@override
String toString() {
return 'IngredientApiSearchEntry(value: $value, data: $data)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$IngredientApiSearchEntryImpl &&
(identical(other.value, value) || other.value == value) &&
(identical(other.data, data) || other.data == data));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, value, data);
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$IngredientApiSearchEntryImplCopyWith<_$IngredientApiSearchEntryImpl> get copyWith =>
__$$IngredientApiSearchEntryImplCopyWithImpl<_$IngredientApiSearchEntryImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$IngredientApiSearchEntryImplToJson(
this,
);
}
}
abstract class _IngredientApiSearchEntry implements IngredientApiSearchEntry {
factory _IngredientApiSearchEntry(
{required final String value,
required final IngredientApiSearchDetails data}) = _$IngredientApiSearchEntryImpl;
factory _IngredientApiSearchEntry.fromJson(Map<String, dynamic> json) =
_$IngredientApiSearchEntryImpl.fromJson;
@override
String get value;
@override
IngredientApiSearchDetails get data;
@override
@JsonKey(ignore: true)
_$$IngredientApiSearchEntryImplCopyWith<_$IngredientApiSearchEntryImpl> get copyWith =>
throw _privateConstructorUsedError;
}
IngredientApiSearch _$IngredientApiSearchFromJson(Map<String, dynamic> json) {
return _IngredientApiSearch.fromJson(json);
}
/// @nodoc
mixin _$IngredientApiSearch {
List<IngredientApiSearchEntry> get suggestions => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$IngredientApiSearchCopyWith<IngredientApiSearch> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $IngredientApiSearchCopyWith<$Res> {
factory $IngredientApiSearchCopyWith(
IngredientApiSearch value, $Res Function(IngredientApiSearch) then) =
_$IngredientApiSearchCopyWithImpl<$Res, IngredientApiSearch>;
@useResult
$Res call({List<IngredientApiSearchEntry> suggestions});
}
/// @nodoc
class _$IngredientApiSearchCopyWithImpl<$Res, $Val extends IngredientApiSearch>
implements $IngredientApiSearchCopyWith<$Res> {
_$IngredientApiSearchCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? suggestions = null,
}) {
return _then(_value.copyWith(
suggestions: null == suggestions
? _value.suggestions
: suggestions // ignore: cast_nullable_to_non_nullable
as List<IngredientApiSearchEntry>,
) as $Val);
}
}
/// @nodoc
abstract class _$$IngredientApiSearchImplCopyWith<$Res>
implements $IngredientApiSearchCopyWith<$Res> {
factory _$$IngredientApiSearchImplCopyWith(
_$IngredientApiSearchImpl value, $Res Function(_$IngredientApiSearchImpl) then) =
__$$IngredientApiSearchImplCopyWithImpl<$Res>;
@override
@useResult
$Res call({List<IngredientApiSearchEntry> suggestions});
}
/// @nodoc
class __$$IngredientApiSearchImplCopyWithImpl<$Res>
extends _$IngredientApiSearchCopyWithImpl<$Res, _$IngredientApiSearchImpl>
implements _$$IngredientApiSearchImplCopyWith<$Res> {
__$$IngredientApiSearchImplCopyWithImpl(
_$IngredientApiSearchImpl _value, $Res Function(_$IngredientApiSearchImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? suggestions = null,
}) {
return _then(_$IngredientApiSearchImpl(
suggestions: null == suggestions
? _value._suggestions
: suggestions // ignore: cast_nullable_to_non_nullable
as List<IngredientApiSearchEntry>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$IngredientApiSearchImpl implements _IngredientApiSearch {
_$IngredientApiSearchImpl({required final List<IngredientApiSearchEntry> suggestions})
: _suggestions = suggestions;
factory _$IngredientApiSearchImpl.fromJson(Map<String, dynamic> json) =>
_$$IngredientApiSearchImplFromJson(json);
final List<IngredientApiSearchEntry> _suggestions;
@override
List<IngredientApiSearchEntry> get suggestions {
if (_suggestions is EqualUnmodifiableListView) return _suggestions;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_suggestions);
}
@override
String toString() {
return 'IngredientApiSearch(suggestions: $suggestions)';
}
@override
bool operator ==(Object other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$IngredientApiSearchImpl &&
const DeepCollectionEquality().equals(other._suggestions, _suggestions));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(runtimeType, const DeepCollectionEquality().hash(_suggestions));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$IngredientApiSearchImplCopyWith<_$IngredientApiSearchImpl> get copyWith =>
__$$IngredientApiSearchImplCopyWithImpl<_$IngredientApiSearchImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$IngredientApiSearchImplToJson(
this,
);
}
}
abstract class _IngredientApiSearch implements IngredientApiSearch {
factory _IngredientApiSearch({required final List<IngredientApiSearchEntry> suggestions}) =
_$IngredientApiSearchImpl;
factory _IngredientApiSearch.fromJson(Map<String, dynamic> json) =
_$IngredientApiSearchImpl.fromJson;
@override
List<IngredientApiSearchEntry> get suggestions;
@override
@JsonKey(ignore: true)
_$$IngredientApiSearchImplCopyWith<_$IngredientApiSearchImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,50 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'ingredient_api.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$IngredientApiSearchDetailsImpl _$$IngredientApiSearchDetailsImplFromJson(
Map<String, dynamic> json) =>
_$IngredientApiSearchDetailsImpl(
id: json['id'] as int,
name: json['name'] as String,
image: json['image'] as String?,
imageThumbnail: json['image_thumbnail'] as String?,
);
Map<String, dynamic> _$$IngredientApiSearchDetailsImplToJson(
_$IngredientApiSearchDetailsImpl instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'image': instance.image,
'image_thumbnail': instance.imageThumbnail,
};
_$IngredientApiSearchEntryImpl _$$IngredientApiSearchEntryImplFromJson(Map<String, dynamic> json) =>
_$IngredientApiSearchEntryImpl(
value: json['value'] as String,
data: IngredientApiSearchDetails.fromJson(json['data'] as Map<String, dynamic>),
);
Map<String, dynamic> _$$IngredientApiSearchEntryImplToJson(
_$IngredientApiSearchEntryImpl instance) =>
<String, dynamic>{
'value': instance.value,
'data': instance.data,
};
_$IngredientApiSearchImpl _$$IngredientApiSearchImplFromJson(Map<String, dynamic> json) =>
_$IngredientApiSearchImpl(
suggestions: (json['suggestions'] as List<dynamic>)
.map((e) => IngredientApiSearchEntry.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$IngredientApiSearchImplToJson(_$IngredientApiSearchImpl instance) =>
<String, dynamic>{
'suggestions': instance.suggestions,
};

View File

@@ -649,12 +649,9 @@ class ExercisesProvider with ChangeNotifier {
),
);
// Process the response
return Future.wait(
(result['suggestions'] as List).map<Future<Exercise>>(
(entry) => fetchAndSetExercise(entry['data']['base_id']),
),
);
// Load the ingredients
final results = ExerciseApiSearch.fromJson(result);
return Future.wait(results.suggestions.map((e) => fetchAndSetExercise(e.data.exerciseId)));
}
}

View File

@@ -24,6 +24,7 @@ import 'package:shared_preferences/shared_preferences.dart';
import 'package:wger/exceptions/http_exception.dart';
import 'package:wger/exceptions/no_such_entry_exception.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/models/exercises/ingredient_api.dart';
import 'package:wger/models/nutrition/image.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/models/nutrition/log.dart';
@@ -331,7 +332,7 @@ class NutritionPlansProvider with ChangeNotifier {
}
/// Searches for an ingredient
Future<List> searchIngredient(
Future<List<IngredientApiSearchEntry>> searchIngredient(
String name, {
String languageCode = 'en',
bool searchEnglish = false,
@@ -352,7 +353,7 @@ class NutritionPlansProvider with ChangeNotifier {
);
// Process the response
return response['suggestions'];
return IngredientApiSearch.fromJson(response).suggestions;
}
/// Searches for an ingredient with code

View File

@@ -17,8 +17,7 @@
*/
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
//import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
import 'package:flutter/services.dart'; //import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:flutter_zxing/flutter_zxing.dart';
@@ -27,6 +26,7 @@ import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/helpers/platform.dart';
import 'package:wger/helpers/ui.dart';
import 'package:wger/models/exercises/ingredient_api.dart';
import 'package:wger/providers/nutrition.dart';
import 'package:wger/widgets/core/core.dart';
@@ -90,44 +90,56 @@ class _IngredientTypeaheadState extends State<IngredientTypeahead> {
Widget build(BuildContext context) {
return Column(
children: [
TypeAheadFormField(
textFieldConfiguration: TextFieldConfiguration(
controller: widget._ingredientController,
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search),
labelText: AppLocalizations.of(context).searchIngredient,
suffixIcon: (widget.showScanner && !isDesktop) ? scanButton() : null,
),
),
suggestionsCallback: (pattern) async {
TypeAheadField<IngredientApiSearchEntry>(
controller: widget._ingredientController,
builder: (context, controller, focusNode) {
return TextFormField(
controller: controller,
focusNode: focusNode,
autofocus: true,
validator: (value) {
if (value!.isEmpty) {
return AppLocalizations.of(context).selectIngredient;
}
return null;
},
decoration: InputDecoration(
prefixIcon: const Icon(Icons.search),
labelText: AppLocalizations.of(context).searchIngredient,
suffixIcon: (widget.showScanner && !isDesktop) ? scanButton() : null,
),
);
},
suggestionsCallback: (pattern) {
if (pattern == '') {
return null;
}
return Provider.of<NutritionPlansProvider>(context, listen: false).searchIngredient(
pattern,
languageCode: Localizations.localeOf(context).languageCode,
searchEnglish: _searchEnglish,
);
},
itemBuilder: (context, dynamic suggestion) {
itemBuilder: (context, suggestion) {
final url = context.read<NutritionPlansProvider>().baseProvider.auth.serverUrl;
return ListTile(
leading: suggestion['data']['image'] != null
? CircleAvatar(backgroundImage: NetworkImage(url! + suggestion['data']['image']))
leading: suggestion.data.image != null
? CircleAvatar(backgroundImage: NetworkImage(url! + suggestion.data.image!))
: const CircleIconAvatar(Icon(Icons.image, color: Colors.grey)),
title: Text(suggestion['value']),
subtitle: Text(suggestion['data']['id'].toString()),
title: Text(suggestion.value),
// subtitle: Text(suggestion.data.id.toString()),
);
},
transitionBuilder: (context, suggestionsBox, controller) {
return suggestionsBox;
},
onSuggestionSelected: (dynamic suggestion) {
widget._ingredientIdController.text = suggestion['data']['id'].toString();
widget._ingredientController.text = suggestion['value'];
},
validator: (value) {
if (value!.isEmpty) {
return AppLocalizations.of(context).selectIngredient;
}
return null;
transitionBuilder: (context, animation, child) => FadeTransition(
opacity: CurvedAnimation(parent: animation, curve: Curves.fastOutSlowIn),
child: child,
),
onSelected: (suggestion) {
//SuggestionsController.of(context).;
widget._ingredientIdController.text = suggestion.data.id.toString();
widget._ingredientController.text = suggestion.value;
},
),
if (Localizations.localeOf(context).languageCode != LANGUAGE_SHORT_ENGLISH)

View File

@@ -363,106 +363,126 @@ class _SetFormWidgetState extends State<SetFormWidget> {
Card(
child: Column(
children: [
TypeAheadFormField<Exercise>(
TypeAheadField<Exercise>(
key: const Key('field-typeahead'),
textFieldConfiguration: TextFieldConfiguration(
controller: _exercisesController,
decoration: InputDecoration(
labelText: AppLocalizations.of(context).searchExercise,
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
icon: const Icon(Icons.help),
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(AppLocalizations.of(context).selectExercises),
const SizedBox(height: 10),
Text(AppLocalizations.of(context).sameRepetitions)
decorationBuilder: (context, child) {
return Material(
type: MaterialType.card,
elevation: 4,
borderRadius: BorderRadius.circular(8),
child: child,
);
},
controller: _exercisesController,
builder: (context, controller, focusNode) {
return TextFormField(
controller: controller,
focusNode: focusNode,
// autofocus: true,
decoration: InputDecoration(
labelText: AppLocalizations.of(context).searchExercise,
prefixIcon: const Icon(Icons.search),
suffixIcon: IconButton(
icon: const Icon(Icons.help),
onPressed: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(AppLocalizations.of(context).selectExercises),
const SizedBox(height: 10),
Text(AppLocalizations.of(context).sameRepetitions)
],
),
actions: [
TextButton(
child: Text(
MaterialLocalizations.of(context).closeButtonLabel),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
actions: [
TextButton(
child: Text(
MaterialLocalizations.of(context).closeButtonLabel),
onPressed: () {
Navigator.of(context).pop();
},
),
],
),
);
},
);
},
),
errorMaxLines: 2,
border: InputBorder.none,
),
errorMaxLines: 2,
border: InputBorder.none,
),
),
validator: (value) {
// At least one exercise must be selected
if (widget._set.exerciseBasesIds.isEmpty) {
return AppLocalizations.of(context).selectExercise;
}
// At least one setting has to be filled in
if (widget._set.settings
.where((s) => s.weight == null && s.reps == null)
.length ==
widget._set.settings.length) {
return AppLocalizations.of(context).enterRepetitionsOrWeight;
}
return null;
},
);
},
suggestionsCallback: (pattern) {
if (pattern == '') {
return null;
}
return context.read<ExercisesProvider>().searchExercise(
pattern,
languageCode: Localizations.localeOf(context).languageCode,
searchEnglish: _searchEnglish,
);
},
itemBuilder: (BuildContext context, Exercise exerciseSuggestion) {
return ListTile(
leading: SizedBox(
width: 45,
child: ExerciseImageWidget(image: exerciseSuggestion.getMainImage),
),
title: Text(
exerciseSuggestion
.getExercise(Localizations.localeOf(context).languageCode)
.name,
),
subtitle: Text(
'${exerciseSuggestion.category!.name} / ${exerciseSuggestion.equipment.map((e) => e.name).join(', ')}',
),
);
},
noItemsFoundBuilder: (context) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(AppLocalizations.of(context).noMatchingExerciseFound),
TextButton(
itemBuilder: (BuildContext context, Exercise exerciseSuggestion) =>
ListTile(
key: Key('exercise-${exerciseSuggestion.id}'),
leading: SizedBox(
width: 45,
child: ExerciseImageWidget(image: exerciseSuggestion.getMainImage),
),
title: Text(
exerciseSuggestion
.getExercise(Localizations.localeOf(context).languageCode)
.name,
),
subtitle: Text(
'${exerciseSuggestion.category!.name} / ${exerciseSuggestion.equipment.map((e) => e.name).join(', ')}',
),
),
emptyBuilder: (context) {
return Column(
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
title: Text(AppLocalizations.of(context).noMatchingExerciseFound),
),
ListTile(
title: OutlinedButton(
onPressed: () {
Navigator.of(context).pushNamed(AddExerciseScreen.routeName);
},
child: Text(AppLocalizations.of(context).contributeExercise),
),
],
),
),
],
);
},
transitionBuilder: (context, suggestionsBox, controller) {
return suggestionsBox;
},
onSuggestionSelected: (Exercise exerciseSuggestion) {
transitionBuilder: (context, animation, child) => FadeTransition(
opacity: CurvedAnimation(parent: animation, curve: Curves.fastOutSlowIn),
child: child,
),
onSelected: (Exercise exerciseSuggestion) {
// SuggestionsController.of(context).select(exerciseSuggestion);
addExercise(exerciseSuggestion);
_exercisesController.text = '';
},
validator: (value) {
// At least one exercise must be selected
if (widget._set.exerciseBasesIds.isEmpty) {
return AppLocalizations.of(context).selectExercise;
}
// At least one setting has to be filled in
if (widget._set.settings
.where((s) => s.weight == null && s.reps == null)
.length ==
widget._set.settings.length) {
return AppLocalizations.of(context).enterRepetitionsOrWeight;
}
return null;
},
),
if (Localizations.localeOf(context).languageCode != LANGUAGE_SHORT_ENGLISH)
SwitchListTile(

View File

@@ -226,7 +226,7 @@ packages:
source: hosted
version: "0.4.1"
clock:
dependency: transitive
dependency: "direct main"
description:
name: clock
sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
@@ -537,10 +537,10 @@ packages:
dependency: "direct main"
description:
name: flutter_typeahead
sha256: ef2dd5a505d2d95a5b4c571c81ad2d6e7955f583dddec49064fec57acffd7a96
sha256: e2070dea278f09ae30885872138ccae75292b33b7af2c241fec5ceafd980c374
url: "https://pub.dev"
source: hosted
version: "5.0.2"
version: "5.1.0"
flutter_web_plugins:
dependency: transitive
description: flutter

View File

@@ -38,7 +38,7 @@ dependencies:
equatable: ^2.0.5
flutter_calendar_carousel: ^2.4.1
flutter_html: ^3.0.0-beta.2
flutter_typeahead: ^5.0.2
flutter_typeahead: ^5.1.0
font_awesome_flutter: ^10.4.0
http: ^1.2.0
image_picker: ^1.0.6

View File

@@ -93,9 +93,7 @@ void main() {
body: anyNamed('body'),
)).thenAnswer((_) => Future(() => Response(json.encode(responseLoginOk), 200)));
when(mockClient.get(
any,
)).thenAnswer((_) => Future(() => Response('"1.2.3.4"', 200)));
when(mockClient.get(any)).thenAnswer((_) => Future(() => Response('"1.2.3.4"', 200)));
when(mockClient.post(
tRegistration,

View File

@@ -76,7 +76,7 @@ void main() {
when(mockExerciseProvider.muscles).thenReturn(testMuscles);
when(mockExerciseProvider.equipment).thenReturn(testEquipment);
when(mockExerciseProvider.exerciseBasesByVariation).thenReturn({});
when(mockExerciseProvider.exercises).thenReturn(getTestExerciseBases());
when(mockExerciseProvider.exercises).thenReturn(getTestExercises());
when(mockExerciseProvider.languages).thenReturn(testLanguages);
when(mockAddExerciseProvider.equipment).thenReturn([]);

View File

@@ -50,7 +50,7 @@ void main() {
mockBaseProvider,
database: ExerciseDatabase.inMemory(NativeDatabase.memory()),
);
provider.exercises = getTestExerciseBases();
provider.exercises = getTestExercises();
provider.languages = [tLanguage1, tLanguage2, tLanguage3];
// Mock base info response

View File

@@ -223,7 +223,7 @@ void main() {
equipment: FilterCategory<Equipment>(title: 'Equipment', items: {}),
);
provider.exercises = data.getTestExerciseBases();
provider.exercises = data.getTestExercises();
});
test('Nothing is selected with no search term', () async {
@@ -238,7 +238,7 @@ void main() {
expect(
provider.filteredExercises,
data.getTestExerciseBases(),
data.getTestExercises(),
);
});
@@ -253,7 +253,7 @@ void main() {
// assert
verifyNever(provider.baseProvider.fetch(tSearchByNameUri));
expect(provider.filteredExercises, [data.getTestExerciseBases()[0]]);
expect(provider.filteredExercises, [data.getTestExercises()[0]]);
});
test('A muscle is selected with no search term. Should not find results', () async {
@@ -281,7 +281,7 @@ void main() {
// assert
verifyNever(provider.baseProvider.fetch(tSearchByNameUri));
expect(provider.filteredExercises, [data.getTestExerciseBases()[0]]);
expect(provider.filteredExercises, [data.getTestExercises()[0]]);
});
test('An equipment is selected with no search term. Should not find results', () async {
@@ -310,7 +310,7 @@ void main() {
// assert
verifyNever(provider.baseProvider.fetch(tSearchByNameUri));
expect(provider.filteredExercises, [data.getTestExerciseBases()[1]]);
expect(provider.filteredExercises, [data.getTestExercises()[1]]);
});
test('A muscle and equipment is selected but no match', () async {
@@ -365,7 +365,7 @@ void main() {
verify(provider.baseProvider.fetch(tSearchByNameUri)).called(1);
expect(
provider.filteredExercises,
[data.getTestExerciseBases()[0], data.getTestExerciseBases()[1]],
[data.getTestExercises()[0], data.getTestExercises()[1]],
);
});
test('Should find items from selection but should filter them by search term', () async {

View File

@@ -38,7 +38,7 @@ void main() {
supportedLocales: AppLocalizations.supportedLocales,
navigatorKey: GlobalKey<NavigatorState>(),
home: Scaffold(
body: ExerciseDetail(getTestExerciseBases()[0]),
body: ExerciseDetail(getTestExercises()[0]),
),
),
);

View File

@@ -14,7 +14,7 @@ void main() {
group('Model tests', () {
test('test getExercise', () async {
// arrange and act
final base = getTestExerciseBases()[1];
final base = getTestExercises()[1];
// assert
expect(base.getExercise('en').id, 5);

View File

@@ -4,9 +4,10 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i8;
import 'dart:ui' as _i9;
import 'dart:ui' as _i10;
import 'package:mockito/mockito.dart' as _i1;
import 'package:wger/models/exercises/ingredient_api.dart' as _i9;
import 'package:wger/models/nutrition/ingredient.dart' as _i6;
import 'package:wger/models/nutrition/meal.dart' as _i4;
import 'package:wger/models/nutrition/meal_item.dart' as _i5;
@@ -341,7 +342,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i7.NutritionPlansP
) as _i8.Future<void>);
@override
_i8.Future<List<dynamic>> searchIngredient(
_i8.Future<List<_i9.IngredientApiSearchEntry>> searchIngredient(
String? name, {
String? languageCode = r'en',
bool? searchEnglish = false,
@@ -355,8 +356,9 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i7.NutritionPlansP
#searchEnglish: searchEnglish,
},
),
returnValue: _i8.Future<List<dynamic>>.value(<dynamic>[]),
) as _i8.Future<List<dynamic>>);
returnValue:
_i8.Future<List<_i9.IngredientApiSearchEntry>>.value(<_i9.IngredientApiSearchEntry>[]),
) as _i8.Future<List<_i9.IngredientApiSearchEntry>>);
@override
_i8.Future<_i6.Ingredient?> searchIngredientWithCode(String? code) => (super.noSuchMethod(
@@ -424,7 +426,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i7.NutritionPlansP
) as _i8.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i10.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@@ -433,7 +435,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i7.NutritionPlansP
);
@override
void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i10.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View File

@@ -9,6 +9,7 @@ import 'package:http/http.dart' as http;
import 'package:mockito/mockito.dart';
import 'package:provider/provider.dart';
import 'package:wger/helpers/consts.dart';
import 'package:wger/models/exercises/ingredient_api.dart';
import 'package:wger/models/nutrition/ingredient.dart';
import 'package:wger/models/nutrition/meal.dart';
import 'package:wger/models/nutrition/meal_item.dart';
@@ -76,8 +77,13 @@ void main() {
when(mockNutrition.searchIngredientWithCode('123')).thenAnswer((_) => Future.value(ingredient));
when(mockNutrition.searchIngredientWithCode('')).thenAnswer((_) => Future.value(null));
when(mockNutrition.searchIngredientWithCode('222')).thenAnswer((_) => Future.value(null));
when(mockNutrition.searchIngredient(any)).thenAnswer((_) =>
Future.value(json.decode(fixture('nutrition/ingredient_suggestions')) as List<dynamic>));
when(mockNutrition.searchIngredient(any,
languageCode: anyNamed('languageCode'), searchEnglish: anyNamed('searchEnglish')))
.thenAnswer(
(_) => Future.value(
IngredientApiSearch.fromJson(json.decode(fixture('nutrition/ingredient_suggestions')))
.suggestions),
);
when(mockNutrition.addMealItem(any, meal1)).thenAnswer((_) => Future.value(mealItem));
});
@@ -109,8 +115,8 @@ void main() {
await tester.pumpWidget(createMealItemFormScreen(meal1, '', true));
await tester.pumpAndSettle();
expect(find.byType(TypeAheadFormField), findsOneWidget);
expect(find.byType(TextFormField), findsOneWidget);
expect(find.byType(TypeAheadField<IngredientApiSearchEntry>), findsOneWidget);
expect(find.byType(TextFormField), findsWidgets);
expect(find.byKey(const Key('scan-button')), findsOneWidget);
expect(find.byKey(const Key(SUBMIT_BUTTON_KEY_NAME)), findsOneWidget);
@@ -248,6 +254,8 @@ void main() {
});
testWidgets('save ingredient without weight', (WidgetTester tester) async {
await tester.binding.setSurfaceSize(const Size(1080, 1920));
tester.view.devicePixelRatio = 1.0;
await tester.pumpWidget(createMealItemFormScreen(meal1, '123', true));
await tester.tap(find.byKey(const Key('scan-button')));

View File

@@ -4,9 +4,10 @@
// ignore_for_file: no_leading_underscores_for_library_prefixes
import 'dart:async' as _i8;
import 'dart:ui' as _i9;
import 'dart:ui' as _i10;
import 'package:mockito/mockito.dart' as _i1;
import 'package:wger/models/exercises/ingredient_api.dart' as _i9;
import 'package:wger/models/nutrition/ingredient.dart' as _i6;
import 'package:wger/models/nutrition/meal.dart' as _i4;
import 'package:wger/models/nutrition/meal_item.dart' as _i5;
@@ -341,7 +342,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i7.NutritionPlansP
) as _i8.Future<void>);
@override
_i8.Future<List<dynamic>> searchIngredient(
_i8.Future<List<_i9.IngredientApiSearchEntry>> searchIngredient(
String? name, {
String? languageCode = r'en',
bool? searchEnglish = false,
@@ -355,8 +356,9 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i7.NutritionPlansP
#searchEnglish: searchEnglish,
},
),
returnValue: _i8.Future<List<dynamic>>.value(<dynamic>[]),
) as _i8.Future<List<dynamic>>);
returnValue:
_i8.Future<List<_i9.IngredientApiSearchEntry>>.value(<_i9.IngredientApiSearchEntry>[]),
) as _i8.Future<List<_i9.IngredientApiSearchEntry>>);
@override
_i8.Future<_i6.Ingredient?> searchIngredientWithCode(String? code) => (super.noSuchMethod(
@@ -424,7 +426,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i7.NutritionPlansP
) as _i8.Future<void>);
@override
void addListener(_i9.VoidCallback? listener) => super.noSuchMethod(
void addListener(_i10.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#addListener,
[listener],
@@ -433,7 +435,7 @@ class MockNutritionPlansProvider extends _i1.Mock implements _i7.NutritionPlansP
);
@override
void removeListener(_i9.VoidCallback? listener) => super.noSuchMethod(
void removeListener(_i10.VoidCallback? listener) => super.noSuchMethod(
Invocation.method(
#removeListener,
[listener],

View File

@@ -41,7 +41,7 @@ void main() {
final mockExerciseProvider = MockExercisesProvider();
final workoutPlan = getWorkout();
final bases = getTestExerciseBases();
final bases = getTestExercises();
Widget createHomeScreen({locale = 'en'}) {
return ChangeNotifierProvider<WorkoutPlansProvider>(

View File

@@ -27,16 +27,16 @@ void main() {
final workout = getWorkout();
expect(workout.logs.length, 3);
final logExercise1 = workout.filterLogsByExerciseBase(getTestExerciseBases()[0]);
final logExercise1 = workout.filterLogsByExerciseBase(getTestExercises()[0]);
expect(logExercise1.length, 2);
expect(logExercise1[0].id, 1);
expect(logExercise1[1].id, 2);
final logExercise2 = workout.filterLogsByExerciseBase(getTestExerciseBases()[1]);
final logExercise2 = workout.filterLogsByExerciseBase(getTestExercises()[1]);
expect(logExercise2.length, 1);
expect(logExercise2[0].id, 3);
expect(workout.filterLogsByExerciseBase(getTestExerciseBases()[2]).length, 0);
expect(workout.filterLogsByExerciseBase(getTestExercises()[2]).length, 0);
});
});
}

View File

@@ -31,6 +31,7 @@ import 'package:wger/providers/exercises.dart';
import 'package:wger/providers/workout_plans.dart';
import 'package:wger/widgets/workouts/forms.dart';
import '../../test_data/exercises.dart';
import '../../test_data/workouts.dart';
import 'workout_set_form_test.mocks.dart';
@@ -84,6 +85,13 @@ void main() {
when(mockWorkoutPlans.addSet(any)).thenAnswer((_) => Future.value(Set.empty()));
when(mockWorkoutPlans.addSetting(any)).thenAnswer((_) => Future.value(Setting.empty()));
when(mockWorkoutPlans.fetchSmartText(any, any)).thenAnswer((_) => Future.value('2 x 10'));
when(mockExerciseProvider.searchExercise(
any,
languageCode: anyNamed('languageCode'),
searchEnglish: anyNamed('searchEnglish'),
)).thenAnswer(
(_) => Future.value([getTestExercises().first]),
);
await tester.pumpWidget(createHomeScreen());
await tester.pumpAndSettle();
@@ -91,6 +99,7 @@ void main() {
await tester.enterText(find.byKey(const Key('field-typeahead')), 'exercise');
await tester.pumpAndSettle();
//await tester.tap(find.byKey(const Key('exercise-1')));
await tester.tap(find.byKey(const Key(SUBMIT_BUTTON_KEY_NAME)));
//verify(mockWorkoutPlans.addSet(any));

View File

@@ -203,7 +203,7 @@ final sideRaisesEn = Translation(
language: tLanguage2,
);
List<Exercise> getTestExerciseBases() {
List<Exercise> getTestExercises() {
benchPress.translations = [benchPressEn, benchPressDe];
crunches.translations = [crunchesEn, crunchesDe, crunchesFr];
deadLift.translations = [deadLiftEn];

View File

@@ -210,8 +210,7 @@ final benchPressDE = Translation(
uuid: '198dcb2e-e35f-4b69-ae8b-e1124d438eae',
created: DateTime(2021, 1, 15),
name: 'Bankdrücken LH',
description:
'''
description: '''
<p>Lege dich auf die Bank, die Stange direkt über die Augen, die Knie etwas angewinkelt und die Füße fest auf dem Boden. Greife die Stange breit und lasse sie langsam und kontrolliert runter, dabei sollte die Stange kurz auf Brustwarzenhöhe den Körper berühren. Dann das Gewicht wieder hochdrücken bis die Arme durchgestreckt sind.</p>
<p>Bei hohem Gewicht, empfielt sich natürlich einen <em>Spotter</em> zu haben, der einen hilft falls man die Stange nicht alleine hochdrücken kann.</p>
<p>Mit der Breite des Griffs kann außerdem kontrolliert werden, welcher Bereich der Brust stärker belastet wird:</p>
@@ -228,8 +227,7 @@ final benchPressEN = Translation(
uuid: '5da6340b-22ec-4c1b-a443-eef2f59f92f0',
created: DateTime(2021, 1, 15),
name: 'Bench Press',
description:
'''
description: '''
<p>Lay down on a bench, the bar should be directly above your eyes, the knees are somewhat angled and the feet are firmly on the floor. Concentrate, breath deeply and grab the bar more than shoulder wide. Bring it slowly down till it briefly touches your chest at the height of your nipples. Push the bar up.</p>
<p>If you train with a high weight it is advisable to have a <em>spotter</em> that can help you up if you can't lift the weight on your own.</p>
<p>With the width of the grip you can also control which part of the chest is trained more:</p>
@@ -258,8 +256,7 @@ final deadLiftEN = Translation(
uuid: '22cca8fc-cfaf-4941-b0f7-faf9f2937c52',
created: DateTime(2021, 1, 15),
name: 'Deadlifts',
description:
'''
description: '''
<p>Stand firmly, with your feet slightly more than shoulder wide apart. Stand directly behind the bar where it should barely touch your shin, your feet pointing a bit out. Bend down with a straight back, the knees also pointing somewhat out. Grab the bar with a shoulder wide grip, one underhand, one reverse grip.</p>
<p>Pull the weight up. At the highest point make a slight hollow back and pull the bar back. Hold 1 or 2 seconds that position. Go down, making sure the back is not bent. Once down you can either go back again as soon as the weights touch the floor, or make a pause, depending on the weight.</p>''',
exerciseId: 184,
@@ -271,8 +268,7 @@ final deadLiftDE = Translation(
uuid: '521a5e4f-6f35-43e5-9d1c-6e75c4956e96',
created: DateTime(2021, 1, 15),
name: 'Kreuzheben',
description:
'''
description: '''
<p>Stelle dich mit etwas mehr als schulterbreitem Stand vor der Stange, die Füße zeigen leicht nach außen, die Stange ist direkt darüber und sehr nahe am Schienbein. Beuge die Knie (zeigen ebenfalls etwas nach außen) und neige den Oberkörper (bleibt während der ganzen Übung gerade). Greife die Stange schulterbreit mit einem Unter- und einem Obergriff.</p>
<p>Ziehe nun die Stange nach oben. An der höchsten Stelle mache ein leichtes Hohlkreuz und drücke die Schultern nach hinten. Gehe wieder runter, wobei du darauf achtest, dass der Rücken gerade bleibt und sich nicht krümmt. Du kannst unten angekommen eine kleine Pause einlegen oder sofort weitermachen.</p>''',
exerciseId: 184,
@@ -284,8 +280,7 @@ final deadLiftPT = Translation(
uuid: 'e570cd82-5a8f-4768-a2f3-8d60bad5c6e8',
created: DateTime(2021, 1, 15),
name: 'Levantamento terra',
description:
'''
description: '''
Fique firme, com os pés ligeiramente mais afastados do que os ombros. Fique diretamente atrás da barra, onde ela mal deve tocar sua canela, com os pés apontando um pouco para fora. Curve-se com as costas retas, os joelhos também apontando um pouco para fora. Agarre a barra com uma pegada na largura dos ombros, uma pegada por baixo e uma pegada reversa.
Puxe o peso para cima. No ponto mais alto, faça uma leve depressão para trás e puxe a barra para trás. Segure 1 ou 2 segundos nessa posição. Desça, certificando-se de que as costas não estão dobradas. Depois de descer, você pode voltar assim que os pesos tocarem o chão ou fazer uma pausa, dependendo do peso.''',
@@ -378,8 +373,7 @@ final crunchesDE = Translation(
uuid: '0e10ac9b-ed1d-42c9-b8cc-123c22ccc5d5',
created: DateTime(2021, 1, 15),
name: 'Crunches',
description:
'''
description: '''
<p>Lege dich auf eine Matte mit angewinkelten Beinen. Die Füße werden irgendwie festgehalten (Partner, Lanhghantel, o.Ä.) und die Hände werden hinter dem Nacken verschränkt. Aus dieser Position führe den Oberkörper so weit nach oben, bis Kopf oder Ellenbogen die angewinkelten Beine berühren.</p>
<p>Es ist wichtig, dass dieser Vorgang mit einer rollenden Bewegung durchgeführt wird: die Wirbelsäule sollte sich Wirbel für Wirbel von der Matte lösen. Ein Hohlkreuz ist stets zu vermeiden.</p>''',
exerciseId: 167,
@@ -506,8 +500,7 @@ final curlsEN = Translation(
uuid: '48a59aa8-4568-409c-8afe-f8cb99c558ea',
created: DateTime(2021, 1, 15),
name: 'Biceps Curls With Dumbbell',
description:
'''
description: '''
<p>Hold two barbells, the arms are streched, the hands are on your side, the palms face inwards. Bend the arms and bring the weight with a fast movement up. At the same time, rotate your arms by 90 degrees at the very beginning of the movement. At the highest point, rotate a little the weights further outwards. Without a pause, bring them down, slowly.</p>
<p>Don't allow your body to swing during the exercise, all work is done by the biceps, which are the only mucles that should move (pay attention to the elbows).</p>''',
exerciseId: 92,
@@ -519,8 +512,7 @@ final curlsDE = Translation(
uuid: '8cbbffcc-1989-43de-9200-03869480398c',
created: DateTime(2021, 1, 15),
name: 'Bizeps KH-Curls',
description:
'''
description: '''
<p>Halte zwei Kurzhantel mit ausgestreckten Armen neben dem Körper, die Handflächen zeigen nach innen. Beuge die Arme und brige die Hanteln mit einer schnellen Bewegung nach oben wobei sie gleichzeitig um 90 Grad gedreht werden. Am höchsten Punkt kann man die Hanteln ganz leicht weiter nach außen drehen. Ohne Pause wird das Gewicht nun kontrolliert nach unten gebracht. Beachte, dass die Bewegung nach oben schneller ist als nach unten.</p>
<p>Während des Bewegungablaufs darf der Körper nicht mitschwingen. Die Ellenbogen bleiben dabei immer an der Stelle.</p>''',
exerciseId: 92,

View File

@@ -34,7 +34,7 @@ const RepetitionUnit repetitionUnit1 = RepetitionUnit(id: 1, name: 'Repetitions'
const RepetitionUnit repetitionUnit2 = RepetitionUnit(id: 2, name: 'Hours');
WorkoutPlan getWorkout({List<Exercise>? exercises}) {
final testBases = exercises ?? getTestExerciseBases();
final testBases = exercises ?? getTestExercises();
final log1 = Log.empty()
..id = 1