mirror of
https://github.com/wger-project/flutter.git
synced 2026-02-18 00:17:48 +01:00
Rework exercise database
This is now separated into individual tables and methods so that they can be tested separately
This commit is contained in:
@@ -20,8 +20,8 @@ Widget createGymModeScreen({locale = 'en'}) {
|
||||
|
||||
final mockExerciseProvider = MockExercisesProvider();
|
||||
|
||||
when(mockExerciseProvider.findExerciseBaseById(1)).thenReturn(bases[0]); // bench press
|
||||
when(mockExerciseProvider.findExerciseBaseById(6)).thenReturn(bases[5]); // side raises
|
||||
when(mockExerciseProvider.findExerciseById(1)).thenReturn(bases[0]); // bench press
|
||||
when(mockExerciseProvider.findExerciseById(6)).thenReturn(bases[5]); // side raises
|
||||
//when(mockExerciseProvider.findExerciseBaseById(2)).thenReturn(bases[1]); // crunches
|
||||
//when(mockExerciseProvider.findExerciseBaseById(3)).thenReturn(bases[2]); // dead lift
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:wger/database/exercise_DB/exercise_database.dart';
|
||||
import 'package:wger/database/exercises/exercise_database.dart';
|
||||
import 'package:wger/database/ingredients/ingredients_database.dart';
|
||||
|
||||
final locator = GetIt.asNewInstance();
|
||||
|
||||
@@ -14,7 +15,9 @@ class ServiceLocator {
|
||||
|
||||
Future<void> _initDB() async {
|
||||
final exerciseDB = ExerciseDatabase();
|
||||
final ingredientDB = IngredientDatabase();
|
||||
locator.registerSingleton<ExerciseDatabase>(exerciseDB);
|
||||
locator.registerSingleton<IngredientDatabase>(ingredientDB);
|
||||
}
|
||||
|
||||
Future<void> configure() async {
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:wger/database/exercise_DB/type_converters.dart';
|
||||
import 'package:wger/models/exercises/base.dart';
|
||||
import 'package:wger/models/exercises/category.dart';
|
||||
import 'package:wger/models/exercises/equipment.dart';
|
||||
import 'package:wger/models/exercises/language.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
import 'package:wger/models/exercises/variation.dart';
|
||||
|
||||
part 'exercise_database.g.dart';
|
||||
|
||||
@DataClassName('ExerciseTable')
|
||||
class ExerciseTableItems extends Table {
|
||||
IntColumn get id => integer().autoIncrement()();
|
||||
TextColumn get exercisebase => text().map(const ExerciseBaseConverter()).nullable()();
|
||||
TextColumn get muscle => text().map(const MuscleConverter()).nullable()();
|
||||
TextColumn get category => text().map(const ExerciseCategoryConverter()).nullable()();
|
||||
TextColumn get variation => text().map(const VariationConverter()).nullable()();
|
||||
TextColumn get language => text().map(const LanguageConverter()).nullable()();
|
||||
TextColumn get equipment => text().map(const EquipmentConverter()).nullable()();
|
||||
DateTimeColumn get expiresIn => dateTime().nullable()();
|
||||
}
|
||||
|
||||
@DriftDatabase(tables: [ExerciseTableItems])
|
||||
class ExerciseDatabase extends _$ExerciseDatabase {
|
||||
ExerciseDatabase() : super(_openConnection());
|
||||
|
||||
@override
|
||||
// TODO: implement schemaVersion
|
||||
int get schemaVersion => 1;
|
||||
}
|
||||
|
||||
LazyDatabase _openConnection() {
|
||||
return LazyDatabase(() async {
|
||||
final dbFolder = await getApplicationDocumentsDirectory();
|
||||
final file = File(p.join(dbFolder.path, 'db.sqlite'));
|
||||
return NativeDatabase.createInBackground(file);
|
||||
});
|
||||
}
|
||||
@@ -1,423 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'exercise_database.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
class $ExerciseTableItemsTable extends ExerciseTableItems
|
||||
with TableInfo<$ExerciseTableItemsTable, ExerciseTable> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$ExerciseTableItemsTable(this.attachedDatabase, [this._alias]);
|
||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>('id', aliasedName, false,
|
||||
hasAutoIncrement: true,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints: GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
|
||||
static const VerificationMeta _exercisebaseMeta = const VerificationMeta('exercisebase');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<ExerciseBase?, String> exercisebase =
|
||||
GeneratedColumn<String>('exercisebase', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false)
|
||||
.withConverter<ExerciseBase?>($ExerciseTableItemsTable.$converterexercisebasen);
|
||||
static const VerificationMeta _muscleMeta = const VerificationMeta('muscle');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<Muscle?, String> muscle = GeneratedColumn<String>(
|
||||
'muscle', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false)
|
||||
.withConverter<Muscle?>($ExerciseTableItemsTable.$convertermusclen);
|
||||
static const VerificationMeta _categoryMeta = const VerificationMeta('category');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<ExerciseCategory?, String> category =
|
||||
GeneratedColumn<String>('category', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false)
|
||||
.withConverter<ExerciseCategory?>($ExerciseTableItemsTable.$convertercategoryn);
|
||||
static const VerificationMeta _variationMeta = const VerificationMeta('variation');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<Variation?, String> variation =
|
||||
GeneratedColumn<String>('variation', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false)
|
||||
.withConverter<Variation?>($ExerciseTableItemsTable.$convertervariationn);
|
||||
static const VerificationMeta _languageMeta = const VerificationMeta('language');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<Language?, String> language = GeneratedColumn<String>(
|
||||
'language', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false)
|
||||
.withConverter<Language?>($ExerciseTableItemsTable.$converterlanguagen);
|
||||
static const VerificationMeta _equipmentMeta = const VerificationMeta('equipment');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<Equipment?, String> equipment =
|
||||
GeneratedColumn<String>('equipment', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false)
|
||||
.withConverter<Equipment?>($ExerciseTableItemsTable.$converterequipmentn);
|
||||
static const VerificationMeta _expiresInMeta = const VerificationMeta('expiresIn');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime> expiresIn = GeneratedColumn<DateTime>(
|
||||
'expires_in', aliasedName, true,
|
||||
type: DriftSqlType.dateTime, requiredDuringInsert: false);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns =>
|
||||
[id, exercisebase, muscle, category, variation, language, equipment, expiresIn];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'exercise_table_items';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<ExerciseTable> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
context.handle(_exercisebaseMeta, const VerificationResult.success());
|
||||
context.handle(_muscleMeta, const VerificationResult.success());
|
||||
context.handle(_categoryMeta, const VerificationResult.success());
|
||||
context.handle(_variationMeta, const VerificationResult.success());
|
||||
context.handle(_languageMeta, const VerificationResult.success());
|
||||
context.handle(_equipmentMeta, const VerificationResult.success());
|
||||
if (data.containsKey('expires_in')) {
|
||||
context.handle(
|
||||
_expiresInMeta, expiresIn.isAcceptableOrUnknown(data['expires_in']!, _expiresInMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
ExerciseTable map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return ExerciseTable(
|
||||
id: attachedDatabase.typeMapping.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
exercisebase: $ExerciseTableItemsTable.$converterexercisebasen.fromSql(attachedDatabase
|
||||
.typeMapping
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}exercisebase'])),
|
||||
muscle: $ExerciseTableItemsTable.$convertermusclen.fromSql(
|
||||
attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}muscle'])),
|
||||
category: $ExerciseTableItemsTable.$convertercategoryn.fromSql(attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}category'])),
|
||||
variation: $ExerciseTableItemsTable.$convertervariationn.fromSql(attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}variation'])),
|
||||
language: $ExerciseTableItemsTable.$converterlanguagen.fromSql(attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}language'])),
|
||||
equipment: $ExerciseTableItemsTable.$converterequipmentn.fromSql(attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}equipment'])),
|
||||
expiresIn: attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.dateTime, data['${effectivePrefix}expires_in']),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$ExerciseTableItemsTable createAlias(String alias) {
|
||||
return $ExerciseTableItemsTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<ExerciseBase, String> $converterexercisebase = const ExerciseBaseConverter();
|
||||
static TypeConverter<ExerciseBase?, String?> $converterexercisebasen =
|
||||
NullAwareTypeConverter.wrap($converterexercisebase);
|
||||
static TypeConverter<Muscle, String> $convertermuscle = const MuscleConverter();
|
||||
static TypeConverter<Muscle?, String?> $convertermusclen =
|
||||
NullAwareTypeConverter.wrap($convertermuscle);
|
||||
static TypeConverter<ExerciseCategory, String> $convertercategory =
|
||||
const ExerciseCategoryConverter();
|
||||
static TypeConverter<ExerciseCategory?, String?> $convertercategoryn =
|
||||
NullAwareTypeConverter.wrap($convertercategory);
|
||||
static TypeConverter<Variation, String> $convertervariation = const VariationConverter();
|
||||
static TypeConverter<Variation?, String?> $convertervariationn =
|
||||
NullAwareTypeConverter.wrap($convertervariation);
|
||||
static TypeConverter<Language, String> $converterlanguage = const LanguageConverter();
|
||||
static TypeConverter<Language?, String?> $converterlanguagen =
|
||||
NullAwareTypeConverter.wrap($converterlanguage);
|
||||
static TypeConverter<Equipment, String> $converterequipment = const EquipmentConverter();
|
||||
static TypeConverter<Equipment?, String?> $converterequipmentn =
|
||||
NullAwareTypeConverter.wrap($converterequipment);
|
||||
}
|
||||
|
||||
class ExerciseTable extends DataClass implements Insertable<ExerciseTable> {
|
||||
final int id;
|
||||
final ExerciseBase? exercisebase;
|
||||
final Muscle? muscle;
|
||||
final ExerciseCategory? category;
|
||||
final Variation? variation;
|
||||
final Language? language;
|
||||
final Equipment? equipment;
|
||||
final DateTime? expiresIn;
|
||||
const ExerciseTable(
|
||||
{required this.id,
|
||||
this.exercisebase,
|
||||
this.muscle,
|
||||
this.category,
|
||||
this.variation,
|
||||
this.language,
|
||||
this.equipment,
|
||||
this.expiresIn});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
if (!nullToAbsent || exercisebase != null) {
|
||||
final converter = $ExerciseTableItemsTable.$converterexercisebasen;
|
||||
map['exercisebase'] = Variable<String>(converter.toSql(exercisebase));
|
||||
}
|
||||
if (!nullToAbsent || muscle != null) {
|
||||
final converter = $ExerciseTableItemsTable.$convertermusclen;
|
||||
map['muscle'] = Variable<String>(converter.toSql(muscle));
|
||||
}
|
||||
if (!nullToAbsent || category != null) {
|
||||
final converter = $ExerciseTableItemsTable.$convertercategoryn;
|
||||
map['category'] = Variable<String>(converter.toSql(category));
|
||||
}
|
||||
if (!nullToAbsent || variation != null) {
|
||||
final converter = $ExerciseTableItemsTable.$convertervariationn;
|
||||
map['variation'] = Variable<String>(converter.toSql(variation));
|
||||
}
|
||||
if (!nullToAbsent || language != null) {
|
||||
final converter = $ExerciseTableItemsTable.$converterlanguagen;
|
||||
map['language'] = Variable<String>(converter.toSql(language));
|
||||
}
|
||||
if (!nullToAbsent || equipment != null) {
|
||||
final converter = $ExerciseTableItemsTable.$converterequipmentn;
|
||||
map['equipment'] = Variable<String>(converter.toSql(equipment));
|
||||
}
|
||||
if (!nullToAbsent || expiresIn != null) {
|
||||
map['expires_in'] = Variable<DateTime>(expiresIn);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
ExerciseTableItemsCompanion toCompanion(bool nullToAbsent) {
|
||||
return ExerciseTableItemsCompanion(
|
||||
id: Value(id),
|
||||
exercisebase:
|
||||
exercisebase == null && nullToAbsent ? const Value.absent() : Value(exercisebase),
|
||||
muscle: muscle == null && nullToAbsent ? const Value.absent() : Value(muscle),
|
||||
category: category == null && nullToAbsent ? const Value.absent() : Value(category),
|
||||
variation: variation == null && nullToAbsent ? const Value.absent() : Value(variation),
|
||||
language: language == null && nullToAbsent ? const Value.absent() : Value(language),
|
||||
equipment: equipment == null && nullToAbsent ? const Value.absent() : Value(equipment),
|
||||
expiresIn: expiresIn == null && nullToAbsent ? const Value.absent() : Value(expiresIn),
|
||||
);
|
||||
}
|
||||
|
||||
factory ExerciseTable.fromJson(Map<String, dynamic> json, {ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return ExerciseTable(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
exercisebase: serializer.fromJson<ExerciseBase?>(json['exercisebase']),
|
||||
muscle: serializer.fromJson<Muscle?>(json['muscle']),
|
||||
category: serializer.fromJson<ExerciseCategory?>(json['category']),
|
||||
variation: serializer.fromJson<Variation?>(json['variation']),
|
||||
language: serializer.fromJson<Language?>(json['language']),
|
||||
equipment: serializer.fromJson<Equipment?>(json['equipment']),
|
||||
expiresIn: serializer.fromJson<DateTime?>(json['expiresIn']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'exercisebase': serializer.toJson<ExerciseBase?>(exercisebase),
|
||||
'muscle': serializer.toJson<Muscle?>(muscle),
|
||||
'category': serializer.toJson<ExerciseCategory?>(category),
|
||||
'variation': serializer.toJson<Variation?>(variation),
|
||||
'language': serializer.toJson<Language?>(language),
|
||||
'equipment': serializer.toJson<Equipment?>(equipment),
|
||||
'expiresIn': serializer.toJson<DateTime?>(expiresIn),
|
||||
};
|
||||
}
|
||||
|
||||
ExerciseTable copyWith(
|
||||
{int? id,
|
||||
Value<ExerciseBase?> exercisebase = const Value.absent(),
|
||||
Value<Muscle?> muscle = const Value.absent(),
|
||||
Value<ExerciseCategory?> category = const Value.absent(),
|
||||
Value<Variation?> variation = const Value.absent(),
|
||||
Value<Language?> language = const Value.absent(),
|
||||
Value<Equipment?> equipment = const Value.absent(),
|
||||
Value<DateTime?> expiresIn = const Value.absent()}) =>
|
||||
ExerciseTable(
|
||||
id: id ?? this.id,
|
||||
exercisebase: exercisebase.present ? exercisebase.value : this.exercisebase,
|
||||
muscle: muscle.present ? muscle.value : this.muscle,
|
||||
category: category.present ? category.value : this.category,
|
||||
variation: variation.present ? variation.value : this.variation,
|
||||
language: language.present ? language.value : this.language,
|
||||
equipment: equipment.present ? equipment.value : this.equipment,
|
||||
expiresIn: expiresIn.present ? expiresIn.value : this.expiresIn,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('ExerciseTable(')
|
||||
..write('id: $id, ')
|
||||
..write('exercisebase: $exercisebase, ')
|
||||
..write('muscle: $muscle, ')
|
||||
..write('category: $category, ')
|
||||
..write('variation: $variation, ')
|
||||
..write('language: $language, ')
|
||||
..write('equipment: $equipment, ')
|
||||
..write('expiresIn: $expiresIn')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode =>
|
||||
Object.hash(id, exercisebase, muscle, category, variation, language, equipment, expiresIn);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is ExerciseTable &&
|
||||
other.id == this.id &&
|
||||
other.exercisebase == this.exercisebase &&
|
||||
other.muscle == this.muscle &&
|
||||
other.category == this.category &&
|
||||
other.variation == this.variation &&
|
||||
other.language == this.language &&
|
||||
other.equipment == this.equipment &&
|
||||
other.expiresIn == this.expiresIn);
|
||||
}
|
||||
|
||||
class ExerciseTableItemsCompanion extends UpdateCompanion<ExerciseTable> {
|
||||
final Value<int> id;
|
||||
final Value<ExerciseBase?> exercisebase;
|
||||
final Value<Muscle?> muscle;
|
||||
final Value<ExerciseCategory?> category;
|
||||
final Value<Variation?> variation;
|
||||
final Value<Language?> language;
|
||||
final Value<Equipment?> equipment;
|
||||
final Value<DateTime?> expiresIn;
|
||||
const ExerciseTableItemsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.exercisebase = const Value.absent(),
|
||||
this.muscle = const Value.absent(),
|
||||
this.category = const Value.absent(),
|
||||
this.variation = const Value.absent(),
|
||||
this.language = const Value.absent(),
|
||||
this.equipment = const Value.absent(),
|
||||
this.expiresIn = const Value.absent(),
|
||||
});
|
||||
ExerciseTableItemsCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
this.exercisebase = const Value.absent(),
|
||||
this.muscle = const Value.absent(),
|
||||
this.category = const Value.absent(),
|
||||
this.variation = const Value.absent(),
|
||||
this.language = const Value.absent(),
|
||||
this.equipment = const Value.absent(),
|
||||
this.expiresIn = const Value.absent(),
|
||||
});
|
||||
static Insertable<ExerciseTable> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? exercisebase,
|
||||
Expression<String>? muscle,
|
||||
Expression<String>? category,
|
||||
Expression<String>? variation,
|
||||
Expression<String>? language,
|
||||
Expression<String>? equipment,
|
||||
Expression<DateTime>? expiresIn,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (exercisebase != null) 'exercisebase': exercisebase,
|
||||
if (muscle != null) 'muscle': muscle,
|
||||
if (category != null) 'category': category,
|
||||
if (variation != null) 'variation': variation,
|
||||
if (language != null) 'language': language,
|
||||
if (equipment != null) 'equipment': equipment,
|
||||
if (expiresIn != null) 'expires_in': expiresIn,
|
||||
});
|
||||
}
|
||||
|
||||
ExerciseTableItemsCompanion copyWith(
|
||||
{Value<int>? id,
|
||||
Value<ExerciseBase?>? exercisebase,
|
||||
Value<Muscle?>? muscle,
|
||||
Value<ExerciseCategory?>? category,
|
||||
Value<Variation?>? variation,
|
||||
Value<Language?>? language,
|
||||
Value<Equipment?>? equipment,
|
||||
Value<DateTime?>? expiresIn}) {
|
||||
return ExerciseTableItemsCompanion(
|
||||
id: id ?? this.id,
|
||||
exercisebase: exercisebase ?? this.exercisebase,
|
||||
muscle: muscle ?? this.muscle,
|
||||
category: category ?? this.category,
|
||||
variation: variation ?? this.variation,
|
||||
language: language ?? this.language,
|
||||
equipment: equipment ?? this.equipment,
|
||||
expiresIn: expiresIn ?? this.expiresIn,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (exercisebase.present) {
|
||||
final converter = $ExerciseTableItemsTable.$converterexercisebasen;
|
||||
|
||||
map['exercisebase'] = Variable<String>(converter.toSql(exercisebase.value));
|
||||
}
|
||||
if (muscle.present) {
|
||||
final converter = $ExerciseTableItemsTable.$convertermusclen;
|
||||
|
||||
map['muscle'] = Variable<String>(converter.toSql(muscle.value));
|
||||
}
|
||||
if (category.present) {
|
||||
final converter = $ExerciseTableItemsTable.$convertercategoryn;
|
||||
|
||||
map['category'] = Variable<String>(converter.toSql(category.value));
|
||||
}
|
||||
if (variation.present) {
|
||||
final converter = $ExerciseTableItemsTable.$convertervariationn;
|
||||
|
||||
map['variation'] = Variable<String>(converter.toSql(variation.value));
|
||||
}
|
||||
if (language.present) {
|
||||
final converter = $ExerciseTableItemsTable.$converterlanguagen;
|
||||
|
||||
map['language'] = Variable<String>(converter.toSql(language.value));
|
||||
}
|
||||
if (equipment.present) {
|
||||
final converter = $ExerciseTableItemsTable.$converterequipmentn;
|
||||
|
||||
map['equipment'] = Variable<String>(converter.toSql(equipment.value));
|
||||
}
|
||||
if (expiresIn.present) {
|
||||
map['expires_in'] = Variable<DateTime>(expiresIn.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('ExerciseTableItemsCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('exercisebase: $exercisebase, ')
|
||||
..write('muscle: $muscle, ')
|
||||
..write('category: $category, ')
|
||||
..write('variation: $variation, ')
|
||||
..write('language: $language, ')
|
||||
..write('equipment: $equipment, ')
|
||||
..write('expiresIn: $expiresIn')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _$ExerciseDatabase extends GeneratedDatabase {
|
||||
_$ExerciseDatabase(QueryExecutor e) : super(e);
|
||||
late final $ExerciseTableItemsTable exerciseTableItems = $ExerciseTableItemsTable(this);
|
||||
@override
|
||||
Iterable<TableInfo<Table, Object?>> get allTables =>
|
||||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||
@override
|
||||
List<DatabaseSchemaEntity> get allSchemaEntities => [exerciseTableItems];
|
||||
}
|
||||
80
lib/database/exercises/exercise_database.dart
Normal file
80
lib/database/exercises/exercise_database.dart
Normal file
@@ -0,0 +1,80 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:wger/database/exercises/type_converters.dart';
|
||||
import 'package:wger/models/exercises/category.dart';
|
||||
import 'package:wger/models/exercises/equipment.dart';
|
||||
import 'package:wger/models/exercises/language.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
|
||||
part 'exercise_database.g.dart';
|
||||
|
||||
@DataClassName('ExerciseTable')
|
||||
class Exercises extends Table {
|
||||
IntColumn get id => integer()();
|
||||
|
||||
TextColumn get data => text()();
|
||||
|
||||
// TextColumn get exercisedata => text().map(const ExerciseBaseConverter())();
|
||||
|
||||
DateTimeColumn get lastUpdate => dateTime()();
|
||||
}
|
||||
|
||||
@DataClassName('MuscleTable')
|
||||
class Muscles extends Table {
|
||||
IntColumn get id => integer()();
|
||||
|
||||
TextColumn get data => text().map(const MuscleConverter())();
|
||||
}
|
||||
|
||||
@DataClassName('CategoryTable')
|
||||
class Categories extends Table {
|
||||
IntColumn get id => integer()();
|
||||
|
||||
TextColumn get data => text().map(const ExerciseCategoryConverter())();
|
||||
}
|
||||
|
||||
@DataClassName('LanguagesTable')
|
||||
class Languages extends Table {
|
||||
IntColumn get id => integer()();
|
||||
|
||||
TextColumn get data => text().map(const LanguageConverter())();
|
||||
}
|
||||
|
||||
@DataClassName('EquipmentTable')
|
||||
class Equipments extends Table {
|
||||
IntColumn get id => integer()();
|
||||
|
||||
TextColumn get data => text().map(const EquipmentConverter())();
|
||||
}
|
||||
|
||||
@DriftDatabase(tables: [Exercises, Muscles, Equipments, Categories, Languages])
|
||||
class ExerciseDatabase extends _$ExerciseDatabase {
|
||||
ExerciseDatabase() : super(_openConnection());
|
||||
|
||||
// Named constructor for creating in-memory database
|
||||
ExerciseDatabase.inMemory(super.e);
|
||||
|
||||
@override
|
||||
// TODO: implement schemaVersion
|
||||
int get schemaVersion => 1;
|
||||
|
||||
Future<void> deleteEverything() {
|
||||
return transaction(() async {
|
||||
for (final table in allTables) {
|
||||
await delete(table).go();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
LazyDatabase _openConnection() {
|
||||
return LazyDatabase(() async {
|
||||
final dbFolder = await getApplicationDocumentsDirectory();
|
||||
final file = File(p.join(dbFolder.path, 'exercises.sqlite'));
|
||||
return NativeDatabase.createInBackground(file);
|
||||
});
|
||||
}
|
||||
938
lib/database/exercises/exercise_database.g.dart
Normal file
938
lib/database/exercises/exercise_database.g.dart
Normal file
@@ -0,0 +1,938 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'exercise_database.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
class $ExercisesTable extends Exercises with TableInfo<$ExercisesTable, ExerciseTable> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$ExercisesTable(this.attachedDatabase, [this._alias]);
|
||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>('id', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||
@override
|
||||
late final GeneratedColumn<String> data = GeneratedColumn<String>('data', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
static const VerificationMeta _lastUpdateMeta = const VerificationMeta('lastUpdate');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime> lastUpdate = GeneratedColumn<DateTime>(
|
||||
'last_update', aliasedName, false,
|
||||
type: DriftSqlType.dateTime, requiredDuringInsert: true);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, data, lastUpdate];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'exercises';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<ExerciseTable> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (data.containsKey('data')) {
|
||||
context.handle(_dataMeta, this.data.isAcceptableOrUnknown(data['data']!, _dataMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_dataMeta);
|
||||
}
|
||||
if (data.containsKey('last_update')) {
|
||||
context.handle(
|
||||
_lastUpdateMeta, lastUpdate.isAcceptableOrUnknown(data['last_update']!, _lastUpdateMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_lastUpdateMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => const {};
|
||||
@override
|
||||
ExerciseTable map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return ExerciseTable(
|
||||
id: attachedDatabase.typeMapping.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
data: attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}data'])!,
|
||||
lastUpdate: attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.dateTime, data['${effectivePrefix}last_update'])!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$ExercisesTable createAlias(String alias) {
|
||||
return $ExercisesTable(attachedDatabase, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class ExerciseTable extends DataClass implements Insertable<ExerciseTable> {
|
||||
final int id;
|
||||
final String data;
|
||||
final DateTime lastUpdate;
|
||||
const ExerciseTable({required this.id, required this.data, required this.lastUpdate});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
map['data'] = Variable<String>(data);
|
||||
map['last_update'] = Variable<DateTime>(lastUpdate);
|
||||
return map;
|
||||
}
|
||||
|
||||
ExercisesCompanion toCompanion(bool nullToAbsent) {
|
||||
return ExercisesCompanion(
|
||||
id: Value(id),
|
||||
data: Value(data),
|
||||
lastUpdate: Value(lastUpdate),
|
||||
);
|
||||
}
|
||||
|
||||
factory ExerciseTable.fromJson(Map<String, dynamic> json, {ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return ExerciseTable(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
data: serializer.fromJson<String>(json['data']),
|
||||
lastUpdate: serializer.fromJson<DateTime>(json['lastUpdate']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'data': serializer.toJson<String>(data),
|
||||
'lastUpdate': serializer.toJson<DateTime>(lastUpdate),
|
||||
};
|
||||
}
|
||||
|
||||
ExerciseTable copyWith({int? id, String? data, DateTime? lastUpdate}) => ExerciseTable(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
lastUpdate: lastUpdate ?? this.lastUpdate,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('ExerciseTable(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data, ')
|
||||
..write('lastUpdate: $lastUpdate')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, data, lastUpdate);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is ExerciseTable &&
|
||||
other.id == this.id &&
|
||||
other.data == this.data &&
|
||||
other.lastUpdate == this.lastUpdate);
|
||||
}
|
||||
|
||||
class ExercisesCompanion extends UpdateCompanion<ExerciseTable> {
|
||||
final Value<int> id;
|
||||
final Value<String> data;
|
||||
final Value<DateTime> lastUpdate;
|
||||
final Value<int> rowid;
|
||||
const ExercisesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.data = const Value.absent(),
|
||||
this.lastUpdate = const Value.absent(),
|
||||
this.rowid = const Value.absent(),
|
||||
});
|
||||
ExercisesCompanion.insert({
|
||||
required int id,
|
||||
required String data,
|
||||
required DateTime lastUpdate,
|
||||
this.rowid = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
data = Value(data),
|
||||
lastUpdate = Value(lastUpdate);
|
||||
static Insertable<ExerciseTable> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? data,
|
||||
Expression<DateTime>? lastUpdate,
|
||||
Expression<int>? rowid,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (data != null) 'data': data,
|
||||
if (lastUpdate != null) 'last_update': lastUpdate,
|
||||
if (rowid != null) 'rowid': rowid,
|
||||
});
|
||||
}
|
||||
|
||||
ExercisesCompanion copyWith(
|
||||
{Value<int>? id, Value<String>? data, Value<DateTime>? lastUpdate, Value<int>? rowid}) {
|
||||
return ExercisesCompanion(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
lastUpdate: lastUpdate ?? this.lastUpdate,
|
||||
rowid: rowid ?? this.rowid,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (data.present) {
|
||||
map['data'] = Variable<String>(data.value);
|
||||
}
|
||||
if (lastUpdate.present) {
|
||||
map['last_update'] = Variable<DateTime>(lastUpdate.value);
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('ExercisesCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data, ')
|
||||
..write('lastUpdate: $lastUpdate, ')
|
||||
..write('rowid: $rowid')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $MusclesTable extends Muscles with TableInfo<$MusclesTable, MuscleTable> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$MusclesTable(this.attachedDatabase, [this._alias]);
|
||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>('id', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<Muscle, String> data = GeneratedColumn<String>(
|
||||
'data', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||
.withConverter<Muscle>($MusclesTable.$converterdata);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, data];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'muscles';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<MuscleTable> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
context.handle(_dataMeta, const VerificationResult.success());
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => const {};
|
||||
@override
|
||||
MuscleTable map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return MuscleTable(
|
||||
id: attachedDatabase.typeMapping.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
data: $MusclesTable.$converterdata.fromSql(
|
||||
attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}data'])!),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$MusclesTable createAlias(String alias) {
|
||||
return $MusclesTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<Muscle, String> $converterdata = const MuscleConverter();
|
||||
}
|
||||
|
||||
class MuscleTable extends DataClass implements Insertable<MuscleTable> {
|
||||
final int id;
|
||||
final Muscle data;
|
||||
const MuscleTable({required this.id, required this.data});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
{
|
||||
final converter = $MusclesTable.$converterdata;
|
||||
map['data'] = Variable<String>(converter.toSql(data));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
MusclesCompanion toCompanion(bool nullToAbsent) {
|
||||
return MusclesCompanion(
|
||||
id: Value(id),
|
||||
data: Value(data),
|
||||
);
|
||||
}
|
||||
|
||||
factory MuscleTable.fromJson(Map<String, dynamic> json, {ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return MuscleTable(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
data: serializer.fromJson<Muscle>(json['data']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'data': serializer.toJson<Muscle>(data),
|
||||
};
|
||||
}
|
||||
|
||||
MuscleTable copyWith({int? id, Muscle? data}) => MuscleTable(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('MuscleTable(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, data);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is MuscleTable && other.id == this.id && other.data == this.data);
|
||||
}
|
||||
|
||||
class MusclesCompanion extends UpdateCompanion<MuscleTable> {
|
||||
final Value<int> id;
|
||||
final Value<Muscle> data;
|
||||
final Value<int> rowid;
|
||||
const MusclesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.data = const Value.absent(),
|
||||
this.rowid = const Value.absent(),
|
||||
});
|
||||
MusclesCompanion.insert({
|
||||
required int id,
|
||||
required Muscle data,
|
||||
this.rowid = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
data = Value(data);
|
||||
static Insertable<MuscleTable> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? data,
|
||||
Expression<int>? rowid,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (data != null) 'data': data,
|
||||
if (rowid != null) 'rowid': rowid,
|
||||
});
|
||||
}
|
||||
|
||||
MusclesCompanion copyWith({Value<int>? id, Value<Muscle>? data, Value<int>? rowid}) {
|
||||
return MusclesCompanion(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
rowid: rowid ?? this.rowid,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (data.present) {
|
||||
final converter = $MusclesTable.$converterdata;
|
||||
|
||||
map['data'] = Variable<String>(converter.toSql(data.value));
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('MusclesCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data, ')
|
||||
..write('rowid: $rowid')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $EquipmentsTable extends Equipments with TableInfo<$EquipmentsTable, EquipmentTable> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$EquipmentsTable(this.attachedDatabase, [this._alias]);
|
||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>('id', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<Equipment, String> data = GeneratedColumn<String>(
|
||||
'data', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||
.withConverter<Equipment>($EquipmentsTable.$converterdata);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, data];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'equipments';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<EquipmentTable> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
context.handle(_dataMeta, const VerificationResult.success());
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => const {};
|
||||
@override
|
||||
EquipmentTable map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return EquipmentTable(
|
||||
id: attachedDatabase.typeMapping.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
data: $EquipmentsTable.$converterdata.fromSql(
|
||||
attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}data'])!),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$EquipmentsTable createAlias(String alias) {
|
||||
return $EquipmentsTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<Equipment, String> $converterdata = const EquipmentConverter();
|
||||
}
|
||||
|
||||
class EquipmentTable extends DataClass implements Insertable<EquipmentTable> {
|
||||
final int id;
|
||||
final Equipment data;
|
||||
const EquipmentTable({required this.id, required this.data});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
{
|
||||
final converter = $EquipmentsTable.$converterdata;
|
||||
map['data'] = Variable<String>(converter.toSql(data));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
EquipmentsCompanion toCompanion(bool nullToAbsent) {
|
||||
return EquipmentsCompanion(
|
||||
id: Value(id),
|
||||
data: Value(data),
|
||||
);
|
||||
}
|
||||
|
||||
factory EquipmentTable.fromJson(Map<String, dynamic> json, {ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return EquipmentTable(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
data: serializer.fromJson<Equipment>(json['data']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'data': serializer.toJson<Equipment>(data),
|
||||
};
|
||||
}
|
||||
|
||||
EquipmentTable copyWith({int? id, Equipment? data}) => EquipmentTable(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('EquipmentTable(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, data);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is EquipmentTable && other.id == this.id && other.data == this.data);
|
||||
}
|
||||
|
||||
class EquipmentsCompanion extends UpdateCompanion<EquipmentTable> {
|
||||
final Value<int> id;
|
||||
final Value<Equipment> data;
|
||||
final Value<int> rowid;
|
||||
const EquipmentsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.data = const Value.absent(),
|
||||
this.rowid = const Value.absent(),
|
||||
});
|
||||
EquipmentsCompanion.insert({
|
||||
required int id,
|
||||
required Equipment data,
|
||||
this.rowid = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
data = Value(data);
|
||||
static Insertable<EquipmentTable> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? data,
|
||||
Expression<int>? rowid,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (data != null) 'data': data,
|
||||
if (rowid != null) 'rowid': rowid,
|
||||
});
|
||||
}
|
||||
|
||||
EquipmentsCompanion copyWith({Value<int>? id, Value<Equipment>? data, Value<int>? rowid}) {
|
||||
return EquipmentsCompanion(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
rowid: rowid ?? this.rowid,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (data.present) {
|
||||
final converter = $EquipmentsTable.$converterdata;
|
||||
|
||||
map['data'] = Variable<String>(converter.toSql(data.value));
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('EquipmentsCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data, ')
|
||||
..write('rowid: $rowid')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $CategoriesTable extends Categories with TableInfo<$CategoriesTable, CategoryTable> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$CategoriesTable(this.attachedDatabase, [this._alias]);
|
||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>('id', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<ExerciseCategory, String> data =
|
||||
GeneratedColumn<String>('data', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||
.withConverter<ExerciseCategory>($CategoriesTable.$converterdata);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, data];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'categories';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<CategoryTable> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
context.handle(_dataMeta, const VerificationResult.success());
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => const {};
|
||||
@override
|
||||
CategoryTable map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return CategoryTable(
|
||||
id: attachedDatabase.typeMapping.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
data: $CategoriesTable.$converterdata.fromSql(
|
||||
attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}data'])!),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$CategoriesTable createAlias(String alias) {
|
||||
return $CategoriesTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<ExerciseCategory, String> $converterdata = const ExerciseCategoryConverter();
|
||||
}
|
||||
|
||||
class CategoryTable extends DataClass implements Insertable<CategoryTable> {
|
||||
final int id;
|
||||
final ExerciseCategory data;
|
||||
const CategoryTable({required this.id, required this.data});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
{
|
||||
final converter = $CategoriesTable.$converterdata;
|
||||
map['data'] = Variable<String>(converter.toSql(data));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
CategoriesCompanion toCompanion(bool nullToAbsent) {
|
||||
return CategoriesCompanion(
|
||||
id: Value(id),
|
||||
data: Value(data),
|
||||
);
|
||||
}
|
||||
|
||||
factory CategoryTable.fromJson(Map<String, dynamic> json, {ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return CategoryTable(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
data: serializer.fromJson<ExerciseCategory>(json['data']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'data': serializer.toJson<ExerciseCategory>(data),
|
||||
};
|
||||
}
|
||||
|
||||
CategoryTable copyWith({int? id, ExerciseCategory? data}) => CategoryTable(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('CategoryTable(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, data);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is CategoryTable && other.id == this.id && other.data == this.data);
|
||||
}
|
||||
|
||||
class CategoriesCompanion extends UpdateCompanion<CategoryTable> {
|
||||
final Value<int> id;
|
||||
final Value<ExerciseCategory> data;
|
||||
final Value<int> rowid;
|
||||
const CategoriesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.data = const Value.absent(),
|
||||
this.rowid = const Value.absent(),
|
||||
});
|
||||
CategoriesCompanion.insert({
|
||||
required int id,
|
||||
required ExerciseCategory data,
|
||||
this.rowid = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
data = Value(data);
|
||||
static Insertable<CategoryTable> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? data,
|
||||
Expression<int>? rowid,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (data != null) 'data': data,
|
||||
if (rowid != null) 'rowid': rowid,
|
||||
});
|
||||
}
|
||||
|
||||
CategoriesCompanion copyWith({Value<int>? id, Value<ExerciseCategory>? data, Value<int>? rowid}) {
|
||||
return CategoriesCompanion(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
rowid: rowid ?? this.rowid,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (data.present) {
|
||||
final converter = $CategoriesTable.$converterdata;
|
||||
|
||||
map['data'] = Variable<String>(converter.toSql(data.value));
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('CategoriesCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data, ')
|
||||
..write('rowid: $rowid')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
class $LanguagesTable extends Languages with TableInfo<$LanguagesTable, LanguagesTable> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$LanguagesTable(this.attachedDatabase, [this._alias]);
|
||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>('id', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<Language, String> data = GeneratedColumn<String>(
|
||||
'data', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||
.withConverter<Language>($LanguagesTable.$converterdata);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, data];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'languages';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<LanguagesTable> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
context.handle(_dataMeta, const VerificationResult.success());
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => const {};
|
||||
@override
|
||||
LanguagesTable map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return LanguagesTable(
|
||||
id: attachedDatabase.typeMapping.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
data: $LanguagesTable.$converterdata.fromSql(
|
||||
attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}data'])!),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$LanguagesTable createAlias(String alias) {
|
||||
return $LanguagesTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<Language, String> $converterdata = const LanguageConverter();
|
||||
}
|
||||
|
||||
class LanguagesTable extends DataClass implements Insertable<LanguagesTable> {
|
||||
final int id;
|
||||
final Language data;
|
||||
const LanguagesTable({required this.id, required this.data});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
{
|
||||
final converter = $LanguagesTable.$converterdata;
|
||||
map['data'] = Variable<String>(converter.toSql(data));
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
LanguagesCompanion toCompanion(bool nullToAbsent) {
|
||||
return LanguagesCompanion(
|
||||
id: Value(id),
|
||||
data: Value(data),
|
||||
);
|
||||
}
|
||||
|
||||
factory LanguagesTable.fromJson(Map<String, dynamic> json, {ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return LanguagesTable(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
data: serializer.fromJson<Language>(json['data']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'data': serializer.toJson<Language>(data),
|
||||
};
|
||||
}
|
||||
|
||||
LanguagesTable copyWith({int? id, Language? data}) => LanguagesTable(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('LanguagesTable(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, data);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is LanguagesTable && other.id == this.id && other.data == this.data);
|
||||
}
|
||||
|
||||
class LanguagesCompanion extends UpdateCompanion<LanguagesTable> {
|
||||
final Value<int> id;
|
||||
final Value<Language> data;
|
||||
final Value<int> rowid;
|
||||
const LanguagesCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.data = const Value.absent(),
|
||||
this.rowid = const Value.absent(),
|
||||
});
|
||||
LanguagesCompanion.insert({
|
||||
required int id,
|
||||
required Language data,
|
||||
this.rowid = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
data = Value(data);
|
||||
static Insertable<LanguagesTable> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? data,
|
||||
Expression<int>? rowid,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (data != null) 'data': data,
|
||||
if (rowid != null) 'rowid': rowid,
|
||||
});
|
||||
}
|
||||
|
||||
LanguagesCompanion copyWith({Value<int>? id, Value<Language>? data, Value<int>? rowid}) {
|
||||
return LanguagesCompanion(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
rowid: rowid ?? this.rowid,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (data.present) {
|
||||
final converter = $LanguagesTable.$converterdata;
|
||||
|
||||
map['data'] = Variable<String>(converter.toSql(data.value));
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('LanguagesCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data, ')
|
||||
..write('rowid: $rowid')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _$ExerciseDatabase extends GeneratedDatabase {
|
||||
_$ExerciseDatabase(QueryExecutor e) : super(e);
|
||||
late final $ExercisesTable exercises = $ExercisesTable(this);
|
||||
late final $MusclesTable muscles = $MusclesTable(this);
|
||||
late final $EquipmentsTable equipments = $EquipmentsTable(this);
|
||||
late final $CategoriesTable categories = $CategoriesTable(this);
|
||||
late final $LanguagesTable languages = $LanguagesTable(this);
|
||||
@override
|
||||
Iterable<TableInfo<Table, Object?>> get allTables =>
|
||||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||
@override
|
||||
List<DatabaseSchemaEntity> get allSchemaEntities =>
|
||||
[exercises, muscles, equipments, categories, languages];
|
||||
}
|
||||
@@ -1,10 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:flutter/src/widgets/framework.dart';
|
||||
// import 'package:path/path.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/exceptions/no_such_entry_exception.dart';
|
||||
import 'package:wger/models/exercises/alias.dart';
|
||||
import 'package:wger/models/exercises/base.dart';
|
||||
import 'package:wger/models/exercises/category.dart';
|
||||
@@ -16,25 +12,6 @@ import 'package:wger/models/exercises/muscle.dart';
|
||||
import 'package:wger/models/exercises/translation.dart';
|
||||
import 'package:wger/models/exercises/variation.dart';
|
||||
import 'package:wger/models/exercises/video.dart';
|
||||
import 'package:wger/providers/auth.dart';
|
||||
import 'package:wger/providers/base_provider.dart';
|
||||
|
||||
// List<Language> _languages = [];
|
||||
// Future<void> fetchAndSetLanguages(BuildContext context) async {
|
||||
// final baseProvider= WgerBaseProvider(Provider.of<AuthProvider>(context, listen: false))
|
||||
// final languageData = await baseProvider.fetchPaginated(baseProvider.makeUrl('language'));
|
||||
|
||||
// for (final language in languageData) {
|
||||
// _languages.add(Language.fromJson(language));
|
||||
// }
|
||||
// }
|
||||
|
||||
// Language findLanguageById(int id) {
|
||||
// return _languages.firstWhere(
|
||||
// (language) => language.id == id,
|
||||
// orElse: () => throw NoSuchEntryException(),
|
||||
// );
|
||||
// }
|
||||
|
||||
class ExerciseBaseConverter extends TypeConverter<ExerciseBase, String> {
|
||||
const ExerciseBaseConverter();
|
||||
@@ -50,20 +27,18 @@ class ExerciseBaseConverter extends TypeConverter<ExerciseBase, String> {
|
||||
final images = baseData['images'].map((e) => ExerciseImage.fromJson(e)).toList();
|
||||
final videos = baseData['videos'].map((e) => Video.fromJson(e)).toList();
|
||||
|
||||
final List<Translation> exercises = [];
|
||||
final List<Translation> translations = [];
|
||||
for (final exerciseData in baseData['translations']) {
|
||||
final exercise = Translation(
|
||||
final translation = Translation(
|
||||
id: exerciseData['id'],
|
||||
name: exerciseData['name'],
|
||||
description: exerciseData['description'],
|
||||
baseId: baseData['id'],
|
||||
);
|
||||
exercise.aliases =
|
||||
exerciseData['aliases'].map((e) => Alias.fromJson(e)).toList().cast<Alias>();
|
||||
exercise.notes =
|
||||
exerciseData['notes'].map((e) => Comment.fromJson(e)).toList().cast<Comment>();
|
||||
exercise.language = Language.fromJson(exerciseData['languageObj']);
|
||||
exercises.add(exercise);
|
||||
translation.aliases = exerciseData['aliases'].map((e) => Alias.fromJson(e)).toList();
|
||||
translation.notes = exerciseData['notes'].map((e) => Comment.fromJson(e)).toList();
|
||||
translation.language = Language.fromJson(exerciseData['languageObj']);
|
||||
translations.add(translation);
|
||||
}
|
||||
|
||||
final exerciseBase = ExerciseBase(
|
||||
@@ -76,7 +51,7 @@ class ExerciseBaseConverter extends TypeConverter<ExerciseBase, String> {
|
||||
equipment: equipment.cast<Equipment>(),
|
||||
category: category,
|
||||
images: images.cast<ExerciseImage>(),
|
||||
exercises: exercises,
|
||||
exercises: translations,
|
||||
videos: videos.cast<Video>(),
|
||||
);
|
||||
return exerciseBase;
|
||||
34
lib/database/ingredients/ingredients_database.dart
Normal file
34
lib/database/ingredients/ingredients_database.dart
Normal file
@@ -0,0 +1,34 @@
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:path/path.dart' as p;
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
|
||||
part 'ingredients_database.g.dart';
|
||||
|
||||
@DataClassName('IngredientTable')
|
||||
class Ingredients extends Table {
|
||||
IntColumn get id => integer()();
|
||||
|
||||
TextColumn get data => text()();
|
||||
|
||||
DateTimeColumn get lastUpdate => dateTime()();
|
||||
}
|
||||
|
||||
@DriftDatabase(tables: [Ingredients])
|
||||
class IngredientDatabase extends _$IngredientDatabase {
|
||||
IngredientDatabase() : super(_openConnection());
|
||||
|
||||
@override
|
||||
// TODO: implement schemaVersion
|
||||
int get schemaVersion => 1;
|
||||
}
|
||||
|
||||
LazyDatabase _openConnection() {
|
||||
return LazyDatabase(() async {
|
||||
final dbFolder = await getApplicationDocumentsDirectory();
|
||||
final file = File(p.join(dbFolder.path, 'ingredients.sqlite'));
|
||||
return NativeDatabase.createInBackground(file);
|
||||
});
|
||||
}
|
||||
221
lib/database/ingredients/ingredients_database.g.dart
Normal file
221
lib/database/ingredients/ingredients_database.g.dart
Normal file
@@ -0,0 +1,221 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'ingredients_database.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
class $IngredientsTable extends Ingredients with TableInfo<$IngredientsTable, IngredientTable> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$IngredientsTable(this.attachedDatabase, [this._alias]);
|
||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>('id', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||
@override
|
||||
late final GeneratedColumn<String> data = GeneratedColumn<String>('data', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true);
|
||||
static const VerificationMeta _lastUpdateMeta = const VerificationMeta('lastUpdate');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime> lastUpdate = GeneratedColumn<DateTime>(
|
||||
'last_update', aliasedName, false,
|
||||
type: DriftSqlType.dateTime, requiredDuringInsert: true);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, data, lastUpdate];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'ingredients';
|
||||
@override
|
||||
VerificationContext validateIntegrity(Insertable<IngredientTable> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (data.containsKey('data')) {
|
||||
context.handle(_dataMeta, this.data.isAcceptableOrUnknown(data['data']!, _dataMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_dataMeta);
|
||||
}
|
||||
if (data.containsKey('last_update')) {
|
||||
context.handle(
|
||||
_lastUpdateMeta, lastUpdate.isAcceptableOrUnknown(data['last_update']!, _lastUpdateMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_lastUpdateMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => const {};
|
||||
@override
|
||||
IngredientTable map(Map<String, dynamic> data, {String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return IngredientTable(
|
||||
id: attachedDatabase.typeMapping.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
data: attachedDatabase.typeMapping.read(DriftSqlType.string, data['${effectivePrefix}data'])!,
|
||||
lastUpdate: attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.dateTime, data['${effectivePrefix}last_update'])!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$IngredientsTable createAlias(String alias) {
|
||||
return $IngredientsTable(attachedDatabase, alias);
|
||||
}
|
||||
}
|
||||
|
||||
class IngredientTable extends DataClass implements Insertable<IngredientTable> {
|
||||
final int id;
|
||||
final String data;
|
||||
final DateTime lastUpdate;
|
||||
const IngredientTable({required this.id, required this.data, required this.lastUpdate});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
map['data'] = Variable<String>(data);
|
||||
map['last_update'] = Variable<DateTime>(lastUpdate);
|
||||
return map;
|
||||
}
|
||||
|
||||
IngredientsCompanion toCompanion(bool nullToAbsent) {
|
||||
return IngredientsCompanion(
|
||||
id: Value(id),
|
||||
data: Value(data),
|
||||
lastUpdate: Value(lastUpdate),
|
||||
);
|
||||
}
|
||||
|
||||
factory IngredientTable.fromJson(Map<String, dynamic> json, {ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return IngredientTable(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
data: serializer.fromJson<String>(json['data']),
|
||||
lastUpdate: serializer.fromJson<DateTime>(json['lastUpdate']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'data': serializer.toJson<String>(data),
|
||||
'lastUpdate': serializer.toJson<DateTime>(lastUpdate),
|
||||
};
|
||||
}
|
||||
|
||||
IngredientTable copyWith({int? id, String? data, DateTime? lastUpdate}) => IngredientTable(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
lastUpdate: lastUpdate ?? this.lastUpdate,
|
||||
);
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('IngredientTable(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data, ')
|
||||
..write('lastUpdate: $lastUpdate')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, data, lastUpdate);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is IngredientTable &&
|
||||
other.id == this.id &&
|
||||
other.data == this.data &&
|
||||
other.lastUpdate == this.lastUpdate);
|
||||
}
|
||||
|
||||
class IngredientsCompanion extends UpdateCompanion<IngredientTable> {
|
||||
final Value<int> id;
|
||||
final Value<String> data;
|
||||
final Value<DateTime> lastUpdate;
|
||||
final Value<int> rowid;
|
||||
const IngredientsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.data = const Value.absent(),
|
||||
this.lastUpdate = const Value.absent(),
|
||||
this.rowid = const Value.absent(),
|
||||
});
|
||||
IngredientsCompanion.insert({
|
||||
required int id,
|
||||
required String data,
|
||||
required DateTime lastUpdate,
|
||||
this.rowid = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
data = Value(data),
|
||||
lastUpdate = Value(lastUpdate);
|
||||
static Insertable<IngredientTable> custom({
|
||||
Expression<int>? id,
|
||||
Expression<String>? data,
|
||||
Expression<DateTime>? lastUpdate,
|
||||
Expression<int>? rowid,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (data != null) 'data': data,
|
||||
if (lastUpdate != null) 'last_update': lastUpdate,
|
||||
if (rowid != null) 'rowid': rowid,
|
||||
});
|
||||
}
|
||||
|
||||
IngredientsCompanion copyWith(
|
||||
{Value<int>? id, Value<String>? data, Value<DateTime>? lastUpdate, Value<int>? rowid}) {
|
||||
return IngredientsCompanion(
|
||||
id: id ?? this.id,
|
||||
data: data ?? this.data,
|
||||
lastUpdate: lastUpdate ?? this.lastUpdate,
|
||||
rowid: rowid ?? this.rowid,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (data.present) {
|
||||
map['data'] = Variable<String>(data.value);
|
||||
}
|
||||
if (lastUpdate.present) {
|
||||
map['last_update'] = Variable<DateTime>(lastUpdate.value);
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('IngredientsCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('data: $data, ')
|
||||
..write('lastUpdate: $lastUpdate, ')
|
||||
..write('rowid: $rowid')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _$IngredientDatabase extends GeneratedDatabase {
|
||||
_$IngredientDatabase(QueryExecutor e) : super(e);
|
||||
late final $IngredientsTable ingredients = $IngredientsTable(this);
|
||||
@override
|
||||
Iterable<TableInfo<Table, Object?>> get allTables =>
|
||||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||
@override
|
||||
List<DatabaseSchemaEntity> get allSchemaEntities => [ingredients];
|
||||
}
|
||||
@@ -51,6 +51,10 @@ const SUBMIT_BUTTON_KEY_NAME = 'submit-button';
|
||||
|
||||
/// Local Preferences keys
|
||||
const PREFS_EXERCISES = 'exerciseData';
|
||||
const PREFS_LAST_UPDATED_MUSCLES = 'lastUpdatedMuscles';
|
||||
const PREFS_LAST_UPDATED_EQUIPMENT = 'lastUpdatedEquipment';
|
||||
const PREFS_LAST_UPDATED_CATEGORIES = 'lastUpdatedCategories';
|
||||
const PREFS_LAST_UPDATED_LANGUAGES = 'lastUpdatedLanguages';
|
||||
const PREFS_EXERCISE_CACHE_VERSION = 'cacheVersion';
|
||||
const PREFS_INGREDIENTS = 'ingredientData';
|
||||
|
||||
|
||||
@@ -16,18 +16,12 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
import 'package:flutter_zxing/flutter_zxing.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:wger/core/locator.dart';
|
||||
import 'package:wger/database/exercise_DB/exercise_database.dart';
|
||||
import 'package:wger/models/exercises/base.dart';
|
||||
import 'package:wger/models/exercises/category.dart';
|
||||
import 'package:wger/models/exercises/equipment.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
import 'package:wger/providers/add_exercise.dart';
|
||||
import 'package:wger/providers/base_provider.dart';
|
||||
import 'package:wger/providers/body_weight.dart';
|
||||
|
||||
@@ -45,6 +45,9 @@ class ExerciseBase extends Equatable {
|
||||
@JsonKey(required: true, name: 'last_update')
|
||||
final DateTime? lastUpdate;
|
||||
|
||||
@JsonKey(required: true, name: 'last_update_global')
|
||||
final DateTime? lastUpdateGlobal;
|
||||
|
||||
@JsonKey(required: true, name: 'category')
|
||||
late int categoryId;
|
||||
|
||||
@@ -54,7 +57,7 @@ class ExerciseBase extends Equatable {
|
||||
@JsonKey(required: true, name: 'muscles')
|
||||
List<int> musclesIds = [];
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: true, name: 'muscless')
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
List<Muscle> muscles = [];
|
||||
|
||||
@JsonKey(required: true, name: 'muscles_secondary')
|
||||
@@ -66,16 +69,16 @@ class ExerciseBase extends Equatable {
|
||||
@JsonKey(required: true, name: 'equipment')
|
||||
List<int> equipmentIds = [];
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: true, name: 'equipments')
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
List<Equipment> equipment = [];
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: true)
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
List<ExerciseImage> images = [];
|
||||
|
||||
@JsonKey(includeFromJson: true, includeToJson: true)
|
||||
@JsonKey(includeFromJson: true, includeToJson: false)
|
||||
List<Translation> translations = [];
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: true)
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
List<Video> videos = [];
|
||||
|
||||
ExerciseBase({
|
||||
@@ -83,6 +86,7 @@ class ExerciseBase extends Equatable {
|
||||
this.uuid,
|
||||
this.created,
|
||||
this.lastUpdate,
|
||||
this.lastUpdateGlobal,
|
||||
this.variationId,
|
||||
List<Muscle>? muscles,
|
||||
List<Muscle>? musclesSecondary,
|
||||
@@ -114,9 +118,9 @@ class ExerciseBase extends Equatable {
|
||||
equipmentIds = equipment.map((e) => e.id).toList();
|
||||
}
|
||||
|
||||
if (exercises == null) {
|
||||
print("Exercises are NULL");
|
||||
}
|
||||
// if (exercises == null) {
|
||||
// print("Exercises are NULL");
|
||||
// }
|
||||
|
||||
if (exercises != null) {
|
||||
translations = exercises;
|
||||
|
||||
@@ -15,6 +15,7 @@ ExerciseBase _$ExerciseBaseFromJson(Map<String, dynamic> json) {
|
||||
'variations',
|
||||
'created',
|
||||
'last_update',
|
||||
'last_update_global',
|
||||
'category',
|
||||
'muscles',
|
||||
'muscles_secondary',
|
||||
@@ -26,6 +27,9 @@ ExerciseBase _$ExerciseBaseFromJson(Map<String, dynamic> json) {
|
||||
uuid: json['uuid'] as String?,
|
||||
created: json['created'] == null ? null : DateTime.parse(json['created'] as String),
|
||||
lastUpdate: json['last_update'] == null ? null : DateTime.parse(json['last_update'] as String),
|
||||
lastUpdateGlobal: json['last_update_global'] == null
|
||||
? null
|
||||
: DateTime.parse(json['last_update_global'] as String),
|
||||
variationId: json['variations'] as int?,
|
||||
category: json['categories'] == null
|
||||
? null
|
||||
@@ -47,15 +51,11 @@ Map<String, dynamic> _$ExerciseBaseToJson(ExerciseBase instance) => <String, dyn
|
||||
'variations': instance.variationId,
|
||||
'created': instance.created?.toIso8601String(),
|
||||
'last_update': instance.lastUpdate?.toIso8601String(),
|
||||
'last_update_global': instance.lastUpdateGlobal?.toIso8601String(),
|
||||
'category': instance.categoryId,
|
||||
'categories': instance.category?.toJson(),
|
||||
'muscles': instance.musclesIds,
|
||||
'muscless': instance.muscles.map((e) => e.toJson()).toList(),
|
||||
'muscles_secondary': instance.musclesSecondaryIds,
|
||||
'musclesSecondary': instance.musclesSecondary.map((e) => e.toJson()).toList(),
|
||||
'equipment': instance.equipmentIds,
|
||||
'equipments': instance.equipment.map((e) => e.toJson()).toList(),
|
||||
'images': instance.images.map((e) => e.toJson()).toList(),
|
||||
'translations': instance.translations.map((e) => e.toJson()).toList(),
|
||||
'videos': instance.videos.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
@@ -4,7 +4,6 @@ import 'package:wger/models/exercises/equipment.dart';
|
||||
import 'package:wger/models/exercises/exercise_model.dart';
|
||||
import 'package:wger/models/exercises/image.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
import 'package:wger/models/exercises/translation.dart';
|
||||
import 'package:wger/models/exercises/video.dart';
|
||||
|
||||
part 'exercise_base_data.freezed.dart';
|
||||
@@ -15,6 +14,12 @@ class ExerciseBaseData with _$ExerciseBaseData {
|
||||
factory ExerciseBaseData({
|
||||
required int id,
|
||||
required String uuid,
|
||||
// ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'created') required DateTime created,
|
||||
// ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'last_update') required DateTime lastUpdate,
|
||||
// ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'last_update_global') required DateTime lastUpdateGlobal,
|
||||
required ExerciseCategory category,
|
||||
required List<Muscle> muscles,
|
||||
// ignore: invalid_annotation_target
|
||||
|
||||
@@ -21,7 +21,14 @@ ExerciseBaseData _$ExerciseBaseDataFromJson(Map<String, dynamic> json) {
|
||||
/// @nodoc
|
||||
mixin _$ExerciseBaseData {
|
||||
int get id => throw _privateConstructorUsedError;
|
||||
String get uuid => throw _privateConstructorUsedError;
|
||||
String get uuid => throw _privateConstructorUsedError; // ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'created')
|
||||
DateTime get created => throw _privateConstructorUsedError; // ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'last_update')
|
||||
DateTime get lastUpdate =>
|
||||
throw _privateConstructorUsedError; // ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'last_update_global')
|
||||
DateTime get lastUpdateGlobal => throw _privateConstructorUsedError;
|
||||
ExerciseCategory get category => throw _privateConstructorUsedError;
|
||||
List<Muscle> get muscles =>
|
||||
throw _privateConstructorUsedError; // ignore: invalid_annotation_target
|
||||
@@ -45,6 +52,9 @@ abstract class $ExerciseBaseDataCopyWith<$Res> {
|
||||
$Res call(
|
||||
{int id,
|
||||
String uuid,
|
||||
@JsonKey(name: 'created') DateTime created,
|
||||
@JsonKey(name: 'last_update') DateTime lastUpdate,
|
||||
@JsonKey(name: 'last_update_global') DateTime lastUpdateGlobal,
|
||||
ExerciseCategory category,
|
||||
List<Muscle> muscles,
|
||||
@JsonKey(name: 'muscles_secondary') List<Muscle> musclesSecondary,
|
||||
@@ -69,6 +79,9 @@ class _$ExerciseBaseDataCopyWithImpl<$Res, $Val extends ExerciseBaseData>
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? uuid = null,
|
||||
Object? created = null,
|
||||
Object? lastUpdate = null,
|
||||
Object? lastUpdateGlobal = null,
|
||||
Object? category = null,
|
||||
Object? muscles = null,
|
||||
Object? musclesSecondary = null,
|
||||
@@ -86,6 +99,18 @@ class _$ExerciseBaseDataCopyWithImpl<$Res, $Val extends ExerciseBaseData>
|
||||
? _value.uuid
|
||||
: uuid // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
created: null == created
|
||||
? _value.created
|
||||
: created // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
lastUpdate: null == lastUpdate
|
||||
? _value.lastUpdate
|
||||
: lastUpdate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
lastUpdateGlobal: null == lastUpdateGlobal
|
||||
? _value.lastUpdateGlobal
|
||||
: lastUpdateGlobal // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
category: null == category
|
||||
? _value.category
|
||||
: category // ignore: cast_nullable_to_non_nullable
|
||||
@@ -128,6 +153,9 @@ abstract class _$$ExerciseBaseDataImplCopyWith<$Res> implements $ExerciseBaseDat
|
||||
$Res call(
|
||||
{int id,
|
||||
String uuid,
|
||||
@JsonKey(name: 'created') DateTime created,
|
||||
@JsonKey(name: 'last_update') DateTime lastUpdate,
|
||||
@JsonKey(name: 'last_update_global') DateTime lastUpdateGlobal,
|
||||
ExerciseCategory category,
|
||||
List<Muscle> muscles,
|
||||
@JsonKey(name: 'muscles_secondary') List<Muscle> musclesSecondary,
|
||||
@@ -150,6 +178,9 @@ class __$$ExerciseBaseDataImplCopyWithImpl<$Res>
|
||||
$Res call({
|
||||
Object? id = null,
|
||||
Object? uuid = null,
|
||||
Object? created = null,
|
||||
Object? lastUpdate = null,
|
||||
Object? lastUpdateGlobal = null,
|
||||
Object? category = null,
|
||||
Object? muscles = null,
|
||||
Object? musclesSecondary = null,
|
||||
@@ -167,6 +198,18 @@ class __$$ExerciseBaseDataImplCopyWithImpl<$Res>
|
||||
? _value.uuid
|
||||
: uuid // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
created: null == created
|
||||
? _value.created
|
||||
: created // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
lastUpdate: null == lastUpdate
|
||||
? _value.lastUpdate
|
||||
: lastUpdate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
lastUpdateGlobal: null == lastUpdateGlobal
|
||||
? _value.lastUpdateGlobal
|
||||
: lastUpdateGlobal // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,
|
||||
category: null == category
|
||||
? _value.category
|
||||
: category // ignore: cast_nullable_to_non_nullable
|
||||
@@ -205,6 +248,9 @@ class _$ExerciseBaseDataImpl implements _ExerciseBaseData {
|
||||
_$ExerciseBaseDataImpl(
|
||||
{required this.id,
|
||||
required this.uuid,
|
||||
@JsonKey(name: 'created') required this.created,
|
||||
@JsonKey(name: 'last_update') required this.lastUpdate,
|
||||
@JsonKey(name: 'last_update_global') required this.lastUpdateGlobal,
|
||||
required this.category,
|
||||
required final List<Muscle> muscles,
|
||||
@JsonKey(name: 'muscles_secondary') required final List<Muscle> musclesSecondary,
|
||||
@@ -226,6 +272,18 @@ class _$ExerciseBaseDataImpl implements _ExerciseBaseData {
|
||||
final int id;
|
||||
@override
|
||||
final String uuid;
|
||||
// ignore: invalid_annotation_target
|
||||
@override
|
||||
@JsonKey(name: 'created')
|
||||
final DateTime created;
|
||||
// ignore: invalid_annotation_target
|
||||
@override
|
||||
@JsonKey(name: 'last_update')
|
||||
final DateTime lastUpdate;
|
||||
// ignore: invalid_annotation_target
|
||||
@override
|
||||
@JsonKey(name: 'last_update_global')
|
||||
final DateTime lastUpdateGlobal;
|
||||
@override
|
||||
final ExerciseCategory category;
|
||||
final List<Muscle> _muscles;
|
||||
@@ -281,7 +339,7 @@ class _$ExerciseBaseDataImpl implements _ExerciseBaseData {
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'ExerciseBaseData(id: $id, uuid: $uuid, category: $category, muscles: $muscles, musclesSecondary: $musclesSecondary, equipment: $equipment, exercises: $exercises, images: $images, videos: $videos)';
|
||||
return 'ExerciseBaseData(id: $id, uuid: $uuid, created: $created, lastUpdate: $lastUpdate, lastUpdateGlobal: $lastUpdateGlobal, category: $category, muscles: $muscles, musclesSecondary: $musclesSecondary, equipment: $equipment, exercises: $exercises, images: $images, videos: $videos)';
|
||||
}
|
||||
|
||||
@override
|
||||
@@ -291,6 +349,10 @@ class _$ExerciseBaseDataImpl implements _ExerciseBaseData {
|
||||
other is _$ExerciseBaseDataImpl &&
|
||||
(identical(other.id, id) || other.id == id) &&
|
||||
(identical(other.uuid, uuid) || other.uuid == uuid) &&
|
||||
(identical(other.created, created) || other.created == created) &&
|
||||
(identical(other.lastUpdate, lastUpdate) || other.lastUpdate == lastUpdate) &&
|
||||
(identical(other.lastUpdateGlobal, lastUpdateGlobal) ||
|
||||
other.lastUpdateGlobal == lastUpdateGlobal) &&
|
||||
(identical(other.category, category) || other.category == category) &&
|
||||
const DeepCollectionEquality().equals(other._muscles, _muscles) &&
|
||||
const DeepCollectionEquality().equals(other._musclesSecondary, _musclesSecondary) &&
|
||||
@@ -306,6 +368,9 @@ class _$ExerciseBaseDataImpl implements _ExerciseBaseData {
|
||||
runtimeType,
|
||||
id,
|
||||
uuid,
|
||||
created,
|
||||
lastUpdate,
|
||||
lastUpdateGlobal,
|
||||
category,
|
||||
const DeepCollectionEquality().hash(_muscles),
|
||||
const DeepCollectionEquality().hash(_musclesSecondary),
|
||||
@@ -332,6 +397,9 @@ abstract class _ExerciseBaseData implements ExerciseBaseData {
|
||||
factory _ExerciseBaseData(
|
||||
{required final int id,
|
||||
required final String uuid,
|
||||
@JsonKey(name: 'created') required final DateTime created,
|
||||
@JsonKey(name: 'last_update') required final DateTime lastUpdate,
|
||||
@JsonKey(name: 'last_update_global') required final DateTime lastUpdateGlobal,
|
||||
required final ExerciseCategory category,
|
||||
required final List<Muscle> muscles,
|
||||
@JsonKey(name: 'muscles_secondary') required final List<Muscle> musclesSecondary,
|
||||
@@ -346,6 +414,15 @@ abstract class _ExerciseBaseData implements ExerciseBaseData {
|
||||
int get id;
|
||||
@override
|
||||
String get uuid;
|
||||
@override // ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'created')
|
||||
DateTime get created;
|
||||
@override // ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'last_update')
|
||||
DateTime get lastUpdate;
|
||||
@override // ignore: invalid_annotation_target
|
||||
@JsonKey(name: 'last_update_global')
|
||||
DateTime get lastUpdateGlobal;
|
||||
@override
|
||||
ExerciseCategory get category;
|
||||
@override
|
||||
|
||||
@@ -10,6 +10,9 @@ _$ExerciseBaseDataImpl _$$ExerciseBaseDataImplFromJson(Map<String, dynamic> json
|
||||
_$ExerciseBaseDataImpl(
|
||||
id: json['id'] as int,
|
||||
uuid: json['uuid'] as String,
|
||||
created: DateTime.parse(json['created'] as String),
|
||||
lastUpdate: DateTime.parse(json['last_update'] as String),
|
||||
lastUpdateGlobal: DateTime.parse(json['last_update_global'] as String),
|
||||
category: ExerciseCategory.fromJson(json['category'] as Map<String, dynamic>),
|
||||
muscles: (json['muscles'] as List<dynamic>)
|
||||
.map((e) => Muscle.fromJson(e as Map<String, dynamic>))
|
||||
@@ -35,6 +38,9 @@ Map<String, dynamic> _$$ExerciseBaseDataImplToJson(_$ExerciseBaseDataImpl instan
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'uuid': instance.uuid,
|
||||
'created': instance.created.toIso8601String(),
|
||||
'last_update': instance.lastUpdate.toIso8601String(),
|
||||
'last_update_global': instance.lastUpdateGlobal.toIso8601String(),
|
||||
'category': instance.category,
|
||||
'muscles': instance.muscles,
|
||||
'muscles_secondary': instance.musclesSecondary,
|
||||
|
||||
@@ -34,7 +34,7 @@ class Muscle extends Equatable {
|
||||
@JsonKey(required: true, name: 'name_en')
|
||||
final String nameEn;
|
||||
|
||||
@JsonKey(name: 'is_front', required: true)
|
||||
@JsonKey(required: true, name: 'is_front')
|
||||
final bool isFront;
|
||||
|
||||
const Muscle({
|
||||
@@ -46,6 +46,7 @@ class Muscle extends Equatable {
|
||||
|
||||
// Boilerplate
|
||||
factory Muscle.fromJson(Map<String, dynamic> json) => _$MuscleFromJson(json);
|
||||
|
||||
Map<String, dynamic> toJson() => _$MuscleToJson(this);
|
||||
|
||||
@override
|
||||
|
||||
@@ -22,24 +22,20 @@ import 'dart:developer';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:json_annotation/json_annotation.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:wger/core/locator.dart';
|
||||
import 'package:wger/database/exercise_DB/exercise_database.dart';
|
||||
import 'package:wger/database/exercises/exercise_database.dart';
|
||||
import 'package:wger/exceptions/no_such_entry_exception.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/models/exercises/alias.dart';
|
||||
import 'package:wger/models/exercises/base.dart';
|
||||
import 'package:wger/models/exercises/category.dart';
|
||||
import 'package:wger/models/exercises/comment.dart';
|
||||
import 'package:wger/models/exercises/equipment.dart';
|
||||
import 'package:wger/models/exercises/exercise_base_data.dart';
|
||||
import 'package:wger/models/exercises/image.dart';
|
||||
import 'package:wger/models/exercises/language.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
import 'package:wger/models/exercises/translation.dart';
|
||||
import 'package:wger/models/exercises/variation.dart';
|
||||
import 'package:wger/models/exercises/video.dart';
|
||||
import 'package:wger/providers/base_provider.dart';
|
||||
|
||||
class ExercisesProvider with ChangeNotifier {
|
||||
@@ -50,14 +46,14 @@ class ExercisesProvider with ChangeNotifier {
|
||||
static const EXERCISE_CACHE_DAYS = 7;
|
||||
static const CACHE_VERSION = 4;
|
||||
|
||||
static const _exerciseBaseInfoUrlPath = 'exercisebaseinfo';
|
||||
static const _exerciseSearchPath = 'exercise/search';
|
||||
static const exerciseBaseInfoUrlPath = 'exercisebaseinfo';
|
||||
static const exerciseSearchPath = 'exercise/search';
|
||||
|
||||
static const _exerciseVariationsUrlPath = 'variation';
|
||||
static const _categoriesUrlPath = 'exercisecategory';
|
||||
static const _musclesUrlPath = 'muscle';
|
||||
static const _equipmentUrlPath = 'equipment';
|
||||
static const _languageUrlPath = 'language';
|
||||
static const exerciseVariationsUrlPath = 'variation';
|
||||
static const categoriesUrlPath = 'exercisecategory';
|
||||
static const musclesUrlPath = 'muscle';
|
||||
static const equipmentUrlPath = 'equipment';
|
||||
static const languageUrlPath = 'language';
|
||||
|
||||
List<ExerciseBase> _exerciseBases = [];
|
||||
|
||||
@@ -188,7 +184,7 @@ class ExercisesProvider with ChangeNotifier {
|
||||
}
|
||||
|
||||
/// Find exercise base by ID
|
||||
ExerciseBase findExerciseBaseById(int id) {
|
||||
ExerciseBase findExerciseById(int id) {
|
||||
return _exerciseBases.firstWhere(
|
||||
(base) => base.id == id,
|
||||
orElse: () => throw NoSuchEntryException(),
|
||||
@@ -242,45 +238,50 @@ class ExercisesProvider with ChangeNotifier {
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> fetchAndSetCategories() async {
|
||||
final categories = await baseProvider.fetchPaginated(baseProvider.makeUrl(_categoriesUrlPath));
|
||||
Future<void> fetchAndSetCategoriesFromApi() async {
|
||||
final categories = await baseProvider.fetchPaginated(baseProvider.makeUrl(categoriesUrlPath));
|
||||
for (final category in categories) {
|
||||
_categories.add(ExerciseCategory.fromJson(category));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchAndSetVariations() async {
|
||||
Future<void> fetchAndSetVariationsFromApi() async {
|
||||
final variations =
|
||||
await baseProvider.fetchPaginated(baseProvider.makeUrl(_exerciseVariationsUrlPath));
|
||||
await baseProvider.fetchPaginated(baseProvider.makeUrl(exerciseVariationsUrlPath));
|
||||
for (final variation in variations) {
|
||||
_variations.add(Variation.fromJson(variation));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchAndSetMuscles() async {
|
||||
final muscles = await baseProvider.fetchPaginated(baseProvider.makeUrl(_musclesUrlPath));
|
||||
Future<void> fetchAndSetMusclesFromApi() async {
|
||||
final muscles = await baseProvider.fetchPaginated(baseProvider.makeUrl(musclesUrlPath));
|
||||
|
||||
for (final muscle in muscles) {
|
||||
_muscles.add(Muscle.fromJson(muscle));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchAndSetEquipment() async {
|
||||
final equipments = await baseProvider.fetchPaginated(baseProvider.makeUrl(_equipmentUrlPath));
|
||||
Future<void> fetchAndSetEquipmentsFromApi() async {
|
||||
final equipments = await baseProvider.fetchPaginated(baseProvider.makeUrl(equipmentUrlPath));
|
||||
|
||||
for (final equipment in equipments) {
|
||||
_equipment.add(Equipment.fromJson(equipment));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchAndSetLanguages() async {
|
||||
final languageData = await baseProvider.fetchPaginated(baseProvider.makeUrl(_languageUrlPath));
|
||||
Future<void> fetchAndSetLanguagesFromApi() async {
|
||||
final languageData = await baseProvider.fetchPaginated(baseProvider.makeUrl(languageUrlPath));
|
||||
|
||||
for (final language in languageData) {
|
||||
_languages.add(Language.fromJson(language));
|
||||
}
|
||||
}
|
||||
|
||||
Future<Language> fetchAndSetLanguageFromApi(int id) async {
|
||||
final language = await baseProvider.fetch(baseProvider.makeUrl(languageUrlPath, id: id));
|
||||
return Language.fromJson(language);
|
||||
}
|
||||
|
||||
/// Returns the exercise with the given ID
|
||||
///
|
||||
/// If the exercise is not known locally, it is fetched from the server.
|
||||
@@ -288,52 +289,79 @@ class ExercisesProvider with ChangeNotifier {
|
||||
/// regular not-async getById method can be used
|
||||
Future<ExerciseBase> fetchAndSetExerciseBase(int exerciseBaseId) async {
|
||||
try {
|
||||
return findExerciseBaseById(exerciseBaseId);
|
||||
return findExerciseById(exerciseBaseId);
|
||||
} on NoSuchEntryException {
|
||||
final baseData = await baseProvider.fetch(
|
||||
baseProvider.makeUrl(_exerciseBaseInfoUrlPath, id: exerciseBaseId),
|
||||
baseProvider.makeUrl(exerciseBaseInfoUrlPath, id: exerciseBaseId),
|
||||
);
|
||||
|
||||
final newBase = readExerciseBaseFromBaseInfo(ExerciseBaseData.fromJson(baseData));
|
||||
final exercise = readExerciseBaseFromBaseInfo(ExerciseBaseData.fromJson(baseData));
|
||||
final database = locator<ExerciseDatabase>();
|
||||
|
||||
// TODO: save to cache. Since we can't easily generate the JSON, perhaps just reload?
|
||||
_exerciseBases.add(newBase);
|
||||
return newBase;
|
||||
final exerciseDb = await (database.select(database.exercises)
|
||||
..where((e) => e.id.equals(baseData['id'])))
|
||||
.getSingleOrNull();
|
||||
|
||||
// New exercise, insert
|
||||
if (exerciseDb == null) {
|
||||
database.into(database.exercises).insert(
|
||||
ExercisesCompanion.insert(
|
||||
id: baseData['id'],
|
||||
data: jsonEncode(baseData),
|
||||
lastUpdate: DateTime.parse(baseData['last_update_global']),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// If there were updates on the server, update
|
||||
final lastUpdateApi = DateTime.parse(baseData['last_update_global']);
|
||||
if (exerciseDb != null && lastUpdateApi.isAfter(exerciseDb.lastUpdate)) {
|
||||
(database.update(database.exercises)..where((e) => e.id.equals(baseData['id']))).write(
|
||||
ExercisesCompanion(
|
||||
id: baseData['id'],
|
||||
data: Value(jsonEncode(baseData)),
|
||||
lastUpdate: Value(DateTime.parse(baseData['last_update_global'])),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
_exerciseBases.add(exercise);
|
||||
return exercise;
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses the response from the exercisebaseinfo endpoint and returns
|
||||
/// Parses the response from the "exercisebaseinfo" endpoint and returns
|
||||
/// a full exercise base
|
||||
ExerciseBase readExerciseBaseFromBaseInfo(ExerciseBaseData baseData) {
|
||||
final List<Translation> exercises = [];
|
||||
for (final exerciseData in baseData.exercises) {
|
||||
final exercise = Translation(
|
||||
id: exerciseData.id,
|
||||
uuid: exerciseData.uuid,
|
||||
name: exerciseData.name,
|
||||
description: exerciseData.description,
|
||||
final List<Translation> translations = [];
|
||||
for (final translationData in baseData.exercises) {
|
||||
final translation = Translation(
|
||||
id: translationData.id,
|
||||
uuid: translationData.uuid,
|
||||
name: translationData.name,
|
||||
description: translationData.description,
|
||||
baseId: baseData.id,
|
||||
);
|
||||
exercise.aliases = exerciseData.aliases
|
||||
.map((e) => Alias(exerciseId: exercise.id ?? 0, alias: e.alias))
|
||||
.toList()
|
||||
.cast<Alias>();
|
||||
exercise.notes = exerciseData.notes;
|
||||
exercise.language = findLanguageById(exerciseData.languageId);
|
||||
exercises.add(exercise);
|
||||
translation.aliases = translationData.aliases
|
||||
.map((e) => Alias(exerciseId: translation.id ?? 0, alias: e.alias))
|
||||
.toList();
|
||||
translation.notes = translationData.notes;
|
||||
translation.language = findLanguageById(translationData.languageId);
|
||||
translations.add(translation);
|
||||
}
|
||||
|
||||
final exerciseBase = ExerciseBase(
|
||||
id: baseData.id,
|
||||
uuid: baseData.uuid,
|
||||
created: null,
|
||||
//creationDate: toDate(baseData['creation_date']),
|
||||
created: baseData.created,
|
||||
lastUpdate: baseData.lastUpdate,
|
||||
lastUpdateGlobal: baseData.lastUpdateGlobal,
|
||||
musclesSecondary: baseData.muscles,
|
||||
muscles: baseData.muscles,
|
||||
equipment: baseData.equipment,
|
||||
category: baseData.category,
|
||||
images: baseData.images,
|
||||
exercises: exercises,
|
||||
exercises: translations,
|
||||
videos: baseData.videos,
|
||||
);
|
||||
|
||||
@@ -342,117 +370,285 @@ class ExercisesProvider with ChangeNotifier {
|
||||
|
||||
/// Checks the required cache version
|
||||
///
|
||||
/// This is needed since the content of the exercise cache can change and we need
|
||||
/// to invalidate it as a result
|
||||
/// This is needed since the content of the exercise cache (the API response)
|
||||
/// can change and we need to invalidate it as a result
|
||||
Future<void> checkExerciseCacheVersion() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final database = locator<ExerciseDatabase>();
|
||||
if (prefs.containsKey(PREFS_EXERCISE_CACHE_VERSION)) {
|
||||
final cacheVersion = prefs.getInt(PREFS_EXERCISE_CACHE_VERSION);
|
||||
final cacheVersion = prefs.getInt(PREFS_EXERCISE_CACHE_VERSION)!;
|
||||
|
||||
// Cache has has a different version, reset
|
||||
if ((cacheVersion ?? 0) != CACHE_VERSION) {
|
||||
database.delete(database.exerciseTableItems).go();
|
||||
await prefs.remove(PREFS_EXERCISES);
|
||||
if (cacheVersion != CACHE_VERSION) {
|
||||
database.delete(database.exercises).go();
|
||||
}
|
||||
await prefs.setInt(PREFS_EXERCISE_CACHE_VERSION, CACHE_VERSION);
|
||||
|
||||
// Cache has no version key, reset
|
||||
// Note: this is only needed for very old apps that update and could probably
|
||||
// be just removed in the future
|
||||
} else {
|
||||
await prefs.remove(PREFS_EXERCISES);
|
||||
database.delete(database.exerciseTableItems).go();
|
||||
database.delete(database.exercises).go();
|
||||
await prefs.setInt(PREFS_EXERCISE_CACHE_VERSION, CACHE_VERSION);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchAndSetExercises() async {
|
||||
Future<void> initCacheTimesLocalPrefs() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
// TODO: The exercise data was previously saved in PREFS_EXERCISES. This
|
||||
// can now be deleted. After some time when we can be sure all users
|
||||
// have updated their app, we can also remove this line and the
|
||||
// PREFS_EXERCISES constant
|
||||
if (prefs.containsKey(PREFS_EXERCISES)) {
|
||||
prefs.remove(PREFS_EXERCISES);
|
||||
}
|
||||
|
||||
final initDate = DateTime(2023, 1, 1).toIso8601String();
|
||||
|
||||
if (!prefs.containsKey(PREFS_LAST_UPDATED_MUSCLES)) {
|
||||
await prefs.setString(PREFS_LAST_UPDATED_MUSCLES, initDate);
|
||||
}
|
||||
if (!prefs.containsKey(PREFS_LAST_UPDATED_EQUIPMENT)) {
|
||||
await prefs.setString(PREFS_LAST_UPDATED_EQUIPMENT, initDate);
|
||||
}
|
||||
if (!prefs.containsKey(PREFS_LAST_UPDATED_LANGUAGES)) {
|
||||
await prefs.setString(PREFS_LAST_UPDATED_LANGUAGES, initDate);
|
||||
}
|
||||
if (!prefs.containsKey(PREFS_LAST_UPDATED_CATEGORIES)) {
|
||||
await prefs.setString(PREFS_LAST_UPDATED_CATEGORIES, initDate);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> clearAllCachesAndPrefs() async {
|
||||
final database = locator<ExerciseDatabase>();
|
||||
await database.deleteEverything();
|
||||
|
||||
await initCacheTimesLocalPrefs();
|
||||
}
|
||||
|
||||
/// Loads all needed data for the exercises from the local cache, or if not available,
|
||||
/// from the API:
|
||||
/// - Muscles
|
||||
/// - Categories
|
||||
/// - Languages
|
||||
/// - Equipment
|
||||
/// - Exercises
|
||||
Future<void> fetchAndSetInitialData() async {
|
||||
clear();
|
||||
|
||||
// Load exercises from cache, if available
|
||||
final database = locator<ExerciseDatabase>();
|
||||
|
||||
// Only uncomment if need to delete the table, (only for testing purposes).
|
||||
// await database.delete(database.exerciseTableItems).go();
|
||||
// Fetch the list of rows from ExercisesDataTable. ExerciseTable is the Type of the Row
|
||||
final List<ExerciseTable> items = await database.select(database.exerciseTableItems).get();
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await initCacheTimesLocalPrefs();
|
||||
await checkExerciseCacheVersion();
|
||||
final cacheData = json.decode(prefs.getString(PREFS_EXERCISES) ?? '{}');
|
||||
|
||||
if (items.isNotEmpty) {
|
||||
if (DateTime.parse(cacheData['expiresIn']).isAfter(DateTime.now())) {
|
||||
for (final element in items) {
|
||||
if (element.equipment != null) {
|
||||
_equipment.add(element.equipment!);
|
||||
}
|
||||
if (element.muscle != null) {
|
||||
_muscles.add(element.muscle!);
|
||||
}
|
||||
if (element.variation != null) {
|
||||
_variations.add(element.variation!);
|
||||
}
|
||||
if (element.language != null) {
|
||||
_languages.add(element.language!);
|
||||
}
|
||||
if (element.category != null) {
|
||||
_categories.add(element.category!);
|
||||
}
|
||||
if (element.exercisebase != null) {
|
||||
_exerciseBases.add(element.exercisebase!);
|
||||
}
|
||||
}
|
||||
_initFilters();
|
||||
log("Read ${_exerciseBases.length} exercises from cache. Valid till ${cacheData['expiresIn']}");
|
||||
// Load categories, muscles, equipment and languages
|
||||
await Future.wait([
|
||||
fetchAndSetMuscles(database),
|
||||
fetchAndSetCategories(database),
|
||||
fetchAndSetLanguages(database),
|
||||
fetchAndSetEquipments(database),
|
||||
]);
|
||||
await fetchAndSetExercises(database);
|
||||
|
||||
_initFilters();
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
/// Fetches and sets the available exercises
|
||||
///
|
||||
/// We first try to read from the local DB, and from the API if the data is too old
|
||||
Future<void> fetchAndSetExercises(ExerciseDatabase database,
|
||||
{bool forceDeleteCache = false}) async {
|
||||
if (forceDeleteCache) {
|
||||
await database.delete(database.exercises).go();
|
||||
}
|
||||
|
||||
final exercises = await database.select(database.exercises).get();
|
||||
log('Loaded ${exercises.length} exercises from cache');
|
||||
|
||||
_exerciseBases = exercises
|
||||
.map((e) => readExerciseBaseFromBaseInfo(ExerciseBaseData.fromJson(json.decode(e.data))))
|
||||
.toList();
|
||||
|
||||
// updateExerciseCache(database);
|
||||
}
|
||||
|
||||
Future<void> updateExerciseCache(ExerciseDatabase database) async {
|
||||
final data = await Future.wait<dynamic>([
|
||||
baseProvider.fetch(baseProvider.makeUrl(exerciseBaseInfoUrlPath, query: {'limit': '1000'})),
|
||||
// TODO: variations!
|
||||
//fetchAndSetVariationsFromApi(),
|
||||
]);
|
||||
|
||||
final List<dynamic> exercisesData = data[0]['results'];
|
||||
final exerciseBaseData = exercisesData.map((e) => ExerciseBaseData.fromJson(e)).toList();
|
||||
_exerciseBases = exerciseBaseData.map((e) => readExerciseBaseFromBaseInfo(e)).toList();
|
||||
|
||||
// Insert new entries and update ones that have been edited
|
||||
Future.forEach(exercisesData, (exerciseData) async {
|
||||
final exercise = await (database.select(database.exercises)
|
||||
..where((e) => e.id.equals(exerciseData['id'])))
|
||||
.getSingleOrNull();
|
||||
|
||||
// New exercise, insert
|
||||
if (exercise == null) {
|
||||
database.into(database.exercises).insert(
|
||||
ExercisesCompanion.insert(
|
||||
id: exerciseData['id'],
|
||||
data: jsonEncode(exerciseData),
|
||||
lastUpdate: DateTime.parse(exerciseData['last_update_global']),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// If there were updates on the server, update
|
||||
final lastUpdateApi = DateTime.parse(exerciseData['last_update_global']);
|
||||
if (exercise != null && lastUpdateApi.isAfter(exercise.lastUpdate)) {
|
||||
// TODO: timezones 🥳
|
||||
print(
|
||||
'Exercise ${exercise.id}: update API $lastUpdateApi | Update DB: ${exercise.lastUpdate}');
|
||||
(database.update(database.exercises)..where((e) => e.id.equals(exerciseData['id']))).write(
|
||||
ExercisesCompanion(
|
||||
id: Value(exerciseData['id']),
|
||||
data: Value(jsonEncode(exerciseData)),
|
||||
lastUpdate: Value(DateTime.parse(exerciseData['last_update_global'])),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Fetches and sets the available muscles
|
||||
///
|
||||
/// We first try to read from the local DB, and from the API if the data is too old
|
||||
Future<void> fetchAndSetMuscles(ExerciseDatabase database) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
var validTill = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_MUSCLES)!);
|
||||
|
||||
// Cache still valid, return it
|
||||
if (validTill.isAfter(DateTime.now())) {
|
||||
final muscles = await database.select(database.muscles).get();
|
||||
|
||||
if (muscles.isNotEmpty) {
|
||||
_muscles = muscles.map((e) => e.data).toList();
|
||||
log('Loaded ${_muscles.length} muscles from cache');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Load categories, muscles, equipment and languages
|
||||
final data = await Future.wait<dynamic>([
|
||||
baseProvider.fetch(baseProvider.makeUrl(_exerciseBaseInfoUrlPath, query: {'limit': '1000'})),
|
||||
fetchAndSetCategories(),
|
||||
fetchAndSetMuscles(),
|
||||
fetchAndSetEquipment(),
|
||||
fetchAndSetLanguages(),
|
||||
fetchAndSetVariations(),
|
||||
]);
|
||||
final List<dynamic> exerciseData = data[0]['results'];
|
||||
// Fetch from API and save to DB
|
||||
await fetchAndSetMusclesFromApi();
|
||||
await database.delete(database.muscles).go();
|
||||
await Future.forEach(_muscles, (e) async {
|
||||
await database.into(database.muscles).insert(
|
||||
MusclesCompanion.insert(
|
||||
id: e.id,
|
||||
data: e,
|
||||
),
|
||||
);
|
||||
});
|
||||
validTill = DateTime.now().add(const Duration(days: EXERCISE_CACHE_DAYS));
|
||||
await prefs.setString(PREFS_LAST_UPDATED_MUSCLES, validTill.toIso8601String());
|
||||
log('Wrote ${_muscles.length} muscles from cache. Valid till ${validTill}');
|
||||
}
|
||||
|
||||
final List<ExerciseBaseData> exerciseBaseData =
|
||||
exerciseData.map((e) => ExerciseBaseData.fromJson(e)).toList();
|
||||
/// Fetches and sets the available categories
|
||||
///
|
||||
/// We first try to read from the local DB, and from the API if the data is too old
|
||||
Future<void> fetchAndSetCategories(ExerciseDatabase database) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
var validTill = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_CATEGORIES)!);
|
||||
|
||||
_exerciseBases =
|
||||
exerciseBaseData.map((e) => readExerciseBaseFromBaseInfo(e)).toList().cast<ExerciseBase>();
|
||||
try {
|
||||
// Save the result to the cache
|
||||
for (int i = 0; i < _exerciseBases.length; i++) {
|
||||
await database.into(database.exerciseTableItems).insert(
|
||||
ExerciseTableItemsCompanion.insert(
|
||||
category: (i < _categories.length) ? Value(_categories[i]) : const Value(null),
|
||||
equipment: (i < _equipment.length) ? Value(_equipment[i]) : const Value(null),
|
||||
exercisebase:
|
||||
(i < _exerciseBases.length) ? Value(_exerciseBases[i]) : const Value(null),
|
||||
muscle: (i < _muscles.length) ? Value(_muscles[i]) : const Value(null),
|
||||
variation: (i < _variations.length) ? Value(_variations[i]) : const Value(null),
|
||||
language: (i < _languages.length) ? Value(_languages[i]) : const Value(null),
|
||||
),
|
||||
);
|
||||
// Cache still valid, return it
|
||||
if (validTill.isAfter(DateTime.now())) {
|
||||
final categories = await database.select(database.categories).get();
|
||||
|
||||
if (categories.isNotEmpty) {
|
||||
_categories = categories.map((e) => e.data).toList();
|
||||
log('Loaded ${categories.length} categories from cache');
|
||||
return;
|
||||
}
|
||||
// final List<ExerciseTable> items = await database.select(database.exerciseTableItems).get();
|
||||
final cacheData = {
|
||||
'expiresIn':
|
||||
DateTime.now().add(const Duration(days: EXERCISE_CACHE_DAYS)).toIso8601String(),
|
||||
};
|
||||
log("Saved ${_exerciseBases.length} exercises to cache. Valid till ${cacheData['expiresIn']}");
|
||||
|
||||
await prefs.setString(PREFS_EXERCISES, json.encode(cacheData));
|
||||
_initFilters();
|
||||
notifyListeners();
|
||||
} on MissingRequiredKeysException catch (error) {
|
||||
log(error.missingKeys.toString());
|
||||
rethrow;
|
||||
}
|
||||
|
||||
// Fetch from API and save to DB
|
||||
await fetchAndSetCategoriesFromApi();
|
||||
await database.delete(database.categories).go();
|
||||
await Future.forEach(_categories, (e) async {
|
||||
await database.into(database.categories).insert(
|
||||
CategoriesCompanion.insert(
|
||||
id: e.id,
|
||||
data: e,
|
||||
),
|
||||
);
|
||||
});
|
||||
validTill = DateTime.now().add(const Duration(days: EXERCISE_CACHE_DAYS));
|
||||
await prefs.setString(PREFS_LAST_UPDATED_CATEGORIES, validTill.toIso8601String());
|
||||
}
|
||||
|
||||
/// Fetches and sets the available languages
|
||||
///
|
||||
/// We first try to read from the local DB, and from the API if the data is too old
|
||||
Future<void> fetchAndSetLanguages(ExerciseDatabase database) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
var validTill = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_LANGUAGES)!);
|
||||
|
||||
// Cache still valid, return it
|
||||
if (validTill.isAfter(DateTime.now())) {
|
||||
final languages = await database.select(database.languages).get();
|
||||
|
||||
if (languages.isNotEmpty) {
|
||||
_languages = languages.map((e) => e.data).toList();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch from API and save to DB
|
||||
await fetchAndSetLanguagesFromApi();
|
||||
await database.delete(database.languages).go();
|
||||
await Future.forEach(_languages, (e) async {
|
||||
await database.into(database.languages).insert(
|
||||
LanguagesCompanion.insert(
|
||||
id: e.id,
|
||||
data: e,
|
||||
),
|
||||
);
|
||||
});
|
||||
validTill = DateTime.now().add(const Duration(days: EXERCISE_CACHE_DAYS));
|
||||
await prefs.setString(PREFS_LAST_UPDATED_LANGUAGES, validTill.toIso8601String());
|
||||
}
|
||||
|
||||
/// Fetches and sets the available equipment
|
||||
///
|
||||
/// We first try to read from the local DB, and from the API if the data is too old
|
||||
Future<void> fetchAndSetEquipments(ExerciseDatabase database) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
var validTill = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_EQUIPMENT)!);
|
||||
|
||||
// Cache still valid, return it
|
||||
if (validTill.isAfter(DateTime.now())) {
|
||||
final equipments = await database.select(database.equipments).get();
|
||||
|
||||
if (equipments.isNotEmpty) {
|
||||
_equipment = equipments.map((e) => e.data).toList();
|
||||
log('Loaded ${equipment.length} equipment from cache');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch from API and save to DB
|
||||
await fetchAndSetEquipmentsFromApi();
|
||||
await database.delete(database.equipments).go();
|
||||
await Future.forEach(_equipment, (e) async {
|
||||
await database.into(database.equipments).insert(
|
||||
EquipmentsCompanion.insert(
|
||||
id: e.id,
|
||||
data: e,
|
||||
),
|
||||
);
|
||||
});
|
||||
validTill = DateTime.now().add(const Duration(days: EXERCISE_CACHE_DAYS));
|
||||
await prefs.setString(PREFS_LAST_UPDATED_EQUIPMENT, validTill.toIso8601String());
|
||||
}
|
||||
|
||||
/// Searches for an exercise
|
||||
@@ -473,7 +669,7 @@ class ExercisesProvider with ChangeNotifier {
|
||||
// Send the request
|
||||
final result = await baseProvider.fetch(
|
||||
baseProvider.makeUrl(
|
||||
_exerciseSearchPath,
|
||||
exerciseSearchPath,
|
||||
query: {'term': name, 'language': languages.join(',')},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -90,7 +90,7 @@ class _HomeTabsScreenState extends State<HomeTabsScreen> with SingleTickerProvid
|
||||
userProvider.fetchAndSetProfile(),
|
||||
workoutPlansProvider.fetchAndSetUnits(),
|
||||
nutritionPlansProvider.fetchIngredientsFromCache(),
|
||||
exercisesProvider.fetchAndSetExercises(),
|
||||
exercisesProvider.fetchAndSetInitialData(),
|
||||
]);
|
||||
} catch (e) {
|
||||
log('fire! fire!');
|
||||
|
||||
@@ -86,7 +86,7 @@ class _GymModeState extends State<GymMode> {
|
||||
var firstPage = true;
|
||||
for (final setting in set.settingsComputed) {
|
||||
final exerciseBase = Provider.of<ExercisesProvider>(context, listen: false)
|
||||
.findExerciseBaseById(setting.exerciseBaseId);
|
||||
.findExerciseById(setting.exerciseBaseId);
|
||||
|
||||
if (firstPage) {
|
||||
_exercisePages[exerciseBase.uuid!] = currentPage;
|
||||
@@ -114,7 +114,7 @@ class _GymModeState extends State<GymMode> {
|
||||
var firstPage = true;
|
||||
for (final setting in set.settingsComputed) {
|
||||
final ratioCompleted = currentElement / _totalElements;
|
||||
final exerciseBase = exerciseProvider.findExerciseBaseById(setting.exerciseBaseId);
|
||||
final exerciseBase = exerciseProvider.findExerciseById(setting.exerciseBaseId);
|
||||
currentElement++;
|
||||
|
||||
if (firstPage) {
|
||||
|
||||
34
pubspec.lock
34
pubspec.lock
@@ -245,10 +245,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: collection
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.2"
|
||||
version: "1.18.0"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -824,10 +824,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: meta
|
||||
sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
|
||||
sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -968,10 +968,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: platform
|
||||
sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76"
|
||||
sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.0"
|
||||
version: "3.1.2"
|
||||
plugin_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1213,18 +1213,18 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stack_trace
|
||||
sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
|
||||
sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.11.0"
|
||||
version: "1.11.1"
|
||||
stream_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: stream_channel
|
||||
sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
|
||||
sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.1"
|
||||
version: "2.1.2"
|
||||
stream_transform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1269,10 +1269,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.6.0"
|
||||
version: "0.6.1"
|
||||
timing:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1445,10 +1445,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vm_service
|
||||
sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f
|
||||
sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.7.1"
|
||||
version: "11.10.0"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1461,10 +1461,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
version: "0.3.0"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -1514,5 +1514,5 @@ packages:
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.1.0 <4.0.0"
|
||||
dart: ">=3.2.0-194.0.dev <4.0.0"
|
||||
flutter: ">=3.13.0"
|
||||
|
||||
417
test/exercises/exercise_provider_db_test.dart
Normal file
417
test/exercises/exercise_provider_db_test.dart
Normal file
@@ -0,0 +1,417 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/native.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:mockito/mockito.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:wger/database/exercises/exercise_database.dart';
|
||||
import 'package:wger/helpers/consts.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
|
||||
import '../../test_data/exercises.dart';
|
||||
import '../fixtures/fixture_reader.dart';
|
||||
import '../measurements/measurement_provider_test.mocks.dart';
|
||||
|
||||
void main() {
|
||||
late MockWgerBaseProvider mockBaseProvider;
|
||||
late ExercisesProvider provider;
|
||||
late ExerciseDatabase database;
|
||||
|
||||
const String categoryUrl = 'exercisecategory';
|
||||
const String exerciseBaseInfoUrl = 'exercisebaseinfo';
|
||||
const String muscleUrl = 'muscle';
|
||||
const String equipmentUrl = 'equipment';
|
||||
const String languageUrl = 'language';
|
||||
|
||||
final Uri tCategoryEntriesUri = Uri(
|
||||
scheme: 'http',
|
||||
host: 'localhost',
|
||||
path: 'api/v2/$categoryUrl/',
|
||||
);
|
||||
|
||||
final Uri texerciseBaseInfoUri = Uri(
|
||||
scheme: 'http',
|
||||
host: 'localhost',
|
||||
path: 'api/v2/$exerciseBaseInfoUrl/',
|
||||
);
|
||||
|
||||
final Uri tMuscleEntriesUri = Uri(
|
||||
scheme: 'http',
|
||||
host: 'localhost',
|
||||
path: 'api/v2/$muscleUrl/',
|
||||
);
|
||||
|
||||
final Uri tEquipmentEntriesUri = Uri(
|
||||
scheme: 'http',
|
||||
host: 'localhost',
|
||||
path: 'api/v2/$equipmentUrl/',
|
||||
);
|
||||
|
||||
final Uri tLanguageEntriesUri = Uri(
|
||||
scheme: 'http',
|
||||
host: 'localhost',
|
||||
path: 'api/v2/$languageUrl/',
|
||||
);
|
||||
|
||||
const muscle1 = Muscle(id: 1, name: 'Biceps brachii', nameEn: 'Biceps', isFront: true);
|
||||
const muscle2 = Muscle(id: 2, name: 'Anterior deltoid', nameEn: 'Biceps', isFront: true);
|
||||
const muscle3 = Muscle(id: 4, name: 'Biceps femoris', nameEn: 'Hamstrings', isFront: false);
|
||||
|
||||
final Map<String, dynamic> tCategoryMap = jsonDecode(
|
||||
fixture('exercises/category_entries.json'),
|
||||
);
|
||||
final Map<String, dynamic> tMuscleMap = jsonDecode(
|
||||
fixture('exercises/muscles_entries.json'),
|
||||
);
|
||||
final Map<String, dynamic> tEquipmentMap = jsonDecode(
|
||||
fixture('exercises/equipment_entries.json'),
|
||||
);
|
||||
final Map<String, dynamic> tLanguageMap = jsonDecode(
|
||||
fixture('exercises/language_entries.json'),
|
||||
);
|
||||
final Map<String, dynamic> tExerciseBaseInfoMap = jsonDecode(
|
||||
fixture('exercises/exercisebaseinfo_response.json'),
|
||||
);
|
||||
|
||||
setUp(() {
|
||||
mockBaseProvider = MockWgerBaseProvider();
|
||||
provider = ExercisesProvider(mockBaseProvider);
|
||||
database = ExerciseDatabase.inMemory(NativeDatabase.memory());
|
||||
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
SharedPreferences.setMockInitialValues({});
|
||||
|
||||
// Mock categories
|
||||
when(mockBaseProvider.makeUrl(categoryUrl)).thenReturn(tCategoryEntriesUri);
|
||||
when(mockBaseProvider.fetchPaginated(tCategoryEntriesUri))
|
||||
.thenAnswer((_) => Future.value(tCategoryMap['results']));
|
||||
|
||||
// Mock muscles
|
||||
when(mockBaseProvider.makeUrl(muscleUrl)).thenReturn(tMuscleEntriesUri);
|
||||
when(mockBaseProvider.fetchPaginated(tMuscleEntriesUri))
|
||||
.thenAnswer((_) => Future.value(tMuscleMap['results']));
|
||||
|
||||
// Mock equipment
|
||||
when(mockBaseProvider.makeUrl(equipmentUrl)).thenReturn(tEquipmentEntriesUri);
|
||||
when(mockBaseProvider.fetchPaginated(tEquipmentEntriesUri))
|
||||
.thenAnswer((_) => Future.value(tEquipmentMap['results']));
|
||||
|
||||
// Mock languages
|
||||
when(mockBaseProvider.makeUrl(languageUrl, query: anyNamed('query')))
|
||||
.thenReturn(tLanguageEntriesUri);
|
||||
when(mockBaseProvider.fetchPaginated(tLanguageEntriesUri))
|
||||
.thenAnswer((_) => Future.value(tLanguageMap['results']));
|
||||
|
||||
// Mock base info response
|
||||
when(mockBaseProvider.makeUrl(exerciseBaseInfoUrl)).thenReturn(texerciseBaseInfoUri);
|
||||
when(mockBaseProvider.fetch(texerciseBaseInfoUri))
|
||||
.thenAnswer((_) => Future.value(tExerciseBaseInfoMap));
|
||||
});
|
||||
|
||||
tearDown(() async {
|
||||
await database.close();
|
||||
});
|
||||
|
||||
group('Muscles', () {
|
||||
test('that fetched data from the API is written to the DB', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetMuscles(database);
|
||||
|
||||
// Assert
|
||||
final updateTime = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_MUSCLES)!);
|
||||
final valid = DateTime.now().add(const Duration(days: ExercisesProvider.EXERCISE_CACHE_DAYS));
|
||||
expect(
|
||||
DateTime(updateTime.year, updateTime.month, updateTime.day),
|
||||
DateTime(valid.year, valid.month, valid.day),
|
||||
);
|
||||
|
||||
final muscles = await database.select(database.muscles).get();
|
||||
|
||||
verify(mockBaseProvider.fetchPaginated(any));
|
||||
|
||||
expect(muscles[0].id, 2);
|
||||
expect(muscles[0].data, muscle2);
|
||||
|
||||
expect(muscles[1].id, 1);
|
||||
expect(muscles[1].data, muscle1);
|
||||
|
||||
expect(muscles[2].id, 4);
|
||||
expect(muscles[2].data, muscle3);
|
||||
|
||||
expect(provider.muscles[0], muscle2);
|
||||
expect(provider.muscles[1], muscle1);
|
||||
expect(provider.muscles[2], muscle3);
|
||||
});
|
||||
|
||||
test('that if there is already valid data in the DB, the API is not hit', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
|
||||
final valid = DateTime.now().add(const Duration(days: 1));
|
||||
prefs.setString(PREFS_LAST_UPDATED_MUSCLES, valid.toIso8601String());
|
||||
|
||||
await database
|
||||
.into(database.muscles)
|
||||
.insert(MusclesCompanion.insert(id: muscle1.id, data: muscle1));
|
||||
await database
|
||||
.into(database.muscles)
|
||||
.insert(MusclesCompanion.insert(id: muscle2.id, data: muscle2));
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetMuscles(database);
|
||||
|
||||
// Assert
|
||||
final updateTime = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_MUSCLES)!);
|
||||
expect(
|
||||
DateTime(updateTime.year, updateTime.month, updateTime.day),
|
||||
DateTime(valid.year, valid.month, valid.day),
|
||||
);
|
||||
|
||||
expect(provider.muscles[0], muscle1);
|
||||
expect(provider.muscles[1], muscle2);
|
||||
|
||||
verifyNever(mockBaseProvider.fetchPaginated(any));
|
||||
});
|
||||
});
|
||||
|
||||
group('Languages', () {
|
||||
test('that fetched data from the API is written to the DB', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetLanguages(database);
|
||||
|
||||
// Assert
|
||||
final updateTime = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_LANGUAGES)!);
|
||||
final valid = DateTime.now().add(const Duration(days: ExercisesProvider.EXERCISE_CACHE_DAYS));
|
||||
expect(
|
||||
DateTime(updateTime.year, updateTime.month, updateTime.day),
|
||||
DateTime(valid.year, valid.month, valid.day),
|
||||
);
|
||||
|
||||
final languages = await database.select(database.languages).get();
|
||||
|
||||
verify(mockBaseProvider.fetchPaginated(any));
|
||||
|
||||
expect(languages[0].id, tLanguage1.id);
|
||||
expect(languages[0].data, tLanguage1);
|
||||
|
||||
expect(languages[1].id, tLanguage2.id);
|
||||
expect(languages[1].data, tLanguage2);
|
||||
|
||||
expect(languages[2].id, tLanguage4.id);
|
||||
expect(languages[2].data, tLanguage4);
|
||||
|
||||
expect(languages[3].id, tLanguage3.id);
|
||||
expect(languages[3].data, tLanguage3);
|
||||
|
||||
expect(provider.languages[0], tLanguage1);
|
||||
expect(provider.languages[1], tLanguage2);
|
||||
expect(provider.languages[2], tLanguage4);
|
||||
expect(provider.languages[3], tLanguage3);
|
||||
});
|
||||
|
||||
test('that if there is already valid data in the DB, the API is not hit', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
|
||||
final valid = DateTime.now().add(const Duration(days: 1));
|
||||
prefs.setString(PREFS_LAST_UPDATED_LANGUAGES, valid.toIso8601String());
|
||||
|
||||
await database
|
||||
.into(database.languages)
|
||||
.insert(LanguagesCompanion.insert(id: tLanguage1.id, data: tLanguage1));
|
||||
await database
|
||||
.into(database.languages)
|
||||
.insert(LanguagesCompanion.insert(id: tLanguage2.id, data: tLanguage2));
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetLanguages(database);
|
||||
|
||||
// Assert
|
||||
final updateTime = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_LANGUAGES)!);
|
||||
expect(
|
||||
DateTime(updateTime.year, updateTime.month, updateTime.day),
|
||||
DateTime(valid.year, valid.month, valid.day),
|
||||
);
|
||||
|
||||
expect(provider.languages[0], tLanguage1);
|
||||
expect(provider.languages[1], tLanguage2);
|
||||
|
||||
verifyNever(mockBaseProvider.fetchPaginated(any));
|
||||
});
|
||||
});
|
||||
group('Categories', () {
|
||||
test('that fetched data from the API is written to the DB', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetCategories(database);
|
||||
|
||||
// Assert
|
||||
final updateTime = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_CATEGORIES)!);
|
||||
final valid = DateTime.now().add(const Duration(days: ExercisesProvider.EXERCISE_CACHE_DAYS));
|
||||
expect(
|
||||
DateTime(updateTime.year, updateTime.month, updateTime.day),
|
||||
DateTime(valid.year, valid.month, valid.day),
|
||||
);
|
||||
|
||||
final categories = await database.select(database.categories).get();
|
||||
|
||||
verify(mockBaseProvider.fetchPaginated(any));
|
||||
|
||||
expect(categories[0].id, tCategory1.id);
|
||||
expect(categories[0].data, tCategory1);
|
||||
|
||||
expect(categories[1].id, tCategory2.id);
|
||||
expect(categories[1].data, tCategory2);
|
||||
|
||||
expect(provider.categories[0], tCategory1);
|
||||
expect(provider.categories[1], tCategory2);
|
||||
});
|
||||
|
||||
test('that if there is already valid data in the DB, the API is not hit', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
|
||||
final valid = DateTime.now().add(const Duration(days: 1));
|
||||
prefs.setString(PREFS_LAST_UPDATED_CATEGORIES, valid.toIso8601String());
|
||||
|
||||
await database
|
||||
.into(database.categories)
|
||||
.insert(CategoriesCompanion.insert(id: tCategory1.id, data: tCategory1));
|
||||
await database
|
||||
.into(database.categories)
|
||||
.insert(CategoriesCompanion.insert(id: tCategory2.id, data: tCategory2));
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetCategories(database);
|
||||
|
||||
// Assert
|
||||
final updateTime = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_CATEGORIES)!);
|
||||
expect(
|
||||
DateTime(updateTime.year, updateTime.month, updateTime.day),
|
||||
DateTime(valid.year, valid.month, valid.day),
|
||||
);
|
||||
|
||||
expect(provider.categories[0], tCategory1);
|
||||
expect(provider.categories[1], tCategory2);
|
||||
|
||||
verifyNever(mockBaseProvider.fetchPaginated(any));
|
||||
});
|
||||
});
|
||||
|
||||
group('Equipment', () {
|
||||
test('that fetched data from the API is written to the DB', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetEquipments(database);
|
||||
|
||||
// Assert
|
||||
final updateTime = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_EQUIPMENT)!);
|
||||
final valid = DateTime.now().add(const Duration(days: ExercisesProvider.EXERCISE_CACHE_DAYS));
|
||||
expect(
|
||||
DateTime(updateTime.year, updateTime.month, updateTime.day),
|
||||
DateTime(valid.year, valid.month, valid.day),
|
||||
);
|
||||
|
||||
final equipmentList = await database.select(database.equipments).get();
|
||||
|
||||
verify(mockBaseProvider.fetchPaginated(any));
|
||||
|
||||
expect(equipmentList[0].id, tEquipment1.id);
|
||||
expect(equipmentList[0].data, tEquipment1);
|
||||
|
||||
expect(equipmentList[1].id, tEquipment2.id);
|
||||
expect(equipmentList[1].data, tEquipment2);
|
||||
|
||||
expect(provider.equipment[0], tEquipment1);
|
||||
expect(provider.equipment[1], tEquipment2);
|
||||
expect(provider.equipment[2], tEquipment3);
|
||||
expect(provider.equipment[3], tEquipment4);
|
||||
});
|
||||
|
||||
test('that if there is already valid data in the DB, the API is not hit', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
|
||||
final valid = DateTime.now().add(const Duration(days: 1));
|
||||
prefs.setString(PREFS_LAST_UPDATED_EQUIPMENT, valid.toIso8601String());
|
||||
|
||||
await database
|
||||
.into(database.equipments)
|
||||
.insert(EquipmentsCompanion.insert(id: tEquipment1.id, data: tEquipment1));
|
||||
await database
|
||||
.into(database.equipments)
|
||||
.insert(EquipmentsCompanion.insert(id: tCategory2.id, data: tEquipment2));
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetEquipments(database);
|
||||
|
||||
// Assert
|
||||
final updateTime = DateTime.parse(prefs.getString(PREFS_LAST_UPDATED_EQUIPMENT)!);
|
||||
expect(
|
||||
DateTime(updateTime.year, updateTime.month, updateTime.day),
|
||||
DateTime(valid.year, valid.month, valid.day),
|
||||
);
|
||||
|
||||
expect(provider.equipment[0], tEquipment1);
|
||||
expect(provider.equipment[1], tEquipment2);
|
||||
|
||||
verifyNever(mockBaseProvider.fetchPaginated(any));
|
||||
});
|
||||
});
|
||||
|
||||
group('Exercises', () {
|
||||
test('that if there is already valid data in the DB, the API is not hit', () async {
|
||||
// Arrange
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await provider.initCacheTimesLocalPrefs();
|
||||
final valid = DateTime.now().add(const Duration(days: 1));
|
||||
prefs.setString(PREFS_LAST_UPDATED_LANGUAGES, valid.toIso8601String());
|
||||
|
||||
await database.into(database.exercises).insert(
|
||||
ExercisesCompanion.insert(
|
||||
id: tExerciseBaseInfoMap['id'],
|
||||
data: json.encode(tExerciseBaseInfoMap),
|
||||
lastUpdate: DateTime.parse(tExerciseBaseInfoMap['last_update_global']),
|
||||
),
|
||||
);
|
||||
await database
|
||||
.into(database.languages)
|
||||
.insert(LanguagesCompanion.insert(id: tLanguage1.id, data: tLanguage1));
|
||||
await database
|
||||
.into(database.languages)
|
||||
.insert(LanguagesCompanion.insert(id: tLanguage2.id, data: tLanguage2));
|
||||
await database
|
||||
.into(database.languages)
|
||||
.insert(LanguagesCompanion.insert(id: tLanguage3.id, data: tLanguage3));
|
||||
|
||||
// Act
|
||||
await provider.fetchAndSetLanguages(database);
|
||||
await provider.fetchAndSetExercises(database);
|
||||
|
||||
// Assert
|
||||
expect(provider.bases[0].id, 9);
|
||||
expect(provider.bases[0].uuid, '1b020b3a-3732-4c7e-92fd-a0cec90ed69b');
|
||||
verifyNever(mockBaseProvider.fetchPaginated(any));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -21,7 +21,7 @@ void main() {
|
||||
path: 'api/v2/$exerciseBaseInfoUrl/9/',
|
||||
);
|
||||
|
||||
final Map<String, dynamic> tExerciseBaseInfoMap = jsonDecode(
|
||||
final Map<String, dynamic> tExerciseInfoMap = jsonDecode(
|
||||
fixture('exercises/exercisebaseinfo_response.json'),
|
||||
);
|
||||
|
||||
@@ -36,7 +36,7 @@ void main() {
|
||||
mockBaseProvider.makeUrl(exerciseBaseInfoUrl, id: 9),
|
||||
).thenReturn(tExerciseBaseInfoUri);
|
||||
when(mockBaseProvider.fetch(tExerciseBaseInfoUri))
|
||||
.thenAnswer((_) => Future.value(tExerciseBaseInfoMap));
|
||||
.thenAnswer((_) => Future.value(tExerciseInfoMap));
|
||||
});
|
||||
|
||||
group('Correctly loads and parses data from the server', () {
|
||||
@@ -63,7 +63,7 @@ void main() {
|
||||
|
||||
// arrange and act
|
||||
final base =
|
||||
provider.readExerciseBaseFromBaseInfo(ExerciseBaseData.fromJson(tExerciseBaseInfoMap));
|
||||
provider.readExerciseBaseFromBaseInfo(ExerciseBaseData.fromJson(tExerciseInfoMap));
|
||||
|
||||
// assert
|
||||
expect(base.id, 9);
|
||||
@@ -76,8 +76,9 @@ void main() {
|
||||
'Obliquus externus abdominis',
|
||||
]);
|
||||
expect(base.musclesSecondary.map((e) => e.name), [
|
||||
'Anterior deltoid',
|
||||
'Trapezius',
|
||||
'Biceps femoris',
|
||||
'Brachialis',
|
||||
'Obliquus externus abdominis',
|
||||
]);
|
||||
expect(base.images.map((e) => e.uuid), [
|
||||
'1f5d2b2f-d4ea-4eeb-9377-56176465e08d',
|
||||
|
||||
@@ -6,11 +6,11 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:wger/exceptions/no_such_entry_exception.dart';
|
||||
import 'package:wger/models/exercises/category.dart';
|
||||
import 'package:wger/models/exercises/equipment.dart';
|
||||
import 'package:wger/models/exercises/language.dart';
|
||||
import 'package:wger/models/exercises/muscle.dart';
|
||||
import 'package:wger/providers/exercises.dart';
|
||||
|
||||
import '../../test_data/exercises.dart' as data;
|
||||
import '../../test_data/exercises.dart';
|
||||
import '../fixtures/fixture_reader.dart';
|
||||
import '../measurements/measurement_provider_test.mocks.dart';
|
||||
|
||||
@@ -63,8 +63,6 @@ void main() {
|
||||
|
||||
const category1 = ExerciseCategory(id: 1, name: 'Arms');
|
||||
const muscle1 = Muscle(id: 1, name: 'Biceps brachii', nameEn: 'Biceps', isFront: true);
|
||||
const equipment1 = Equipment(id: 1, name: 'Barbell');
|
||||
const language1 = Language(id: 1, shortName: 'de', fullName: 'Deutsch');
|
||||
|
||||
final Map<String, dynamic> tCategoryMap = jsonDecode(
|
||||
fixture('exercises/category_entries.json'),
|
||||
@@ -116,7 +114,7 @@ void main() {
|
||||
group('findCategoryById()', () {
|
||||
test('should return a category for an id', () async {
|
||||
// arrange
|
||||
await provider.fetchAndSetCategories();
|
||||
await provider.fetchAndSetCategoriesFromApi();
|
||||
|
||||
// act
|
||||
final result = provider.findCategoryById(1);
|
||||
@@ -134,7 +132,7 @@ void main() {
|
||||
group('findMuscleById()', () {
|
||||
test('should return a muscle for an id', () async {
|
||||
// arrange
|
||||
await provider.fetchAndSetMuscles();
|
||||
await provider.fetchAndSetMusclesFromApi();
|
||||
|
||||
// act
|
||||
final result = provider.findMuscleById(1);
|
||||
@@ -152,13 +150,13 @@ void main() {
|
||||
group('findEquipmentById()', () {
|
||||
test('should return an equipment for an id', () async {
|
||||
// arrange
|
||||
await provider.fetchAndSetEquipment();
|
||||
await provider.fetchAndSetEquipmentsFromApi();
|
||||
|
||||
// act
|
||||
final result = provider.findEquipmentById(1);
|
||||
|
||||
// assert
|
||||
expect(result, equipment1);
|
||||
expect(result, tEquipment1);
|
||||
});
|
||||
|
||||
test('should throw a NoResultException if no equipment is found', () {
|
||||
@@ -170,13 +168,13 @@ void main() {
|
||||
group('findLanguageById()', () {
|
||||
test('should return a language for an id', () async {
|
||||
// arrange
|
||||
await provider.fetchAndSetLanguages();
|
||||
await provider.fetchAndSetLanguagesFromApi();
|
||||
|
||||
// act
|
||||
final result = provider.findLanguageById(1);
|
||||
|
||||
// assert
|
||||
expect(result, language1);
|
||||
expect(result, tLanguage1);
|
||||
});
|
||||
|
||||
test('should throw a NoResultException if no equipment is found', () {
|
||||
@@ -302,7 +300,7 @@ void main() {
|
||||
// arrange
|
||||
final Filters tFilters = filters.copyWith(
|
||||
exerciseCategories: filters.exerciseCategories.copyWith(items: {data.tCategory2: true}),
|
||||
equipment: filters.equipment.copyWith(items: {equipment1: true}),
|
||||
equipment: filters.equipment.copyWith(items: {tEquipment1: true}),
|
||||
);
|
||||
|
||||
// act
|
||||
|
||||
16
test/fixtures/exercises/category_entries.json
vendored
16
test/fixtures/exercises/category_entries.json
vendored
@@ -3,13 +3,13 @@
|
||||
"next": null,
|
||||
"previous": null,
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Arms"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Abs"
|
||||
}
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Arms"
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"name": "Legs"
|
||||
}
|
||||
]
|
||||
}
|
||||
12
test/fixtures/exercises/equipment_entries.json
vendored
12
test/fixtures/exercises/equipment_entries.json
vendored
@@ -5,18 +5,18 @@
|
||||
"results": [
|
||||
{
|
||||
"id": 1,
|
||||
"name": "Barbell"
|
||||
},
|
||||
{
|
||||
"id": 8,
|
||||
"name": "Bench"
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"id": 2,
|
||||
"name": "Dumbbell"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"id": 3,
|
||||
"name": "Bench"
|
||||
},
|
||||
{
|
||||
"id": 10,
|
||||
"name": "Gym mat"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -14,19 +14,19 @@
|
||||
"full_name": "English"
|
||||
},
|
||||
{
|
||||
"id": 4,
|
||||
"id": 12,
|
||||
"short_name": "es",
|
||||
"full_name": "Español"
|
||||
},
|
||||
{
|
||||
"id": 12,
|
||||
"id": 3,
|
||||
"short_name": "fr",
|
||||
"full_name": "Français"
|
||||
},
|
||||
{
|
||||
"id": 13,
|
||||
"short_name": "it",
|
||||
"full_name": "Italian"
|
||||
"full_name": "Italiano"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -75,8 +75,8 @@ void main() {
|
||||
}
|
||||
|
||||
testWidgets('Test the widgets on the gym mode screen', (WidgetTester tester) async {
|
||||
when(mockExerciseProvider.findExerciseBaseById(1)).thenReturn(bases[0]);
|
||||
when(mockExerciseProvider.findExerciseBaseById(6)).thenReturn(bases[5]);
|
||||
when(mockExerciseProvider.findExerciseById(1)).thenReturn(bases[0]);
|
||||
when(mockExerciseProvider.findExerciseById(6)).thenReturn(bases[5]);
|
||||
|
||||
await tester.pumpWidget(createHomeScreen());
|
||||
await tester.tap(find.byType(TextButton));
|
||||
|
||||
@@ -4,10 +4,11 @@
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:async' as _i10;
|
||||
import 'dart:ui' as _i13;
|
||||
import 'dart:ui' as _i14;
|
||||
|
||||
import 'package:http/http.dart' as _i3;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
import 'package:wger/database/exercises/exercise_database.dart' as _i13;
|
||||
import 'package:wger/models/exercises/base.dart' as _i5;
|
||||
import 'package:wger/models/exercises/category.dart' as _i6;
|
||||
import 'package:wger/models/exercises/equipment.dart' as _i7;
|
||||
@@ -414,15 +415,15 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
_i5.ExerciseBase findExerciseBaseById(int? id) => (super.noSuchMethod(
|
||||
_i5.ExerciseBase findExerciseById(int? id) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#findExerciseBaseById,
|
||||
#findExerciseById,
|
||||
[id],
|
||||
),
|
||||
returnValue: _FakeExerciseBase_5(
|
||||
this,
|
||||
Invocation.method(
|
||||
#findExerciseBaseById,
|
||||
#findExerciseById,
|
||||
[id],
|
||||
),
|
||||
),
|
||||
@@ -503,9 +504,9 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
) as _i9.Language);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetCategories() => (super.noSuchMethod(
|
||||
_i10.Future<void> fetchAndSetCategoriesFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetCategories,
|
||||
#fetchAndSetCategoriesFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
@@ -513,9 +514,9 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetVariations() => (super.noSuchMethod(
|
||||
_i10.Future<void> fetchAndSetVariationsFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetVariations,
|
||||
#fetchAndSetVariationsFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
@@ -523,9 +524,9 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetMuscles() => (super.noSuchMethod(
|
||||
_i10.Future<void> fetchAndSetMusclesFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetMuscles,
|
||||
#fetchAndSetMusclesFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
@@ -533,9 +534,9 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetEquipment() => (super.noSuchMethod(
|
||||
_i10.Future<void> fetchAndSetEquipmentsFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetEquipment,
|
||||
#fetchAndSetEquipmentsFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
@@ -543,15 +544,30 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetLanguages() => (super.noSuchMethod(
|
||||
_i10.Future<void> fetchAndSetLanguagesFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetLanguages,
|
||||
#fetchAndSetLanguagesFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<_i9.Language> fetchAndSetLanguageFromApi(int? id) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetLanguageFromApi,
|
||||
[id],
|
||||
),
|
||||
returnValue: _i10.Future<_i9.Language>.value(_FakeLanguage_9(
|
||||
this,
|
||||
Invocation.method(
|
||||
#fetchAndSetLanguageFromApi,
|
||||
[id],
|
||||
),
|
||||
)),
|
||||
) as _i10.Future<_i9.Language>);
|
||||
|
||||
@override
|
||||
_i10.Future<_i5.ExerciseBase> fetchAndSetExerciseBase(int? exerciseBaseId) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -594,10 +610,95 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetExercises() => (super.noSuchMethod(
|
||||
_i10.Future<void> initCacheTimesLocalPrefs() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#initCacheTimesLocalPrefs,
|
||||
[],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> clearAllCachesAndPrefs() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#clearAllCachesAndPrefs,
|
||||
[],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetInitialData() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetInitialData,
|
||||
[],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetExercises(
|
||||
_i13.ExerciseDatabase? database, {
|
||||
bool? forceDeleteCache = false,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetExercises,
|
||||
[],
|
||||
[database],
|
||||
{#forceDeleteCache: forceDeleteCache},
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> updateExerciseCache(_i13.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#updateExerciseCache,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetMuscles(_i13.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetMuscles,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetCategories(_i13.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetCategories,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetLanguages(_i13.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetLanguages,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
) as _i10.Future<void>);
|
||||
|
||||
@override
|
||||
_i10.Future<void> fetchAndSetEquipments(_i13.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetEquipments,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i10.Future<void>.value(),
|
||||
returnValueForMissingStub: _i10.Future<void>.value(),
|
||||
@@ -622,7 +723,7 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
) as _i10.Future<List<_i5.ExerciseBase>>);
|
||||
|
||||
@override
|
||||
void addListener(_i13.VoidCallback? listener) => super.noSuchMethod(
|
||||
void addListener(_i14.VoidCallback? listener) => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#addListener,
|
||||
[listener],
|
||||
@@ -631,7 +732,7 @@ class MockExercisesProvider extends _i1.Mock implements _i11.ExercisesProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
void removeListener(_i13.VoidCallback? listener) => super.noSuchMethod(
|
||||
void removeListener(_i14.VoidCallback? listener) => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#removeListener,
|
||||
[listener],
|
||||
|
||||
@@ -4,18 +4,19 @@
|
||||
|
||||
// ignore_for_file: no_leading_underscores_for_library_prefixes
|
||||
import 'dart:async' as _i19;
|
||||
import 'dart:ui' as _i21;
|
||||
import 'dart:ui' as _i22;
|
||||
|
||||
import 'package:http/http.dart' as _i9;
|
||||
import 'package:mockito/mockito.dart' as _i1;
|
||||
import 'package:mockito/src/dummies.dart' as _i24;
|
||||
import 'package:mockito/src/dummies.dart' as _i25;
|
||||
import 'package:wger/database/exercises/exercise_database.dart' as _i21;
|
||||
import 'package:wger/models/exercises/base.dart' as _i3;
|
||||
import 'package:wger/models/exercises/category.dart' as _i4;
|
||||
import 'package:wger/models/exercises/equipment.dart' as _i5;
|
||||
import 'package:wger/models/exercises/exercise_base_data.dart' as _i20;
|
||||
import 'package:wger/models/exercises/language.dart' as _i7;
|
||||
import 'package:wger/models/exercises/muscle.dart' as _i6;
|
||||
import 'package:wger/models/exercises/translation.dart' as _i23;
|
||||
import 'package:wger/models/exercises/translation.dart' as _i24;
|
||||
import 'package:wger/models/workouts/day.dart' as _i13;
|
||||
import 'package:wger/models/workouts/log.dart' as _i17;
|
||||
import 'package:wger/models/workouts/repetition_unit.dart' as _i11;
|
||||
@@ -27,7 +28,7 @@ import 'package:wger/models/workouts/workout_plan.dart' as _i12;
|
||||
import 'package:wger/providers/auth.dart' as _i8;
|
||||
import 'package:wger/providers/base_provider.dart' as _i2;
|
||||
import 'package:wger/providers/exercises.dart' as _i18;
|
||||
import 'package:wger/providers/workout_plans.dart' as _i22;
|
||||
import 'package:wger/providers/workout_plans.dart' as _i23;
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: avoid_redundant_argument_values
|
||||
@@ -344,15 +345,15 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
_i3.ExerciseBase findExerciseBaseById(int? id) => (super.noSuchMethod(
|
||||
_i3.ExerciseBase findExerciseById(int? id) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#findExerciseBaseById,
|
||||
#findExerciseById,
|
||||
[id],
|
||||
),
|
||||
returnValue: _FakeExerciseBase_1(
|
||||
this,
|
||||
Invocation.method(
|
||||
#findExerciseBaseById,
|
||||
#findExerciseById,
|
||||
[id],
|
||||
),
|
||||
),
|
||||
@@ -433,9 +434,9 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
) as _i7.Language);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetCategories() => (super.noSuchMethod(
|
||||
_i19.Future<void> fetchAndSetCategoriesFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetCategories,
|
||||
#fetchAndSetCategoriesFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
@@ -443,9 +444,9 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetVariations() => (super.noSuchMethod(
|
||||
_i19.Future<void> fetchAndSetVariationsFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetVariations,
|
||||
#fetchAndSetVariationsFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
@@ -453,9 +454,9 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetMuscles() => (super.noSuchMethod(
|
||||
_i19.Future<void> fetchAndSetMusclesFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetMuscles,
|
||||
#fetchAndSetMusclesFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
@@ -463,9 +464,9 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetEquipment() => (super.noSuchMethod(
|
||||
_i19.Future<void> fetchAndSetEquipmentsFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetEquipment,
|
||||
#fetchAndSetEquipmentsFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
@@ -473,15 +474,30 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetLanguages() => (super.noSuchMethod(
|
||||
_i19.Future<void> fetchAndSetLanguagesFromApi() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetLanguages,
|
||||
#fetchAndSetLanguagesFromApi,
|
||||
[],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<_i7.Language> fetchAndSetLanguageFromApi(int? id) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetLanguageFromApi,
|
||||
[id],
|
||||
),
|
||||
returnValue: _i19.Future<_i7.Language>.value(_FakeLanguage_5(
|
||||
this,
|
||||
Invocation.method(
|
||||
#fetchAndSetLanguageFromApi,
|
||||
[id],
|
||||
),
|
||||
)),
|
||||
) as _i19.Future<_i7.Language>);
|
||||
|
||||
@override
|
||||
_i19.Future<_i3.ExerciseBase> fetchAndSetExerciseBase(int? exerciseBaseId) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -524,10 +540,95 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetExercises() => (super.noSuchMethod(
|
||||
_i19.Future<void> initCacheTimesLocalPrefs() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#initCacheTimesLocalPrefs,
|
||||
[],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> clearAllCachesAndPrefs() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#clearAllCachesAndPrefs,
|
||||
[],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetInitialData() => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetInitialData,
|
||||
[],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetExercises(
|
||||
_i21.ExerciseDatabase? database, {
|
||||
bool? forceDeleteCache = false,
|
||||
}) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetExercises,
|
||||
[],
|
||||
[database],
|
||||
{#forceDeleteCache: forceDeleteCache},
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> updateExerciseCache(_i21.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#updateExerciseCache,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetMuscles(_i21.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetMuscles,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetCategories(_i21.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetCategories,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetLanguages(_i21.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetLanguages,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
_i19.Future<void> fetchAndSetEquipments(_i21.ExerciseDatabase? database) => (super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#fetchAndSetEquipments,
|
||||
[database],
|
||||
),
|
||||
returnValue: _i19.Future<void>.value(),
|
||||
returnValueForMissingStub: _i19.Future<void>.value(),
|
||||
@@ -552,7 +653,7 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
) as _i19.Future<List<_i3.ExerciseBase>>);
|
||||
|
||||
@override
|
||||
void addListener(_i21.VoidCallback? listener) => super.noSuchMethod(
|
||||
void addListener(_i22.VoidCallback? listener) => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#addListener,
|
||||
[listener],
|
||||
@@ -561,7 +662,7 @@ class MockExercisesProvider extends _i1.Mock implements _i18.ExercisesProvider {
|
||||
);
|
||||
|
||||
@override
|
||||
void removeListener(_i21.VoidCallback? listener) => super.noSuchMethod(
|
||||
void removeListener(_i22.VoidCallback? listener) => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#removeListener,
|
||||
[listener],
|
||||
@@ -752,7 +853,7 @@ class MockWgerBaseProvider extends _i1.Mock implements _i2.WgerBaseProvider {
|
||||
/// A class which mocks [WorkoutPlansProvider].
|
||||
///
|
||||
/// See the documentation for Mockito's code generation for more information.
|
||||
class MockWorkoutPlansProvider extends _i1.Mock implements _i22.WorkoutPlansProvider {
|
||||
class MockWorkoutPlansProvider extends _i1.Mock implements _i23.WorkoutPlansProvider {
|
||||
MockWorkoutPlansProvider() {
|
||||
_i1.throwOnMissingStub(this);
|
||||
}
|
||||
@@ -1098,7 +1199,7 @@ class MockWorkoutPlansProvider extends _i1.Mock implements _i22.WorkoutPlansProv
|
||||
@override
|
||||
_i19.Future<String> fetchSmartText(
|
||||
_i14.Set? workoutSet,
|
||||
_i23.Translation? exercise,
|
||||
_i24.Translation? exercise,
|
||||
) =>
|
||||
(super.noSuchMethod(
|
||||
Invocation.method(
|
||||
@@ -1108,7 +1209,7 @@ class MockWorkoutPlansProvider extends _i1.Mock implements _i22.WorkoutPlansProv
|
||||
exercise,
|
||||
],
|
||||
),
|
||||
returnValue: _i19.Future<String>.value(_i24.dummyValue<String>(
|
||||
returnValue: _i19.Future<String>.value(_i25.dummyValue<String>(
|
||||
this,
|
||||
Invocation.method(
|
||||
#fetchSmartText,
|
||||
@@ -1195,7 +1296,7 @@ class MockWorkoutPlansProvider extends _i1.Mock implements _i22.WorkoutPlansProv
|
||||
) as _i19.Future<void>);
|
||||
|
||||
@override
|
||||
void addListener(_i21.VoidCallback? listener) => super.noSuchMethod(
|
||||
void addListener(_i22.VoidCallback? listener) => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#addListener,
|
||||
[listener],
|
||||
@@ -1204,7 +1305,7 @@ class MockWorkoutPlansProvider extends _i1.Mock implements _i22.WorkoutPlansProv
|
||||
);
|
||||
|
||||
@override
|
||||
void removeListener(_i21.VoidCallback? listener) => super.noSuchMethod(
|
||||
void removeListener(_i22.VoidCallback? listener) => super.noSuchMethod(
|
||||
Invocation.method(
|
||||
#removeListener,
|
||||
[listener],
|
||||
|
||||
@@ -26,6 +26,8 @@ import 'package:wger/models/exercises/translation.dart';
|
||||
const tLanguage1 = Language(id: 1, shortName: 'de', fullName: 'Deutsch');
|
||||
const tLanguage2 = Language(id: 2, shortName: 'en', fullName: 'English');
|
||||
const tLanguage3 = Language(id: 3, shortName: 'fr', fullName: 'Français');
|
||||
const tLanguage4 = Language(id: 12, shortName: 'es', fullName: 'Español');
|
||||
const tLanguage5 = Language(id: 13, shortName: 'it', fullName: 'Italiano');
|
||||
const testLanguages = [tLanguage1, tLanguage2, tLanguage3];
|
||||
|
||||
const tMuscle1 = Muscle(id: 1, name: 'Flutterus maximus', nameEn: 'Glutes', isFront: true);
|
||||
@@ -41,8 +43,9 @@ const tCategory5 = ExerciseCategory(id: 5, name: 'Calves');
|
||||
const testCategories = [tCategory1, tCategory2, tCategory3, tCategory4, tCategory5];
|
||||
|
||||
const tEquipment1 = Equipment(id: 1, name: 'Bench');
|
||||
const tEquipment2 = Equipment(id: 1, name: 'Dumbbell');
|
||||
const tEquipment3 = Equipment(id: 2, name: 'Bench');
|
||||
const tEquipment2 = Equipment(id: 2, name: 'Dumbbell');
|
||||
const tEquipment3 = Equipment(id: 3, name: 'Bench');
|
||||
const tEquipment4 = Equipment(id: 10, name: 'Gym mat');
|
||||
const testEquipment = [tEquipment1, tEquipment2, tEquipment3];
|
||||
|
||||
final benchPress = ExerciseBase(
|
||||
|
||||
Reference in New Issue
Block a user