Files
flutter/lib/providers/exercise_data.dart
2025-11-03 15:40:37 +01:00

166 lines
5.2 KiB
Dart

/*
* This file is part of wger Workout Manager <https://github.com/wger-project>.
* Copyright (c) 2020, wger Team
*
* wger Workout Manager is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import 'package:drift/drift.dart';
import 'package:logging/logging.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart';
import 'package:wger/database/powersync/database.dart';
import 'package:wger/models/exercises/category.dart';
import 'package:wger/models/exercises/equipment.dart';
import 'package:wger/models/exercises/exercise.dart';
import 'package:wger/models/exercises/muscle.dart';
part 'exercise_data.g.dart';
@Riverpod(keepAlive: true)
Stream<List<Exercise>> exercises(Ref ref) {
final logger = Logger('ExerciseNotifier');
ref.keepAlive();
final db = ref.read(driftPowerSyncDatabase);
logger.finer('Building exercise stream');
final primaryMuscleTable = db.alias(db.muscleTable, 'pm');
final secondaryMuscleTable = db.alias(db.muscleTable, 'sm');
final joined = db.select(db.exerciseTable).join([
// Translations
leftOuterJoin(
db.exerciseTranslationTable,
db.exerciseTranslationTable.exerciseId.equalsExp(db.exerciseTable.id),
),
// Language
leftOuterJoin(
db.languageTable,
db.languageTable.id.equalsExp(db.exerciseTranslationTable.languageId),
),
// Exercise <-> Muscle
leftOuterJoin(
db.exerciseMuscleM2N,
db.exerciseMuscleM2N.exerciseId.equalsExp(db.exerciseTable.id),
),
leftOuterJoin(
primaryMuscleTable,
primaryMuscleTable.id.equalsExp(db.exerciseMuscleM2N.muscleId),
),
// Exercise <-> Secondary Muscle
leftOuterJoin(
db.exerciseSecondaryMuscleM2N,
db.exerciseSecondaryMuscleM2N.exerciseId.equalsExp(db.exerciseTable.id),
),
leftOuterJoin(
secondaryMuscleTable,
secondaryMuscleTable.id.equalsExp(db.exerciseSecondaryMuscleM2N.muscleId),
),
// Exercise <-> Equipment
leftOuterJoin(
db.exerciseEquipmentM2N,
db.exerciseEquipmentM2N.exerciseId.equalsExp(db.exerciseTable.id),
),
leftOuterJoin(
db.equipmentTable,
db.equipmentTable.id.equalsExp(db.exerciseEquipmentM2N.equipmentId),
),
// Category
leftOuterJoin(
db.exerciseCategoryTable,
db.exerciseCategoryTable.id.equalsExp(db.exerciseTable.categoryId),
),
// Images
leftOuterJoin(
db.exerciseImageTable,
db.exerciseImageTable.exerciseId.equalsExp(db.exerciseTable.id),
),
]);
return joined.watch().map((rows) {
final Map<int, Exercise> map = {};
for (final row in rows) {
final exercise = row.readTable(db.exerciseTable);
final primaryMuscle = row.readTableOrNull(primaryMuscleTable);
final secondaryMuscle = row.readTableOrNull(secondaryMuscleTable);
final equipment = row.readTableOrNull(db.equipmentTable);
final image = row.readTableOrNull(db.exerciseImageTable);
final video = row.readTableOrNull(db.exerciseVideoTable);
final translation = row.readTableOrNull(db.exerciseTranslationTable);
final category = row.readTableOrNull(db.exerciseCategoryTable);
final entry = map.putIfAbsent(
exercise.id,
() => exercise,
);
if (category != null) {
entry.category = category;
}
if (translation != null && !entry.translations.any((t) => t.id == translation.id)) {
translation.language = row.readTable(db.languageTable);
entry.translations.add(translation);
}
if (image != null && !entry.images.any((t) => t.id == image.id)) {
entry.images.add(image);
}
if (video != null && !entry.videos.any((t) => t.id == video.id)) {
entry.videos.add(video);
}
if (equipment != null && !entry.equipment.any((e) => e.id == equipment.id)) {
entry.equipment.add(equipment);
}
if (primaryMuscle != null && !entry.muscles.any((m) => m.id == primaryMuscle.id)) {
entry.muscles.add(primaryMuscle);
}
if (secondaryMuscle != null &&
!entry.musclesSecondary.any((m) => m.id == secondaryMuscle.id)) {
entry.musclesSecondary.add(secondaryMuscle);
}
}
return map.values.toList();
});
}
@riverpod
Stream<List<ExerciseCategory>> exerciseCategories(Ref ref) {
final db = ref.read(driftPowerSyncDatabase);
return db.select(db.exerciseCategoryTable).watch();
}
@riverpod
Stream<List<Equipment>> exerciseEquipment(Ref ref) {
final db = ref.read(driftPowerSyncDatabase);
return db.select(db.equipmentTable).watch();
}
@riverpod
Stream<List<Muscle>> exerciseMuscles(Ref ref) {
final db = ref.read(driftPowerSyncDatabase);
return db.select(db.muscleTable).watch();
}