From 666359155ddf7fe9ce26ef9fdb9c7a75c1467b9c Mon Sep 17 00:00:00 2001 From: Roland Geider Date: Fri, 24 Oct 2025 20:52:02 +0200 Subject: [PATCH] Use the powersync drift provider to show exercises --- lib/database/powersync/database.dart | 6 + lib/database/powersync/database.g.dart | 1363 +++++++++++++++++ .../powersync/tables/measurements.dart | 24 + lib/database/powersync/tables/routines.dart | 29 + lib/helpers/errors.dart | 2 +- lib/powersync/schema.dart | 40 + lib/providers/exercise_data.dart | 33 + lib/providers/exercise_data.g.dart | 47 +- lib/screens/exercises_screen.dart | 40 +- lib/widgets/core/app_bar.dart | 2 +- 10 files changed, 1564 insertions(+), 22 deletions(-) create mode 100644 lib/database/powersync/tables/measurements.dart create mode 100644 lib/database/powersync/tables/routines.dart diff --git a/lib/database/powersync/database.dart b/lib/database/powersync/database.dart index f3014f95..3d1fa9f9 100644 --- a/lib/database/powersync/database.dart +++ b/lib/database/powersync/database.dart @@ -11,10 +11,14 @@ 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/video.dart'; +import 'package:wger/models/measurements/measurement_category.dart'; +import 'package:wger/models/workouts/log.dart'; import 'powersync.dart'; import 'tables/exercise.dart'; import 'tables/language.dart'; +import 'tables/measurements.dart'; +import 'tables/routines.dart'; import 'tables/weight.dart'; part 'database.g.dart'; @@ -37,6 +41,8 @@ part 'database.g.dart'; // User data WeightEntryTable, + MeasurementCategoryTable, + WorkoutLogTable, ], //include: {'queries.drift'}, ) diff --git a/lib/database/powersync/database.g.dart b/lib/database/powersync/database.g.dart index 3f7bc64f..a8f7d287 100644 --- a/lib/database/powersync/database.g.dart +++ b/lib/database/powersync/database.g.dart @@ -2763,6 +2763,780 @@ class WeightEntryTableCompanion extends UpdateCompanion { } } +class $MeasurementCategoryTableTable extends MeasurementCategoryTable + with TableInfo<$MeasurementCategoryTableTable, MeasurementCategory> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $MeasurementCategoryTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _nameMeta = const VerificationMeta('name'); + @override + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _unitMeta = const VerificationMeta('unit'); + @override + late final GeneratedColumn unit = GeneratedColumn( + 'unit', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + @override + List get $columns => [id, name, unit]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'measurements_category'; + @override + VerificationContext validateIntegrity( + Insertable instance, { + bool isInserting = false, + }) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('name')) { + context.handle( + _nameMeta, + name.isAcceptableOrUnknown(data['name']!, _nameMeta), + ); + } else if (isInserting) { + context.missing(_nameMeta); + } + if (data.containsKey('unit')) { + context.handle( + _unitMeta, + unit.isAcceptableOrUnknown(data['unit']!, _unitMeta), + ); + } else if (isInserting) { + context.missing(_unitMeta); + } + return context; + } + + @override + Set get $primaryKey => const {}; + @override + MeasurementCategory map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return MeasurementCategory( + id: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + unit: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}unit'], + )!, + ); + } + + @override + $MeasurementCategoryTableTable createAlias(String alias) { + return $MeasurementCategoryTableTable(attachedDatabase, alias); + } +} + +class MeasurementCategoryTableCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value unit; + final Value rowid; + const MeasurementCategoryTableCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.unit = const Value.absent(), + this.rowid = const Value.absent(), + }); + MeasurementCategoryTableCompanion.insert({ + required int id, + required String name, + required String unit, + this.rowid = const Value.absent(), + }) : id = Value(id), + name = Value(name), + unit = Value(unit); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? unit, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (unit != null) 'unit': unit, + if (rowid != null) 'rowid': rowid, + }); + } + + MeasurementCategoryTableCompanion copyWith({ + Value? id, + Value? name, + Value? unit, + Value? rowid, + }) { + return MeasurementCategoryTableCompanion( + id: id ?? this.id, + name: name ?? this.name, + unit: unit ?? this.unit, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (unit.present) { + map['unit'] = Variable(unit.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('MeasurementCategoryTableCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('unit: $unit, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $WorkoutLogTableTable extends WorkoutLogTable with TableInfo<$WorkoutLogTableTable, Log> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $WorkoutLogTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: false, + clientDefault: () => uuid.v4(), + ); + static const VerificationMeta _exerciseIdMeta = const VerificationMeta( + 'exerciseId', + ); + @override + late final GeneratedColumn exerciseId = GeneratedColumn( + 'exercise_id', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _routineIdMeta = const VerificationMeta( + 'routineId', + ); + @override + late final GeneratedColumn routineId = GeneratedColumn( + 'routine_id', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _sessionIdMeta = const VerificationMeta( + 'sessionId', + ); + @override + late final GeneratedColumn sessionId = GeneratedColumn( + 'session_id', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + static const VerificationMeta _iterationMeta = const VerificationMeta( + 'iteration', + ); + @override + late final GeneratedColumn iteration = GeneratedColumn( + 'iteration', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + static const VerificationMeta _slotEntryIdMeta = const VerificationMeta( + 'slotEntryId', + ); + @override + late final GeneratedColumn slotEntryId = GeneratedColumn( + 'slot_entry_id', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + static const VerificationMeta _rirMeta = const VerificationMeta('rir'); + @override + late final GeneratedColumn rir = GeneratedColumn( + 'rir', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + static const VerificationMeta _rirTargetMeta = const VerificationMeta( + 'rirTarget', + ); + @override + late final GeneratedColumn rirTarget = GeneratedColumn( + 'rir_target', + aliasedName, + true, + type: DriftSqlType.double, + requiredDuringInsert: false, + ); + static const VerificationMeta _repetitionsMeta = const VerificationMeta( + 'repetitions', + ); + @override + late final GeneratedColumn repetitions = GeneratedColumn( + 'repetitions', + aliasedName, + false, + type: DriftSqlType.double, + requiredDuringInsert: true, + ); + static const VerificationMeta _repetitionsTargetMeta = const VerificationMeta( + 'repetitionsTarget', + ); + @override + late final GeneratedColumn repetitionsTarget = GeneratedColumn( + 'repetitions_target', + aliasedName, + false, + type: DriftSqlType.double, + requiredDuringInsert: true, + ); + static const VerificationMeta _repetitionsUnitIdMeta = const VerificationMeta( + 'repetitionsUnitId', + ); + @override + late final GeneratedColumn repetitionsUnitId = GeneratedColumn( + 'repetitions_unit_id', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + static const VerificationMeta _weightMeta = const VerificationMeta('weight'); + @override + late final GeneratedColumn weight = GeneratedColumn( + 'weight', + aliasedName, + false, + type: DriftSqlType.double, + requiredDuringInsert: true, + ); + static const VerificationMeta _weightTargetMeta = const VerificationMeta( + 'weightTarget', + ); + @override + late final GeneratedColumn weightTarget = GeneratedColumn( + 'weight_target', + aliasedName, + false, + type: DriftSqlType.double, + requiredDuringInsert: true, + ); + static const VerificationMeta _weightUnitIdMeta = const VerificationMeta( + 'weightUnitId', + ); + @override + late final GeneratedColumn weightUnitId = GeneratedColumn( + 'weight_unit_id', + aliasedName, + true, + type: DriftSqlType.int, + requiredDuringInsert: false, + ); + static const VerificationMeta _dateMeta = const VerificationMeta('date'); + @override + late final GeneratedColumn date = GeneratedColumn( + 'date', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + exerciseId, + routineId, + sessionId, + iteration, + slotEntryId, + rir, + rirTarget, + repetitions, + repetitionsTarget, + repetitionsUnitId, + weight, + weightTarget, + weightUnitId, + date, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'manager_workoutlog'; + @override + VerificationContext validateIntegrity( + Insertable instance, { + bool isInserting = false, + }) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } + if (data.containsKey('exercise_id')) { + context.handle( + _exerciseIdMeta, + exerciseId.isAcceptableOrUnknown(data['exercise_id']!, _exerciseIdMeta), + ); + } else if (isInserting) { + context.missing(_exerciseIdMeta); + } + if (data.containsKey('routine_id')) { + context.handle( + _routineIdMeta, + routineId.isAcceptableOrUnknown(data['routine_id']!, _routineIdMeta), + ); + } else if (isInserting) { + context.missing(_routineIdMeta); + } + if (data.containsKey('session_id')) { + context.handle( + _sessionIdMeta, + sessionId.isAcceptableOrUnknown(data['session_id']!, _sessionIdMeta), + ); + } + if (data.containsKey('iteration')) { + context.handle( + _iterationMeta, + iteration.isAcceptableOrUnknown(data['iteration']!, _iterationMeta), + ); + } + if (data.containsKey('slot_entry_id')) { + context.handle( + _slotEntryIdMeta, + slotEntryId.isAcceptableOrUnknown( + data['slot_entry_id']!, + _slotEntryIdMeta, + ), + ); + } + if (data.containsKey('rir')) { + context.handle( + _rirMeta, + rir.isAcceptableOrUnknown(data['rir']!, _rirMeta), + ); + } + if (data.containsKey('rir_target')) { + context.handle( + _rirTargetMeta, + rirTarget.isAcceptableOrUnknown(data['rir_target']!, _rirTargetMeta), + ); + } + if (data.containsKey('repetitions')) { + context.handle( + _repetitionsMeta, + repetitions.isAcceptableOrUnknown( + data['repetitions']!, + _repetitionsMeta, + ), + ); + } else if (isInserting) { + context.missing(_repetitionsMeta); + } + if (data.containsKey('repetitions_target')) { + context.handle( + _repetitionsTargetMeta, + repetitionsTarget.isAcceptableOrUnknown( + data['repetitions_target']!, + _repetitionsTargetMeta, + ), + ); + } else if (isInserting) { + context.missing(_repetitionsTargetMeta); + } + if (data.containsKey('repetitions_unit_id')) { + context.handle( + _repetitionsUnitIdMeta, + repetitionsUnitId.isAcceptableOrUnknown( + data['repetitions_unit_id']!, + _repetitionsUnitIdMeta, + ), + ); + } + if (data.containsKey('weight')) { + context.handle( + _weightMeta, + weight.isAcceptableOrUnknown(data['weight']!, _weightMeta), + ); + } else if (isInserting) { + context.missing(_weightMeta); + } + if (data.containsKey('weight_target')) { + context.handle( + _weightTargetMeta, + weightTarget.isAcceptableOrUnknown( + data['weight_target']!, + _weightTargetMeta, + ), + ); + } else if (isInserting) { + context.missing(_weightTargetMeta); + } + if (data.containsKey('weight_unit_id')) { + context.handle( + _weightUnitIdMeta, + weightUnitId.isAcceptableOrUnknown( + data['weight_unit_id']!, + _weightUnitIdMeta, + ), + ); + } + if (data.containsKey('date')) { + context.handle( + _dateMeta, + date.isAcceptableOrUnknown(data['date']!, _dateMeta), + ); + } else if (isInserting) { + context.missing(_dateMeta); + } + return context; + } + + @override + Set get $primaryKey => const {}; + @override + Log map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return Log( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + exerciseId: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}exercise_id'], + )!, + iteration: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}iteration'], + ), + slotEntryId: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}slot_entry_id'], + ), + routineId: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}routine_id'], + )!, + repetitions: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}repetitions'], + )!, + repetitionsTarget: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}repetitions_target'], + )!, + repetitionsUnitId: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}repetitions_unit_id'], + ), + rir: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}rir'], + ), + rirTarget: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}rir_target'], + ), + weight: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}weight'], + )!, + weightTarget: attachedDatabase.typeMapping.read( + DriftSqlType.double, + data['${effectivePrefix}weight_target'], + )!, + weightUnitId: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}weight_unit_id'], + ), + date: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}date'], + )!, + ); + } + + @override + $WorkoutLogTableTable createAlias(String alias) { + return $WorkoutLogTableTable(attachedDatabase, alias); + } +} + +class WorkoutLogTableCompanion extends UpdateCompanion { + final Value id; + final Value exerciseId; + final Value routineId; + final Value sessionId; + final Value iteration; + final Value slotEntryId; + final Value rir; + final Value rirTarget; + final Value repetitions; + final Value repetitionsTarget; + final Value repetitionsUnitId; + final Value weight; + final Value weightTarget; + final Value weightUnitId; + final Value date; + final Value rowid; + const WorkoutLogTableCompanion({ + this.id = const Value.absent(), + this.exerciseId = const Value.absent(), + this.routineId = const Value.absent(), + this.sessionId = const Value.absent(), + this.iteration = const Value.absent(), + this.slotEntryId = const Value.absent(), + this.rir = const Value.absent(), + this.rirTarget = const Value.absent(), + this.repetitions = const Value.absent(), + this.repetitionsTarget = const Value.absent(), + this.repetitionsUnitId = const Value.absent(), + this.weight = const Value.absent(), + this.weightTarget = const Value.absent(), + this.weightUnitId = const Value.absent(), + this.date = const Value.absent(), + this.rowid = const Value.absent(), + }); + WorkoutLogTableCompanion.insert({ + this.id = const Value.absent(), + required int exerciseId, + required int routineId, + this.sessionId = const Value.absent(), + this.iteration = const Value.absent(), + this.slotEntryId = const Value.absent(), + this.rir = const Value.absent(), + this.rirTarget = const Value.absent(), + required double repetitions, + required double repetitionsTarget, + this.repetitionsUnitId = const Value.absent(), + required double weight, + required double weightTarget, + this.weightUnitId = const Value.absent(), + required DateTime date, + this.rowid = const Value.absent(), + }) : exerciseId = Value(exerciseId), + routineId = Value(routineId), + repetitions = Value(repetitions), + repetitionsTarget = Value(repetitionsTarget), + weight = Value(weight), + weightTarget = Value(weightTarget), + date = Value(date); + static Insertable custom({ + Expression? id, + Expression? exerciseId, + Expression? routineId, + Expression? sessionId, + Expression? iteration, + Expression? slotEntryId, + Expression? rir, + Expression? rirTarget, + Expression? repetitions, + Expression? repetitionsTarget, + Expression? repetitionsUnitId, + Expression? weight, + Expression? weightTarget, + Expression? weightUnitId, + Expression? date, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (exerciseId != null) 'exercise_id': exerciseId, + if (routineId != null) 'routine_id': routineId, + if (sessionId != null) 'session_id': sessionId, + if (iteration != null) 'iteration': iteration, + if (slotEntryId != null) 'slot_entry_id': slotEntryId, + if (rir != null) 'rir': rir, + if (rirTarget != null) 'rir_target': rirTarget, + if (repetitions != null) 'repetitions': repetitions, + if (repetitionsTarget != null) 'repetitions_target': repetitionsTarget, + if (repetitionsUnitId != null) 'repetitions_unit_id': repetitionsUnitId, + if (weight != null) 'weight': weight, + if (weightTarget != null) 'weight_target': weightTarget, + if (weightUnitId != null) 'weight_unit_id': weightUnitId, + if (date != null) 'date': date, + if (rowid != null) 'rowid': rowid, + }); + } + + WorkoutLogTableCompanion copyWith({ + Value? id, + Value? exerciseId, + Value? routineId, + Value? sessionId, + Value? iteration, + Value? slotEntryId, + Value? rir, + Value? rirTarget, + Value? repetitions, + Value? repetitionsTarget, + Value? repetitionsUnitId, + Value? weight, + Value? weightTarget, + Value? weightUnitId, + Value? date, + Value? rowid, + }) { + return WorkoutLogTableCompanion( + id: id ?? this.id, + exerciseId: exerciseId ?? this.exerciseId, + routineId: routineId ?? this.routineId, + sessionId: sessionId ?? this.sessionId, + iteration: iteration ?? this.iteration, + slotEntryId: slotEntryId ?? this.slotEntryId, + rir: rir ?? this.rir, + rirTarget: rirTarget ?? this.rirTarget, + repetitions: repetitions ?? this.repetitions, + repetitionsTarget: repetitionsTarget ?? this.repetitionsTarget, + repetitionsUnitId: repetitionsUnitId ?? this.repetitionsUnitId, + weight: weight ?? this.weight, + weightTarget: weightTarget ?? this.weightTarget, + weightUnitId: weightUnitId ?? this.weightUnitId, + date: date ?? this.date, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (exerciseId.present) { + map['exercise_id'] = Variable(exerciseId.value); + } + if (routineId.present) { + map['routine_id'] = Variable(routineId.value); + } + if (sessionId.present) { + map['session_id'] = Variable(sessionId.value); + } + if (iteration.present) { + map['iteration'] = Variable(iteration.value); + } + if (slotEntryId.present) { + map['slot_entry_id'] = Variable(slotEntryId.value); + } + if (rir.present) { + map['rir'] = Variable(rir.value); + } + if (rirTarget.present) { + map['rir_target'] = Variable(rirTarget.value); + } + if (repetitions.present) { + map['repetitions'] = Variable(repetitions.value); + } + if (repetitionsTarget.present) { + map['repetitions_target'] = Variable(repetitionsTarget.value); + } + if (repetitionsUnitId.present) { + map['repetitions_unit_id'] = Variable(repetitionsUnitId.value); + } + if (weight.present) { + map['weight'] = Variable(weight.value); + } + if (weightTarget.present) { + map['weight_target'] = Variable(weightTarget.value); + } + if (weightUnitId.present) { + map['weight_unit_id'] = Variable(weightUnitId.value); + } + if (date.present) { + map['date'] = Variable(date.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('WorkoutLogTableCompanion(') + ..write('id: $id, ') + ..write('exerciseId: $exerciseId, ') + ..write('routineId: $routineId, ') + ..write('sessionId: $sessionId, ') + ..write('iteration: $iteration, ') + ..write('slotEntryId: $slotEntryId, ') + ..write('rir: $rir, ') + ..write('rirTarget: $rirTarget, ') + ..write('repetitions: $repetitions, ') + ..write('repetitionsTarget: $repetitionsTarget, ') + ..write('repetitionsUnitId: $repetitionsUnitId, ') + ..write('weight: $weight, ') + ..write('weightTarget: $weightTarget, ') + ..write('weightUnitId: $weightUnitId, ') + ..write('date: $date, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + abstract class _$DriftPowersyncDatabase extends GeneratedDatabase { _$DriftPowersyncDatabase(QueryExecutor e) : super(e); $DriftPowersyncDatabaseManager get managers => $DriftPowersyncDatabaseManager(this); @@ -2781,6 +3555,11 @@ abstract class _$DriftPowersyncDatabase extends GeneratedDatabase { late final $WeightEntryTableTable weightEntryTable = $WeightEntryTableTable( this, ); + late final $MeasurementCategoryTableTable measurementCategoryTable = + $MeasurementCategoryTableTable(this); + late final $WorkoutLogTableTable workoutLogTable = $WorkoutLogTableTable( + this, + ); @override Iterable> get allTables => allSchemaEntities.whereType>(); @@ -2797,6 +3576,8 @@ abstract class _$DriftPowersyncDatabase extends GeneratedDatabase { exerciseImageTable, exerciseVideoTable, weightEntryTable, + measurementCategoryTable, + workoutLogTable, ]; @override DriftDatabaseOptions get options => const DriftDatabaseOptions(storeDateTimeAsText: true); @@ -4946,6 +5727,581 @@ typedef $$WeightEntryTableTableProcessedTableManager = WeightEntry, PrefetchHooks Function() >; +typedef $$MeasurementCategoryTableTableCreateCompanionBuilder = + MeasurementCategoryTableCompanion Function({ + required int id, + required String name, + required String unit, + Value rowid, + }); +typedef $$MeasurementCategoryTableTableUpdateCompanionBuilder = + MeasurementCategoryTableCompanion Function({ + Value id, + Value name, + Value unit, + Value rowid, + }); + +class $$MeasurementCategoryTableTableFilterComposer + extends Composer<_$DriftPowersyncDatabase, $MeasurementCategoryTableTable> { + $$MeasurementCategoryTableTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get name => $composableBuilder( + column: $table.name, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get unit => $composableBuilder( + column: $table.unit, + builder: (column) => ColumnFilters(column), + ); +} + +class $$MeasurementCategoryTableTableOrderingComposer + extends Composer<_$DriftPowersyncDatabase, $MeasurementCategoryTableTable> { + $$MeasurementCategoryTableTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get name => $composableBuilder( + column: $table.name, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get unit => $composableBuilder( + column: $table.unit, + builder: (column) => ColumnOrderings(column), + ); +} + +class $$MeasurementCategoryTableTableAnnotationComposer + extends Composer<_$DriftPowersyncDatabase, $MeasurementCategoryTableTable> { + $$MeasurementCategoryTableTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get name => + $composableBuilder(column: $table.name, builder: (column) => column); + + GeneratedColumn get unit => + $composableBuilder(column: $table.unit, builder: (column) => column); +} + +class $$MeasurementCategoryTableTableTableManager + extends + RootTableManager< + _$DriftPowersyncDatabase, + $MeasurementCategoryTableTable, + MeasurementCategory, + $$MeasurementCategoryTableTableFilterComposer, + $$MeasurementCategoryTableTableOrderingComposer, + $$MeasurementCategoryTableTableAnnotationComposer, + $$MeasurementCategoryTableTableCreateCompanionBuilder, + $$MeasurementCategoryTableTableUpdateCompanionBuilder, + ( + MeasurementCategory, + BaseReferences< + _$DriftPowersyncDatabase, + $MeasurementCategoryTableTable, + MeasurementCategory + >, + ), + MeasurementCategory, + PrefetchHooks Function() + > { + $$MeasurementCategoryTableTableTableManager( + _$DriftPowersyncDatabase db, + $MeasurementCategoryTableTable table, + ) : super( + TableManagerState( + db: db, + table: table, + createFilteringComposer: () => $$MeasurementCategoryTableTableFilterComposer( + $db: db, + $table: table, + ), + createOrderingComposer: () => $$MeasurementCategoryTableTableOrderingComposer( + $db: db, + $table: table, + ), + createComputedFieldComposer: () => $$MeasurementCategoryTableTableAnnotationComposer( + $db: db, + $table: table, + ), + updateCompanionCallback: + ({ + Value id = const Value.absent(), + Value name = const Value.absent(), + Value unit = const Value.absent(), + Value rowid = const Value.absent(), + }) => MeasurementCategoryTableCompanion( + id: id, + name: name, + unit: unit, + rowid: rowid, + ), + createCompanionCallback: + ({ + required int id, + required String name, + required String unit, + Value rowid = const Value.absent(), + }) => MeasurementCategoryTableCompanion.insert( + id: id, + name: name, + unit: unit, + rowid: rowid, + ), + withReferenceMapper: (p0) => + p0.map((e) => (e.readTable(table), BaseReferences(db, table, e))).toList(), + prefetchHooksCallback: null, + ), + ); +} + +typedef $$MeasurementCategoryTableTableProcessedTableManager = + ProcessedTableManager< + _$DriftPowersyncDatabase, + $MeasurementCategoryTableTable, + MeasurementCategory, + $$MeasurementCategoryTableTableFilterComposer, + $$MeasurementCategoryTableTableOrderingComposer, + $$MeasurementCategoryTableTableAnnotationComposer, + $$MeasurementCategoryTableTableCreateCompanionBuilder, + $$MeasurementCategoryTableTableUpdateCompanionBuilder, + ( + MeasurementCategory, + BaseReferences< + _$DriftPowersyncDatabase, + $MeasurementCategoryTableTable, + MeasurementCategory + >, + ), + MeasurementCategory, + PrefetchHooks Function() + >; +typedef $$WorkoutLogTableTableCreateCompanionBuilder = + WorkoutLogTableCompanion Function({ + Value id, + required int exerciseId, + required int routineId, + Value sessionId, + Value iteration, + Value slotEntryId, + Value rir, + Value rirTarget, + required double repetitions, + required double repetitionsTarget, + Value repetitionsUnitId, + required double weight, + required double weightTarget, + Value weightUnitId, + required DateTime date, + Value rowid, + }); +typedef $$WorkoutLogTableTableUpdateCompanionBuilder = + WorkoutLogTableCompanion Function({ + Value id, + Value exerciseId, + Value routineId, + Value sessionId, + Value iteration, + Value slotEntryId, + Value rir, + Value rirTarget, + Value repetitions, + Value repetitionsTarget, + Value repetitionsUnitId, + Value weight, + Value weightTarget, + Value weightUnitId, + Value date, + Value rowid, + }); + +class $$WorkoutLogTableTableFilterComposer + extends Composer<_$DriftPowersyncDatabase, $WorkoutLogTableTable> { + $$WorkoutLogTableTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get exerciseId => $composableBuilder( + column: $table.exerciseId, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get routineId => $composableBuilder( + column: $table.routineId, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get sessionId => $composableBuilder( + column: $table.sessionId, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get iteration => $composableBuilder( + column: $table.iteration, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get slotEntryId => $composableBuilder( + column: $table.slotEntryId, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get rir => $composableBuilder( + column: $table.rir, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get rirTarget => $composableBuilder( + column: $table.rirTarget, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get repetitions => $composableBuilder( + column: $table.repetitions, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get repetitionsTarget => $composableBuilder( + column: $table.repetitionsTarget, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get repetitionsUnitId => $composableBuilder( + column: $table.repetitionsUnitId, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get weight => $composableBuilder( + column: $table.weight, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get weightTarget => $composableBuilder( + column: $table.weightTarget, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get weightUnitId => $composableBuilder( + column: $table.weightUnitId, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get date => $composableBuilder( + column: $table.date, + builder: (column) => ColumnFilters(column), + ); +} + +class $$WorkoutLogTableTableOrderingComposer + extends Composer<_$DriftPowersyncDatabase, $WorkoutLogTableTable> { + $$WorkoutLogTableTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get exerciseId => $composableBuilder( + column: $table.exerciseId, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get routineId => $composableBuilder( + column: $table.routineId, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get sessionId => $composableBuilder( + column: $table.sessionId, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get iteration => $composableBuilder( + column: $table.iteration, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get slotEntryId => $composableBuilder( + column: $table.slotEntryId, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get rir => $composableBuilder( + column: $table.rir, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get rirTarget => $composableBuilder( + column: $table.rirTarget, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get repetitions => $composableBuilder( + column: $table.repetitions, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get repetitionsTarget => $composableBuilder( + column: $table.repetitionsTarget, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get repetitionsUnitId => $composableBuilder( + column: $table.repetitionsUnitId, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get weight => $composableBuilder( + column: $table.weight, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get weightTarget => $composableBuilder( + column: $table.weightTarget, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get weightUnitId => $composableBuilder( + column: $table.weightUnitId, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get date => $composableBuilder( + column: $table.date, + builder: (column) => ColumnOrderings(column), + ); +} + +class $$WorkoutLogTableTableAnnotationComposer + extends Composer<_$DriftPowersyncDatabase, $WorkoutLogTableTable> { + $$WorkoutLogTableTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get exerciseId => $composableBuilder( + column: $table.exerciseId, + builder: (column) => column, + ); + + GeneratedColumn get routineId => + $composableBuilder(column: $table.routineId, builder: (column) => column); + + GeneratedColumn get sessionId => + $composableBuilder(column: $table.sessionId, builder: (column) => column); + + GeneratedColumn get iteration => + $composableBuilder(column: $table.iteration, builder: (column) => column); + + GeneratedColumn get slotEntryId => $composableBuilder( + column: $table.slotEntryId, + builder: (column) => column, + ); + + GeneratedColumn get rir => + $composableBuilder(column: $table.rir, builder: (column) => column); + + GeneratedColumn get rirTarget => + $composableBuilder(column: $table.rirTarget, builder: (column) => column); + + GeneratedColumn get repetitions => $composableBuilder( + column: $table.repetitions, + builder: (column) => column, + ); + + GeneratedColumn get repetitionsTarget => $composableBuilder( + column: $table.repetitionsTarget, + builder: (column) => column, + ); + + GeneratedColumn get repetitionsUnitId => $composableBuilder( + column: $table.repetitionsUnitId, + builder: (column) => column, + ); + + GeneratedColumn get weight => + $composableBuilder(column: $table.weight, builder: (column) => column); + + GeneratedColumn get weightTarget => $composableBuilder( + column: $table.weightTarget, + builder: (column) => column, + ); + + GeneratedColumn get weightUnitId => $composableBuilder( + column: $table.weightUnitId, + builder: (column) => column, + ); + + GeneratedColumn get date => + $composableBuilder(column: $table.date, builder: (column) => column); +} + +class $$WorkoutLogTableTableTableManager + extends + RootTableManager< + _$DriftPowersyncDatabase, + $WorkoutLogTableTable, + Log, + $$WorkoutLogTableTableFilterComposer, + $$WorkoutLogTableTableOrderingComposer, + $$WorkoutLogTableTableAnnotationComposer, + $$WorkoutLogTableTableCreateCompanionBuilder, + $$WorkoutLogTableTableUpdateCompanionBuilder, + (Log, BaseReferences<_$DriftPowersyncDatabase, $WorkoutLogTableTable, Log>), + Log, + PrefetchHooks Function() + > { + $$WorkoutLogTableTableTableManager( + _$DriftPowersyncDatabase db, + $WorkoutLogTableTable table, + ) : super( + TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$WorkoutLogTableTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$WorkoutLogTableTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$WorkoutLogTableTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + Value id = const Value.absent(), + Value exerciseId = const Value.absent(), + Value routineId = const Value.absent(), + Value sessionId = const Value.absent(), + Value iteration = const Value.absent(), + Value slotEntryId = const Value.absent(), + Value rir = const Value.absent(), + Value rirTarget = const Value.absent(), + Value repetitions = const Value.absent(), + Value repetitionsTarget = const Value.absent(), + Value repetitionsUnitId = const Value.absent(), + Value weight = const Value.absent(), + Value weightTarget = const Value.absent(), + Value weightUnitId = const Value.absent(), + Value date = const Value.absent(), + Value rowid = const Value.absent(), + }) => WorkoutLogTableCompanion( + id: id, + exerciseId: exerciseId, + routineId: routineId, + sessionId: sessionId, + iteration: iteration, + slotEntryId: slotEntryId, + rir: rir, + rirTarget: rirTarget, + repetitions: repetitions, + repetitionsTarget: repetitionsTarget, + repetitionsUnitId: repetitionsUnitId, + weight: weight, + weightTarget: weightTarget, + weightUnitId: weightUnitId, + date: date, + rowid: rowid, + ), + createCompanionCallback: + ({ + Value id = const Value.absent(), + required int exerciseId, + required int routineId, + Value sessionId = const Value.absent(), + Value iteration = const Value.absent(), + Value slotEntryId = const Value.absent(), + Value rir = const Value.absent(), + Value rirTarget = const Value.absent(), + required double repetitions, + required double repetitionsTarget, + Value repetitionsUnitId = const Value.absent(), + required double weight, + required double weightTarget, + Value weightUnitId = const Value.absent(), + required DateTime date, + Value rowid = const Value.absent(), + }) => WorkoutLogTableCompanion.insert( + id: id, + exerciseId: exerciseId, + routineId: routineId, + sessionId: sessionId, + iteration: iteration, + slotEntryId: slotEntryId, + rir: rir, + rirTarget: rirTarget, + repetitions: repetitions, + repetitionsTarget: repetitionsTarget, + repetitionsUnitId: repetitionsUnitId, + weight: weight, + weightTarget: weightTarget, + weightUnitId: weightUnitId, + date: date, + rowid: rowid, + ), + withReferenceMapper: (p0) => + p0.map((e) => (e.readTable(table), BaseReferences(db, table, e))).toList(), + prefetchHooksCallback: null, + ), + ); +} + +typedef $$WorkoutLogTableTableProcessedTableManager = + ProcessedTableManager< + _$DriftPowersyncDatabase, + $WorkoutLogTableTable, + Log, + $$WorkoutLogTableTableFilterComposer, + $$WorkoutLogTableTableOrderingComposer, + $$WorkoutLogTableTableAnnotationComposer, + $$WorkoutLogTableTableCreateCompanionBuilder, + $$WorkoutLogTableTableUpdateCompanionBuilder, + (Log, BaseReferences<_$DriftPowersyncDatabase, $WorkoutLogTableTable, Log>), + Log, + PrefetchHooks Function() + >; class $DriftPowersyncDatabaseManager { final _$DriftPowersyncDatabase _db; @@ -4978,4 +6334,11 @@ class $DriftPowersyncDatabaseManager { $$ExerciseVideoTableTableTableManager(_db, _db.exerciseVideoTable); $$WeightEntryTableTableTableManager get weightEntryTable => $$WeightEntryTableTableTableManager(_db, _db.weightEntryTable); + $$MeasurementCategoryTableTableTableManager get measurementCategoryTable => + $$MeasurementCategoryTableTableTableManager( + _db, + _db.measurementCategoryTable, + ); + $$WorkoutLogTableTableTableManager get workoutLogTable => + $$WorkoutLogTableTableTableManager(_db, _db.workoutLogTable); } diff --git a/lib/database/powersync/tables/measurements.dart b/lib/database/powersync/tables/measurements.dart new file mode 100644 index 00000000..f65429f5 --- /dev/null +++ b/lib/database/powersync/tables/measurements.dart @@ -0,0 +1,24 @@ +import 'package:drift/drift.dart'; +import 'package:wger/models/measurements/measurement_category.dart'; +import 'package:wger/models/measurements/measurement_entry.dart'; + +@UseRowClass(MeasurementCategory) +class MeasurementCategoryTable extends Table { + @override + String get tableName => 'measurements_category'; + + IntColumn get id => integer()(); + TextColumn get name => text()(); + TextColumn get unit => text()(); +} + +@UseRowClass(MeasurementEntry) +class MeasurementEntryTable extends Table { + @override + String get tableName => 'measurements_measurement'; + + IntColumn get id => integer()(); + DateTimeColumn get date => dateTime()(); + RealColumn get value => real()(); + TextColumn get notes => text()(); +} diff --git a/lib/database/powersync/tables/routines.dart b/lib/database/powersync/tables/routines.dart new file mode 100644 index 00000000..8cfff277 --- /dev/null +++ b/lib/database/powersync/tables/routines.dart @@ -0,0 +1,29 @@ +import 'package:drift/drift.dart'; +import 'package:powersync/powersync.dart' show uuid; +import 'package:wger/models/workouts/log.dart'; + +@UseRowClass(Log) +class WorkoutLogTable extends Table { + @override + String get tableName => 'manager_workoutlog'; + + TextColumn get id => text().clientDefault(() => uuid.v4())(); + IntColumn get exerciseId => integer().named('exercise_id')(); + IntColumn get routineId => integer().named('routine_id')(); + IntColumn get sessionId => integer().named('session_id').nullable()(); + IntColumn get iteration => integer().nullable()(); + IntColumn get slotEntryId => integer().named('slot_entry_id').nullable()(); + + RealColumn get rir => real().nullable()(); + RealColumn get rirTarget => real().named('rir_target').nullable()(); + + RealColumn get repetitions => real()(); + RealColumn get repetitionsTarget => real().named('repetitions_target')(); + IntColumn get repetitionsUnitId => integer().named('repetitions_unit_id').nullable()(); + + RealColumn get weight => real()(); + RealColumn get weightTarget => real().named('weight_target')(); + IntColumn get weightUnitId => integer().named('weight_unit_id').nullable()(); + + DateTimeColumn get date => dateTime()(); +} diff --git a/lib/helpers/errors.dart b/lib/helpers/errors.dart index 77d03a0a..aed7bc94 100644 --- a/lib/helpers/errors.dart +++ b/lib/helpers/errors.dart @@ -296,7 +296,7 @@ void showDeleteDialog(BuildContext context, String confirmDeleteName, Log log) a style: TextStyle(color: Theme.of(context).colorScheme.error), ), onPressed: () { - context.read().deleteLog(log.id!, log.routineId); + context.read().deleteLog(log.id.toString(), log.routineId); Navigator.of(contextDialog).pop(); diff --git a/lib/powersync/schema.dart b/lib/powersync/schema.dart index 295537a0..038eefa0 100644 --- a/lib/powersync/schema.dart +++ b/lib/powersync/schema.dart @@ -95,6 +95,9 @@ Schema schema = const Schema([ Column.text('url'), Column.integer('is_main'), ], + indexes: [ + Index('exercise', [IndexedColumn('exercise_id')]), + ], ), Table( 'exercises_exercisevideo', @@ -111,6 +114,9 @@ Schema schema = const Schema([ Column.integer('license_id'), Column.text('license_author'), ], + indexes: [ + Index('exercise', [IndexedColumn('exercise_id')]), + ], ), // @@ -124,4 +130,38 @@ Schema schema = const Schema([ Column.text('date'), ], ), + Table( + 'measurements_category', + [ + Column.text('name'), + Column.real('unit'), + ], + ), + Table( + 'manager_workoutlog', + [ + Column.integer('exercise_id'), + Column.integer('routine_id'), + Column.integer('session_id'), + Column.integer('iteration'), + Column.integer('slot_entry_id'), + Column.real('rir'), + Column.real('rir_target'), + Column.real('repetitions'), + Column.real('repetitions_target'), + Column.integer('repetitions_unit_id'), + Column.real('weight'), + Column.real('weight_target'), + Column.integer('weight_unit_id'), + Column.text('date'), + ], + indexes: [ + Index('exercise', [IndexedColumn('exercise_id')]), + Index('slot_entry', [IndexedColumn('slot_entry_id')]), + Index('routine', [IndexedColumn('routine_id')]), + Index('session', [IndexedColumn('session_id')]), + Index('repetitions_unit', [IndexedColumn('repetitions_unit_id')]), + Index('weight_unit', [IndexedColumn('weight_unit_id')]), + ], + ), ]); diff --git a/lib/providers/exercise_data.dart b/lib/providers/exercise_data.dart index 2dda77bc..b32c3e4e 100644 --- a/lib/providers/exercise_data.dart +++ b/lib/providers/exercise_data.dart @@ -4,6 +4,7 @@ import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:wger/database/powersync/database.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'; @@ -14,6 +15,7 @@ final class ExerciseNotifier extends _$ExerciseNotifier { @override Stream> build() { final db = ref.read(driftPowerSyncDatabase); + _logger.fine('Building exercise stream'); final primaryMuscleTable = db.alias(db.muscleTable, 'pm'); final secondaryMuscleTable = db.alias(db.muscleTable, 'sm'); @@ -25,6 +27,12 @@ final class ExerciseNotifier extends _$ExerciseNotifier { db.exerciseTranslationTable.exerciseId.equalsExp(db.exerciseTable.id), ), + // Language + leftOuterJoin( + db.languageTable, + db.languageTable.id.equalsExp(db.exerciseTranslationTable.languageId), + ), + // Exercise <-> Muscle leftOuterJoin( db.exerciseMuscleM2N, @@ -80,6 +88,7 @@ final class ExerciseNotifier extends _$ExerciseNotifier { } if (translation != null && !entry.translations.any((t) => t.id == translation.id)) { + translation.language = row.readTable(db.languageTable); entry.translations.add(translation); } @@ -104,6 +113,21 @@ final class ExerciseNotifier extends _$ExerciseNotifier { return map.values.toList(); }); } + + Exercise? getById(int id) { + // Can be null e.g. during initial loading + final cached = state.asData?.value; + if (cached == null) { + return null; + } + + for (final e in cached) { + if (e.id == id) { + return e; + } + } + return null; + } } @riverpod @@ -114,3 +138,12 @@ final class ExerciseEquipmentNotifier extends _$ExerciseEquipmentNotifier { return db.select(db.equipmentTable).watch(); } } + +@riverpod +final class ExerciseMuscleNotifier extends _$ExerciseMuscleNotifier { + @override + Stream> build() { + final db = ref.read(driftPowerSyncDatabase); + return db.select(db.muscleTable).watch(); + } +} diff --git a/lib/providers/exercise_data.g.dart b/lib/providers/exercise_data.g.dart index 1d2ff3d3..5a2e240e 100644 --- a/lib/providers/exercise_data.g.dart +++ b/lib/providers/exercise_data.g.dart @@ -33,7 +33,7 @@ final class ExerciseNotifierProvider ExerciseNotifier create() => ExerciseNotifier(); } -String _$exerciseNotifierHash() => r'4f6613f81e292dd3c74f9eebbbb20482b8da1e42'; +String _$exerciseNotifierHash() => r'2b7dafd181f3659590ddbd961e7f903d6ba31338'; abstract class _$ExerciseNotifier extends $StreamNotifier> { Stream> build(); @@ -98,3 +98,48 @@ abstract class _$ExerciseEquipmentNotifier extends $StreamNotifier> { + const ExerciseMuscleNotifierProvider._() + : super( + from: null, + argument: null, + retry: null, + name: r'exerciseMuscleProvider', + isAutoDispose: true, + dependencies: null, + $allTransitiveDependencies: null, + ); + + @override + String debugGetCreateSourceHash() => _$exerciseMuscleNotifierHash(); + + @$internal + @override + ExerciseMuscleNotifier create() => ExerciseMuscleNotifier(); +} + +String _$exerciseMuscleNotifierHash() => r'6be0b7400776f1593194fb43667acbeee8e3a4a8'; + +abstract class _$ExerciseMuscleNotifier extends $StreamNotifier> { + Stream> build(); + @$mustCallSuper + @override + void runBuild() { + final created = build(); + final ref = this.ref as $Ref>, List>; + final element = + ref.element + as $ClassProviderElement< + AnyNotifier>, List>, + AsyncValue>, + Object?, + Object? + >; + element.handleValue(ref, created); + } +} diff --git a/lib/screens/exercises_screen.dart b/lib/screens/exercises_screen.dart index 6c335025..3184d40d 100644 --- a/lib/screens/exercises_screen.dart +++ b/lib/screens/exercises_screen.dart @@ -1,25 +1,21 @@ import 'package:flutter/material.dart'; -import 'package:provider/provider.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:wger/l10n/generated/app_localizations.dart'; import 'package:wger/models/exercises/exercise.dart'; -import 'package:wger/providers/exercises.dart'; +import 'package:wger/providers/exercise_data.dart'; import 'package:wger/widgets/core/app_bar.dart'; +import 'package:wger/widgets/core/progress_indicator.dart'; import 'package:wger/widgets/exercises/filter_row.dart'; import 'package:wger/widgets/exercises/list_tile.dart'; -class ExercisesScreen extends StatefulWidget { +class ExercisesScreen extends ConsumerWidget { const ExercisesScreen({super.key}); static const routeName = '/exercises'; @override - _ExercisesScreenState createState() => _ExercisesScreenState(); -} - -class _ExercisesScreenState extends State { - @override - Widget build(BuildContext context) { - final exercisesList = Provider.of(context).filteredExercises; + Widget build(BuildContext context, WidgetRef ref) { + final exercises = ref.watch(exerciseProvider); return Scaffold( appBar: EmptyAppBar(AppLocalizations.of(context).exercises), @@ -27,15 +23,21 @@ class _ExercisesScreenState extends State { children: [ const FilterRow(), Expanded( - child: exercisesList.isEmpty - ? const Center( - child: SizedBox( - height: 30, - width: 30, - child: CircularProgressIndicator(), - ), - ) - : _ExercisesList(exerciseList: exercisesList), + child: exercises.when( + data: (List exercisesList) { + return exercisesList.isEmpty + ? const Center( + child: SizedBox( + height: 30, + width: 30, + child: CircularProgressIndicator(), + ), + ) + : _ExercisesList(exerciseList: exercisesList); + }, + loading: () => const BoxedProgressIndicator(), + error: (err, st) => Center(child: Text('Error: $err')), + ), ), ], ), diff --git a/lib/widgets/core/app_bar.dart b/lib/widgets/core/app_bar.dart index 1d78fb14..f4699de2 100644 --- a/lib/widgets/core/app_bar.dart +++ b/lib/widgets/core/app_bar.dart @@ -61,7 +61,7 @@ Widget _getStatusIcon(ps.SyncStatus status) { } else if (status.downloading) { return _makeIcon('Downloading', Icons.cloud_download_outlined); } else { - return _makeIcon('Connected', Icons.cloud_queue); + return _makeIcon('Connected', Icons.cloud_done_outlined); } }