fix(drift): built a model for exercise and fixes in fromSql type converter

This commit is contained in:
Abhishek Saini
2023-12-23 14:28:38 +05:30
parent c21b278e36
commit c69c639fac
212 changed files with 3674 additions and 1313 deletions

View File

@@ -18,7 +18,8 @@ void main(List<String> arguments) async {
'You must run this script with a metadata file argument, using the --meta flag.');
}
if (arguments.length == metaIndex + 1) {
throw Exception('The --meta flag must be followed by the path to the metadata file.');
throw Exception(
'The --meta flag must be followed by the path to the metadata file.');
}
final metaFile = File(arguments[metaIndex + 1]);
@@ -30,14 +31,18 @@ void main(List<String> arguments) async {
final fetchFromGithub = arguments.contains('--github');
final outputDir = Directory('${Directory.current.path}/flatpak_generator_exports');
final outputDir =
Directory('${Directory.current.path}/flatpak_generator_exports');
outputDir.createSync();
final packageGenerator = PackageGenerator(inputDir: metaFile.parent, meta: meta);
final packageGenerator =
PackageGenerator(inputDir: metaFile.parent, meta: meta);
packageGenerator.generatePackage(
outputDir,
PackageGenerator.runningOnARM() ? CPUArchitecture.aarch64 : CPUArchitecture.x86_64,
PackageGenerator.runningOnARM()
? CPUArchitecture.aarch64
: CPUArchitecture.x86_64,
fetchFromGithub,
);
}
@@ -49,8 +54,8 @@ class PackageGenerator {
PackageGenerator({required this.inputDir, required this.meta});
Future<void> generatePackage(
Directory outputDir, CPUArchitecture arch, bool fetchReleasesFromGithub) async {
Future<void> generatePackage(Directory outputDir, CPUArchitecture arch,
bool fetchReleasesFromGithub) async {
final tempDir = outputDir.createTempSync('flutter_generator_temp');
final appId = meta.appId;
@@ -85,7 +90,8 @@ class PackageGenerator {
}
final editedAppDataContent = AppDataModifier.replaceVersions(
origAppDataFile.readAsStringSync(), await meta.getReleases(fetchReleasesFromGithub));
origAppDataFile.readAsStringSync(),
await meta.getReleases(fetchReleasesFromGithub));
final editedAppDataFile = File('${tempDir.path}/$appId.appdata.xml');
editedAppDataFile.writeAsStringSync(editedAppDataContent);
@@ -101,17 +107,21 @@ class PackageGenerator {
final destDir = Directory('${tempDir.path}/bin');
destDir.createSync();
final baseFileName = '${meta.lowercaseAppName}-linux-${arch.flatpakArchCode}';
final baseFileName =
'${meta.lowercaseAppName}-linux-${arch.flatpakArchCode}';
final packagePath = '${outputDir.absolute.path}/$baseFileName.tar.gz';
Process.runSync('cp', ['-r', '${buildDir.absolute.path}/.', destDir.absolute.path]);
Process.runSync('tar', ['-czvf', packagePath, '.'], workingDirectory: tempDir.absolute.path);
Process.runSync(
'cp', ['-r', '${buildDir.absolute.path}/.', destDir.absolute.path]);
Process.runSync('tar', ['-czvf', packagePath, '.'],
workingDirectory: tempDir.absolute.path);
print('Generated $packagePath');
final preShasum = Process.runSync('shasum', ['-a', '256', packagePath]);
final sha256 = preShasum.stdout.toString().split(' ').first;
final shaFile = await File('${outputDir.path}/$baseFileName.sha256').writeAsString(sha256);
final shaFile = await File('${outputDir.path}/$baseFileName.sha256')
.writeAsString(sha256);
print('Generated ${shaFile.path}');
shaByArch.putIfAbsent(arch, () => sha256);
@@ -128,17 +138,21 @@ class PackageGenerator {
// updates releases in ${appName}.appdata.xml
class AppDataModifier {
static String replaceVersions(String origAppDataContent, List<Release> versions) {
final joinedReleases =
versions.map((v) => '\t\t<release version="${v.version}" date="${v.date}" />').join('\n');
final releasesSection = '<releases>\n$joinedReleases\n\t</releases>'; //todo check this
static String replaceVersions(
String origAppDataContent, List<Release> versions) {
final joinedReleases = versions
.map((v) => '\t\t<release version="${v.version}" date="${v.date}" />')
.join('\n');
final releasesSection =
'<releases>\n$joinedReleases\n\t</releases>'; //todo check this
if (origAppDataContent.contains('<releases')) {
return origAppDataContent
.replaceAll('\n', '<~>')
.replaceFirst(RegExp('<releases.*</releases>'), releasesSection)
.replaceAll('<~>', '\n');
} else {
return origAppDataContent.replaceFirst('</component>', '\n\t$releasesSection\n</component>');
return origAppDataContent.replaceFirst(
'</component>', '\n\t$releasesSection\n</component>');
}
}
}

View File

@@ -43,8 +43,9 @@ class Icon {
_fileExtension = path.split('.').last;
}
String getFilename(String appId) =>
(type == _symbolicType) ? '$appId-symbolic.$_fileExtension' : '$appId.$_fileExtension';
String getFilename(String appId) => (type == _symbolicType)
? '$appId-symbolic.$_fileExtension'
: '$appId.$_fileExtension';
}
class GithubReleases {
@@ -73,7 +74,8 @@ class GithubReleases {
final releaseJsonContent = (await http.get(Uri(
scheme: 'https',
host: 'api.github.com',
path: '/repos/$githubReleaseOrganization/$githubReleaseProject/releases')))
path:
'/repos/$githubReleaseOrganization/$githubReleaseProject/releases')))
.body;
final decodedJson = jsonDecode(releaseJsonContent) as List;
@@ -84,8 +86,10 @@ class GithubReleases {
await Future.forEach<dynamic>(decodedJson, (dynamic releaseDynamic) async {
final releaseMap = releaseDynamic as Map;
final releaseDateAndTime = DateTime.parse(releaseMap['published_at'] as String);
final releaseDateString = releaseDateAndTime.toIso8601String().split('T').first;
final releaseDateAndTime =
DateTime.parse(releaseMap['published_at'] as String);
final releaseDateString =
releaseDateAndTime.toIso8601String().split('T').first;
if (latestReleaseAssetDate == null ||
(latestReleaseAssetDate?.compareTo(releaseDateAndTime) == -1)) {
@@ -96,7 +100,8 @@ class GithubReleases {
}
}
releases.add(Release(version: releaseMap['name'] as String, date: releaseDateString));
releases.add(Release(
version: releaseMap['name'] as String, date: releaseDateString));
});
if (releases.isNotEmpty) {
@@ -115,7 +120,8 @@ class GithubReleases {
final downloadUrl = amMap['browser_download_url'] as String;
final filename = amMap['name'] as String;
final fileExtension = filename.substring(filename.indexOf('.') + 1);
final filenameWithoutExtension = filename.substring(0, filename.indexOf('.'));
final filenameWithoutExtension =
filename.substring(0, filename.indexOf('.'));
final arch = filenameWithoutExtension.endsWith('aarch64')
? CPUArchitecture.aarch64
@@ -212,7 +218,8 @@ class FlatpakMeta {
: _localReleases = localReleases,
_localReleaseAssets = localReleaseAssets {
if (githubReleaseOrganization != null && githubReleaseProject != null) {
_githubReleases = GithubReleases(githubReleaseOrganization!, githubReleaseProject!);
_githubReleases =
GithubReleases(githubReleaseOrganization!, githubReleaseProject!);
}
}
@@ -225,13 +232,15 @@ class FlatpakMeta {
return await _githubReleases!.getReleases();
} else {
if (_localReleases == null) {
throw Exception('Metadata must include releases if not fetching releases from Github.');
throw Exception(
'Metadata must include releases if not fetching releases from Github.');
}
return _localReleases!;
}
}
Future<List<ReleaseAsset>?> getReleaseAssets(bool fetchReleasesFromGithub) async {
Future<List<ReleaseAsset>?> getReleaseAssets(
bool fetchReleasesFromGithub) async {
if (fetchReleasesFromGithub) {
if (_githubReleases == null) {
throw Exception(
@@ -240,7 +249,8 @@ class FlatpakMeta {
return _githubReleases!.getLatestReleaseAssets();
} else {
if (_localReleases == null) {
throw Exception('Metadata must include releases if not fetching releases from Github.');
throw Exception(
'Metadata must include releases if not fetching releases from Github.');
}
return _localReleaseAssets;
}
@@ -252,13 +262,17 @@ class FlatpakMeta {
return FlatpakMeta(
appId: json['appId'] as String,
lowercaseAppName: json['lowercaseAppName'] as String,
githubReleaseOrganization: json['githubReleaseOrganization'] as String?,
githubReleaseOrganization:
json['githubReleaseOrganization'] as String?,
githubReleaseProject: json['githubReleaseProject'] as String?,
localReleases: (json['localReleases'] as List?)?.map((dynamic r) {
final rMap = r as Map;
return Release(version: rMap['version'] as String, date: rMap['date'] as String);
return Release(
version: rMap['version'] as String,
date: rMap['date'] as String);
}).toList(),
localReleaseAssets: (json['localReleaseAssets'] as List?)?.map((dynamic ra) {
localReleaseAssets:
(json['localReleaseAssets'] as List?)?.map((dynamic ra) {
final raMap = ra as Map;
final archString = raMap['arch'] as String;
final arch = (archString == CPUArchitecture.x86_64.flatpakArchCode)
@@ -270,8 +284,10 @@ class FlatpakMeta {
throw Exception(
'Architecture must be either "${CPUArchitecture.x86_64.flatpakArchCode}" or "${CPUArchitecture.aarch64.flatpakArchCode}"');
}
final tarballPath = '${jsonFile.parent.path}/${raMap['tarballPath'] as String}';
final preShasum = Process.runSync('shasum', ['-a', '256', tarballPath]);
final tarballPath =
'${jsonFile.parent.path}/${raMap['tarballPath'] as String}';
final preShasum =
Process.runSync('shasum', ['-a', '256', tarballPath]);
final shasum = preShasum.stdout.toString().split(' ').first;
if (preShasum.exitCode != 0) {
throw Exception(preShasum.stderr);
@@ -286,14 +302,17 @@ class FlatpakMeta {
appDataPath: json['appDataPath'] as String,
desktopPath: json['desktopPath'] as String,
icons: (json['icons'] as Map).entries.map((mapEntry) {
return Icon(type: mapEntry.key as String, path: mapEntry.value as String);
return Icon(
type: mapEntry.key as String, path: mapEntry.value as String);
}).toList(),
freedesktopRuntime: json['freedesktopRuntime'] as String,
buildCommandsAfterUnpack: (json['buildCommandsAfterUnpack'] as List?)
?.map((dynamic bc) => bc as String)
.toList(),
extraModules: json['extraModules'] as List?,
finishArgs: (json['finishArgs'] as List).map((dynamic fa) => fa as String).toList());
finishArgs: (json['finishArgs'] as List)
.map((dynamic fa) => fa as String)
.toList());
} catch (e) {
throw Exception('Could not parse JSON file, due to this error:\n$e');
}

View File

@@ -14,7 +14,8 @@ void main(List<String> arguments) async {
'You must run this script with a metadata file argument, using the --meta flag.');
}
if (arguments.length == metaIndex + 1) {
throw Exception('The --meta flag must be followed by the path to the metadata file.');
throw Exception(
'The --meta flag must be followed by the path to the metadata file.');
}
final metaFile = File(arguments[metaIndex + 1]);
@@ -26,17 +27,20 @@ void main(List<String> arguments) async {
final fetchFromGithub = arguments.contains('--github');
final outputDir = Directory('${Directory.current.path}/flatpak_generator_exports');
final outputDir =
Directory('${Directory.current.path}/flatpak_generator_exports');
outputDir.createSync();
final manifestGenerator = FlatpakManifestGenerator(meta);
final manifestContent = await manifestGenerator.generateFlatpakManifest(fetchFromGithub);
final manifestContent =
await manifestGenerator.generateFlatpakManifest(fetchFromGithub);
final manifestPath = '${outputDir.path}/${meta.appId}.json';
final manifestFile = File(manifestPath);
manifestFile.writeAsStringSync(manifestContent);
print('Generated $manifestPath');
final flathubJsonContent = await manifestGenerator.generateFlathubJson(fetchFromGithub);
final flathubJsonContent =
await manifestGenerator.generateFlathubJson(fetchFromGithub);
if (flathubJsonContent != null) {
final flathubJsonPath = '${outputDir.path}/flathub.json';
final flathubJsonFile = File(flathubJsonPath);
@@ -115,7 +119,8 @@ class FlatpakManifestGenerator {
const encoder = JsonEncoder.withIndent(' ');
final onlyArchListInput = fetchFromGithub ? _githubArchSupport! : _localArchSupport!;
final onlyArchListInput =
fetchFromGithub ? _githubArchSupport! : _localArchSupport!;
final onlyArchList = List<String>.empty(growable: true);
for (final e in onlyArchListInput.entries) {
@@ -131,7 +136,8 @@ class FlatpakManifestGenerator {
}
}
void _lazyGenerateArchSupportMap(bool fetchFromGithub, List<ReleaseAsset> assets) {
void _lazyGenerateArchSupportMap(
bool fetchFromGithub, List<ReleaseAsset> assets) {
if (fetchFromGithub) {
if (_githubArchSupport == null) {
_githubArchSupport = <CPUArchitecture, bool>{

View File

@@ -34,17 +34,20 @@ Widget createDashboardScreen({locale = 'en'}) {
}
]
};
when(mockWorkoutProvider.fetchSessionData()).thenAnswer((a) => Future.value(logs));
when(mockWorkoutProvider.fetchSessionData())
.thenAnswer((a) => Future.value(logs));
final mockNutritionProvider = MockNutritionPlansProvider();
when(mockNutritionProvider.currentPlan).thenAnswer((realInvocation) => getNutritionalPlan());
when(mockNutritionProvider.currentPlan)
.thenAnswer((realInvocation) => getNutritionalPlan());
when(mockNutritionProvider.items).thenReturn([getNutritionalPlan()]);
final mockWeightProvider = MockBodyWeightProvider();
when(mockWeightProvider.items).thenReturn(getWeightEntries());
final mockMeasurementProvider = MockMeasurementProvider();
when(mockMeasurementProvider.categories).thenReturn(getMeasurementCategories());
when(mockMeasurementProvider.categories)
.thenReturn(getMeasurementCategories());
return MultiProvider(
providers: [

View File

@@ -15,7 +15,8 @@ Widget createWorkoutDetailScreen({locale = 'en'}) {
final mockWorkoutProvider = MockWorkoutPlansProvider();
final workout = getWorkout();
when(mockWorkoutProvider.activePlan).thenReturn(workout);
when(mockWorkoutProvider.fetchAndSetWorkoutPlanFull(1)).thenAnswer((_) => Future.value(workout));
when(mockWorkoutProvider.fetchAndSetWorkoutPlanFull(1))
.thenAnswer((_) => Future.value(workout));
return MultiProvider(
providers: [

View File

@@ -20,8 +20,10 @@ 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.findExerciseBaseById(1))
.thenReturn(bases[0]); // bench press
when(mockExerciseProvider.findExerciseBaseById(6))
.thenReturn(bases[5]); // side raises
//when(mockExerciseProvider.findExerciseBaseById(2)).thenReturn(bases[1]); // crunches
//when(mockExerciseProvider.findExerciseBaseById(3)).thenReturn(bases[2]); // dead lift

View File

@@ -11,7 +11,8 @@ import '../test_data/measurements.dart';
Widget createMeasurementScreen({locale = 'en'}) {
final mockMeasurementProvider = MockMeasurementProvider();
when(mockMeasurementProvider.categories).thenReturn(getMeasurementCategories());
when(mockMeasurementProvider.categories)
.thenReturn(getMeasurementCategories());
return MultiProvider(
providers: [

View File

@@ -11,12 +11,14 @@ import '4_measurements.dart';
import '5_nutritional_plan.dart';
import '6_weight.dart';
Future<void> takeScreenshot(tester, binding, String language, String name) async {
Future<void> takeScreenshot(
tester, binding, String language, String name) async {
if (Platform.isAndroid) {
await binding.convertFlutterSurfaceToImage();
await tester.pumpAndSettle();
}
final filename = 'fastlane/metadata/android/$language/images/phoneScreenshots/$name.png';
final filename =
'fastlane/metadata/android/$language/images/phoneScreenshots/$name.png';
await binding.takeScreenshot(filename);
}
@@ -60,8 +62,10 @@ void main() {
await takeScreenshot(tester, binding, language, '01 - dashboard');
});
testWidgets('workout detail screen - $language', (WidgetTester tester) async {
await tester.pumpWidget(createWorkoutDetailScreen(locale: languageCode));
testWidgets('workout detail screen - $language',
(WidgetTester tester) async {
await tester
.pumpWidget(createWorkoutDetailScreen(locale: languageCode));
await tester.tap(find.byType(TextButton));
await tester.pumpAndSettle();
await takeScreenshot(tester, binding, language, '02 - workout detail');
@@ -74,19 +78,24 @@ void main() {
await takeScreenshot(tester, binding, language, '03 - gym mode');
});
testWidgets('measurement screen - $language', (WidgetTester tester) async {
testWidgets('measurement screen - $language',
(WidgetTester tester) async {
await tester.pumpWidget(createMeasurementScreen(locale: languageCode));
await takeScreenshot(tester, binding, language, '04 - measurements');
});
testWidgets('nutritional plan detail - $language', (WidgetTester tester) async {
await tester.pumpWidget(createNutritionalPlanScreen(locale: languageCode));
testWidgets('nutritional plan detail - $language',
(WidgetTester tester) async {
await tester
.pumpWidget(createNutritionalPlanScreen(locale: languageCode));
await tester.tap(find.byType(TextButton));
await tester.pumpAndSettle();
await takeScreenshot(tester, binding, language, '05 - nutritional plan');
await takeScreenshot(
tester, binding, language, '05 - nutritional plan');
});
testWidgets('body weight screen - $language', (WidgetTester tester) async {
testWidgets('body weight screen - $language',
(WidgetTester tester) async {
await tester.pumpWidget(createWeightScreen(locale: languageCode));
await tester.pumpAndSettle();
await takeScreenshot(tester, binding, language, '06 - weight');

View File

@@ -17,12 +17,16 @@ 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 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 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()();
TextColumn get equipment =>
text().map(const EquipmentConverter()).nullable()();
DateTimeColumn get expiresIn => dateTime().nullable()();
}

View File

@@ -11,55 +11,76 @@ class $ExerciseTableItemsTable extends ExerciseTableItems
$ExerciseTableItemsTable(this.attachedDatabase, [this._alias]);
static const VerificationMeta _idMeta = const VerificationMeta('id');
@override
late final GeneratedColumn<int> id = GeneratedColumn<int>('id', aliasedName, false,
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');
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,
late final GeneratedColumnWithTypeConverter<ExerciseBase?, String>
exercisebase = GeneratedColumn<String>('exercisebase', aliasedName, true,
type: DriftSqlType.string, requiredDuringInsert: false)
.withConverter<ExerciseBase?>($ExerciseTableItemsTable.$converterexercisebasen);
.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,
late final GeneratedColumnWithTypeConverter<Muscle?, String> muscle =
GeneratedColumn<String>('muscle', aliasedName, true,
type: DriftSqlType.string, requiredDuringInsert: false)
.withConverter<ExerciseCategory?>($ExerciseTableItemsTable.$convertercategoryn);
static const VerificationMeta _variationMeta = const VerificationMeta('variation');
.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');
.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');
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');
.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];
List<GeneratedColumn> get $columns => [
id,
exercisebase,
muscle,
category,
variation,
language,
equipment,
expiresIn
];
@override
String get aliasedName => _alias ?? actualTableName;
@override
@@ -80,8 +101,8 @@ class $ExerciseTableItemsTable extends ExerciseTableItems
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));
context.handle(_expiresInMeta,
expiresIn.isAcceptableOrUnknown(data['expires_in']!, _expiresInMeta));
}
return context;
}
@@ -92,20 +113,26 @@ class $ExerciseTableItemsTable extends ExerciseTableItems
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'])),
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'])),
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']),
);
@@ -116,23 +143,28 @@ class $ExerciseTableItemsTable extends ExerciseTableItems
return $ExerciseTableItemsTable(attachedDatabase, alias);
}
static TypeConverter<ExerciseBase, String> $converterexercisebase = const ExerciseBaseConverter();
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> $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> $convertervariation =
const VariationConverter();
static TypeConverter<Variation?, String?> $convertervariationn =
NullAwareTypeConverter.wrap($convertervariation);
static TypeConverter<Language, String> $converterlanguage = const LanguageConverter();
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> $converterequipment =
const EquipmentConverter();
static TypeConverter<Equipment?, String?> $converterequipmentn =
NullAwareTypeConverter.wrap($converterequipment);
}
@@ -192,18 +224,31 @@ class ExerciseTable extends DataClass implements Insertable<ExerciseTable> {
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),
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}) {
factory ExerciseTable.fromJson(Map<String, dynamic> json,
{ValueSerializer? serializer}) {
serializer ??= driftRuntimeOptions.defaultSerializer;
return ExerciseTable(
id: serializer.fromJson<int>(json['id']),
@@ -242,7 +287,8 @@ class ExerciseTable extends DataClass implements Insertable<ExerciseTable> {
Value<DateTime?> expiresIn = const Value.absent()}) =>
ExerciseTable(
id: id ?? this.id,
exercisebase: exercisebase.present ? exercisebase.value : this.exercisebase,
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,
@@ -266,8 +312,8 @@ class ExerciseTable extends DataClass implements Insertable<ExerciseTable> {
}
@override
int get hashCode =>
Object.hash(id, exercisebase, muscle, category, variation, language, equipment, expiresIn);
int get hashCode => Object.hash(id, exercisebase, muscle, category, variation,
language, equipment, expiresIn);
@override
bool operator ==(Object other) =>
identical(this, other) ||
@@ -363,7 +409,8 @@ class ExerciseTableItemsCompanion extends UpdateCompanion<ExerciseTable> {
if (exercisebase.present) {
final converter = $ExerciseTableItemsTable.$converterexercisebasen;
map['exercisebase'] = Variable<String>(converter.toSql(exercisebase.value));
map['exercisebase'] =
Variable<String>(converter.toSql(exercisebase.value));
}
if (muscle.present) {
final converter = $ExerciseTableItemsTable.$convertermusclen;
@@ -414,7 +461,8 @@ class ExerciseTableItemsCompanion extends UpdateCompanion<ExerciseTable> {
abstract class _$ExerciseDatabase extends GeneratedDatabase {
_$ExerciseDatabase(QueryExecutor e) : super(e);
late final $ExerciseTableItemsTable exerciseTableItems = $ExerciseTableItemsTable(this);
late final $ExerciseTableItemsTable exerciseTableItems =
$ExerciseTableItemsTable(this);
@override
Iterable<TableInfo<Table, Object?>> get allTables =>
allSchemaEntities.whereType<TableInfo<Table, Object?>>();

View File

@@ -1,19 +1,93 @@
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';
import 'package:wger/models/exercises/comment.dart';
import 'package:wger/models/exercises/equipment.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/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();
@override
ExerciseBase fromSql(String fromDb) {
return ExerciseBase.fromJson(json.decode(fromDb) as Map<String, dynamic>);
final Map<String, dynamic> baseData = json.decode(fromDb);
final category = ExerciseCategory.fromJson(baseData['categories']);
final musclesPrimary =
baseData['muscless'].map((e) => Muscle.fromJson(e)).toList();
final musclesSecondary =
baseData['musclesSecondary'].map((e) => Muscle.fromJson(e)).toList();
final equipment =
baseData['equipments'].map((e) => Equipment.fromJson(e)).toList();
final images =
baseData['images'].map((e) => ExerciseImage.fromJson(e)).toList();
final videos = baseData['videos'].map((e) => Video.fromJson(e)).toList();
final List<Translation> exercises = [];
for (final exerciseData in baseData['translations']) {
final exercise = 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);
}
final exerciseBase = ExerciseBase(
id: baseData['id'],
uuid: baseData['uuid'],
created: null,
//creationDate: toDate(baseData['creation_date']),
musclesSecondary: musclesSecondary.cast<Muscle>(),
muscles: musclesPrimary.cast<Muscle>(),
equipment: equipment.cast<Equipment>(),
category: category,
images: images.cast<ExerciseImage>(),
exercises: exercises,
videos: videos.cast<Video>(),
);
return exerciseBase;
}
@override
@@ -50,12 +124,14 @@ class EquipmentConverter extends TypeConverter<Equipment, String> {
}
}
class ExerciseCategoryConverter extends TypeConverter<ExerciseCategory, String> {
class ExerciseCategoryConverter
extends TypeConverter<ExerciseCategory, String> {
const ExerciseCategoryConverter();
@override
ExerciseCategory fromSql(String fromDb) {
return ExerciseCategory.fromJson(json.decode(fromDb) as Map<String, dynamic>);
return ExerciseCategory.fromJson(
json.decode(fromDb) as Map<String, dynamic>);
}
@override

View File

@@ -26,7 +26,10 @@ class WgerHttpException implements Exception {
/// JSON. Will use the response as-is if it fails.
WgerHttpException(dynamic responseBody) {
if (responseBody == null) {
errors = {'unknown_error': 'An unknown error occurred, no further information available'};
errors = {
'unknown_error':
'An unknown error occurred, no further information available'
};
} else {
try {
errors = {'unknown_error': json.decode(responseBody)};

View File

@@ -1,5 +1,7 @@
double chartGetInterval(DateTime first, DateTime last, {divider = 3}) {
final dayDiff = last.difference(first);
return dayDiff.inMilliseconds == 0 ? 1000 : dayDiff.inMilliseconds.abs() / divider;
return dayDiff.inMilliseconds == 0
? 1000
: dayDiff.inMilliseconds.abs() / divider;
}

View File

@@ -14,7 +14,8 @@ String? validateName(String? name, BuildContext context) {
}
if (name.length < MIN_CHARS_NAME || name.length > MAX_CHARS_NAME) {
return AppLocalizations.of(context).enterCharacters(MIN_CHARS_NAME, MAX_CHARS_NAME);
return AppLocalizations.of(context)
.enterCharacters(MIN_CHARS_NAME, MAX_CHARS_NAME);
}
return null;
@@ -26,7 +27,8 @@ String? validateDescription(String? name, BuildContext context) {
}
if (name.length < MIN_CHARS_DESCRIPTION) {
return AppLocalizations.of(context).enterMinCharacters(MIN_CHARS_DESCRIPTION);
return AppLocalizations.of(context)
.enterMinCharacters(MIN_CHARS_DESCRIPTION);
}
return null;

View File

@@ -60,5 +60,6 @@ String? timeToString(TimeOfDay? time) {
if (time == null) {
return null;
}
return const DefaultMaterialLocalizations().formatTimeOfDay(time, alwaysUse24HourFormat: true);
return const DefaultMaterialLocalizations()
.formatTimeOfDay(time, alwaysUse24HourFormat: true);
}

View File

@@ -42,7 +42,9 @@ String repText(
// rather "8 repetitions". If there is weight we want to output "8 x 50kg",
// since the repetitions are implied. If other units are used, we always
// print them
if (repetitionUnitObj.id != REP_UNIT_REPETITIONS || weight == 0 || weight == null) {
if (repetitionUnitObj.id != REP_UNIT_REPETITIONS ||
weight == 0 ||
weight == null) {
out.add(repetitionUnitObj.name);
}
}

View File

@@ -21,4 +21,5 @@ import 'package:flutter/foundation.dart';
// Note: we're not using Platform.isAndroid etc because during tests these would+
// always take the value of the current platform. TargetPlatform is always Android
// during tests, but can be changed to check for correct UI switches, etc.
final isDesktop = [TargetPlatform.linux, TargetPlatform.macOS].contains(defaultTargetPlatform);
final isDesktop = [TargetPlatform.linux, TargetPlatform.macOS]
.contains(defaultTargetPlatform);

View File

@@ -49,7 +49,8 @@ void showErrorDialog(dynamic exception, BuildContext context) {
);
}
void showHttpExceptionErrorDialog(WgerHttpException exception, BuildContext context) async {
void showHttpExceptionErrorDialog(
WgerHttpException exception, BuildContext context) async {
log('showHttpExceptionErrorDialog: ');
log(exception.toString());
log('-------------------');
@@ -58,7 +59,8 @@ void showHttpExceptionErrorDialog(WgerHttpException exception, BuildContext cont
for (final key in exception.errors!.keys) {
// Error headers
// Ensure that the error heading first letter is capitalized.
final String errorHeaderMsg = key[0].toUpperCase() + key.substring(1, key.length);
final String errorHeaderMsg =
key[0].toUpperCase() + key.substring(1, key.length);
errorList.add(
Text(
@@ -129,7 +131,8 @@ dynamic showDeleteDialog(
),
onPressed: () {
exerciseData[exercise]!.removeWhere((el) => el.id == log.id);
Provider.of<WorkoutPlansProvider>(context, listen: false).deleteLog(
Provider.of<WorkoutPlansProvider>(context, listen: false)
.deleteLog(
log,
);

View File

@@ -81,19 +81,21 @@ class MyApp extends StatelessWidget {
create: (ctx) => AuthProvider(),
),
ChangeNotifierProxyProvider<AuthProvider, ExercisesProvider>(
create: (context) => ExercisesProvider(
WgerBaseProvider(Provider.of<AuthProvider>(context, listen: false))),
create: (context) => ExercisesProvider(WgerBaseProvider(
Provider.of<AuthProvider>(context, listen: false))),
update: (context, base, previous) =>
previous ?? ExercisesProvider(WgerBaseProvider(base)),
),
ChangeNotifierProxyProvider2<AuthProvider, ExercisesProvider, WorkoutPlansProvider>(
ChangeNotifierProxyProvider2<AuthProvider, ExercisesProvider,
WorkoutPlansProvider>(
create: (context) => WorkoutPlansProvider(
WgerBaseProvider(Provider.of<AuthProvider>(context, listen: false)),
Provider.of<ExercisesProvider>(context, listen: false),
[],
),
update: (context, auth, exercises, previous) =>
previous ?? WorkoutPlansProvider(WgerBaseProvider(auth), exercises, []),
previous ??
WorkoutPlansProvider(WgerBaseProvider(auth), exercises, []),
),
ChangeNotifierProxyProvider<AuthProvider, NutritionPlansProvider>(
create: (context) => NutritionPlansProvider(
@@ -114,7 +116,8 @@ class MyApp extends StatelessWidget {
create: (context) => UserProvider(
WgerBaseProvider(Provider.of<AuthProvider>(context, listen: false)),
),
update: (context, base, previous) => previous ?? UserProvider(WgerBaseProvider(base)),
update: (context, base, previous) =>
previous ?? UserProvider(WgerBaseProvider(base)),
),
ChangeNotifierProxyProvider<AuthProvider, BodyWeightProvider>(
create: (context) => BodyWeightProvider(
@@ -124,9 +127,10 @@ class MyApp extends StatelessWidget {
previous ?? BodyWeightProvider(WgerBaseProvider(base)),
),
ChangeNotifierProxyProvider<AuthProvider, GalleryProvider>(
create: (context) =>
GalleryProvider(Provider.of<AuthProvider>(context, listen: false), []),
update: (context, auth, previous) => previous ?? GalleryProvider(auth, []),
create: (context) => GalleryProvider(
Provider.of<AuthProvider>(context, listen: false), []),
update: (context, auth, previous) =>
previous ?? GalleryProvider(auth, []),
),
ChangeNotifierProxyProvider<AuthProvider, AddExerciseProvider>(
create: (context) => AddExerciseProvider(
@@ -149,7 +153,8 @@ class MyApp extends StatelessWidget {
: FutureBuilder(
future: auth.tryAutoLogin(),
builder: (ctx, authResultSnapshot) =>
authResultSnapshot.connectionState == ConnectionState.waiting
authResultSnapshot.connectionState ==
ConnectionState.waiting
? SplashScreen()
: AuthScreen(),
),
@@ -159,8 +164,10 @@ class MyApp extends StatelessWidget {
GalleryScreen.routeName: (ctx) => const GalleryScreen(),
GymModeScreen.routeName: (ctx) => GymModeScreen(),
HomeTabsScreen.routeName: (ctx) => HomeTabsScreen(),
MeasurementCategoriesScreen.routeName: (ctx) => MeasurementCategoriesScreen(),
MeasurementEntriesScreen.routeName: (ctx) => MeasurementEntriesScreen(),
MeasurementCategoriesScreen.routeName: (ctx) =>
MeasurementCategoriesScreen(),
MeasurementEntriesScreen.routeName: (ctx) =>
MeasurementEntriesScreen(),
NutritionScreen.routeName: (ctx) => NutritionScreen(),
NutritionalDiaryScreen.routeName: (ctx) => NutritionalDiaryScreen(),
NutritionalPlanScreen.routeName: (ctx) => NutritionalPlanScreen(),
@@ -168,7 +175,8 @@ class MyApp extends StatelessWidget {
WorkoutPlanScreen.routeName: (ctx) => WorkoutPlanScreen(),
WorkoutPlansScreen.routeName: (ctx) => WorkoutPlansScreen(),
ExercisesScreen.routeName: (ctx) => const ExercisesScreen(),
ExerciseDetailScreen.routeName: (ctx) => const ExerciseDetailScreen(),
ExerciseDetailScreen.routeName: (ctx) =>
const ExerciseDetailScreen(),
AddExerciseScreen.routeName: (ctx) => const AddExerciseScreen(),
AboutPage.routeName: (ctx) => const AboutPage(),
},

View File

@@ -45,6 +45,7 @@ class WeightEntry {
}
// Boilerplate
factory WeightEntry.fromJson(Map<String, dynamic> json) => _$WeightEntryFromJson(json);
factory WeightEntry.fromJson(Map<String, dynamic> json) =>
_$WeightEntryFromJson(json);
Map<String, dynamic> toJson() => _$WeightEntryToJson(this);
}

View File

@@ -18,7 +18,8 @@ WeightEntry _$WeightEntryFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$WeightEntryToJson(WeightEntry instance) => <String, dynamic>{
Map<String, dynamic> _$WeightEntryToJson(WeightEntry instance) =>
<String, dynamic>{
'id': instance.id,
'weight': numToString(instance.weight),
'date': toDate(instance.date),

View File

@@ -25,8 +25,8 @@ class Alias {
@JsonKey(required: true)
final int? id;
@JsonKey(required: true, name: 'exercise')
final int exerciseId;
@JsonKey(name: 'exercise')
final int? exerciseId;
@JsonKey(required: true)
final String alias;

View File

@@ -9,11 +9,11 @@ part of 'alias.dart';
Alias _$AliasFromJson(Map<String, dynamic> json) {
$checkKeys(
json,
requiredKeys: const ['id', 'exercise', 'alias'],
requiredKeys: const ['id', 'alias'],
);
return Alias(
id: json['id'] as int?,
exerciseId: json['exercise'] as int,
exerciseId: json['exercise'] as int?,
alias: json['alias'] as String,
);
}

View File

@@ -48,34 +48,34 @@ class ExerciseBase extends Equatable {
@JsonKey(required: true, name: 'category')
late int categoryId;
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: true, includeToJson: true, name: 'categories')
ExerciseCategory? category;
@JsonKey(required: true, name: 'muscles')
List<int> musclesIds = [];
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: false, includeToJson: true, name: 'muscless')
List<Muscle> muscles = [];
@JsonKey(required: true, name: 'muscles_secondary')
List<int> musclesSecondaryIds = [];
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: false, includeToJson: true)
List<Muscle> musclesSecondary = [];
@JsonKey(required: true, name: 'equipment')
List<int> equipmentIds = [];
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: false, includeToJson: true, name: 'equipments')
List<Equipment> equipment = [];
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: false, includeToJson: true)
List<ExerciseImage> images = [];
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: true, includeToJson: true)
List<Translation> translations = [];
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: false, includeToJson: true)
List<Video> videos = [];
ExerciseBase({
@@ -114,6 +114,10 @@ class ExerciseBase extends Equatable {
equipmentIds = equipment.map((e) => e.id).toList();
}
if (exercises == null) {
print("Exercises are NULL");
}
if (exercises != null) {
translations = exercises;
}
@@ -139,7 +143,7 @@ class ExerciseBase extends Equatable {
(e) => e.languageObj.shortName == languageCode,
orElse: () => translations.firstWhere(
(e) => e.languageObj.shortName == LANGUAGE_SHORT_ENGLISH,
orElse: () => translations.first,
orElse: () => Translation(name: "name", description: "description"),
),
);
}
@@ -158,7 +162,8 @@ class ExerciseBase extends Equatable {
}
// Boilerplate
factory ExerciseBase.fromJson(Map<String, dynamic> json) => _$ExerciseBaseFromJson(json);
factory ExerciseBase.fromJson(Map<String, dynamic> json) =>
_$ExerciseBaseFromJson(json);
Map<String, dynamic> toJson() => _$ExerciseBaseToJson(this);

View File

@@ -24,25 +24,47 @@ ExerciseBase _$ExerciseBaseFromJson(Map<String, dynamic> json) {
return ExerciseBase(
id: json['id'] as int?,
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),
created: json['created'] == null
? null
: DateTime.parse(json['created'] as String),
lastUpdate: json['last_update'] == null
? null
: DateTime.parse(json['last_update'] as String),
variationId: json['variations'] as int?,
category: json['categories'] == null
? null
: ExerciseCategory.fromJson(json['categories'] as Map<String, dynamic>),
)
..categoryId = json['category'] as int
..musclesIds = (json['muscles'] as List<dynamic>).map((e) => e as int).toList()
..musclesSecondaryIds =
(json['muscles_secondary'] as List<dynamic>).map((e) => e as int).toList()
..equipmentIds = (json['equipment'] as List<dynamic>).map((e) => e as int).toList();
..musclesIds =
(json['muscles'] as List<dynamic>).map((e) => e as int).toList()
..musclesSecondaryIds = (json['muscles_secondary'] as List<dynamic>)
.map((e) => e as int)
.toList()
..equipmentIds =
(json['equipment'] as List<dynamic>).map((e) => e as int).toList()
..translations = (json['translations'] as List<dynamic>)
.map((e) => Translation.fromJson(e as Map<String, dynamic>))
.toList();
}
Map<String, dynamic> _$ExerciseBaseToJson(ExerciseBase instance) => <String, dynamic>{
Map<String, dynamic> _$ExerciseBaseToJson(ExerciseBase instance) =>
<String, dynamic>{
'id': instance.id,
'uuid': instance.uuid,
'variations': instance.variationId,
'created': instance.created?.toIso8601String(),
'last_update': instance.lastUpdate?.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(),
};

View File

@@ -40,7 +40,8 @@ class ExerciseCategory extends Equatable {
}
// Boilerplate
factory ExerciseCategory.fromJson(Map<String, dynamic> json) => _$ExerciseCategoryFromJson(json);
factory ExerciseCategory.fromJson(Map<String, dynamic> json) =>
_$ExerciseCategoryFromJson(json);
Map<String, dynamic> toJson() => _$ExerciseCategoryToJson(this);
@override

View File

@@ -17,7 +17,8 @@ ExerciseCategory _$ExerciseCategoryFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$ExerciseCategoryToJson(ExerciseCategory instance) => <String, dynamic>{
Map<String, dynamic> _$ExerciseCategoryToJson(ExerciseCategory instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
};

View File

@@ -25,7 +25,7 @@ class Comment {
@JsonKey(required: true)
final int id;
@JsonKey(required: true, name: 'exercise')
@JsonKey(name: 'exercise')
final int exerciseId;
@JsonKey(required: true)
@@ -38,6 +38,7 @@ class Comment {
});
// Boilerplate
factory Comment.fromJson(Map<String, dynamic> json) => _$CommentFromJson(json);
factory Comment.fromJson(Map<String, dynamic> json) =>
_$CommentFromJson(json);
Map<String, dynamic> toJson() => _$CommentToJson(this);
}

View File

@@ -9,7 +9,7 @@ part of 'comment.dart';
Comment _$CommentFromJson(Map<String, dynamic> json) {
$checkKeys(
json,
requiredKeys: const ['id', 'exercise', 'comment'],
requiredKeys: const ['id', 'comment'],
);
return Comment(
id: json['id'] as int,

View File

@@ -35,7 +35,8 @@ class Equipment extends Equatable {
});
// Boilerplate
factory Equipment.fromJson(Map<String, dynamic> json) => _$EquipmentFromJson(json);
factory Equipment.fromJson(Map<String, dynamic> json) =>
_$EquipmentFromJson(json);
Map<String, dynamic> toJson() => _$EquipmentToJson(this);
@override

View File

@@ -0,0 +1,30 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:wger/models/exercises/category.dart';
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';
part 'exercise_base_data.g.dart';
@freezed
class ExerciseBaseData with _$ExerciseBaseData {
factory ExerciseBaseData({
required int id,
required String uuid,
required ExerciseCategory category,
required List<Muscle> muscles,
// ignore: invalid_annotation_target
@JsonKey(name: 'muscles_secondary') required List<Muscle> musclesSecondary,
required List<Equipment> equipment,
required List<ExerciseData> exercises,
required List<ExerciseImage> images,
required List<Video> videos,
}) = _ExerciseBaseData;
factory ExerciseBaseData.fromJson(Map<String, dynamic> json) =>
_$ExerciseBaseDataFromJson(json);
}

View File

@@ -0,0 +1,380 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'exercise_base_data.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
ExerciseBaseData _$ExerciseBaseDataFromJson(Map<String, dynamic> json) {
return _ExerciseBaseData.fromJson(json);
}
/// @nodoc
mixin _$ExerciseBaseData {
int get id => throw _privateConstructorUsedError;
String get uuid => throw _privateConstructorUsedError;
ExerciseCategory get category => throw _privateConstructorUsedError;
List<Muscle> get muscles =>
throw _privateConstructorUsedError; // ignore: invalid_annotation_target
@JsonKey(name: 'muscles_secondary')
List<Muscle> get musclesSecondary => throw _privateConstructorUsedError;
List<Equipment> get equipment => throw _privateConstructorUsedError;
List<ExerciseData> get exercises => throw _privateConstructorUsedError;
List<ExerciseImage> get images => throw _privateConstructorUsedError;
List<Video> get videos => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ExerciseBaseDataCopyWith<ExerciseBaseData> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ExerciseBaseDataCopyWith<$Res> {
factory $ExerciseBaseDataCopyWith(
ExerciseBaseData value, $Res Function(ExerciseBaseData) then) =
_$ExerciseBaseDataCopyWithImpl<$Res, ExerciseBaseData>;
@useResult
$Res call(
{int id,
String uuid,
ExerciseCategory category,
List<Muscle> muscles,
@JsonKey(name: 'muscles_secondary') List<Muscle> musclesSecondary,
List<Equipment> equipment,
List<ExerciseData> exercises,
List<ExerciseImage> images,
List<Video> videos});
}
/// @nodoc
class _$ExerciseBaseDataCopyWithImpl<$Res, $Val extends ExerciseBaseData>
implements $ExerciseBaseDataCopyWith<$Res> {
_$ExerciseBaseDataCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? uuid = null,
Object? category = null,
Object? muscles = null,
Object? musclesSecondary = null,
Object? equipment = null,
Object? exercises = null,
Object? images = null,
Object? videos = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
uuid: null == uuid
? _value.uuid
: uuid // ignore: cast_nullable_to_non_nullable
as String,
category: null == category
? _value.category
: category // ignore: cast_nullable_to_non_nullable
as ExerciseCategory,
muscles: null == muscles
? _value.muscles
: muscles // ignore: cast_nullable_to_non_nullable
as List<Muscle>,
musclesSecondary: null == musclesSecondary
? _value.musclesSecondary
: musclesSecondary // ignore: cast_nullable_to_non_nullable
as List<Muscle>,
equipment: null == equipment
? _value.equipment
: equipment // ignore: cast_nullable_to_non_nullable
as List<Equipment>,
exercises: null == exercises
? _value.exercises
: exercises // ignore: cast_nullable_to_non_nullable
as List<ExerciseData>,
images: null == images
? _value.images
: images // ignore: cast_nullable_to_non_nullable
as List<ExerciseImage>,
videos: null == videos
? _value.videos
: videos // ignore: cast_nullable_to_non_nullable
as List<Video>,
) as $Val);
}
}
/// @nodoc
abstract class _$$ExerciseBaseDataImplCopyWith<$Res>
implements $ExerciseBaseDataCopyWith<$Res> {
factory _$$ExerciseBaseDataImplCopyWith(_$ExerciseBaseDataImpl value,
$Res Function(_$ExerciseBaseDataImpl) then) =
__$$ExerciseBaseDataImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
String uuid,
ExerciseCategory category,
List<Muscle> muscles,
@JsonKey(name: 'muscles_secondary') List<Muscle> musclesSecondary,
List<Equipment> equipment,
List<ExerciseData> exercises,
List<ExerciseImage> images,
List<Video> videos});
}
/// @nodoc
class __$$ExerciseBaseDataImplCopyWithImpl<$Res>
extends _$ExerciseBaseDataCopyWithImpl<$Res, _$ExerciseBaseDataImpl>
implements _$$ExerciseBaseDataImplCopyWith<$Res> {
__$$ExerciseBaseDataImplCopyWithImpl(_$ExerciseBaseDataImpl _value,
$Res Function(_$ExerciseBaseDataImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? uuid = null,
Object? category = null,
Object? muscles = null,
Object? musclesSecondary = null,
Object? equipment = null,
Object? exercises = null,
Object? images = null,
Object? videos = null,
}) {
return _then(_$ExerciseBaseDataImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
uuid: null == uuid
? _value.uuid
: uuid // ignore: cast_nullable_to_non_nullable
as String,
category: null == category
? _value.category
: category // ignore: cast_nullable_to_non_nullable
as ExerciseCategory,
muscles: null == muscles
? _value._muscles
: muscles // ignore: cast_nullable_to_non_nullable
as List<Muscle>,
musclesSecondary: null == musclesSecondary
? _value._musclesSecondary
: musclesSecondary // ignore: cast_nullable_to_non_nullable
as List<Muscle>,
equipment: null == equipment
? _value._equipment
: equipment // ignore: cast_nullable_to_non_nullable
as List<Equipment>,
exercises: null == exercises
? _value._exercises
: exercises // ignore: cast_nullable_to_non_nullable
as List<ExerciseData>,
images: null == images
? _value._images
: images // ignore: cast_nullable_to_non_nullable
as List<ExerciseImage>,
videos: null == videos
? _value._videos
: videos // ignore: cast_nullable_to_non_nullable
as List<Video>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ExerciseBaseDataImpl implements _ExerciseBaseData {
_$ExerciseBaseDataImpl(
{required this.id,
required this.uuid,
required this.category,
required final List<Muscle> muscles,
@JsonKey(name: 'muscles_secondary')
required final List<Muscle> musclesSecondary,
required final List<Equipment> equipment,
required final List<ExerciseData> exercises,
required final List<ExerciseImage> images,
required final List<Video> videos})
: _muscles = muscles,
_musclesSecondary = musclesSecondary,
_equipment = equipment,
_exercises = exercises,
_images = images,
_videos = videos;
factory _$ExerciseBaseDataImpl.fromJson(Map<String, dynamic> json) =>
_$$ExerciseBaseDataImplFromJson(json);
@override
final int id;
@override
final String uuid;
@override
final ExerciseCategory category;
final List<Muscle> _muscles;
@override
List<Muscle> get muscles {
if (_muscles is EqualUnmodifiableListView) return _muscles;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_muscles);
}
// ignore: invalid_annotation_target
final List<Muscle> _musclesSecondary;
// ignore: invalid_annotation_target
@override
@JsonKey(name: 'muscles_secondary')
List<Muscle> get musclesSecondary {
if (_musclesSecondary is EqualUnmodifiableListView)
return _musclesSecondary;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_musclesSecondary);
}
final List<Equipment> _equipment;
@override
List<Equipment> get equipment {
if (_equipment is EqualUnmodifiableListView) return _equipment;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_equipment);
}
final List<ExerciseData> _exercises;
@override
List<ExerciseData> get exercises {
if (_exercises is EqualUnmodifiableListView) return _exercises;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_exercises);
}
final List<ExerciseImage> _images;
@override
List<ExerciseImage> get images {
if (_images is EqualUnmodifiableListView) return _images;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_images);
}
final List<Video> _videos;
@override
List<Video> get videos {
if (_videos is EqualUnmodifiableListView) return _videos;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_videos);
}
@override
String toString() {
return 'ExerciseBaseData(id: $id, uuid: $uuid, category: $category, muscles: $muscles, musclesSecondary: $musclesSecondary, equipment: $equipment, exercises: $exercises, images: $images, videos: $videos)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ExerciseBaseDataImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.uuid, uuid) || other.uuid == uuid) &&
(identical(other.category, category) ||
other.category == category) &&
const DeepCollectionEquality().equals(other._muscles, _muscles) &&
const DeepCollectionEquality()
.equals(other._musclesSecondary, _musclesSecondary) &&
const DeepCollectionEquality()
.equals(other._equipment, _equipment) &&
const DeepCollectionEquality()
.equals(other._exercises, _exercises) &&
const DeepCollectionEquality().equals(other._images, _images) &&
const DeepCollectionEquality().equals(other._videos, _videos));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType,
id,
uuid,
category,
const DeepCollectionEquality().hash(_muscles),
const DeepCollectionEquality().hash(_musclesSecondary),
const DeepCollectionEquality().hash(_equipment),
const DeepCollectionEquality().hash(_exercises),
const DeepCollectionEquality().hash(_images),
const DeepCollectionEquality().hash(_videos));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ExerciseBaseDataImplCopyWith<_$ExerciseBaseDataImpl> get copyWith =>
__$$ExerciseBaseDataImplCopyWithImpl<_$ExerciseBaseDataImpl>(
this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ExerciseBaseDataImplToJson(
this,
);
}
}
abstract class _ExerciseBaseData implements ExerciseBaseData {
factory _ExerciseBaseData(
{required final int id,
required final String uuid,
required final ExerciseCategory category,
required final List<Muscle> muscles,
@JsonKey(name: 'muscles_secondary')
required final List<Muscle> musclesSecondary,
required final List<Equipment> equipment,
required final List<ExerciseData> exercises,
required final List<ExerciseImage> images,
required final List<Video> videos}) = _$ExerciseBaseDataImpl;
factory _ExerciseBaseData.fromJson(Map<String, dynamic> json) =
_$ExerciseBaseDataImpl.fromJson;
@override
int get id;
@override
String get uuid;
@override
ExerciseCategory get category;
@override
List<Muscle> get muscles;
@override // ignore: invalid_annotation_target
@JsonKey(name: 'muscles_secondary')
List<Muscle> get musclesSecondary;
@override
List<Equipment> get equipment;
@override
List<ExerciseData> get exercises;
@override
List<ExerciseImage> get images;
@override
List<Video> get videos;
@override
@JsonKey(ignore: true)
_$$ExerciseBaseDataImplCopyWith<_$ExerciseBaseDataImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,48 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'exercise_base_data.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ExerciseBaseDataImpl _$$ExerciseBaseDataImplFromJson(
Map<String, dynamic> json) =>
_$ExerciseBaseDataImpl(
id: json['id'] as int,
uuid: json['uuid'] 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>))
.toList(),
musclesSecondary: (json['muscles_secondary'] as List<dynamic>)
.map((e) => Muscle.fromJson(e as Map<String, dynamic>))
.toList(),
equipment: (json['equipment'] as List<dynamic>)
.map((e) => Equipment.fromJson(e as Map<String, dynamic>))
.toList(),
exercises: (json['exercises'] as List<dynamic>)
.map((e) => ExerciseData.fromJson(e as Map<String, dynamic>))
.toList(),
images: (json['images'] as List<dynamic>)
.map((e) => ExerciseImage.fromJson(e as Map<String, dynamic>))
.toList(),
videos: (json['videos'] as List<dynamic>)
.map((e) => Video.fromJson(e as Map<String, dynamic>))
.toList(),
);
Map<String, dynamic> _$$ExerciseBaseDataImplToJson(
_$ExerciseBaseDataImpl instance) =>
<String, dynamic>{
'id': instance.id,
'uuid': instance.uuid,
'category': instance.category,
'muscles': instance.muscles,
'muscles_secondary': instance.musclesSecondary,
'equipment': instance.equipment,
'exercises': instance.exercises,
'images': instance.images,
'videos': instance.videos,
};

View File

@@ -0,0 +1,23 @@
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:wger/models/exercises/alias.dart';
import 'package:wger/models/exercises/comment.dart';
part 'exercise_model.freezed.dart';
part 'exercise_model.g.dart';
@freezed
class ExerciseData with _$ExerciseData {
factory ExerciseData({
required int id,
required String uuid,
@JsonKey(name: 'language') required int languageId,
@JsonKey(required: true, name: 'exercise_base') required int baseId,
required String description,
required String name,
required List<Alias> aliases,
required List<Comment> notes,
}) = _ExerciseData;
factory ExerciseData.fromJson(Map<String, dynamic> json) =>
_$ExerciseDataFromJson(json);
}

View File

@@ -0,0 +1,325 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
part of 'exercise_model.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
ExerciseData _$ExerciseDataFromJson(Map<String, dynamic> json) {
return _ExerciseData.fromJson(json);
}
/// @nodoc
mixin _$ExerciseData {
int get id => throw _privateConstructorUsedError;
String get uuid => throw _privateConstructorUsedError;
@JsonKey(name: 'language')
int get languageId => throw _privateConstructorUsedError;
@JsonKey(required: true, name: 'exercise_base')
int get baseId => throw _privateConstructorUsedError;
String get description => throw _privateConstructorUsedError;
String get name => throw _privateConstructorUsedError;
List<Alias> get aliases => throw _privateConstructorUsedError;
List<Comment> get notes => throw _privateConstructorUsedError;
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$ExerciseDataCopyWith<ExerciseData> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $ExerciseDataCopyWith<$Res> {
factory $ExerciseDataCopyWith(
ExerciseData value, $Res Function(ExerciseData) then) =
_$ExerciseDataCopyWithImpl<$Res, ExerciseData>;
@useResult
$Res call(
{int id,
String uuid,
@JsonKey(name: 'language') int languageId,
@JsonKey(required: true, name: 'exercise_base') int baseId,
String description,
String name,
List<Alias> aliases,
List<Comment> notes});
}
/// @nodoc
class _$ExerciseDataCopyWithImpl<$Res, $Val extends ExerciseData>
implements $ExerciseDataCopyWith<$Res> {
_$ExerciseDataCopyWithImpl(this._value, this._then);
// ignore: unused_field
final $Val _value;
// ignore: unused_field
final $Res Function($Val) _then;
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? uuid = null,
Object? languageId = null,
Object? baseId = null,
Object? description = null,
Object? name = null,
Object? aliases = null,
Object? notes = null,
}) {
return _then(_value.copyWith(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
uuid: null == uuid
? _value.uuid
: uuid // ignore: cast_nullable_to_non_nullable
as String,
languageId: null == languageId
? _value.languageId
: languageId // ignore: cast_nullable_to_non_nullable
as int,
baseId: null == baseId
? _value.baseId
: baseId // ignore: cast_nullable_to_non_nullable
as int,
description: null == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
aliases: null == aliases
? _value.aliases
: aliases // ignore: cast_nullable_to_non_nullable
as List<Alias>,
notes: null == notes
? _value.notes
: notes // ignore: cast_nullable_to_non_nullable
as List<Comment>,
) as $Val);
}
}
/// @nodoc
abstract class _$$ExerciseDataImplCopyWith<$Res>
implements $ExerciseDataCopyWith<$Res> {
factory _$$ExerciseDataImplCopyWith(
_$ExerciseDataImpl value, $Res Function(_$ExerciseDataImpl) then) =
__$$ExerciseDataImplCopyWithImpl<$Res>;
@override
@useResult
$Res call(
{int id,
String uuid,
@JsonKey(name: 'language') int languageId,
@JsonKey(required: true, name: 'exercise_base') int baseId,
String description,
String name,
List<Alias> aliases,
List<Comment> notes});
}
/// @nodoc
class __$$ExerciseDataImplCopyWithImpl<$Res>
extends _$ExerciseDataCopyWithImpl<$Res, _$ExerciseDataImpl>
implements _$$ExerciseDataImplCopyWith<$Res> {
__$$ExerciseDataImplCopyWithImpl(
_$ExerciseDataImpl _value, $Res Function(_$ExerciseDataImpl) _then)
: super(_value, _then);
@pragma('vm:prefer-inline')
@override
$Res call({
Object? id = null,
Object? uuid = null,
Object? languageId = null,
Object? baseId = null,
Object? description = null,
Object? name = null,
Object? aliases = null,
Object? notes = null,
}) {
return _then(_$ExerciseDataImpl(
id: null == id
? _value.id
: id // ignore: cast_nullable_to_non_nullable
as int,
uuid: null == uuid
? _value.uuid
: uuid // ignore: cast_nullable_to_non_nullable
as String,
languageId: null == languageId
? _value.languageId
: languageId // ignore: cast_nullable_to_non_nullable
as int,
baseId: null == baseId
? _value.baseId
: baseId // ignore: cast_nullable_to_non_nullable
as int,
description: null == description
? _value.description
: description // ignore: cast_nullable_to_non_nullable
as String,
name: null == name
? _value.name
: name // ignore: cast_nullable_to_non_nullable
as String,
aliases: null == aliases
? _value._aliases
: aliases // ignore: cast_nullable_to_non_nullable
as List<Alias>,
notes: null == notes
? _value._notes
: notes // ignore: cast_nullable_to_non_nullable
as List<Comment>,
));
}
}
/// @nodoc
@JsonSerializable()
class _$ExerciseDataImpl implements _ExerciseData {
_$ExerciseDataImpl(
{required this.id,
required this.uuid,
@JsonKey(name: 'language') required this.languageId,
@JsonKey(required: true, name: 'exercise_base') required this.baseId,
required this.description,
required this.name,
required final List<Alias> aliases,
required final List<Comment> notes})
: _aliases = aliases,
_notes = notes;
factory _$ExerciseDataImpl.fromJson(Map<String, dynamic> json) =>
_$$ExerciseDataImplFromJson(json);
@override
final int id;
@override
final String uuid;
@override
@JsonKey(name: 'language')
final int languageId;
@override
@JsonKey(required: true, name: 'exercise_base')
final int baseId;
@override
final String description;
@override
final String name;
final List<Alias> _aliases;
@override
List<Alias> get aliases {
if (_aliases is EqualUnmodifiableListView) return _aliases;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_aliases);
}
final List<Comment> _notes;
@override
List<Comment> get notes {
if (_notes is EqualUnmodifiableListView) return _notes;
// ignore: implicit_dynamic_type
return EqualUnmodifiableListView(_notes);
}
@override
String toString() {
return 'ExerciseData(id: $id, uuid: $uuid, languageId: $languageId, baseId: $baseId, description: $description, name: $name, aliases: $aliases, notes: $notes)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is _$ExerciseDataImpl &&
(identical(other.id, id) || other.id == id) &&
(identical(other.uuid, uuid) || other.uuid == uuid) &&
(identical(other.languageId, languageId) ||
other.languageId == languageId) &&
(identical(other.baseId, baseId) || other.baseId == baseId) &&
(identical(other.description, description) ||
other.description == description) &&
(identical(other.name, name) || other.name == name) &&
const DeepCollectionEquality().equals(other._aliases, _aliases) &&
const DeepCollectionEquality().equals(other._notes, _notes));
}
@JsonKey(ignore: true)
@override
int get hashCode => Object.hash(
runtimeType,
id,
uuid,
languageId,
baseId,
description,
name,
const DeepCollectionEquality().hash(_aliases),
const DeepCollectionEquality().hash(_notes));
@JsonKey(ignore: true)
@override
@pragma('vm:prefer-inline')
_$$ExerciseDataImplCopyWith<_$ExerciseDataImpl> get copyWith =>
__$$ExerciseDataImplCopyWithImpl<_$ExerciseDataImpl>(this, _$identity);
@override
Map<String, dynamic> toJson() {
return _$$ExerciseDataImplToJson(
this,
);
}
}
abstract class _ExerciseData implements ExerciseData {
factory _ExerciseData(
{required final int id,
required final String uuid,
@JsonKey(name: 'language') required final int languageId,
@JsonKey(required: true, name: 'exercise_base') required final int baseId,
required final String description,
required final String name,
required final List<Alias> aliases,
required final List<Comment> notes}) = _$ExerciseDataImpl;
factory _ExerciseData.fromJson(Map<String, dynamic> json) =
_$ExerciseDataImpl.fromJson;
@override
int get id;
@override
String get uuid;
@override
@JsonKey(name: 'language')
int get languageId;
@override
@JsonKey(required: true, name: 'exercise_base')
int get baseId;
@override
String get description;
@override
String get name;
@override
List<Alias> get aliases;
@override
List<Comment> get notes;
@override
@JsonKey(ignore: true)
_$$ExerciseDataImplCopyWith<_$ExerciseDataImpl> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@@ -0,0 +1,40 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'exercise_model.dart';
// **************************************************************************
// JsonSerializableGenerator
// **************************************************************************
_$ExerciseDataImpl _$$ExerciseDataImplFromJson(Map<String, dynamic> json) {
$checkKeys(
json,
requiredKeys: const ['exercise_base'],
);
return _$ExerciseDataImpl(
id: json['id'] as int,
uuid: json['uuid'] as String,
languageId: json['language'] as int,
baseId: json['exercise_base'] as int,
description: json['description'] as String,
name: json['name'] as String,
aliases: (json['aliases'] as List<dynamic>)
.map((e) => Alias.fromJson(e as Map<String, dynamic>))
.toList(),
notes: (json['notes'] as List<dynamic>)
.map((e) => Comment.fromJson(e as Map<String, dynamic>))
.toList(),
);
}
Map<String, dynamic> _$$ExerciseDataImplToJson(_$ExerciseDataImpl instance) =>
<String, dynamic>{
'id': instance.id,
'uuid': instance.uuid,
'language': instance.languageId,
'exercise_base': instance.baseId,
'description': instance.description,
'name': instance.name,
'aliases': instance.aliases,
'notes': instance.notes,
};

View File

@@ -46,7 +46,8 @@ class ExerciseImage {
});
// Boilerplate
factory ExerciseImage.fromJson(Map<String, dynamic> json) => _$ExerciseImageFromJson(json);
factory ExerciseImage.fromJson(Map<String, dynamic> json) =>
_$ExerciseImageFromJson(json);
Map<String, dynamic> toJson() => _$ExerciseImageToJson(this);
@override

View File

@@ -20,7 +20,8 @@ ExerciseImage _$ExerciseImageFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$ExerciseImageToJson(ExerciseImage instance) => <String, dynamic>{
Map<String, dynamic> _$ExerciseImageToJson(ExerciseImage instance) =>
<String, dynamic>{
'id': instance.id,
'uuid': instance.uuid,
'exercise_base': instance.exerciseBaseId,

View File

@@ -39,7 +39,8 @@ class Language extends Equatable {
});
// Boilerplate
factory Language.fromJson(Map<String, dynamic> json) => _$LanguageFromJson(json);
factory Language.fromJson(Map<String, dynamic> json) =>
_$LanguageFromJson(json);
Map<String, dynamic> toJson() => _$LanguageToJson(this);
@override

View File

@@ -52,7 +52,8 @@ class Muscle extends Equatable {
List<Object?> get props => [id, name, isFront];
String nameTranslated(BuildContext context) {
return name + (nameEn.isNotEmpty ? ' (${getTranslation(nameEn, context)})' : '');
return name +
(nameEn.isNotEmpty ? ' (${getTranslation(nameEn, context)})' : '');
}
@override

View File

@@ -36,7 +36,7 @@ class Translation extends Equatable {
@JsonKey(required: true, name: 'language')
late int languageId;
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: true, includeToJson: true)
late Language languageObj;
@JsonKey(required: true, name: 'created')
@@ -51,11 +51,11 @@ class Translation extends Equatable {
@JsonKey(required: true)
final String description;
@JsonKey(includeFromJson: false, includeToJson: false)
@JsonKey(includeFromJson: true, includeToJson: true)
List<Comment> notes = [];
@JsonKey(includeFromJson: false, includeToJson: false)
List<Alias> alias = [];
@JsonKey(includeFromJson: true, includeToJson: true)
List<Alias> aliases = [];
Translation({
this.id,
@@ -67,7 +67,7 @@ class Translation extends Equatable {
language,
}) {
if (baseId != null) {
baseId = baseId;
this.baseId = baseId;
}
if (language != null) {
@@ -86,7 +86,8 @@ class Translation extends Equatable {
}
// Boilerplate
factory Translation.fromJson(Map<String, dynamic> json) => _$TranslationFromJson(json);
factory Translation.fromJson(Map<String, dynamic> json) =>
_$TranslationFromJson(json);
Map<String, dynamic> toJson() => _$TranslationToJson(this);

View File

@@ -22,19 +22,34 @@ Translation _$TranslationFromJson(Map<String, dynamic> json) {
return Translation(
id: json['id'] as int?,
uuid: json['uuid'] as String?,
created: json['created'] == null ? null : DateTime.parse(json['created'] as String),
created: json['created'] == null
? null
: DateTime.parse(json['created'] as String),
name: json['name'] as String,
description: json['description'] as String,
baseId: json['exercise_base'] as int?,
)..languageId = json['language'] as int;
)
..languageId = json['language'] as int
..languageObj =
Language.fromJson(json['languageObj'] as Map<String, dynamic>)
..notes = (json['notes'] as List<dynamic>)
.map((e) => Comment.fromJson(e as Map<String, dynamic>))
.toList()
..aliases = (json['aliases'] as List<dynamic>)
.map((e) => Alias.fromJson(e as Map<String, dynamic>))
.toList();
}
Map<String, dynamic> _$TranslationToJson(Translation instance) => <String, dynamic>{
Map<String, dynamic> _$TranslationToJson(Translation instance) =>
<String, dynamic>{
'id': instance.id,
'uuid': instance.uuid,
'language': instance.languageId,
'languageObj': instance.languageObj,
'created': instance.created?.toIso8601String(),
'exercise_base': instance.baseId,
'name': instance.name,
'description': instance.description,
'notes': instance.notes,
'aliases': instance.aliases,
};

View File

@@ -30,6 +30,7 @@ class Variation {
});
// Boilerplate
factory Variation.fromJson(Map<String, dynamic> json) => _$VariationFromJson(json);
factory Variation.fromJson(Map<String, dynamic> json) =>
_$VariationFromJson(json);
Map<String, dynamic> toJson() => _$VariationToJson(this);
}

View File

@@ -22,7 +22,9 @@ MeasurementCategory _$MeasurementCategoryFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$MeasurementCategoryToJson(MeasurementCategory instance) => <String, dynamic>{
Map<String, dynamic> _$MeasurementCategoryToJson(
MeasurementCategory instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
'unit': instance.unit,

View File

@@ -29,7 +29,12 @@ class MeasurementEntry extends Equatable {
required this.notes,
});
MeasurementEntry copyWith({int? id, int? category, DateTime? date, num? value, String? notes}) =>
MeasurementEntry copyWith(
{int? id,
int? category,
DateTime? date,
num? value,
String? notes}) =>
MeasurementEntry(
id: id ?? this.id,
category: category ?? this.category,
@@ -39,7 +44,8 @@ class MeasurementEntry extends Equatable {
);
// Boilerplate
factory MeasurementEntry.fromJson(Map<String, dynamic> json) => _$MeasurementEntryFromJson(json);
factory MeasurementEntry.fromJson(Map<String, dynamic> json) =>
_$MeasurementEntryFromJson(json);
Map<String, dynamic> toJson() => _$MeasurementEntryToJson(this);

View File

@@ -20,7 +20,8 @@ MeasurementEntry _$MeasurementEntryFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$MeasurementEntryToJson(MeasurementEntry instance) => <String, dynamic>{
Map<String, dynamic> _$MeasurementEntryToJson(MeasurementEntry instance) =>
<String, dynamic>{
'id': instance.id,
'category': instance.category,
'date': toDate(instance.date),

View File

@@ -81,7 +81,8 @@ class IngredientImage {
});
// Boilerplate
factory IngredientImage.fromJson(Map<String, dynamic> json) => _$IngredientImageFromJson(json);
factory IngredientImage.fromJson(Map<String, dynamic> json) =>
_$IngredientImageFromJson(json);
Map<String, dynamic> toJson() => _$IngredientImageToJson(this);
}

View File

@@ -38,7 +38,8 @@ IngredientImage _$IngredientImageFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$IngredientImageToJson(IngredientImage instance) => <String, dynamic>{
Map<String, dynamic> _$IngredientImageToJson(IngredientImage instance) =>
<String, dynamic>{
'id': instance.id,
'uuid': instance.uuid,
'ingredient_id': instance.ingredientId,

View File

@@ -46,7 +46,11 @@ class Ingredient {
final num carbohydrates;
/// g per 100g of product
@JsonKey(required: true, fromJson: stringToNum, toJson: numToString, name: 'carbohydrates_sugar')
@JsonKey(
required: true,
fromJson: stringToNum,
toJson: numToString,
name: 'carbohydrates_sugar')
final num carbohydratesSugar;
/// g per 100g of product
@@ -58,7 +62,11 @@ class Ingredient {
final num fat;
/// g per 100g of product
@JsonKey(required: true, fromJson: stringToNum, toJson: numToString, name: 'fat_saturated')
@JsonKey(
required: true,
fromJson: stringToNum,
toJson: numToString,
name: 'fat_saturated')
final num fatSaturated;
/// g per 100g of product
@@ -88,7 +96,8 @@ class Ingredient {
});
// Boilerplate
factory Ingredient.fromJson(Map<String, dynamic> json) => _$IngredientFromJson(json);
factory Ingredient.fromJson(Map<String, dynamic> json) =>
_$IngredientFromJson(json);
Map<String, dynamic> toJson() => _$IngredientToJson(this);
}

View File

@@ -43,7 +43,8 @@ Ingredient _$IngredientFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$IngredientToJson(Ingredient instance) => <String, dynamic>{
Map<String, dynamic> _$IngredientToJson(Ingredient instance) =>
<String, dynamic>{
'id': instance.id,
'code': instance.code,
'name': instance.name,

View File

@@ -13,14 +13,16 @@ IngredientWeightUnit _$IngredientWeightUnitFromJson(Map<String, dynamic> json) {
);
return IngredientWeightUnit(
id: json['id'] as int,
weightUnit: WeightUnit.fromJson(json['weight_unit'] as Map<String, dynamic>),
weightUnit:
WeightUnit.fromJson(json['weight_unit'] as Map<String, dynamic>),
ingredient: Ingredient.fromJson(json['ingredient'] as Map<String, dynamic>),
grams: json['grams'] as int,
amount: (json['amount'] as num).toDouble(),
);
}
Map<String, dynamic> _$IngredientWeightUnitToJson(IngredientWeightUnit instance) =>
Map<String, dynamic> _$IngredientWeightUnitToJson(
IngredientWeightUnit instance) =>
<String, dynamic>{
'id': instance.id,
'weight_unit': instance.weightUnit,

View File

@@ -67,7 +67,8 @@ class Log {
this.comment,
});
Log.fromMealItem(MealItem mealItem, this.planId, this.mealId, [DateTime? dateTime]) {
Log.fromMealItem(MealItem mealItem, this.planId, this.mealId,
[DateTime? dateTime]) {
ingredientId = mealItem.ingredientId;
ingredientObj = mealItem.ingredientObj;
weightUnitId = mealItem.weightUnitId;
@@ -86,8 +87,9 @@ class Log {
final out = NutritionalValues();
//final weight = amount;
final weight =
weightUnitObj == null ? amount : amount * weightUnitObj!.amount * weightUnitObj!.grams;
final weight = weightUnitObj == null
? amount
: amount * weightUnitObj!.amount * weightUnitObj!.grams;
out.energy = ingredientObj.energy * weight / 100;
out.protein = ingredientObj.protein * weight / 100;

View File

@@ -9,7 +9,14 @@ part of 'log.dart';
Log _$LogFromJson(Map<String, dynamic> json) {
$checkKeys(
json,
requiredKeys: const ['id', 'plan', 'datetime', 'ingredient', 'weight_unit', 'amount'],
requiredKeys: const [
'id',
'plan',
'datetime',
'ingredient',
'weight_unit',
'amount'
],
);
return Log(
id: json['id'] as int?,

View File

@@ -38,7 +38,11 @@ class Meal {
@JsonKey(name: 'name')
late String name;
@JsonKey(includeFromJson: false, includeToJson: false, name: 'meal_items', defaultValue: [])
@JsonKey(
includeFromJson: false,
includeToJson: false,
name: 'meal_items',
defaultValue: [])
List<MealItem> mealItems = [];
Meal({

View File

@@ -67,7 +67,8 @@ class MealItem {
MealItem.empty();
// Boilerplate
factory MealItem.fromJson(Map<String, dynamic> json) => _$MealItemFromJson(json);
factory MealItem.fromJson(Map<String, dynamic> json) =>
_$MealItemFromJson(json);
Map<String, dynamic> toJson() => _$MealItemToJson(this);

View File

@@ -62,12 +62,15 @@ class NutritionalPlan {
}
// Boilerplate
factory NutritionalPlan.fromJson(Map<String, dynamic> json) => _$NutritionalPlanFromJson(json);
factory NutritionalPlan.fromJson(Map<String, dynamic> json) =>
_$NutritionalPlanFromJson(json);
Map<String, dynamic> toJson() => _$NutritionalPlanToJson(this);
String getLabel(BuildContext context) {
return description != '' ? description : AppLocalizations.of(context).nutritionalPlan;
return description != ''
? description
: AppLocalizations.of(context).nutritionalPlan;
}
/// Calculations
@@ -86,7 +89,9 @@ class NutritionalPlan {
final now = DateTime.now();
final today = DateTime(now.year, now.month, now.day);
return logEntriesValues.containsKey(today) ? logEntriesValues[today]! : NutritionalValues();
return logEntriesValues.containsKey(today)
? logEntriesValues[today]!
: NutritionalValues();
}
NutritionalValues get nutritionalValues7DayAvg {
@@ -109,9 +114,12 @@ class NutritionalPlan {
/// Calculates the percentage each macro nutrient adds to the total energy
BaseNutritionalValues energyPercentage(NutritionalValues values) {
return BaseNutritionalValues(
values.protein > 0 ? ((values.protein * ENERGY_PROTEIN * 100) / values.energy) : 0,
values.protein > 0
? ((values.protein * ENERGY_PROTEIN * 100) / values.energy)
: 0,
values.carbohydrates > 0
? ((values.carbohydrates * ENERGY_CARBOHYDRATES * 100) / values.energy)
? ((values.carbohydrates * ENERGY_CARBOHYDRATES * 100) /
values.energy)
: 0,
values.fat > 0 ? ((values.fat * ENERGY_FAT * 100) / values.energy) : 0,
);
@@ -131,7 +139,8 @@ class NutritionalPlan {
Map<DateTime, NutritionalValues> get logEntriesValues {
final out = <DateTime, NutritionalValues>{};
for (final log in logs) {
final date = DateTime(log.datetime.year, log.datetime.month, log.datetime.day);
final date =
DateTime(log.datetime.year, log.datetime.month, log.datetime.day);
if (!out.containsKey(date)) {
out[date] = NutritionalValues();
@@ -156,7 +165,8 @@ class NutritionalPlan {
final List<Log> out = [];
for (final log in logs) {
final dateKey = DateTime(date.year, date.month, date.day);
final logKey = DateTime(log.datetime.year, log.datetime.month, log.datetime.day);
final logKey =
DateTime(log.datetime.year, log.datetime.month, log.datetime.day);
if (dateKey == logKey) {
out.add(log);
@@ -173,7 +183,8 @@ class NutritionalPlan {
final List<MealItem> out = [];
for (final meal in meals) {
for (final mealItem in meal.mealItems) {
final ingredientInList = out.where((e) => e.ingredientId == mealItem.ingredientId);
final ingredientInList =
out.where((e) => e.ingredientId == mealItem.ingredientId);
if (ingredientInList.isEmpty) {
out.add(mealItem);

View File

@@ -18,7 +18,8 @@ NutritionalPlan _$NutritionalPlanFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$NutritionalPlanToJson(NutritionalPlan instance) => <String, dynamic>{
Map<String, dynamic> _$NutritionalPlanToJson(NutritionalPlan instance) =>
<String, dynamic>{
'id': instance.id,
'description': instance.description,
'creation_date': toDate(instance.creationDate),

View File

@@ -89,8 +89,8 @@ class NutritionalValues {
@override
//ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode => Object.hash(
energy, protein, carbohydrates, carbohydratesSugar, fat, fatSaturated, fibres, sodium);
int get hashCode => Object.hash(energy, protein, carbohydrates,
carbohydratesSugar, fat, fatSaturated, fibres, sodium);
}
class BaseNutritionalValues {

View File

@@ -34,6 +34,7 @@ class WeightUnit {
});
// Boilerplate
factory WeightUnit.fromJson(Map<String, dynamic> json) => _$WeightUnitFromJson(json);
factory WeightUnit.fromJson(Map<String, dynamic> json) =>
_$WeightUnitFromJson(json);
Map<String, dynamic> toJson() => _$WeightUnitToJson(this);
}

View File

@@ -17,7 +17,8 @@ WeightUnit _$WeightUnitFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$WeightUnitToJson(WeightUnit instance) => <String, dynamic>{
Map<String, dynamic> _$WeightUnitToJson(WeightUnit instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
};

View File

@@ -42,6 +42,7 @@ class Profile {
});
// Boilerplate
factory Profile.fromJson(Map<String, dynamic> json) => _$ProfileFromJson(json);
factory Profile.fromJson(Map<String, dynamic> json) =>
_$ProfileFromJson(json);
Map<String, dynamic> toJson() => _$ProfileToJson(this);
}

View File

@@ -9,7 +9,12 @@ part of 'profile.dart';
Profile _$ProfileFromJson(Map<String, dynamic> json) {
$checkKeys(
json,
requiredKeys: const ['username', 'email_verified', 'is_trustworthy', 'email'],
requiredKeys: const [
'username',
'email_verified',
'is_trustworthy',
'email'
],
);
return Profile(
username: json['username'] as String,

View File

@@ -75,7 +75,8 @@ class Day {
final now = DateTime.now();
final firstDayOfWeek = now.subtract(Duration(days: now.weekday));
return DateFormat(DateFormat.WEEKDAY, locale).format(firstDayOfWeek.add(Duration(days: day)));
return DateFormat(DateFormat.WEEKDAY, locale)
.format(firstDayOfWeek.add(Duration(days: day)));
}
// Boilerplate

View File

@@ -111,7 +111,8 @@ class Log {
/// Returns the text representation for a single setting, used in the gym mode
String get singleLogRepTextNoNl {
return repText(reps, repetitionUnitObj, weight, weightUnitObj, rir).replaceAll('\n', '');
return repText(reps, repetitionUnitObj, weight, weightUnitObj, rir)
.replaceAll('\n', '');
}
/// Override the equals operator
@@ -132,8 +133,8 @@ class Log {
@override
//ignore: avoid_equals_and_hash_code_on_mutable_classes
int get hashCode =>
Object.hash(exerciseBaseId, weight, weightUnitId, reps, repetitionUnitId, rir);
int get hashCode => Object.hash(
exerciseBaseId, weight, weightUnitId, reps, repetitionUnitId, rir);
//@override
//int get hashCode => super.hashCode;

View File

@@ -34,6 +34,7 @@ class RepetitionUnit {
});
// Boilerplate
factory RepetitionUnit.fromJson(Map<String, dynamic> json) => _$RepetitionUnitFromJson(json);
factory RepetitionUnit.fromJson(Map<String, dynamic> json) =>
_$RepetitionUnitFromJson(json);
Map<String, dynamic> toJson() => _$RepetitionUnitToJson(this);
}

View File

@@ -17,7 +17,8 @@ RepetitionUnit _$RepetitionUnitFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$RepetitionUnitToJson(RepetitionUnit instance) => <String, dynamic>{
Map<String, dynamic> _$RepetitionUnitToJson(RepetitionUnit instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
};

View File

@@ -41,10 +41,18 @@ class WorkoutSession {
@JsonKey(required: false, defaultValue: '')
late String notes;
@JsonKey(required: true, name: 'time_start', toJson: timeToString, fromJson: stringToTime)
@JsonKey(
required: true,
name: 'time_start',
toJson: timeToString,
fromJson: stringToTime)
late TimeOfDay timeStart;
@JsonKey(required: true, name: 'time_end', toJson: timeToString, fromJson: stringToTime)
@JsonKey(
required: true,
name: 'time_end',
toJson: timeToString,
fromJson: stringToTime)
late TimeOfDay timeEnd;
WorkoutSession();
@@ -65,7 +73,8 @@ class WorkoutSession {
}
// Boilerplate
factory WorkoutSession.fromJson(Map<String, dynamic> json) => _$WorkoutSessionFromJson(json);
factory WorkoutSession.fromJson(Map<String, dynamic> json) =>
_$WorkoutSessionFromJson(json);
Map<String, dynamic> toJson() => _$WorkoutSessionToJson(this);
String? get impressionAsString {

View File

@@ -9,7 +9,14 @@ part of 'session.dart';
WorkoutSession _$WorkoutSessionFromJson(Map<String, dynamic> json) {
$checkKeys(
json,
requiredKeys: const ['id', 'workout', 'date', 'impression', 'time_start', 'time_end'],
requiredKeys: const [
'id',
'workout',
'date',
'impression',
'time_start',
'time_end'
],
);
return WorkoutSession()
..id = json['id'] as int?
@@ -21,7 +28,8 @@ WorkoutSession _$WorkoutSessionFromJson(Map<String, dynamic> json) {
..timeEnd = stringToTime(json['time_end'] as String?);
}
Map<String, dynamic> _$WorkoutSessionToJson(WorkoutSession instance) => <String, dynamic>{
Map<String, dynamic> _$WorkoutSessionToJson(WorkoutSession instance) =>
<String, dynamic>{
'id': instance.id,
'workout': instance.workoutId,
'date': toDate(instance.date),

View File

@@ -114,7 +114,9 @@ class Set {
/// Returns all settings for the given exercise
List<Setting> filterSettingsByExercise(ExerciseBase exerciseBase) {
return settings.where((element) => element.exerciseBaseId == exerciseBase.id).toList();
return settings
.where((element) => element.exerciseBaseId == exerciseBase.id)
.toList();
}
/// Returns a list with all repetitions for the given exercise

View File

@@ -29,7 +29,18 @@ part 'setting.g.dart';
class Setting {
/// Allowed RiR values. This list must be kept in sync with RIR_OPTIONS in the
/// wger server
static const POSSIBLE_RIR_VALUES = ['', '0', '0.5', '1', '1.5', '2', '2.5', '3', '3.5', '4'];
static const POSSIBLE_RIR_VALUES = [
'',
'0',
'0.5',
'1',
'1.5',
'2',
'2.5',
'3',
'3.5',
'4'
];
static const DEFAULT_RIR = '';
@JsonKey(required: true)
@@ -88,7 +99,8 @@ class Setting {
Setting.empty();
// Boilerplate
factory Setting.fromJson(Map<String, dynamic> json) => _$SettingFromJson(json);
factory Setting.fromJson(Map<String, dynamic> json) =>
_$SettingFromJson(json);
Map<String, dynamic> toJson() => _$SettingToJson(this);

View File

@@ -34,6 +34,7 @@ class WeightUnit {
});
// Boilerplate
factory WeightUnit.fromJson(Map<String, dynamic> json) => _$WeightUnitFromJson(json);
factory WeightUnit.fromJson(Map<String, dynamic> json) =>
_$WeightUnitFromJson(json);
Map<String, dynamic> toJson() => _$WeightUnitToJson(this);
}

View File

@@ -17,7 +17,8 @@ WeightUnit _$WeightUnitFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$WeightUnitToJson(WeightUnit instance) => <String, dynamic>{
Map<String, dynamic> _$WeightUnitToJson(WeightUnit instance) =>
<String, dynamic>{
'id': instance.id,
'name': instance.name,
};

View File

@@ -63,7 +63,8 @@ class WorkoutPlan {
}
// Boilerplate
factory WorkoutPlan.fromJson(Map<String, dynamic> json) => _$WorkoutPlanFromJson(json);
factory WorkoutPlan.fromJson(Map<String, dynamic> json) =>
_$WorkoutPlanFromJson(json);
Map<String, dynamic> toJson() => _$WorkoutPlanToJson(this);
@@ -73,8 +74,11 @@ class WorkoutPlan {
/// means here that the values are the same, i.e. logs with the same weight,
/// reps, etc. are considered equal. Workout ID, Log ID and date are not
/// considered.
List<Log> filterLogsByExerciseBase(ExerciseBase exerciseBase, {bool unique = false}) {
var out = logs.where((element) => element.exerciseBaseId == exerciseBase.id).toList();
List<Log> filterLogsByExerciseBase(ExerciseBase exerciseBase,
{bool unique = false}) {
var out = logs
.where((element) => element.exerciseBaseId == exerciseBase.id)
.toList();
if (unique) {
out = out.toSet().toList();

View File

@@ -19,7 +19,8 @@ WorkoutPlan _$WorkoutPlanFromJson(Map<String, dynamic> json) {
);
}
Map<String, dynamic> _$WorkoutPlanToJson(WorkoutPlan instance) => <String, dynamic>{
Map<String, dynamic> _$WorkoutPlanToJson(WorkoutPlan instance) =>
<String, dynamic>{
'id': instance.id,
'creation_date': instance.creationDate.toIso8601String(),
'name': instance.name,

View File

@@ -65,11 +65,13 @@ class AddExerciseProvider with ChangeNotifier {
set descriptionEn(String description) => _descriptionEn = description;
set descriptionTrans(String description) => _descriptionTranslation = description;
set descriptionTrans(String description) =>
_descriptionTranslation = description;
set alternateNamesEn(List<String> names) => _alternativeNamesEn = names;
set alternateNamesTrans(List<String> names) => _alternativeNamesTranslation = names;
set alternateNamesTrans(List<String> names) =>
_alternativeNamesTranslation = names;
set equipment(List<Equipment> equipment) => _equipment = equipment;
@@ -185,7 +187,8 @@ class AddExerciseProvider with ChangeNotifier {
exerciseTranslationEn = await addExerciseTranslation(exerciseTranslationEn);
for (final alias in _alternativeNamesEn) {
if (alias.isNotEmpty) {
exerciseTranslationEn.alias.add(await addExerciseAlias(alias, exerciseTranslationEn.id!));
exerciseTranslationEn.aliases
.add(await addExerciseAlias(alias, exerciseTranslationEn.id!));
}
}
@@ -193,10 +196,11 @@ class AddExerciseProvider with ChangeNotifier {
if (language != null) {
Translation exerciseTranslationLang = exerciseTranslation;
exerciseTranslationLang.base = base;
exerciseTranslationLang = await addExerciseTranslation(exerciseTranslationLang);
exerciseTranslationLang =
await addExerciseTranslation(exerciseTranslationLang);
for (final alias in _alternativeNamesTranslation) {
if (alias.isNotEmpty) {
exerciseTranslationLang.alias.add(
exerciseTranslationLang.aliases.add(
await addExerciseAlias(alias, exerciseTranslationLang.id!),
);
}
@@ -217,7 +221,8 @@ class AddExerciseProvider with ChangeNotifier {
Future<ExerciseBase> addExerciseBase() async {
final Uri postUri = baseProvider.makeUrl(_exerciseBaseUrlPath);
final Map<String, dynamic> newBaseMap = await baseProvider.post(base.toJson(), postUri);
final Map<String, dynamic> newBaseMap =
await baseProvider.post(base.toJson(), postUri);
final ExerciseBase newExerciseBase = ExerciseBase.fromJson(newBaseMap);
notifyListeners();
@@ -228,7 +233,8 @@ class AddExerciseProvider with ChangeNotifier {
final Uri postUri = baseProvider.makeUrl(_exerciseVariationPath);
// We send an empty dictionary since at the moment the variations only have an ID
final Map<String, dynamic> variationMap = await baseProvider.post({}, postUri);
final Map<String, dynamic> variationMap =
await baseProvider.post({}, postUri);
final Variation newVariation = Variation.fromJson(variationMap);
_variationId = newVariation.id;
notifyListeners();
@@ -237,7 +243,8 @@ class AddExerciseProvider with ChangeNotifier {
Future<void> addImages(ExerciseBase base) async {
for (final image in _exerciseImages) {
final request = http.MultipartRequest('POST', baseProvider.makeUrl(_imagesUrlPath));
final request =
http.MultipartRequest('POST', baseProvider.makeUrl(_imagesUrlPath));
request.headers.addAll(baseProvider.getDefaultHeaders(includeAuth: true));
request.files.add(await http.MultipartFile.fromPath('image', image.path));
@@ -253,7 +260,8 @@ class AddExerciseProvider with ChangeNotifier {
Future<Translation> addExerciseTranslation(Translation exercise) async {
final Uri postUri = baseProvider.makeUrl(_exerciseTranslationUrlPath);
final Map<String, dynamic> newTranslation = await baseProvider.post(exercise.toJson(), postUri);
final Map<String, dynamic> newTranslation =
await baseProvider.post(exercise.toJson(), postUri);
final Translation newExercise = Translation.fromJson(newTranslation);
notifyListeners();
@@ -264,7 +272,8 @@ class AddExerciseProvider with ChangeNotifier {
final alias = Alias(exerciseId: exerciseId, alias: name);
final Uri postUri = baseProvider.makeUrl(_exerciseAliasPath);
final Alias newAlias = Alias.fromJson(await baseProvider.post(alias.toJson(), postUri));
final Alias newAlias =
Alias.fromJson(await baseProvider.post(alias.toJson(), postUri));
notifyListeners();
return newAlias;

View File

@@ -63,12 +63,14 @@ class AuthProvider with ChangeNotifier {
AndroidMetadata.metaDataAsMap.then((value) => metadata = value!);
} else if (Platform.isLinux || Platform.isMacOS) {
metadata = {
MANIFEST_KEY_CHECK_UPDATE: Platform.environment[MANIFEST_KEY_CHECK_UPDATE] ?? '',
MANIFEST_KEY_CHECK_UPDATE:
Platform.environment[MANIFEST_KEY_CHECK_UPDATE] ?? '',
MANIFEST_KEY_API: Platform.environment[MANIFEST_KEY_API] ?? ''
};
}
} on PlatformException {
throw Exception('An error occurred reading the metadata from AndroidManifest');
throw Exception(
'An error occurred reading the metadata from AndroidManifest');
} catch (error) {}
}
}
@@ -99,7 +101,8 @@ class AuthProvider with ChangeNotifier {
}
/// Checking if there is a new version of the application.
Future<bool> applicationUpdateRequired([String? version, Map<String, String>? metadata]) async {
Future<bool> applicationUpdateRequired(
[String? version, Map<String, String>? metadata]) async {
metadata ??= this.metadata;
if (!metadata.containsKey(MANIFEST_KEY_CHECK_UPDATE) ||
metadata[MANIFEST_KEY_CHECK_UPDATE] == 'false') {
@@ -122,7 +125,10 @@ class AuthProvider with ChangeNotifier {
required String serverUrl}) async {
// Register
try {
final Map<String, String> data = {'username': username, 'password': password};
final Map<String, String> data = {
'username': username,
'password': password
};
if (email != '') {
data['email'] = email;
}
@@ -130,7 +136,8 @@ class AuthProvider with ChangeNotifier {
makeUri(serverUrl, REGISTRATION_URL),
headers: {
HttpHeaders.contentTypeHeader: 'application/json; charset=UTF-8',
HttpHeaders.authorizationHeader: 'Token ${metadata[MANIFEST_KEY_API]}',
HttpHeaders.authorizationHeader:
'Token ${metadata[MANIFEST_KEY_API]}',
HttpHeaders.userAgentHeader: getAppNameHeader(),
},
body: json.encode(data),

View File

@@ -51,7 +51,8 @@ class WgerBaseProvider {
}
/// Helper function to make a URL.
Uri makeUrl(String path, {int? id, String? objectMethod, Map<String, dynamic>? query}) {
Uri makeUrl(String path,
{int? id, String? objectMethod, Map<String, dynamic>? query}) {
return makeUri(auth.serverUrl!, path, id, objectMethod, query);
}

View File

@@ -77,7 +77,8 @@ class BodyWeightProvider with ChangeNotifier {
Future<WeightEntry> addEntry(WeightEntry entry) async {
// Create entry and return it
final data = await baseProvider.post(entry.toJson(), baseProvider.makeUrl(BODY_WEIGHT_URL));
final data = await baseProvider.post(
entry.toJson(), baseProvider.makeUrl(BODY_WEIGHT_URL));
final WeightEntry weightEntry = WeightEntry.fromJson(data);
_entries.add(weightEntry);
_entries.sort((a, b) => b.date.compareTo(a.date));
@@ -96,7 +97,8 @@ class BodyWeightProvider with ChangeNotifier {
Future<void> deleteEntry(int id) async {
// Send the request and remove the entry from the list...
final existingEntryIndex = _entries.indexWhere((element) => element.id == id);
final existingEntryIndex =
_entries.indexWhere((element) => element.id == id);
final existingWeightEntry = _entries[existingEntryIndex];
_entries.removeAt(existingEntryIndex);
notifyListeners();

View File

@@ -33,6 +33,7 @@ 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';
@@ -136,7 +137,8 @@ class ExercisesProvider with ChangeNotifier {
title: 'Equipment',
items: Map.fromEntries(
_equipment.map(
(singleEquipment) => MapEntry<Equipment, bool>(singleEquipment, false),
(singleEquipment) =>
MapEntry<Equipment, bool>(singleEquipment, false),
),
),
),
@@ -166,13 +168,15 @@ class ExercisesProvider with ChangeNotifier {
// Filter by exercise category and equipment (REPLACE WITH HTTP REQUEST)
filteredExerciseBases = filteredItems.where((exercise) {
final bool isInAnyCategory = filters!.exerciseCategories.selected.contains(exercise.category);
final bool isInAnyCategory =
filters!.exerciseCategories.selected.contains(exercise.category);
final bool doesContainAnyEquipment = filters!.equipment.selected.any(
(selectedEquipment) => exercise.equipment.contains(selectedEquipment),
);
return (isInAnyCategory || filters!.exerciseCategories.selected.isEmpty) &&
return (isInAnyCategory ||
filters!.exerciseCategories.selected.isEmpty) &&
(doesContainAnyEquipment || filters!.equipment.selected.isEmpty);
}).toList();
}
@@ -200,7 +204,8 @@ class ExercisesProvider with ChangeNotifier {
/// returned exercises. Since this is typically called by one exercise, we are
/// not interested in seeing that same exercise returned in the list of variations.
/// If this parameter is not passed, all exercises are returned.
List<ExerciseBase> findExerciseBasesByVariationId(int id, {int? exerciseBaseIdToExclude}) {
List<ExerciseBase> findExerciseBasesByVariationId(int id,
{int? exerciseBaseIdToExclude}) {
var out = _exerciseBases.where((base) => base.variationId == id).toList();
if (exerciseBaseIdToExclude != null) {
@@ -242,22 +247,24 @@ class ExercisesProvider with ChangeNotifier {
}
Future<void> fetchAndSetCategories() async {
final categories = await baseProvider.fetchPaginated(baseProvider.makeUrl(_categoriesUrlPath));
final categories = await baseProvider
.fetchPaginated(baseProvider.makeUrl(_categoriesUrlPath));
for (final category in categories) {
_categories.add(ExerciseCategory.fromJson(category));
}
}
Future<void> fetchAndSetVariations() async {
final variations =
await baseProvider.fetchPaginated(baseProvider.makeUrl(_exerciseVariationsUrlPath));
final variations = 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));
final muscles = await baseProvider
.fetchPaginated(baseProvider.makeUrl(_musclesUrlPath));
for (final muscle in muscles) {
_muscles.add(Muscle.fromJson(muscle));
@@ -265,7 +272,8 @@ class ExercisesProvider with ChangeNotifier {
}
Future<void> fetchAndSetEquipment() async {
final equipments = await baseProvider.fetchPaginated(baseProvider.makeUrl(_equipmentUrlPath));
final equipments = await baseProvider
.fetchPaginated(baseProvider.makeUrl(_equipmentUrlPath));
for (final equipment in equipments) {
_equipment.add(Equipment.fromJson(equipment));
@@ -273,7 +281,8 @@ class ExercisesProvider with ChangeNotifier {
}
Future<void> fetchAndSetLanguages() async {
final languageData = await baseProvider.fetchPaginated(baseProvider.makeUrl(_languageUrlPath));
final languageData = await baseProvider
.fetchPaginated(baseProvider.makeUrl(_languageUrlPath));
for (final language in languageData) {
_languages.add(Language.fromJson(language));
@@ -293,7 +302,8 @@ class ExercisesProvider with ChangeNotifier {
baseProvider.makeUrl(_exerciseBaseInfoUrlPath, id: exerciseBaseId),
);
final newBase = readExerciseBaseFromBaseInfo(baseData);
final newBase =
readExerciseBaseFromBaseInfo(ExerciseBaseData.fromJson(baseData));
// TODO: save to cache. Since we can't easily generate the JSON, perhaps just reload?
_exerciseBases.add(newBase);
@@ -303,40 +313,37 @@ class ExercisesProvider with ChangeNotifier {
/// Parses the response from the exercisebaseinfo endpoint and returns
/// a full exercise base
ExerciseBase readExerciseBaseFromBaseInfo(dynamic baseData) {
final category = ExerciseCategory.fromJson(baseData['category']);
final musclesPrimary = baseData['muscles'].map((e) => Muscle.fromJson(e)).toList();
final musclesSecondary = baseData['muscles_secondary'].map((e) => Muscle.fromJson(e)).toList();
final equipment = baseData['equipment'].map((e) => Equipment.fromJson(e)).toList();
final images = baseData['images'].map((e) => ExerciseImage.fromJson(e)).toList();
final videos = baseData['videos'].map((e) => Video.fromJson(e)).toList();
ExerciseBase readExerciseBaseFromBaseInfo(ExerciseBaseData baseData) {
final List<Translation> exercises = [];
for (final exerciseData in baseData['exercises']) {
final exercise = Translation.fromJson(exerciseData);
exercise.alias = exerciseData['aliases']
.map((e) => Alias(exerciseId: exercise.id!, alias: e['alias']))
for (final exerciseData in baseData.exercises) {
final exercise = Translation(
id: exerciseData.id,
uuid: exerciseData.uuid,
name: exerciseData.name,
description: exerciseData.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'].map((e) => Comment.fromJson(e)).toList().cast<Comment>();
exercise.baseId = baseData['id'];
exercise.language = findLanguageById(exerciseData['language']);
exercise.notes = exerciseData.notes;
exercise.language = findLanguageById(exerciseData.languageId);
exercises.add(exercise);
}
final exerciseBase = ExerciseBase(
id: baseData['id'],
uuid: baseData['uuid'],
id: baseData.id,
uuid: baseData.uuid,
created: null,
//creationDate: toDate(baseData['creation_date']),
musclesSecondary: musclesSecondary.cast<Muscle>(),
muscles: musclesPrimary.cast<Muscle>(),
equipment: equipment.cast<Equipment>(),
category: category,
images: images.cast<ExerciseImage>(),
musclesSecondary: baseData.muscles,
muscles: baseData.muscles,
equipment: baseData.equipment,
category: baseData.category,
images: baseData.images,
exercises: exercises,
videos: videos.cast<Video>(),
videos: baseData.videos,
);
return exerciseBase;
@@ -374,9 +381,10 @@ class ExercisesProvider with ChangeNotifier {
final database = locator<ExerciseDatabase>();
// Only uncomment if need to delete the table, (only for testing purposes).
// database.delete(database.exerciseTableItems).go();
// 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 List<ExerciseTable> items =
await database.select(database.exerciseTableItems).get();
final prefs = await SharedPreferences.getInstance();
await checkExerciseCacheVersion();
@@ -412,37 +420,54 @@ class ExercisesProvider with ChangeNotifier {
// Load categories, muscles, equipment and languages
final data = await Future.wait<dynamic>([
baseProvider.fetch(baseProvider.makeUrl(_exerciseBaseInfoUrlPath, query: {'limit': '1000'})),
baseProvider.fetch(baseProvider
.makeUrl(_exerciseBaseInfoUrlPath, query: {'limit': '1000'})),
fetchAndSetCategories(),
fetchAndSetMuscles(),
fetchAndSetEquipment(),
fetchAndSetLanguages(),
fetchAndSetVariations(),
]);
final List<dynamic> exerciseData = data[0]['results'];
final exerciseBaseData = data[0]['results'];
_exerciseBases =
exerciseBaseData.map((e) => readExerciseBaseFromBaseInfo(e)).toList().cast<ExerciseBase>();
final List<ExerciseBaseData> exerciseBaseData =
exerciseData.map((e) => ExerciseBaseData.fromJson(e)).toList();
_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),
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),
),
);
}
// final List<ExerciseTable> items = await database.select(database.exerciseTableItems).get();
final cacheData = {
'expiresIn':
DateTime.now().add(const Duration(days: EXERCISE_CACHE_DAYS)).toIso8601String(),
'expiresIn': DateTime.now()
.add(const Duration(days: EXERCISE_CACHE_DAYS))
.toIso8601String(),
};
log("Saved ${_exerciseBases.length} exercises to cache. Valid till ${cacheData['expiresIn']}");
@@ -460,7 +485,8 @@ class ExercisesProvider with ChangeNotifier {
/// We could do this locally, but the server has better text searching capabilities
/// with postgresql.
Future<List<ExerciseBase>> searchExercise(String name,
{String languageCode = LANGUAGE_SHORT_ENGLISH, bool searchEnglish = false}) async {
{String languageCode = LANGUAGE_SHORT_ENGLISH,
bool searchEnglish = false}) async {
if (name.length <= 1) {
return [];
}
@@ -528,8 +554,10 @@ class Filters {
List<FilterCategory> get filterCategories => [exerciseCategories, equipment];
bool get isNothingMarked {
final isExerciseCategoryMarked = exerciseCategories.items.values.any((isMarked) => isMarked);
final isEquipmentMarked = equipment.items.values.any((isMarked) => isMarked);
final isExerciseCategoryMarked =
exerciseCategories.items.values.any((isMarked) => isMarked);
final isEquipmentMarked =
equipment.items.values.any((isMarked) => isMarked);
return !isExerciseCategoryMarked && !isEquipmentMarked;
}

View File

@@ -32,7 +32,8 @@ class GalleryProvider extends WgerBaseProvider with ChangeNotifier {
List<gallery.Image> images = [];
GalleryProvider(AuthProvider auth, List<gallery.Image> entries, [http.Client? client])
GalleryProvider(AuthProvider auth, List<gallery.Image> entries,
[http.Client? client])
: images = entries,
super(auth, client);
@@ -63,7 +64,8 @@ class GalleryProvider extends WgerBaseProvider with ChangeNotifier {
HttpHeaders.authorizationHeader: 'Token ${auth.token}',
HttpHeaders.userAgentHeader: auth.getAppNameHeader(),
});
request.files.add(await http.MultipartFile.fromPath('image', imageFile.path));
request.files
.add(await http.MultipartFile.fromPath('image', imageFile.path));
request.fields['date'] = toDate(image.date)!;
request.fields['description'] = image.description;
@@ -77,7 +79,8 @@ class GalleryProvider extends WgerBaseProvider with ChangeNotifier {
}
Future<void> editImage(gallery.Image image, XFile? imageFile) async {
final request = http.MultipartRequest('PATCH', makeUrl(_galleryUrlPath, id: image.id));
final request =
http.MultipartRequest('PATCH', makeUrl(_galleryUrlPath, id: image.id));
request.headers.addAll({
HttpHeaders.authorizationHeader: 'Token ${auth.token}',
HttpHeaders.userAgentHeader: auth.getAppNameHeader(),
@@ -85,7 +88,8 @@ class GalleryProvider extends WgerBaseProvider with ChangeNotifier {
// Only send the image if a new one was selected
if (imageFile != null) {
request.files.add(await http.MultipartFile.fromPath('image', imageFile.path));
request.files
.add(await http.MultipartFile.fromPath('image', imageFile.path));
}
// Update image info

View File

@@ -68,13 +68,15 @@ class MeasurementProvider with ChangeNotifier {
final categoryIndex = _categories.indexOf(category);
// Process the response
final requestUrl = baseProvider.makeUrl(_entryUrl, query: {'category': category.id.toString()});
final requestUrl = baseProvider
.makeUrl(_entryUrl, query: {'category': category.id.toString()});
final data = await baseProvider.fetch(requestUrl);
final List<MeasurementEntry> loadedEntries = [];
for (final entry in data['results']) {
loadedEntries.add(MeasurementEntry.fromJson(entry));
}
final MeasurementCategory editedCategory = category.copyWith(entries: loadedEntries);
final MeasurementCategory editedCategory =
category.copyWith(entries: loadedEntries);
_categories.removeAt(categoryIndex);
_categories.insert(categoryIndex, editedCategory);
notifyListeners();
@@ -83,15 +85,18 @@ class MeasurementProvider with ChangeNotifier {
/// Fetches and sets the measurement categories and their entries
Future<void> fetchAndSetAllCategoriesAndEntries() async {
await fetchAndSetCategories();
await Future.wait(_categories.map((e) => fetchAndSetCategoryEntries(e.id!)).toList());
await Future.wait(
_categories.map((e) => fetchAndSetCategoryEntries(e.id!)).toList());
}
/// Adds a measurement category
Future<void> addCategory(MeasurementCategory category) async {
final Uri postUri = baseProvider.makeUrl(_categoryUrl);
final Map<String, dynamic> newCategoryMap = await baseProvider.post(category.toJson(), postUri);
final MeasurementCategory newCategory = MeasurementCategory.fromJson(newCategoryMap);
final Map<String, dynamic> newCategoryMap =
await baseProvider.post(category.toJson(), postUri);
final MeasurementCategory newCategory =
MeasurementCategory.fromJson(newCategoryMap);
_categories.add(newCategory);
_categories.sort((a, b) => a.name.compareTo(b.name));
notifyListeners();
@@ -118,14 +123,16 @@ class MeasurementProvider with ChangeNotifier {
Future<void> editCategory(int id, String? newName, String? newUnit) async {
final MeasurementCategory oldCategory = findCategoryById(id);
final int categoryIndex = _categories.indexOf(oldCategory);
final MeasurementCategory tempNewCategory = oldCategory.copyWith(name: newName, unit: newUnit);
final MeasurementCategory tempNewCategory =
oldCategory.copyWith(name: newName, unit: newUnit);
final Map<String, dynamic> response = await baseProvider.patch(
tempNewCategory.toJson(),
baseProvider.makeUrl(_categoryUrl, id: id),
);
final MeasurementCategory newCategory =
MeasurementCategory.fromJson(response).copyWith(entries: oldCategory.entries);
MeasurementCategory.fromJson(response)
.copyWith(entries: oldCategory.entries);
_categories.removeAt(categoryIndex);
_categories.insert(categoryIndex, newCategory);
notifyListeners();
@@ -135,7 +142,8 @@ class MeasurementProvider with ChangeNotifier {
Future<void> addEntry(MeasurementEntry entry) async {
final Uri postUri = baseProvider.makeUrl(_entryUrl);
final Map<String, dynamic> newEntryMap = await baseProvider.post(entry.toJson(), postUri);
final Map<String, dynamic> newEntryMap =
await baseProvider.post(entry.toJson(), postUri);
final MeasurementEntry newEntry = MeasurementEntry.fromJson(newEntryMap);
final MeasurementCategory category = findCategoryById(newEntry.category);
@@ -183,8 +191,8 @@ class MeasurementProvider with ChangeNotifier {
date: newDate,
);
final Map<String, dynamic> response =
await baseProvider.patch(tempNewEntry.toJson(), baseProvider.makeUrl(_entryUrl, id: id));
final Map<String, dynamic> response = await baseProvider.patch(
tempNewEntry.toJson(), baseProvider.makeUrl(_entryUrl, id: id));
final MeasurementEntry newEntry = MeasurementEntry.fromJson(response);
category.entries.removeAt(entryIndex);

View File

@@ -46,7 +46,8 @@ class NutritionPlansProvider with ChangeNotifier {
List<NutritionalPlan> _plans = [];
List<Ingredient> _ingredients = [];
NutritionPlansProvider(this.baseProvider, List<NutritionalPlan> entries) : _plans = entries;
NutritionPlansProvider(this.baseProvider, List<NutritionalPlan> entries)
: _plans = entries;
List<NutritionalPlan> get items {
return [..._plans];
@@ -91,8 +92,8 @@ class NutritionPlansProvider with ChangeNotifier {
/// Fetches and sets all plans sparsely, i.e. only with the data on the plan
/// object itself and no child attributes
Future<void> fetchAndSetAllPlansSparse() async {
final data = await baseProvider
.fetchPaginated(baseProvider.makeUrl(_nutritionalPlansPath, query: {'limit': '1000'}));
final data = await baseProvider.fetchPaginated(
baseProvider.makeUrl(_nutritionalPlansPath, query: {'limit': '1000'}));
_plans = [];
for (final planData in data) {
final plan = NutritionalPlan.fromJson(planData);
@@ -104,7 +105,8 @@ class NutritionPlansProvider with ChangeNotifier {
/// Fetches and sets all plans fully, i.e. with all corresponding child objects
Future<void> fetchAndSetAllPlansFull() async {
final data = await baseProvider.fetchPaginated(baseProvider.makeUrl(_nutritionalPlansPath));
final data = await baseProvider
.fetchPaginated(baseProvider.makeUrl(_nutritionalPlansPath));
for (final entry in data) {
await fetchAndSetPlanFull(entry['id']);
}
@@ -194,7 +196,8 @@ class NutritionPlansProvider with ChangeNotifier {
_plans.removeAt(existingPlanIndex);
notifyListeners();
final response = await baseProvider.deleteRequest(_nutritionalPlansPath, id);
final response =
await baseProvider.deleteRequest(_nutritionalPlansPath, id);
if (response.statusCode >= 400) {
_plans.insert(existingPlanIndex, existingPlan);
@@ -251,7 +254,8 @@ class NutritionPlansProvider with ChangeNotifier {
/// Adds a meal item to a meal
Future<MealItem> addMealItem(MealItem mealItem, Meal meal) async {
final data = await baseProvider.post(mealItem.toJson(), baseProvider.makeUrl(_mealItemPath));
final data = await baseProvider.post(
mealItem.toJson(), baseProvider.makeUrl(_mealItemPath));
mealItem = MealItem.fromJson(data);
mealItem.ingredientObj = await fetchIngredient(mealItem.ingredientId);
@@ -271,7 +275,8 @@ class NutritionPlansProvider with ChangeNotifier {
notifyListeners();
// Try to delete
final response = await baseProvider.deleteRequest(_mealItemPath, mealItem.id!);
final response =
await baseProvider.deleteRequest(_mealItemPath, mealItem.id!);
if (response.statusCode >= 400) {
meal.mealItems.insert(mealItemIndex, existingMealItem);
notifyListeners();
@@ -314,7 +319,8 @@ class NutritionPlansProvider with ChangeNotifier {
if (prefs.containsKey(PREFS_INGREDIENTS)) {
final ingredientData = json.decode(prefs.getString(PREFS_INGREDIENTS)!);
if (DateTime.parse(ingredientData['expiresIn']).isAfter(DateTime.now())) {
ingredientData['ingredients'].forEach((e) => _ingredients.add(Ingredient.fromJson(e)));
ingredientData['ingredients']
.forEach((e) => _ingredients.add(Ingredient.fromJson(e)));
log("Read ${ingredientData['ingredients'].length} ingredients from cache. Valid till ${ingredientData['expiresIn']}");
return;
}
@@ -323,7 +329,9 @@ class NutritionPlansProvider with ChangeNotifier {
// Initialise an empty cache
final ingredientData = {
'date': DateTime.now().toIso8601String(),
'expiresIn': DateTime.now().add(const Duration(days: DAYS_TO_CACHE)).toIso8601String(),
'expiresIn': DateTime.now()
.add(const Duration(days: DAYS_TO_CACHE))
.toIso8601String(),
'ingredients': []
};
prefs.setString(PREFS_INGREDIENTS, json.encode(ingredientData));
@@ -347,8 +355,8 @@ class NutritionPlansProvider with ChangeNotifier {
// Send the request
final response = await baseProvider.fetch(
baseProvider
.makeUrl(_ingredientSearchPath, query: {'term': name, 'language': languages.join(',')}),
baseProvider.makeUrl(_ingredientSearchPath,
query: {'term': name, 'language': languages.join(',')}),
);
// Process the response
@@ -390,12 +398,14 @@ class NutritionPlansProvider with ChangeNotifier {
}
/// Log custom ingredient to nutrition diary
Future<void> logIngredientToDiary(MealItem mealItem, int planId, [DateTime? dateTime]) async {
Future<void> logIngredientToDiary(MealItem mealItem, int planId,
[DateTime? dateTime]) async {
final plan = findById(planId);
mealItem.ingredientObj = await fetchIngredient(mealItem.ingredientId);
final Log log = Log.fromMealItem(mealItem, plan.id!, null, dateTime);
final data = await baseProvider.post(log.toJson(), baseProvider.makeUrl(_nutritionDiaryPath));
final data = await baseProvider.post(
log.toJson(), baseProvider.makeUrl(_nutritionDiaryPath));
log.id = data['id'];
plan.logs.add(log);
notifyListeners();
@@ -415,7 +425,11 @@ class NutritionPlansProvider with ChangeNotifier {
final data = await baseProvider.fetchPaginated(
baseProvider.makeUrl(
_nutritionDiaryPath,
query: {'plan': plan.id.toString(), 'limit': '999', 'ordering': 'datetime'},
query: {
'plan': plan.id.toString(),
'limit': '999',
'ordering': 'datetime'
},
),
);

View File

@@ -38,7 +38,8 @@ class UserProvider with ChangeNotifier {
/// Fetch the current user's profile
Future<void> fetchAndSetProfile() async {
final userData = await baseProvider.fetch(baseProvider.makeUrl(PROFILE_URL));
final userData =
await baseProvider.fetch(baseProvider.makeUrl(PROFILE_URL));
try {
profile = Profile.fromJson(userData);
} catch (error) {

View File

@@ -53,7 +53,8 @@ class WorkoutPlansProvider with ChangeNotifier {
List<WeightUnit> _weightUnits = [];
List<RepetitionUnit> _repetitionUnit = [];
WorkoutPlansProvider(this.baseProvider, ExercisesProvider exercises, List<WorkoutPlan> entries)
WorkoutPlansProvider(
this.baseProvider, ExercisesProvider exercises, List<WorkoutPlan> entries)
: _exercises = exercises,
_workoutPlans = entries;
@@ -75,7 +76,8 @@ class WorkoutPlansProvider with ChangeNotifier {
/// Return the default weight unit (kg)
WeightUnit get defaultWeightUnit {
return _weightUnits.firstWhere((element) => element.id == DEFAULT_WEIGHT_UNIT);
return _weightUnits
.firstWhere((element) => element.id == DEFAULT_WEIGHT_UNIT);
}
List<RepetitionUnit> get repetitionUnits {
@@ -84,7 +86,8 @@ class WorkoutPlansProvider with ChangeNotifier {
/// Return the default weight unit (reps)
RepetitionUnit get defaultRepetitionUnit {
return _repetitionUnit.firstWhere((element) => element.id == REP_UNIT_REPETITIONS);
return _repetitionUnit
.firstWhere((element) => element.id == REP_UNIT_REPETITIONS);
}
List<WorkoutPlan> getPlans() {
@@ -191,7 +194,8 @@ class WorkoutPlansProvider with ChangeNotifier {
// Days
final List<Day> days = [];
final daysData = await baseProvider.fetch(
baseProvider.makeUrl(_daysUrlPath, query: {'training': plan.id.toString()}),
baseProvider
.makeUrl(_daysUrlPath, query: {'training': plan.id.toString()}),
);
for (final dayEntry in daysData['results']) {
final day = Day.fromJson(dayEntry);
@@ -199,7 +203,8 @@ class WorkoutPlansProvider with ChangeNotifier {
// Sets
final List<Set> sets = [];
final setData = await baseProvider.fetch(
baseProvider.makeUrl(_setsUrlPath, query: {'exerciseday': day.id.toString()}),
baseProvider
.makeUrl(_setsUrlPath, query: {'exerciseday': day.id.toString()}),
);
for (final setEntry in setData['results']) {
final workoutSet = Set.fromJson(setEntry);
@@ -208,20 +213,22 @@ class WorkoutPlansProvider with ChangeNotifier {
// Settings
final List<Setting> settings = [];
final settingData = allSettingsData['results'].where((s) => s['set'] == workoutSet.id);
final settingData =
allSettingsData['results'].where((s) => s['set'] == workoutSet.id);
for (final settingEntry in settingData) {
final workoutSetting = Setting.fromJson(settingEntry);
workoutSetting.exerciseBase =
await _exercises.fetchAndSetExerciseBase(workoutSetting.exerciseBaseId);
workoutSetting.exerciseBase = await _exercises
.fetchAndSetExerciseBase(workoutSetting.exerciseBaseId);
workoutSetting.weightUnit = _weightUnits.firstWhere(
(e) => e.id == workoutSetting.weightUnitId,
);
workoutSetting.repetitionUnit = _repetitionUnit.firstWhere(
(e) => e.id == workoutSetting.repetitionUnitId,
);
if (!workoutSet.exerciseBasesIds.contains(workoutSetting.exerciseBaseId)) {
if (!workoutSet.exerciseBasesIds
.contains(workoutSetting.exerciseBaseId)) {
workoutSet.addExerciseBase(workoutSetting.exerciseBaseObj);
}
@@ -245,9 +252,12 @@ class WorkoutPlansProvider with ChangeNotifier {
for (final logEntry in logData) {
try {
final log = Log.fromJson(logEntry);
log.weightUnit = _weightUnits.firstWhere((e) => e.id == log.weightUnitId);
log.repetitionUnit = _repetitionUnit.firstWhere((e) => e.id == log.weightUnitId);
log.exerciseBase = await _exercises.fetchAndSetExerciseBase(log.exerciseBaseId);
log.weightUnit =
_weightUnits.firstWhere((e) => e.id == log.weightUnitId);
log.repetitionUnit =
_repetitionUnit.firstWhere((e) => e.id == log.weightUnitId);
log.exerciseBase =
await _exercises.fetchAndSetExerciseBase(log.exerciseBaseId);
plan.logs.add(log);
} catch (e) {
dev.log('fire! fire!');
@@ -261,8 +271,8 @@ class WorkoutPlansProvider with ChangeNotifier {
}
Future<WorkoutPlan> addWorkout(WorkoutPlan workout) async {
final data =
await baseProvider.post(workout.toJson(), baseProvider.makeUrl(_workoutPlansUrlPath));
final data = await baseProvider.post(
workout.toJson(), baseProvider.makeUrl(_workoutPlansUrlPath));
final plan = WorkoutPlan.fromJson(data);
_workoutPlans.insert(0, plan);
notifyListeners();
@@ -270,13 +280,14 @@ class WorkoutPlansProvider with ChangeNotifier {
}
Future<void> editWorkout(WorkoutPlan workout) async {
await baseProvider.patch(
workout.toJson(), baseProvider.makeUrl(_workoutPlansUrlPath, id: workout.id));
await baseProvider.patch(workout.toJson(),
baseProvider.makeUrl(_workoutPlansUrlPath, id: workout.id));
notifyListeners();
}
Future<void> deleteWorkout(int id) async {
final existingWorkoutIndex = _workoutPlans.indexWhere((element) => element.id == id);
final existingWorkoutIndex =
_workoutPlans.indexWhere((element) => element.id == id);
final existingWorkout = _workoutPlans[existingWorkoutIndex];
_workoutPlans.removeAt(existingWorkoutIndex);
notifyListeners();
@@ -290,7 +301,8 @@ class WorkoutPlansProvider with ChangeNotifier {
}
}
Future<Map<String, dynamic>> fetchLogData(WorkoutPlan workout, ExerciseBase base) async {
Future<Map<String, dynamic>> fetchLogData(
WorkoutPlan workout, ExerciseBase base) async {
final data = await baseProvider.fetch(
baseProvider.makeUrl(
_workoutPlansUrlPath,
@@ -304,8 +316,8 @@ class WorkoutPlansProvider with ChangeNotifier {
/// Fetch and set weight units for workout (kg, lb, plate, etc.)
Future<void> fetchAndSetRepetitionUnits() async {
final response =
await baseProvider.fetchPaginated(baseProvider.makeUrl(_repetitionUnitUrlPath));
final response = await baseProvider
.fetchPaginated(baseProvider.makeUrl(_repetitionUnitUrlPath));
for (final unit in response) {
_repetitionUnit.add(RepetitionUnit.fromJson(unit));
}
@@ -313,7 +325,8 @@ class WorkoutPlansProvider with ChangeNotifier {
/// Fetch and set weight units for workout (kg, lb, plate, etc.)
Future<void> fetchAndSetWeightUnits() async {
final response = await baseProvider.fetchPaginated(baseProvider.makeUrl(_weightUnitUrlPath));
final response = await baseProvider
.fetchPaginated(baseProvider.makeUrl(_weightUnitUrlPath));
for (final unit in response) {
_weightUnits.add(WeightUnit.fromJson(unit));
}
@@ -331,7 +344,8 @@ class WorkoutPlansProvider with ChangeNotifier {
unitData['weightUnit'].forEach(
(e) => _weightUnits.add(WeightUnit.fromJson(e)),
);
dev.log("Read workout units data from cache. Valid till ${unitData['expiresIn']}");
dev.log(
"Read workout units data from cache. Valid till ${unitData['expiresIn']}");
return;
}
}
@@ -343,7 +357,9 @@ class WorkoutPlansProvider with ChangeNotifier {
// Save the result to the cache
final exerciseData = {
'date': DateTime.now().toIso8601String(),
'expiresIn': DateTime.now().add(const Duration(days: DAYS_TO_CACHE)).toIso8601String(),
'expiresIn': DateTime.now()
.add(const Duration(days: DAYS_TO_CACHE))
.toIso8601String(),
'repetitionUnits': _repetitionUnit.map((e) => e.toJson()).toList(),
'weightUnit': _weightUnits.map((e) => e.toJson()).toList(),
};
@@ -359,7 +375,8 @@ class WorkoutPlansProvider with ChangeNotifier {
* Saves a new day instance to the DB and adds it to the given workout
*/
day.workoutId = workout.id!;
final data = await baseProvider.post(day.toJson(), baseProvider.makeUrl(_daysUrlPath));
final data = await baseProvider.post(
day.toJson(), baseProvider.makeUrl(_daysUrlPath));
day = Day.fromJson(data);
day.sets = [];
workout.days.insert(0, day);
@@ -368,7 +385,8 @@ class WorkoutPlansProvider with ChangeNotifier {
}
Future<void> editDay(Day day) async {
await baseProvider.patch(day.toJson(), baseProvider.makeUrl(_daysUrlPath, id: day.id));
await baseProvider.patch(
day.toJson(), baseProvider.makeUrl(_daysUrlPath, id: day.id));
notifyListeners();
}
@@ -487,7 +505,8 @@ class WorkoutPlansProvider with ChangeNotifier {
}
Future<WorkoutSession> addSession(WorkoutSession session) async {
final data = await baseProvider.post(session.toJson(), baseProvider.makeUrl(_sessionUrlPath));
final data = await baseProvider.post(
session.toJson(), baseProvider.makeUrl(_sessionUrlPath));
final newSession = WorkoutSession.fromJson(data);
notifyListeners();
return newSession;
@@ -497,13 +516,16 @@ class WorkoutPlansProvider with ChangeNotifier {
* Logs
*/
Future<Log> addLog(Log log) async {
final data = await baseProvider.post(log.toJson(), baseProvider.makeUrl(_logsUrlPath));
final data = await baseProvider.post(
log.toJson(), baseProvider.makeUrl(_logsUrlPath));
final newLog = Log.fromJson(data);
log.id = newLog.id;
log.weightUnit = _weightUnits.firstWhere((e) => e.id == log.weightUnitId);
log.repetitionUnit = _repetitionUnit.firstWhere((e) => e.id == log.weightUnitId);
log.exerciseBase = await _exercises.fetchAndSetExerciseBase(log.exerciseBaseId);
log.repetitionUnit =
_repetitionUnit.firstWhere((e) => e.id == log.weightUnitId);
log.exerciseBase =
await _exercises.fetchAndSetExerciseBase(log.exerciseBaseId);
final plan = findById(log.workoutPlan);
plan.logs.add(log);

View File

@@ -25,7 +25,9 @@ class AddExerciseScreen extends StatelessWidget {
Widget build(BuildContext context) {
final profile = context.read<UserProvider>().profile;
return profile!.isTrustworthy ? const AddExerciseStepper() : const EmailNotVerified();
return profile!.isTrustworthy
? const AddExerciseStepper()
: const EmailNotVerified();
}
}
@@ -70,13 +72,18 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
setState(() {
_isLoading = true;
});
final addExerciseProvider = context.read<AddExerciseProvider>();
final exerciseProvider = context.read<ExercisesProvider>();
final addExerciseProvider =
context.read<AddExerciseProvider>();
final exerciseProvider =
context.read<ExercisesProvider>();
final baseId = await addExerciseProvider.addExercise();
final base = await exerciseProvider.fetchAndSetExerciseBase(baseId);
final name =
base.getExercise(Localizations.localeOf(context).languageCode).name;
final base = await exerciseProvider
.fetchAndSetExerciseBase(baseId);
final name = base
.getExercise(
Localizations.localeOf(context).languageCode)
.name;
setState(() {
_isLoading = false;
@@ -88,7 +95,8 @@ class _AddExerciseStepperState extends State<AddExerciseStepper> {
builder: (BuildContext context) {
return AlertDialog(
title: Text(AppLocalizations.of(context).success),
content: Text(AppLocalizations.of(context).cacheWarning),
content: Text(
AppLocalizations.of(context).cacheWarning),
actions: [
TextButton(
child: Text(name),

View File

@@ -68,7 +68,8 @@ class AuthScreen extends StatelessWidget {
),
Container(
margin: const EdgeInsets.only(bottom: 20.0),
padding: const EdgeInsets.symmetric(vertical: 8.0, horizontal: 94.0),
padding: const EdgeInsets.symmetric(
vertical: 8.0, horizontal: 94.0),
child: const Text(
'wger',
style: TextStyle(
@@ -137,8 +138,10 @@ class _AuthCardState extends State<AuthCard> {
//
// If not, the user will not be able to register via the app
try {
final metadata = Provider.of<AuthProvider>(context, listen: false).metadata;
if (metadata.containsKey(MANIFEST_KEY_API) && metadata[MANIFEST_KEY_API] == '') {
final metadata =
Provider.of<AuthProvider>(context, listen: false).metadata;
if (metadata.containsKey(MANIFEST_KEY_API) &&
metadata[MANIFEST_KEY_API] == '') {
_canRegister = false;
}
} on PlatformException {
@@ -160,8 +163,10 @@ class _AuthCardState extends State<AuthCard> {
// Login existing user
late Map<String, LoginActions> res;
if (_authMode == AuthMode.Login) {
res = await Provider.of<AuthProvider>(context, listen: false)
.login(_authData['username']!, _authData['password']!, _authData['serverUrl']!);
res = await Provider.of<AuthProvider>(context, listen: false).login(
_authData['username']!,
_authData['password']!,
_authData['serverUrl']!);
// Register new user
} else {
@@ -229,7 +234,8 @@ class _AuthCardState extends State<AuthCard> {
elevation: 8.0,
child: Container(
width: deviceSize.width * 0.9,
padding: EdgeInsets.symmetric(horizontal: 15.0, vertical: 0.025 * deviceSize.height),
padding: EdgeInsets.symmetric(
horizontal: 15.0, vertical: 0.025 * deviceSize.height),
child: Form(
key: _formKey,
child: SingleChildScrollView(
@@ -256,7 +262,9 @@ class _AuthCardState extends State<AuthCard> {
return null;
},
inputFormatters: [FilteringTextInputFormatter.deny(RegExp(r'\s\b|\b\s'))],
inputFormatters: [
FilteringTextInputFormatter.deny(RegExp(r'\s\b|\b\s'))
],
onSaved: (value) {
_authData['username'] = value!;
},
@@ -291,7 +299,9 @@ class _AuthCardState extends State<AuthCard> {
labelText: AppLocalizations.of(context).password,
prefixIcon: const Icon(Icons.password),
suffixIcon: IconButton(
icon: Icon(isObscure ? Icons.visibility_off : Icons.visibility),
icon: Icon(isObscure
? Icons.visibility_off
: Icons.visibility),
onPressed: () {
isObscure = !isObscure;
updateState(() {});
@@ -318,10 +328,13 @@ class _AuthCardState extends State<AuthCard> {
return TextFormField(
key: const Key('inputPassword2'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context).confirmPassword,
labelText:
AppLocalizations.of(context).confirmPassword,
prefixIcon: const Icon(Icons.password),
suffixIcon: IconButton(
icon: Icon(confirmIsObscure ? Icons.visibility_off : Icons.visibility),
icon: Icon(confirmIsObscure
? Icons.visibility_off
: Icons.visibility),
onPressed: () {
confirmIsObscure = !confirmIsObscure;
updateState(() {});
@@ -334,7 +347,8 @@ class _AuthCardState extends State<AuthCard> {
validator: _authMode == AuthMode.Signup
? (value) {
if (value != _passwordController.text) {
return AppLocalizations.of(context).passwordsDontMatch;
return AppLocalizations.of(context)
.passwordsDontMatch;
}
return null;
}
@@ -352,8 +366,10 @@ class _AuthCardState extends State<AuthCard> {
child: TextFormField(
key: const Key('inputServer'),
decoration: InputDecoration(
labelText: AppLocalizations.of(context).customServerUrl,
helperText: AppLocalizations.of(context).customServerHint,
labelText: AppLocalizations.of(context)
.customServerUrl,
helperText: AppLocalizations.of(context)
.customServerHint,
helperMaxLines: 4),
controller: _serverUrlController,
validator: (value) {
@@ -368,8 +384,10 @@ class _AuthCardState extends State<AuthCard> {
},
onSaved: (value) {
// Remove any trailing slash
if (value!.lastIndexOf('/') == (value.length - 1)) {
value = value.substring(0, value.lastIndexOf('/'));
if (value!.lastIndexOf('/') ==
(value.length - 1)) {
value =
value.substring(0, value.lastIndexOf('/'));
}
_authData['serverUrl'] = value;
},
@@ -413,7 +431,8 @@ class _AuthCardState extends State<AuthCard> {
child: Center(
child: _isLoading
? const CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation(Colors.white),
valueColor:
AlwaysStoppedAnimation(Colors.white),
)
: Text(
_authMode == AuthMode.Login
@@ -448,7 +467,8 @@ class _AuthCardState extends State<AuthCard> {
text.substring(0, text.lastIndexOf('?') + 1),
),
Text(
text.substring(text.lastIndexOf('?') + 1, text.length),
text.substring(
text.lastIndexOf('?') + 1, text.length),
style: const TextStyle(
//color: wgerPrimaryColor,
fontWeight: FontWeight.w700,

View File

@@ -27,11 +27,14 @@ class ExerciseDetailScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final exerciseBase = ModalRoute.of(context)!.settings.arguments as ExerciseBase;
final exerciseBase =
ModalRoute.of(context)!.settings.arguments as ExerciseBase;
return Scaffold(
appBar: AppBar(
title: Text(exerciseBase.getExercise(Localizations.localeOf(context).languageCode).name),
title: Text(exerciseBase
.getExercise(Localizations.localeOf(context).languageCode)
.name),
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10),

View File

@@ -21,7 +21,8 @@ class _ExercisesScreenState extends State<ExercisesScreen> {
@override
Widget build(BuildContext context) {
//final size = MediaQuery.of(context).size;
final exercisesList = Provider.of<ExercisesProvider>(context).filteredExerciseBases;
final exercisesList =
Provider.of<ExercisesProvider>(context).filteredExerciseBases;
return Scaffold(
appBar: EmptyAppBar(AppLocalizations.of(context).exercises),

View File

@@ -55,7 +55,8 @@ class FormScreen extends StatelessWidget {
appBar: AppBar(title: Text(args.title)),
body: args.hasListView
? Scrollable(
viewportBuilder: (BuildContext context, ViewportOffset position) => Padding(
viewportBuilder:
(BuildContext context, ViewportOffset position) => Padding(
padding: args.padding,
child: args.widget,
),

View File

@@ -44,7 +44,8 @@ class HomeTabsScreen extends StatefulWidget {
_HomeTabsScreenState createState() => _HomeTabsScreenState();
}
class _HomeTabsScreenState extends State<HomeTabsScreen> with SingleTickerProviderStateMixin {
class _HomeTabsScreenState extends State<HomeTabsScreen>
with SingleTickerProviderStateMixin {
late Future<void> _initialData;
int _selectedIndex = 0;

View File

@@ -35,7 +35,8 @@ class MeasurementEntriesScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final categoryId = ModalRoute.of(context)!.settings.arguments as int;
final category = Provider.of<MeasurementProvider>(context).findCategoryById(categoryId);
final category =
Provider.of<MeasurementProvider>(context).findCategoryById(categoryId);
return Scaffold(
appBar: AppBar(
@@ -62,21 +63,26 @@ class MeasurementEntriesScreen extends StatelessWidget {
builder: (BuildContext contextDialog) {
return AlertDialog(
content: Text(
AppLocalizations.of(context).confirmDelete(category.name),
AppLocalizations.of(context)
.confirmDelete(category.name),
),
actions: [
TextButton(
child: Text(MaterialLocalizations.of(context).cancelButtonLabel),
onPressed: () => Navigator.of(contextDialog).pop(),
child: Text(MaterialLocalizations.of(context)
.cancelButtonLabel),
onPressed: () =>
Navigator.of(contextDialog).pop(),
),
TextButton(
child: Text(
AppLocalizations.of(context).delete,
style: TextStyle(color: Theme.of(context).colorScheme.error),
style: TextStyle(
color: Theme.of(context).colorScheme.error),
),
onPressed: () {
// Confirmed, delete the workout
Provider.of<MeasurementProvider>(context, listen: false)
Provider.of<MeasurementProvider>(context,
listen: false)
.deleteCategory(category.id!);
// Close the popup
@@ -86,7 +92,8 @@ class MeasurementEntriesScreen extends StatelessWidget {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context).successfullyDeleted,
AppLocalizations.of(context)
.successfullyDeleted,
textAlign: TextAlign.center,
),
),

View File

@@ -39,11 +39,13 @@ class NutritionalDiaryScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
final args = ModalRoute.of(context)!.settings.arguments as NutritionalDiaryArguments;
final args =
ModalRoute.of(context)!.settings.arguments as NutritionalDiaryArguments;
return Scaffold(
appBar: AppBar(
title: Text(DateFormat.yMd(Localizations.localeOf(context).languageCode).format(args.date)),
title: Text(DateFormat.yMd(Localizations.localeOf(context).languageCode)
.format(args.date)),
),
body: Consumer<NutritionPlansProvider>(
builder: (context, nutritionProvider, child) => SingleChildScrollView(

View File

@@ -35,13 +35,15 @@ class NutritionalPlanScreen extends StatelessWidget {
static const routeName = '/nutritional-plan-detail';
Future<NutritionalPlan> _loadFullPlan(BuildContext context, int planId) {
return Provider.of<NutritionPlansProvider>(context, listen: false).fetchAndSetPlanFull(planId);
return Provider.of<NutritionPlansProvider>(context, listen: false)
.fetchAndSetPlanFull(planId);
}
@override
Widget build(BuildContext context) {
const appBarForeground = Colors.white;
final nutritionalPlan = ModalRoute.of(context)!.settings.arguments as NutritionalPlan;
final nutritionalPlan =
ModalRoute.of(context)!.settings.arguments as NutritionalPlan;
return Scaffold(
//appBar: getAppBar(nutritionalPlan),
@@ -109,10 +111,14 @@ class NutritionalPlanScreen extends StatelessWidget {
flexibleSpace: FlexibleSpaceBar(
title: Text(
nutritionalPlan.getLabel(context),
style: Theme.of(context).textTheme.titleLarge?.copyWith(color: appBarForeground),
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(color: appBarForeground),
),
background: const Image(
image: AssetImage('assets/images/backgrounds/nutritional_plans.jpg'),
image: AssetImage(
'assets/images/backgrounds/nutritional_plans.jpg'),
fit: BoxFit.cover,
),
),

View File

@@ -49,7 +49,8 @@ class NutritionScreen extends StatelessWidget {
},
),
body: Consumer<NutritionPlansProvider>(
builder: (context, nutritionProvider, child) => NutritionalPlansList(nutritionProvider),
builder: (context, nutritionProvider, child) =>
NutritionalPlansList(nutritionProvider),
),
);
}

View File

@@ -71,7 +71,8 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
@override
Widget build(BuildContext context) {
const appBarForeground = Colors.white;
final workoutPlan = ModalRoute.of(context)!.settings.arguments as WorkoutPlan;
final workoutPlan =
ModalRoute.of(context)!.settings.arguments as WorkoutPlan;
return Scaffold(
body: CustomScrollView(
@@ -84,10 +85,14 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
flexibleSpace: FlexibleSpaceBar(
title: Text(
workoutPlan.name,
style: Theme.of(context).textTheme.titleLarge?.copyWith(color: appBarForeground),
style: Theme.of(context)
.textTheme
.titleLarge
?.copyWith(color: appBarForeground),
),
background: const Image(
image: AssetImage('assets/images/backgrounds/workout_plans.jpg'),
image:
AssetImage('assets/images/backgrounds/workout_plans.jpg'),
fit: BoxFit.cover,
),
),
@@ -133,7 +138,8 @@ class _WorkoutPlanScreenState extends State<WorkoutPlanScreen> {
),
FutureBuilder(
future: _loadFullWorkout(context, workoutPlan.id!),
builder: (context, AsyncSnapshot<WorkoutPlan> snapshot) => SliverList(
builder: (context, AsyncSnapshot<WorkoutPlan> snapshot) =>
SliverList(
delegate: SliverChildListDelegate(
[
if (snapshot.connectionState == ConnectionState.waiting)

View File

@@ -50,7 +50,8 @@ class WorkoutPlansScreen extends StatelessWidget {
),
),
body: Consumer<WorkoutPlansProvider>(
builder: (context, workoutProvider, child) => WorkoutPlansList(workoutProvider),
builder: (context, workoutProvider, child) =>
WorkoutPlansList(workoutProvider),
),
);
}

View File

@@ -44,8 +44,12 @@ const FlexSubThemesData wgerSubThemeData = FlexSubThemesData(
);
const String wgerDisplayFont = 'RobotoCondensed';
const List<FontVariation> displayFontBoldWeight = <FontVariation>[FontVariation('wght', 600)];
const List<FontVariation> displayFontHeavyWeight = <FontVariation>[FontVariation('wght', 800)];
const List<FontVariation> displayFontBoldWeight = <FontVariation>[
FontVariation('wght', 600)
];
const List<FontVariation> displayFontHeavyWeight = <FontVariation>[
FontVariation('wght', 800)
];
// Make a light ColorScheme from the seeds.
final ColorScheme schemeLight = SeedColorScheme.fromSeeds(

View File

@@ -17,7 +17,8 @@ class AddExerciseDropdownButton extends StatefulWidget {
final FormFieldSetter<String?>? onSaved;
@override
_AddExerciseDropdownButtonState createState() => _AddExerciseDropdownButtonState();
_AddExerciseDropdownButtonState createState() =>
_AddExerciseDropdownButtonState();
}
class _AddExerciseDropdownButtonState extends State<AddExerciseDropdownButton> {
@@ -39,7 +40,8 @@ class _AddExerciseDropdownButtonState extends State<AddExerciseDropdownButton> {
},
value: _selectedItem,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
contentPadding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),

View File

@@ -20,10 +20,12 @@ class AddExerciseMultiselectButton<T> extends StatefulWidget {
: super(key: key);
@override
_AddExerciseMultiselectButtonState createState() => _AddExerciseMultiselectButtonState<T>();
_AddExerciseMultiselectButtonState createState() =>
_AddExerciseMultiselectButtonState<T>();
}
class _AddExerciseMultiselectButtonState<T> extends State<AddExerciseMultiselectButton> {
class _AddExerciseMultiselectButtonState<T>
extends State<AddExerciseMultiselectButton> {
List<T> _selectedItems = [];
@override
@@ -33,8 +35,9 @@ class _AddExerciseMultiselectButtonState<T> extends State<AddExerciseMultiselect
child: MultiSelectDialogField(
initialValue: widget.initialItems,
onSaved: widget.onSaved,
items:
widget.items.map((item) => MultiSelectItem<T>(item, widget.displayName(item))).toList(),
items: widget.items
.map((item) => MultiSelectItem<T>(item, widget.displayName(item)))
.toList(),
onConfirm: (value) {
setState(() {
_selectedItems = value.cast<T>();

View File

@@ -28,13 +28,15 @@ class AddExerciseTextArea extends StatelessWidget {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
keyboardType: isMultiline ? TextInputType.multiline : TextInputType.text,
keyboardType:
isMultiline ? TextInputType.multiline : TextInputType.text,
maxLines: isMultiline ? null : DEFAULT_LINES,
minLines: isMultiline ? MULTILINE_MIN_LINES : DEFAULT_LINES,
validator: validator,
onSaved: onSaved,
decoration: InputDecoration(
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
contentPadding:
const EdgeInsets.symmetric(horizontal: 10, vertical: 10),
border: const OutlineInputBorder(
borderRadius: BorderRadius.all(Radius.circular(10)),
),

Some files were not shown because too many files have changed in this diff Show More