diff --git a/lib/application/use_cases.dart b/lib/application/use_cases.dart index f703c33..1edae8a 100644 --- a/lib/application/use_cases.dart +++ b/lib/application/use_cases.dart @@ -592,6 +592,10 @@ final class ShareUseCases { exerciseStepsSnapshot: _exerciseStepsFromSnapshot( map['exerciseStepsSnapshot'], ), + autoStartNextTimedStepSnapshot: + map['autoStartNextTimedStepSnapshot'] as bool? ?? true, + autoStartNextTimedStepOverride: + map['autoStartNextTimedStepOverride'] as bool?, exerciseArchivedSnapshot: map['exerciseArchivedSnapshot'] == true, availableTimeSnapshot: map['availableTimeSnapshot'] == true, availableRepsSnapshot: map['availableRepsSnapshot'] == true, @@ -733,6 +737,8 @@ final class ShareUseCases { targetRepsOverride: map['targetRepsOverride'] as int?, targetScoreOverride: (map['targetScoreOverride'] as num?)?.toDouble(), targetScoreTimeMsOverride: map['targetScoreTimeMsOverride'] as int?, + autoStartNextTimedStepOverride: + map['autoStartNextTimedStepOverride'] as bool?, ), ); } @@ -772,6 +778,7 @@ final class ExerciseUseCases { int? defaultTargetReps, double? defaultTargetScore, int? defaultTargetScoreTimeMs, + bool autoStartNextTimedStep = true, List steps = const [], }) async { _validateExerciseSteps(steps); @@ -803,6 +810,7 @@ final class ExerciseUseCases { defaultTargetReps: defaultTargetReps, defaultTargetScore: defaultTargetScore, defaultTargetScoreTimeMs: defaultTargetScoreTimeMs, + autoStartNextTimedStep: autoStartNextTimedStep, steps: steps, ); await repository.save(exercise); @@ -835,6 +843,7 @@ final class ExerciseUseCases { Object? defaultTargetReps = _useCaseUnchanged, Object? defaultTargetScore = _useCaseUnchanged, Object? defaultTargetScoreTimeMs = _useCaseUnchanged, + bool? autoStartNextTimedStep, Object? steps = _useCaseUnchanged, }) async { final exercise = await repository.findById(id); @@ -895,6 +904,7 @@ final class ExerciseUseCases { defaultTargetReps: resolvedDefaultTargetReps, defaultTargetScore: resolvedDefaultTargetScore, defaultTargetScoreTimeMs: resolvedDefaultTargetScoreTimeMs, + autoStartNextTimedStep: autoStartNextTimedStep, steps: resolvedSteps, ); await repository.save(updated); @@ -1204,6 +1214,10 @@ final class ProgramUseCases { exerciseImageMediaIdsSnapshot: input.exerciseImageMediaIdsSnapshot, exerciseVideoMediaIdSnapshot: input.exerciseVideoMediaIdSnapshot, exerciseStepsSnapshot: input.exerciseStepsSnapshot, + autoStartNextTimedStepSnapshot: + input.autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride: + input.autoStartNextTimedStepOverride, exerciseArchivedSnapshot: input.exerciseArchivedSnapshot, availableTimeSnapshot: input.availableTimeSnapshot, availableRepsSnapshot: input.availableRepsSnapshot, @@ -1322,6 +1336,8 @@ final class ProgramExerciseConfig { this.exerciseImageMediaIdsSnapshot = const [], this.exerciseVideoMediaIdSnapshot, this.exerciseStepsSnapshot = const [], + this.autoStartNextTimedStepSnapshot = true, + this.autoStartNextTimedStepOverride, this.exerciseArchivedSnapshot = false, required this.availableTimeSnapshot, required this.availableRepsSnapshot, @@ -1346,6 +1362,8 @@ final class ProgramExerciseConfig { final List exerciseImageMediaIdsSnapshot; final String? exerciseVideoMediaIdSnapshot; final List exerciseStepsSnapshot; + final bool autoStartNextTimedStepSnapshot; + final bool? autoStartNextTimedStepOverride; final bool exerciseArchivedSnapshot; final bool availableTimeSnapshot; final bool availableRepsSnapshot; @@ -1460,6 +1478,8 @@ final class WorkoutTemplateUseCases { targetRepsOverride: input.targetRepsOverride, targetScoreOverride: input.targetScoreOverride, targetScoreTimeMsOverride: input.targetScoreTimeMsOverride, + autoStartNextTimedStepOverride: + input.autoStartNextTimedStepOverride, ), ); } @@ -1502,6 +1522,7 @@ final class WorkoutTemplateUseCases { int? targetRepsOverride, double? targetScoreOverride, int? targetScoreTimeMsOverride, + bool? autoStartNextTimedStepOverride, Set? attemptedMeasureOverride, }) async { if (attemptedMeasureOverride != null) { @@ -1519,6 +1540,7 @@ final class WorkoutTemplateUseCases { targetRepsOverride: targetRepsOverride, targetScoreOverride: targetScoreOverride, targetScoreTimeMsOverride: targetScoreTimeMsOverride, + autoStartNextTimedStepOverride: autoStartNextTimedStepOverride, ); await templateRepository.saveOverride(override); return override; @@ -1568,6 +1590,7 @@ final class WorkoutTemplateExerciseOverrideConfig { this.targetRepsOverride, this.targetScoreOverride, this.targetScoreTimeMsOverride, + this.autoStartNextTimedStepOverride, }); final EntityMetadata? existingMetadata; @@ -1578,6 +1601,7 @@ final class WorkoutTemplateExerciseOverrideConfig { final int? targetRepsOverride; final double? targetScoreOverride; final int? targetScoreTimeMsOverride; + final bool? autoStartNextTimedStepOverride; } final class ActiveWorkoutSessionUseCases { @@ -1635,6 +1659,8 @@ final class ActiveWorkoutSessionUseCases { 'targetRepsOverride': override.targetRepsOverride, 'targetScoreOverride': override.targetScoreOverride, 'targetScoreTimeMsOverride': override.targetScoreTimeMsOverride, + 'autoStartNextTimedStepOverride': + override.autoStartNextTimedStepOverride, }, ) .toList(), @@ -3185,6 +3211,8 @@ Map _workoutTemplateSharePayload(WorkoutTemplate template) => { 'targetRepsOverride': override.targetRepsOverride, 'targetScoreOverride': override.targetScoreOverride, 'targetScoreTimeMsOverride': override.targetScoreTimeMsOverride, + 'autoStartNextTimedStepOverride': + override.autoStartNextTimedStepOverride, }, ) .toList(), diff --git a/lib/domain/entities.dart b/lib/domain/entities.dart index e4045a7..088b9ef 100644 --- a/lib/domain/entities.dart +++ b/lib/domain/entities.dart @@ -318,6 +318,7 @@ final class Exercise { this.defaultTargetReps, this.defaultTargetScore, this.defaultTargetScoreTimeMs, + this.autoStartNextTimedStep = true, List steps = const [], this.archivedAt, }) : name = _nonBlank(name, 'Exercise name'), @@ -375,6 +376,7 @@ final class Exercise { final int? defaultTargetReps; final double? defaultTargetScore; final int? defaultTargetScoreTimeMs; + final bool autoStartNextTimedStep; final List steps; final DateTime? archivedAt; @@ -409,6 +411,7 @@ final class Exercise { Object? defaultTargetReps = _unchanged, Object? defaultTargetScore = _unchanged, Object? defaultTargetScoreTimeMs = _unchanged, + bool? autoStartNextTimedStep, Object? steps = _unchanged, Object? archivedAt = _unchanged, }) { @@ -456,6 +459,8 @@ final class Exercise { defaultTargetScoreTimeMs: defaultTargetScoreTimeMs == _unchanged ? this.defaultTargetScoreTimeMs : defaultTargetScoreTimeMs as int?, + autoStartNextTimedStep: + autoStartNextTimedStep ?? this.autoStartNextTimedStep, steps: steps == _unchanged ? this.steps : steps as List, archivedAt: archivedAt == _unchanged ? this.archivedAt @@ -562,6 +567,8 @@ final class ProgramExercise { List exerciseImageMediaIdsSnapshot = const [], this.exerciseVideoMediaIdSnapshot, List exerciseStepsSnapshot = const [], + this.autoStartNextTimedStepSnapshot = true, + this.autoStartNextTimedStepOverride, this.exerciseArchivedSnapshot = false, required this.availableTimeSnapshot, required this.availableRepsSnapshot, @@ -628,6 +635,8 @@ final class ProgramExercise { final List exerciseImageMediaIdsSnapshot; final String? exerciseVideoMediaIdSnapshot; final List exerciseStepsSnapshot; + final bool autoStartNextTimedStepSnapshot; + final bool? autoStartNextTimedStepOverride; final bool exerciseArchivedSnapshot; final bool availableTimeSnapshot; final bool availableRepsSnapshot; @@ -675,6 +684,7 @@ final class ProgramExercise { exerciseImageMediaIdsSnapshot: exercise.imageMediaIds, exerciseVideoMediaIdSnapshot: exercise.videoMediaId, exerciseStepsSnapshot: exercise.steps, + autoStartNextTimedStepSnapshot: exercise.autoStartNextTimedStep, exerciseArchivedSnapshot: exercise.archivedAt != null, availableTimeSnapshot: exercise.hasTimeMeasure, availableRepsSnapshot: exercise.hasRepsMeasure, @@ -707,6 +717,8 @@ final class ProgramExercise { 'exerciseStepsSnapshot': exerciseStepsSnapshot .map((step) => step.toSnapshotJson()) .toList(), + 'autoStartNextTimedStepSnapshot': autoStartNextTimedStepSnapshot, + 'autoStartNextTimedStepOverride': autoStartNextTimedStepOverride, 'exerciseArchivedSnapshot': exerciseArchivedSnapshot, 'availableTimeSnapshot': availableTimeSnapshot, 'availableRepsSnapshot': availableRepsSnapshot, @@ -802,6 +814,7 @@ final class WorkoutTemplateExerciseOverride { this.targetRepsOverride, this.targetScoreOverride, this.targetScoreTimeMsOverride, + this.autoStartNextTimedStepOverride, }) : snapshotProgramExerciseId = _nonBlank( snapshotProgramExerciseId, 'Snapshot program exercise id', @@ -835,6 +848,7 @@ final class WorkoutTemplateExerciseOverride { final int? targetRepsOverride; final double? targetScoreOverride; final int? targetScoreTimeMsOverride; + final bool? autoStartNextTimedStepOverride; } final class ActiveWorkoutSession { diff --git a/lib/infrastructure/local/app_database.dart b/lib/infrastructure/local/app_database.dart index 05c47a1..9608606 100644 --- a/lib/infrastructure/local/app_database.dart +++ b/lib/infrastructure/local/app_database.dart @@ -46,7 +46,7 @@ final class AppDatabase extends _$AppDatabase { } @override - int get schemaVersion => 13; + int get schemaVersion => 14; @override MigrationStrategy get migration { @@ -100,6 +100,9 @@ final class AppDatabase extends _$AppDatabase { if (from < 13) { await _migrateToSchema13(); } + if (from < 14) { + await _migrateToSchema14(); + } await _createIndexes(); }, beforeOpen: (details) async { @@ -469,4 +472,26 @@ FROM exercises await customStatement('ALTER TABLE exercises_new RENAME TO exercises'); await customStatement('PRAGMA foreign_keys = ON'); } + + Future _migrateToSchema14() async { + await customStatement( + 'ALTER TABLE exercises ADD COLUMN auto_start_next_timed_step ' + 'INTEGER NOT NULL DEFAULT 1 CHECK (auto_start_next_timed_step IN (0, 1))', + ); + await customStatement( + 'ALTER TABLE program_exercises ADD COLUMN ' + 'auto_start_next_timed_step_snapshot INTEGER NOT NULL DEFAULT 1 ' + 'CHECK (auto_start_next_timed_step_snapshot IN (0, 1))', + ); + await customStatement( + 'ALTER TABLE program_exercises ADD COLUMN ' + 'auto_start_next_timed_step_override INTEGER ' + 'CHECK (auto_start_next_timed_step_override IN (0, 1))', + ); + await customStatement( + 'ALTER TABLE workout_template_exercise_overrides ADD COLUMN ' + 'auto_start_next_timed_step_override INTEGER ' + 'CHECK (auto_start_next_timed_step_override IN (0, 1))', + ); + } } diff --git a/lib/infrastructure/local/app_database.g.dart b/lib/infrastructure/local/app_database.g.dart index a5d64b7..e621f7a 100644 --- a/lib/infrastructure/local/app_database.g.dart +++ b/lib/infrastructure/local/app_database.g.dart @@ -11542,6 +11542,21 @@ class $ExercisesTable extends Exercises type: DriftSqlType.int, requiredDuringInsert: false, ); + static const VerificationMeta _autoStartNextTimedStepMeta = + const VerificationMeta('autoStartNextTimedStep'); + @override + late final GeneratedColumn autoStartNextTimedStep = + GeneratedColumn( + 'auto_start_next_timed_step', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("auto_start_next_timed_step" IN (0, 1))', + ), + defaultValue: const Constant(true), + ); static const VerificationMeta _archivedAtMeta = const VerificationMeta( 'archivedAt', ); @@ -11580,6 +11595,7 @@ class $ExercisesTable extends Exercises defaultTargetReps, defaultTargetScore, defaultTargetScoreTimeMs, + autoStartNextTimedStep, archivedAt, ]; @override @@ -11812,6 +11828,15 @@ class $ExercisesTable extends Exercises ), ); } + if (data.containsKey('auto_start_next_timed_step')) { + context.handle( + _autoStartNextTimedStepMeta, + autoStartNextTimedStep.isAcceptableOrUnknown( + data['auto_start_next_timed_step']!, + _autoStartNextTimedStepMeta, + ), + ); + } if (data.containsKey('archived_at')) { context.handle( _archivedAtMeta, @@ -11927,6 +11952,10 @@ class $ExercisesTable extends Exercises DriftSqlType.int, data['${effectivePrefix}default_target_score_time_ms'], ), + autoStartNextTimedStep: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}auto_start_next_timed_step'], + )!, archivedAt: attachedDatabase.typeMapping.read( DriftSqlType.dateTime, data['${effectivePrefix}archived_at'], @@ -11966,6 +11995,7 @@ class Exercise extends DataClass implements Insertable { final int? defaultTargetReps; final double? defaultTargetScore; final int? defaultTargetScoreTimeMs; + final bool autoStartNextTimedStep; final DateTime? archivedAt; const Exercise({ required this.id, @@ -11993,6 +12023,7 @@ class Exercise extends DataClass implements Insertable { this.defaultTargetReps, this.defaultTargetScore, this.defaultTargetScoreTimeMs, + required this.autoStartNextTimedStep, this.archivedAt, }); @override @@ -12053,6 +12084,7 @@ class Exercise extends DataClass implements Insertable { defaultTargetScoreTimeMs, ); } + map['auto_start_next_timed_step'] = Variable(autoStartNextTimedStep); if (!nullToAbsent || archivedAt != null) { map['archived_at'] = Variable(archivedAt); } @@ -12112,6 +12144,7 @@ class Exercise extends DataClass implements Insertable { defaultTargetScoreTimeMs: defaultTargetScoreTimeMs == null && nullToAbsent ? const Value.absent() : Value(defaultTargetScoreTimeMs), + autoStartNextTimedStep: Value(autoStartNextTimedStep), archivedAt: archivedAt == null && nullToAbsent ? const Value.absent() : Value(archivedAt), @@ -12157,6 +12190,9 @@ class Exercise extends DataClass implements Insertable { defaultTargetScoreTimeMs: serializer.fromJson( json['defaultTargetScoreTimeMs'], ), + autoStartNextTimedStep: serializer.fromJson( + json['autoStartNextTimedStep'], + ), archivedAt: serializer.fromJson(json['archivedAt']), ); } @@ -12193,6 +12229,7 @@ class Exercise extends DataClass implements Insertable { 'defaultTargetScoreTimeMs': serializer.toJson( defaultTargetScoreTimeMs, ), + 'autoStartNextTimedStep': serializer.toJson(autoStartNextTimedStep), 'archivedAt': serializer.toJson(archivedAt), }; } @@ -12223,6 +12260,7 @@ class Exercise extends DataClass implements Insertable { Value defaultTargetReps = const Value.absent(), Value defaultTargetScore = const Value.absent(), Value defaultTargetScoreTimeMs = const Value.absent(), + bool? autoStartNextTimedStep, Value archivedAt = const Value.absent(), }) => Exercise( id: id ?? this.id, @@ -12262,6 +12300,8 @@ class Exercise extends DataClass implements Insertable { defaultTargetScoreTimeMs: defaultTargetScoreTimeMs.present ? defaultTargetScoreTimeMs.value : this.defaultTargetScoreTimeMs, + autoStartNextTimedStep: + autoStartNextTimedStep ?? this.autoStartNextTimedStep, archivedAt: archivedAt.present ? archivedAt.value : this.archivedAt, ); Exercise copyWithCompanion(ExercisesCompanion data) { @@ -12327,6 +12367,9 @@ class Exercise extends DataClass implements Insertable { defaultTargetScoreTimeMs: data.defaultTargetScoreTimeMs.present ? data.defaultTargetScoreTimeMs.value : this.defaultTargetScoreTimeMs, + autoStartNextTimedStep: data.autoStartNextTimedStep.present + ? data.autoStartNextTimedStep.value + : this.autoStartNextTimedStep, archivedAt: data.archivedAt.present ? data.archivedAt.value : this.archivedAt, @@ -12361,6 +12404,7 @@ class Exercise extends DataClass implements Insertable { ..write('defaultTargetReps: $defaultTargetReps, ') ..write('defaultTargetScore: $defaultTargetScore, ') ..write('defaultTargetScoreTimeMs: $defaultTargetScoreTimeMs, ') + ..write('autoStartNextTimedStep: $autoStartNextTimedStep, ') ..write('archivedAt: $archivedAt') ..write(')')) .toString(); @@ -12393,6 +12437,7 @@ class Exercise extends DataClass implements Insertable { defaultTargetReps, defaultTargetScore, defaultTargetScoreTimeMs, + autoStartNextTimedStep, archivedAt, ]); @override @@ -12424,6 +12469,7 @@ class Exercise extends DataClass implements Insertable { other.defaultTargetReps == this.defaultTargetReps && other.defaultTargetScore == this.defaultTargetScore && other.defaultTargetScoreTimeMs == this.defaultTargetScoreTimeMs && + other.autoStartNextTimedStep == this.autoStartNextTimedStep && other.archivedAt == this.archivedAt); } @@ -12453,6 +12499,7 @@ class ExercisesCompanion extends UpdateCompanion { final Value defaultTargetReps; final Value defaultTargetScore; final Value defaultTargetScoreTimeMs; + final Value autoStartNextTimedStep; final Value archivedAt; final Value rowid; const ExercisesCompanion({ @@ -12481,6 +12528,7 @@ class ExercisesCompanion extends UpdateCompanion { this.defaultTargetReps = const Value.absent(), this.defaultTargetScore = const Value.absent(), this.defaultTargetScoreTimeMs = const Value.absent(), + this.autoStartNextTimedStep = const Value.absent(), this.archivedAt = const Value.absent(), this.rowid = const Value.absent(), }); @@ -12510,6 +12558,7 @@ class ExercisesCompanion extends UpdateCompanion { this.defaultTargetReps = const Value.absent(), this.defaultTargetScore = const Value.absent(), this.defaultTargetScoreTimeMs = const Value.absent(), + this.autoStartNextTimedStep = const Value.absent(), this.archivedAt = const Value.absent(), this.rowid = const Value.absent(), }) : id = Value(id), @@ -12548,6 +12597,7 @@ class ExercisesCompanion extends UpdateCompanion { Expression? defaultTargetReps, Expression? defaultTargetScore, Expression? defaultTargetScoreTimeMs, + Expression? autoStartNextTimedStep, Expression? archivedAt, Expression? rowid, }) { @@ -12581,6 +12631,8 @@ class ExercisesCompanion extends UpdateCompanion { 'default_target_score': defaultTargetScore, if (defaultTargetScoreTimeMs != null) 'default_target_score_time_ms': defaultTargetScoreTimeMs, + if (autoStartNextTimedStep != null) + 'auto_start_next_timed_step': autoStartNextTimedStep, if (archivedAt != null) 'archived_at': archivedAt, if (rowid != null) 'rowid': rowid, }); @@ -12612,6 +12664,7 @@ class ExercisesCompanion extends UpdateCompanion { Value? defaultTargetReps, Value? defaultTargetScore, Value? defaultTargetScoreTimeMs, + Value? autoStartNextTimedStep, Value? archivedAt, Value? rowid, }) { @@ -12643,6 +12696,8 @@ class ExercisesCompanion extends UpdateCompanion { defaultTargetScore: defaultTargetScore ?? this.defaultTargetScore, defaultTargetScoreTimeMs: defaultTargetScoreTimeMs ?? this.defaultTargetScoreTimeMs, + autoStartNextTimedStep: + autoStartNextTimedStep ?? this.autoStartNextTimedStep, archivedAt: archivedAt ?? this.archivedAt, rowid: rowid ?? this.rowid, ); @@ -12732,6 +12787,11 @@ class ExercisesCompanion extends UpdateCompanion { defaultTargetScoreTimeMs.value, ); } + if (autoStartNextTimedStep.present) { + map['auto_start_next_timed_step'] = Variable( + autoStartNextTimedStep.value, + ); + } if (archivedAt.present) { map['archived_at'] = Variable(archivedAt.value); } @@ -12769,6 +12829,7 @@ class ExercisesCompanion extends UpdateCompanion { ..write('defaultTargetReps: $defaultTargetReps, ') ..write('defaultTargetScore: $defaultTargetScore, ') ..write('defaultTargetScoreTimeMs: $defaultTargetScoreTimeMs, ') + ..write('autoStartNextTimedStep: $autoStartNextTimedStep, ') ..write('archivedAt: $archivedAt, ') ..write('rowid: $rowid') ..write(')')) @@ -17138,6 +17199,35 @@ class $ProgramExercisesTable extends ProgramExercises type: DriftSqlType.string, requiredDuringInsert: false, ); + static const VerificationMeta _autoStartNextTimedStepSnapshotMeta = + const VerificationMeta('autoStartNextTimedStepSnapshot'); + @override + late final GeneratedColumn autoStartNextTimedStepSnapshot = + GeneratedColumn( + 'auto_start_next_timed_step_snapshot', + aliasedName, + false, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("auto_start_next_timed_step_snapshot" IN (0, 1))', + ), + defaultValue: const Constant(true), + ); + static const VerificationMeta _autoStartNextTimedStepOverrideMeta = + const VerificationMeta('autoStartNextTimedStepOverride'); + @override + late final GeneratedColumn autoStartNextTimedStepOverride = + GeneratedColumn( + 'auto_start_next_timed_step_override', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("auto_start_next_timed_step_override" IN (0, 1))', + ), + ); static const VerificationMeta _exerciseVideoMediaIdSnapshotMeta = const VerificationMeta('exerciseVideoMediaIdSnapshot'); @override @@ -17372,6 +17462,8 @@ class $ProgramExercisesTable extends ProgramExercises exerciseImageMediaIdSnapshot, exerciseImageMediaIdsSnapshotJson, exerciseStepsSnapshotJson, + autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride, exerciseVideoMediaIdSnapshot, exerciseArchivedSnapshot, availableTimeSnapshot, @@ -17567,6 +17659,24 @@ class $ProgramExercisesTable extends ProgramExercises ), ); } + if (data.containsKey('auto_start_next_timed_step_snapshot')) { + context.handle( + _autoStartNextTimedStepSnapshotMeta, + autoStartNextTimedStepSnapshot.isAcceptableOrUnknown( + data['auto_start_next_timed_step_snapshot']!, + _autoStartNextTimedStepSnapshotMeta, + ), + ); + } + if (data.containsKey('auto_start_next_timed_step_override')) { + context.handle( + _autoStartNextTimedStepOverrideMeta, + autoStartNextTimedStepOverride.isAcceptableOrUnknown( + data['auto_start_next_timed_step_override']!, + _autoStartNextTimedStepOverrideMeta, + ), + ); + } if (data.containsKey('exercise_video_media_id_snapshot')) { context.handle( _exerciseVideoMediaIdSnapshotMeta, @@ -17813,6 +17923,14 @@ class $ProgramExercisesTable extends ProgramExercises DriftSqlType.string, data['${effectivePrefix}exercise_steps_snapshot_json'], ), + autoStartNextTimedStepSnapshot: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}auto_start_next_timed_step_snapshot'], + )!, + autoStartNextTimedStepOverride: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}auto_start_next_timed_step_override'], + ), exerciseVideoMediaIdSnapshot: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}exercise_video_media_id_snapshot'], @@ -17910,6 +18028,8 @@ class ProgramExercise extends DataClass implements Insertable { final String? exerciseImageMediaIdSnapshot; final String? exerciseImageMediaIdsSnapshotJson; final String? exerciseStepsSnapshotJson; + final bool autoStartNextTimedStepSnapshot; + final bool? autoStartNextTimedStepOverride; final String? exerciseVideoMediaIdSnapshot; final bool exerciseArchivedSnapshot; final bool availableTimeSnapshot; @@ -17947,6 +18067,8 @@ class ProgramExercise extends DataClass implements Insertable { this.exerciseImageMediaIdSnapshot, this.exerciseImageMediaIdsSnapshotJson, this.exerciseStepsSnapshotJson, + required this.autoStartNextTimedStepSnapshot, + this.autoStartNextTimedStepOverride, this.exerciseVideoMediaIdSnapshot, required this.exerciseArchivedSnapshot, required this.availableTimeSnapshot, @@ -18013,6 +18135,14 @@ class ProgramExercise extends DataClass implements Insertable { exerciseStepsSnapshotJson, ); } + map['auto_start_next_timed_step_snapshot'] = Variable( + autoStartNextTimedStepSnapshot, + ); + if (!nullToAbsent || autoStartNextTimedStepOverride != null) { + map['auto_start_next_timed_step_override'] = Variable( + autoStartNextTimedStepOverride, + ); + } if (!nullToAbsent || exerciseVideoMediaIdSnapshot != null) { map['exercise_video_media_id_snapshot'] = Variable( exerciseVideoMediaIdSnapshot, @@ -18096,6 +18226,11 @@ class ProgramExercise extends DataClass implements Insertable { exerciseStepsSnapshotJson == null && nullToAbsent ? const Value.absent() : Value(exerciseStepsSnapshotJson), + autoStartNextTimedStepSnapshot: Value(autoStartNextTimedStepSnapshot), + autoStartNextTimedStepOverride: + autoStartNextTimedStepOverride == null && nullToAbsent + ? const Value.absent() + : Value(autoStartNextTimedStepOverride), exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot == null && nullToAbsent ? const Value.absent() @@ -18170,6 +18305,12 @@ class ProgramExercise extends DataClass implements Insertable { exerciseStepsSnapshotJson: serializer.fromJson( json['exerciseStepsSnapshotJson'], ), + autoStartNextTimedStepSnapshot: serializer.fromJson( + json['autoStartNextTimedStepSnapshot'], + ), + autoStartNextTimedStepOverride: serializer.fromJson( + json['autoStartNextTimedStepOverride'], + ), exerciseVideoMediaIdSnapshot: serializer.fromJson( json['exerciseVideoMediaIdSnapshot'], ), @@ -18238,6 +18379,12 @@ class ProgramExercise extends DataClass implements Insertable { 'exerciseStepsSnapshotJson': serializer.toJson( exerciseStepsSnapshotJson, ), + 'autoStartNextTimedStepSnapshot': serializer.toJson( + autoStartNextTimedStepSnapshot, + ), + 'autoStartNextTimedStepOverride': serializer.toJson( + autoStartNextTimedStepOverride, + ), 'exerciseVideoMediaIdSnapshot': serializer.toJson( exerciseVideoMediaIdSnapshot, ), @@ -18284,6 +18431,8 @@ class ProgramExercise extends DataClass implements Insertable { Value exerciseImageMediaIdSnapshot = const Value.absent(), Value exerciseImageMediaIdsSnapshotJson = const Value.absent(), Value exerciseStepsSnapshotJson = const Value.absent(), + bool? autoStartNextTimedStepSnapshot, + Value autoStartNextTimedStepOverride = const Value.absent(), Value exerciseVideoMediaIdSnapshot = const Value.absent(), bool? exerciseArchivedSnapshot, bool? availableTimeSnapshot, @@ -18335,6 +18484,11 @@ class ProgramExercise extends DataClass implements Insertable { exerciseStepsSnapshotJson: exerciseStepsSnapshotJson.present ? exerciseStepsSnapshotJson.value : this.exerciseStepsSnapshotJson, + autoStartNextTimedStepSnapshot: + autoStartNextTimedStepSnapshot ?? this.autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride: autoStartNextTimedStepOverride.present + ? autoStartNextTimedStepOverride.value + : this.autoStartNextTimedStepOverride, exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot.present ? exerciseVideoMediaIdSnapshot.value : this.exerciseVideoMediaIdSnapshot, @@ -18414,6 +18568,14 @@ class ProgramExercise extends DataClass implements Insertable { exerciseStepsSnapshotJson: data.exerciseStepsSnapshotJson.present ? data.exerciseStepsSnapshotJson.value : this.exerciseStepsSnapshotJson, + autoStartNextTimedStepSnapshot: + data.autoStartNextTimedStepSnapshot.present + ? data.autoStartNextTimedStepSnapshot.value + : this.autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride: + data.autoStartNextTimedStepOverride.present + ? data.autoStartNextTimedStepOverride.value + : this.autoStartNextTimedStepOverride, exerciseVideoMediaIdSnapshot: data.exerciseVideoMediaIdSnapshot.present ? data.exerciseVideoMediaIdSnapshot.value : this.exerciseVideoMediaIdSnapshot, @@ -18492,6 +18654,12 @@ class ProgramExercise extends DataClass implements Insertable { 'exerciseImageMediaIdsSnapshotJson: $exerciseImageMediaIdsSnapshotJson, ', ) ..write('exerciseStepsSnapshotJson: $exerciseStepsSnapshotJson, ') + ..write( + 'autoStartNextTimedStepSnapshot: $autoStartNextTimedStepSnapshot, ', + ) + ..write( + 'autoStartNextTimedStepOverride: $autoStartNextTimedStepOverride, ', + ) ..write( 'exerciseVideoMediaIdSnapshot: $exerciseVideoMediaIdSnapshot, ', ) @@ -18536,6 +18704,8 @@ class ProgramExercise extends DataClass implements Insertable { exerciseImageMediaIdSnapshot, exerciseImageMediaIdsSnapshotJson, exerciseStepsSnapshotJson, + autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride, exerciseVideoMediaIdSnapshot, exerciseArchivedSnapshot, availableTimeSnapshot, @@ -18580,6 +18750,10 @@ class ProgramExercise extends DataClass implements Insertable { other.exerciseImageMediaIdsSnapshotJson == this.exerciseImageMediaIdsSnapshotJson && other.exerciseStepsSnapshotJson == this.exerciseStepsSnapshotJson && + other.autoStartNextTimedStepSnapshot == + this.autoStartNextTimedStepSnapshot && + other.autoStartNextTimedStepOverride == + this.autoStartNextTimedStepOverride && other.exerciseVideoMediaIdSnapshot == this.exerciseVideoMediaIdSnapshot && other.exerciseArchivedSnapshot == this.exerciseArchivedSnapshot && @@ -18620,6 +18794,8 @@ class ProgramExercisesCompanion extends UpdateCompanion { final Value exerciseImageMediaIdSnapshot; final Value exerciseImageMediaIdsSnapshotJson; final Value exerciseStepsSnapshotJson; + final Value autoStartNextTimedStepSnapshot; + final Value autoStartNextTimedStepOverride; final Value exerciseVideoMediaIdSnapshot; final Value exerciseArchivedSnapshot; final Value availableTimeSnapshot; @@ -18658,6 +18834,8 @@ class ProgramExercisesCompanion extends UpdateCompanion { this.exerciseImageMediaIdSnapshot = const Value.absent(), this.exerciseImageMediaIdsSnapshotJson = const Value.absent(), this.exerciseStepsSnapshotJson = const Value.absent(), + this.autoStartNextTimedStepSnapshot = const Value.absent(), + this.autoStartNextTimedStepOverride = const Value.absent(), this.exerciseVideoMediaIdSnapshot = const Value.absent(), this.exerciseArchivedSnapshot = const Value.absent(), this.availableTimeSnapshot = const Value.absent(), @@ -18697,6 +18875,8 @@ class ProgramExercisesCompanion extends UpdateCompanion { this.exerciseImageMediaIdSnapshot = const Value.absent(), this.exerciseImageMediaIdsSnapshotJson = const Value.absent(), this.exerciseStepsSnapshotJson = const Value.absent(), + this.autoStartNextTimedStepSnapshot = const Value.absent(), + this.autoStartNextTimedStepOverride = const Value.absent(), this.exerciseVideoMediaIdSnapshot = const Value.absent(), this.exerciseArchivedSnapshot = const Value.absent(), required bool availableTimeSnapshot, @@ -18751,6 +18931,8 @@ class ProgramExercisesCompanion extends UpdateCompanion { Expression? exerciseImageMediaIdSnapshot, Expression? exerciseImageMediaIdsSnapshotJson, Expression? exerciseStepsSnapshotJson, + Expression? autoStartNextTimedStepSnapshot, + Expression? autoStartNextTimedStepOverride, Expression? exerciseVideoMediaIdSnapshot, Expression? exerciseArchivedSnapshot, Expression? availableTimeSnapshot, @@ -18797,6 +18979,10 @@ class ProgramExercisesCompanion extends UpdateCompanion { exerciseImageMediaIdsSnapshotJson, if (exerciseStepsSnapshotJson != null) 'exercise_steps_snapshot_json': exerciseStepsSnapshotJson, + if (autoStartNextTimedStepSnapshot != null) + 'auto_start_next_timed_step_snapshot': autoStartNextTimedStepSnapshot, + if (autoStartNextTimedStepOverride != null) + 'auto_start_next_timed_step_override': autoStartNextTimedStepOverride, if (exerciseVideoMediaIdSnapshot != null) 'exercise_video_media_id_snapshot': exerciseVideoMediaIdSnapshot, if (exerciseArchivedSnapshot != null) @@ -18846,6 +19032,8 @@ class ProgramExercisesCompanion extends UpdateCompanion { Value? exerciseImageMediaIdSnapshot, Value? exerciseImageMediaIdsSnapshotJson, Value? exerciseStepsSnapshotJson, + Value? autoStartNextTimedStepSnapshot, + Value? autoStartNextTimedStepOverride, Value? exerciseVideoMediaIdSnapshot, Value? exerciseArchivedSnapshot, Value? availableTimeSnapshot, @@ -18890,6 +19078,10 @@ class ProgramExercisesCompanion extends UpdateCompanion { this.exerciseImageMediaIdsSnapshotJson, exerciseStepsSnapshotJson: exerciseStepsSnapshotJson ?? this.exerciseStepsSnapshotJson, + autoStartNextTimedStepSnapshot: + autoStartNextTimedStepSnapshot ?? this.autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride: + autoStartNextTimedStepOverride ?? this.autoStartNextTimedStepOverride, exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot ?? this.exerciseVideoMediaIdSnapshot, exerciseArchivedSnapshot: @@ -18989,6 +19181,16 @@ class ProgramExercisesCompanion extends UpdateCompanion { exerciseStepsSnapshotJson.value, ); } + if (autoStartNextTimedStepSnapshot.present) { + map['auto_start_next_timed_step_snapshot'] = Variable( + autoStartNextTimedStepSnapshot.value, + ); + } + if (autoStartNextTimedStepOverride.present) { + map['auto_start_next_timed_step_override'] = Variable( + autoStartNextTimedStepOverride.value, + ); + } if (exerciseVideoMediaIdSnapshot.present) { map['exercise_video_media_id_snapshot'] = Variable( exerciseVideoMediaIdSnapshot.value, @@ -19084,6 +19286,12 @@ class ProgramExercisesCompanion extends UpdateCompanion { 'exerciseImageMediaIdsSnapshotJson: $exerciseImageMediaIdsSnapshotJson, ', ) ..write('exerciseStepsSnapshotJson: $exerciseStepsSnapshotJson, ') + ..write( + 'autoStartNextTimedStepSnapshot: $autoStartNextTimedStepSnapshot, ', + ) + ..write( + 'autoStartNextTimedStepOverride: $autoStartNextTimedStepOverride, ', + ) ..write( 'exerciseVideoMediaIdSnapshot: $exerciseVideoMediaIdSnapshot, ', ) @@ -27197,6 +27405,20 @@ class $WorkoutTemplateExerciseOverridesTable type: DriftSqlType.int, requiredDuringInsert: false, ); + static const VerificationMeta _autoStartNextTimedStepOverrideMeta = + const VerificationMeta('autoStartNextTimedStepOverride'); + @override + late final GeneratedColumn autoStartNextTimedStepOverride = + GeneratedColumn( + 'auto_start_next_timed_step_override', + aliasedName, + true, + type: DriftSqlType.bool, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'CHECK ("auto_start_next_timed_step_override" IN (0, 1))', + ), + ); @override List get $columns => [ id, @@ -27217,6 +27439,7 @@ class $WorkoutTemplateExerciseOverridesTable targetRepsOverride, targetScoreOverride, targetScoreTimeMsOverride, + autoStartNextTimedStepOverride, ]; @override String get aliasedName => _alias ?? actualTableName; @@ -27390,6 +27613,15 @@ class $WorkoutTemplateExerciseOverridesTable ), ); } + if (data.containsKey('auto_start_next_timed_step_override')) { + context.handle( + _autoStartNextTimedStepOverrideMeta, + autoStartNextTimedStepOverride.isAcceptableOrUnknown( + data['auto_start_next_timed_step_override']!, + _autoStartNextTimedStepOverrideMeta, + ), + ); + } return context; } @@ -27474,6 +27706,10 @@ class $WorkoutTemplateExerciseOverridesTable DriftSqlType.int, data['${effectivePrefix}target_score_time_ms_override'], ), + autoStartNextTimedStepOverride: attachedDatabase.typeMapping.read( + DriftSqlType.bool, + data['${effectivePrefix}auto_start_next_timed_step_override'], + ), ); } @@ -27503,6 +27739,7 @@ class WorkoutTemplateExerciseOverride extends DataClass final int? targetRepsOverride; final double? targetScoreOverride; final int? targetScoreTimeMsOverride; + final bool? autoStartNextTimedStepOverride; const WorkoutTemplateExerciseOverride({ required this.id, required this.createdAt, @@ -27522,6 +27759,7 @@ class WorkoutTemplateExerciseOverride extends DataClass this.targetRepsOverride, this.targetScoreOverride, this.targetScoreTimeMsOverride, + this.autoStartNextTimedStepOverride, }); @override Map toColumns(bool nullToAbsent) { @@ -27570,6 +27808,11 @@ class WorkoutTemplateExerciseOverride extends DataClass targetScoreTimeMsOverride, ); } + if (!nullToAbsent || autoStartNextTimedStepOverride != null) { + map['auto_start_next_timed_step_override'] = Variable( + autoStartNextTimedStepOverride, + ); + } return map; } @@ -27613,6 +27856,10 @@ class WorkoutTemplateExerciseOverride extends DataClass targetScoreTimeMsOverride == null && nullToAbsent ? const Value.absent() : Value(targetScoreTimeMsOverride), + autoStartNextTimedStepOverride: + autoStartNextTimedStepOverride == null && nullToAbsent + ? const Value.absent() + : Value(autoStartNextTimedStepOverride), ); } @@ -27652,6 +27899,9 @@ class WorkoutTemplateExerciseOverride extends DataClass targetScoreTimeMsOverride: serializer.fromJson( json['targetScoreTimeMsOverride'], ), + autoStartNextTimedStepOverride: serializer.fromJson( + json['autoStartNextTimedStepOverride'], + ), ); } @override @@ -27684,6 +27934,9 @@ class WorkoutTemplateExerciseOverride extends DataClass 'targetScoreTimeMsOverride': serializer.toJson( targetScoreTimeMsOverride, ), + 'autoStartNextTimedStepOverride': serializer.toJson( + autoStartNextTimedStepOverride, + ), }; } @@ -27706,6 +27959,7 @@ class WorkoutTemplateExerciseOverride extends DataClass Value targetRepsOverride = const Value.absent(), Value targetScoreOverride = const Value.absent(), Value targetScoreTimeMsOverride = const Value.absent(), + Value autoStartNextTimedStepOverride = const Value.absent(), }) => WorkoutTemplateExerciseOverride( id: id ?? this.id, createdAt: createdAt ?? this.createdAt, @@ -27741,6 +27995,9 @@ class WorkoutTemplateExerciseOverride extends DataClass targetScoreTimeMsOverride: targetScoreTimeMsOverride.present ? targetScoreTimeMsOverride.value : this.targetScoreTimeMsOverride, + autoStartNextTimedStepOverride: autoStartNextTimedStepOverride.present + ? autoStartNextTimedStepOverride.value + : this.autoStartNextTimedStepOverride, ); WorkoutTemplateExerciseOverride copyWithCompanion( WorkoutTemplateExerciseOverridesCompanion data, @@ -27790,6 +28047,10 @@ class WorkoutTemplateExerciseOverride extends DataClass targetScoreTimeMsOverride: data.targetScoreTimeMsOverride.present ? data.targetScoreTimeMsOverride.value : this.targetScoreTimeMsOverride, + autoStartNextTimedStepOverride: + data.autoStartNextTimedStepOverride.present + ? data.autoStartNextTimedStepOverride.value + : this.autoStartNextTimedStepOverride, ); } @@ -27813,7 +28074,10 @@ class WorkoutTemplateExerciseOverride extends DataClass ..write('targetTimeSecondsOverride: $targetTimeSecondsOverride, ') ..write('targetRepsOverride: $targetRepsOverride, ') ..write('targetScoreOverride: $targetScoreOverride, ') - ..write('targetScoreTimeMsOverride: $targetScoreTimeMsOverride') + ..write('targetScoreTimeMsOverride: $targetScoreTimeMsOverride, ') + ..write( + 'autoStartNextTimedStepOverride: $autoStartNextTimedStepOverride', + ) ..write(')')) .toString(); } @@ -27838,6 +28102,7 @@ class WorkoutTemplateExerciseOverride extends DataClass targetRepsOverride, targetScoreOverride, targetScoreTimeMsOverride, + autoStartNextTimedStepOverride, ); @override bool operator ==(Object other) => @@ -27860,7 +28125,9 @@ class WorkoutTemplateExerciseOverride extends DataClass other.targetTimeSecondsOverride == this.targetTimeSecondsOverride && other.targetRepsOverride == this.targetRepsOverride && other.targetScoreOverride == this.targetScoreOverride && - other.targetScoreTimeMsOverride == this.targetScoreTimeMsOverride); + other.targetScoreTimeMsOverride == this.targetScoreTimeMsOverride && + other.autoStartNextTimedStepOverride == + this.autoStartNextTimedStepOverride); } class WorkoutTemplateExerciseOverridesCompanion @@ -27883,6 +28150,7 @@ class WorkoutTemplateExerciseOverridesCompanion final Value targetRepsOverride; final Value targetScoreOverride; final Value targetScoreTimeMsOverride; + final Value autoStartNextTimedStepOverride; final Value rowid; const WorkoutTemplateExerciseOverridesCompanion({ this.id = const Value.absent(), @@ -27903,6 +28171,7 @@ class WorkoutTemplateExerciseOverridesCompanion this.targetRepsOverride = const Value.absent(), this.targetScoreOverride = const Value.absent(), this.targetScoreTimeMsOverride = const Value.absent(), + this.autoStartNextTimedStepOverride = const Value.absent(), this.rowid = const Value.absent(), }); WorkoutTemplateExerciseOverridesCompanion.insert({ @@ -27924,6 +28193,7 @@ class WorkoutTemplateExerciseOverridesCompanion this.targetRepsOverride = const Value.absent(), this.targetScoreOverride = const Value.absent(), this.targetScoreTimeMsOverride = const Value.absent(), + this.autoStartNextTimedStepOverride = const Value.absent(), this.rowid = const Value.absent(), }) : id = Value(id), createdAt = Value(createdAt), @@ -27952,6 +28222,7 @@ class WorkoutTemplateExerciseOverridesCompanion Expression? targetRepsOverride, Expression? targetScoreOverride, Expression? targetScoreTimeMsOverride, + Expression? autoStartNextTimedStepOverride, Expression? rowid, }) { return RawValuesInsertable({ @@ -27980,6 +28251,8 @@ class WorkoutTemplateExerciseOverridesCompanion 'target_score_override': targetScoreOverride, if (targetScoreTimeMsOverride != null) 'target_score_time_ms_override': targetScoreTimeMsOverride, + if (autoStartNextTimedStepOverride != null) + 'auto_start_next_timed_step_override': autoStartNextTimedStepOverride, if (rowid != null) 'rowid': rowid, }); } @@ -28003,6 +28276,7 @@ class WorkoutTemplateExerciseOverridesCompanion Value? targetRepsOverride, Value? targetScoreOverride, Value? targetScoreTimeMsOverride, + Value? autoStartNextTimedStepOverride, Value? rowid, }) { return WorkoutTemplateExerciseOverridesCompanion( @@ -28028,6 +28302,8 @@ class WorkoutTemplateExerciseOverridesCompanion targetScoreOverride: targetScoreOverride ?? this.targetScoreOverride, targetScoreTimeMsOverride: targetScoreTimeMsOverride ?? this.targetScoreTimeMsOverride, + autoStartNextTimedStepOverride: + autoStartNextTimedStepOverride ?? this.autoStartNextTimedStepOverride, rowid: rowid ?? this.rowid, ); } @@ -28101,6 +28377,11 @@ class WorkoutTemplateExerciseOverridesCompanion targetScoreTimeMsOverride.value, ); } + if (autoStartNextTimedStepOverride.present) { + map['auto_start_next_timed_step_override'] = Variable( + autoStartNextTimedStepOverride.value, + ); + } if (rowid.present) { map['rowid'] = Variable(rowid.value); } @@ -28128,6 +28409,9 @@ class WorkoutTemplateExerciseOverridesCompanion ..write('targetRepsOverride: $targetRepsOverride, ') ..write('targetScoreOverride: $targetScoreOverride, ') ..write('targetScoreTimeMsOverride: $targetScoreTimeMsOverride, ') + ..write( + 'autoStartNextTimedStepOverride: $autoStartNextTimedStepOverride, ', + ) ..write('rowid: $rowid') ..write(')')) .toString(); @@ -35424,6 +35708,7 @@ typedef $$ExercisesTableCreateCompanionBuilder = Value defaultTargetReps, Value defaultTargetScore, Value defaultTargetScoreTimeMs, + Value autoStartNextTimedStep, Value archivedAt, Value rowid, }); @@ -35454,6 +35739,7 @@ typedef $$ExercisesTableUpdateCompanionBuilder = Value defaultTargetReps, Value defaultTargetScore, Value defaultTargetScoreTimeMs, + Value autoStartNextTimedStep, Value archivedAt, Value rowid, }); @@ -35677,6 +35963,11 @@ class $$ExercisesTableFilterComposer builder: (column) => ColumnFilters(column), ); + ColumnFilters get autoStartNextTimedStep => $composableBuilder( + column: $table.autoStartNextTimedStep, + builder: (column) => ColumnFilters(column), + ); + ColumnFilters get archivedAt => $composableBuilder( column: $table.archivedAt, builder: (column) => ColumnFilters(column), @@ -35928,6 +36219,11 @@ class $$ExercisesTableOrderingComposer builder: (column) => ColumnOrderings(column), ); + ColumnOrderings get autoStartNextTimedStep => $composableBuilder( + column: $table.autoStartNextTimedStep, + builder: (column) => ColumnOrderings(column), + ); + ColumnOrderings get archivedAt => $composableBuilder( column: $table.archivedAt, builder: (column) => ColumnOrderings(column), @@ -36090,6 +36386,11 @@ class $$ExercisesTableAnnotationComposer builder: (column) => column, ); + GeneratedColumn get autoStartNextTimedStep => $composableBuilder( + column: $table.autoStartNextTimedStep, + builder: (column) => column, + ); + GeneratedColumn get archivedAt => $composableBuilder( column: $table.archivedAt, builder: (column) => column, @@ -36276,6 +36577,7 @@ class $$ExercisesTableTableManager Value defaultTargetReps = const Value.absent(), Value defaultTargetScore = const Value.absent(), Value defaultTargetScoreTimeMs = const Value.absent(), + Value autoStartNextTimedStep = const Value.absent(), Value archivedAt = const Value.absent(), Value rowid = const Value.absent(), }) => ExercisesCompanion( @@ -36304,6 +36606,7 @@ class $$ExercisesTableTableManager defaultTargetReps: defaultTargetReps, defaultTargetScore: defaultTargetScore, defaultTargetScoreTimeMs: defaultTargetScoreTimeMs, + autoStartNextTimedStep: autoStartNextTimedStep, archivedAt: archivedAt, rowid: rowid, ), @@ -36334,6 +36637,7 @@ class $$ExercisesTableTableManager Value defaultTargetReps = const Value.absent(), Value defaultTargetScore = const Value.absent(), Value defaultTargetScoreTimeMs = const Value.absent(), + Value autoStartNextTimedStep = const Value.absent(), Value archivedAt = const Value.absent(), Value rowid = const Value.absent(), }) => ExercisesCompanion.insert( @@ -36362,6 +36666,7 @@ class $$ExercisesTableTableManager defaultTargetReps: defaultTargetReps, defaultTargetScore: defaultTargetScore, defaultTargetScoreTimeMs: defaultTargetScoreTimeMs, + autoStartNextTimedStep: autoStartNextTimedStep, archivedAt: archivedAt, rowid: rowid, ), @@ -39001,6 +39306,8 @@ typedef $$ProgramExercisesTableCreateCompanionBuilder = Value exerciseImageMediaIdSnapshot, Value exerciseImageMediaIdsSnapshotJson, Value exerciseStepsSnapshotJson, + Value autoStartNextTimedStepSnapshot, + Value autoStartNextTimedStepOverride, Value exerciseVideoMediaIdSnapshot, Value exerciseArchivedSnapshot, required bool availableTimeSnapshot, @@ -39041,6 +39348,8 @@ typedef $$ProgramExercisesTableUpdateCompanionBuilder = Value exerciseImageMediaIdSnapshot, Value exerciseImageMediaIdsSnapshotJson, Value exerciseStepsSnapshotJson, + Value autoStartNextTimedStepSnapshot, + Value autoStartNextTimedStepOverride, Value exerciseVideoMediaIdSnapshot, Value exerciseArchivedSnapshot, Value availableTimeSnapshot, @@ -39240,6 +39549,16 @@ class $$ProgramExercisesTableFilterComposer builder: (column) => ColumnFilters(column), ); + ColumnFilters get autoStartNextTimedStepSnapshot => $composableBuilder( + column: $table.autoStartNextTimedStepSnapshot, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get autoStartNextTimedStepOverride => $composableBuilder( + column: $table.autoStartNextTimedStepOverride, + builder: (column) => ColumnFilters(column), + ); + ColumnFilters get exerciseArchivedSnapshot => $composableBuilder( column: $table.exerciseArchivedSnapshot, builder: (column) => ColumnFilters(column), @@ -39503,6 +39822,18 @@ class $$ProgramExercisesTableOrderingComposer builder: (column) => ColumnOrderings(column), ); + ColumnOrderings get autoStartNextTimedStepSnapshot => + $composableBuilder( + column: $table.autoStartNextTimedStepSnapshot, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get autoStartNextTimedStepOverride => + $composableBuilder( + column: $table.autoStartNextTimedStepOverride, + builder: (column) => ColumnOrderings(column), + ); + ColumnOrderings get exerciseArchivedSnapshot => $composableBuilder( column: $table.exerciseArchivedSnapshot, builder: (column) => ColumnOrderings(column), @@ -39754,6 +40085,18 @@ class $$ProgramExercisesTableAnnotationComposer builder: (column) => column, ); + GeneratedColumn get autoStartNextTimedStepSnapshot => + $composableBuilder( + column: $table.autoStartNextTimedStepSnapshot, + builder: (column) => column, + ); + + GeneratedColumn get autoStartNextTimedStepOverride => + $composableBuilder( + column: $table.autoStartNextTimedStepOverride, + builder: (column) => column, + ); + GeneratedColumn get exerciseArchivedSnapshot => $composableBuilder( column: $table.exerciseArchivedSnapshot, builder: (column) => column, @@ -39982,6 +40325,10 @@ class $$ProgramExercisesTableTableManager Value exerciseImageMediaIdsSnapshotJson = const Value.absent(), Value exerciseStepsSnapshotJson = const Value.absent(), + Value autoStartNextTimedStepSnapshot = + const Value.absent(), + Value autoStartNextTimedStepOverride = + const Value.absent(), Value exerciseVideoMediaIdSnapshot = const Value.absent(), Value exerciseArchivedSnapshot = const Value.absent(), @@ -40022,6 +40369,8 @@ class $$ProgramExercisesTableTableManager exerciseImageMediaIdsSnapshotJson: exerciseImageMediaIdsSnapshotJson, exerciseStepsSnapshotJson: exerciseStepsSnapshotJson, + autoStartNextTimedStepSnapshot: autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride: autoStartNextTimedStepOverride, exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot, exerciseArchivedSnapshot: exerciseArchivedSnapshot, availableTimeSnapshot: availableTimeSnapshot, @@ -40065,6 +40414,10 @@ class $$ProgramExercisesTableTableManager Value exerciseImageMediaIdsSnapshotJson = const Value.absent(), Value exerciseStepsSnapshotJson = const Value.absent(), + Value autoStartNextTimedStepSnapshot = + const Value.absent(), + Value autoStartNextTimedStepOverride = + const Value.absent(), Value exerciseVideoMediaIdSnapshot = const Value.absent(), Value exerciseArchivedSnapshot = const Value.absent(), @@ -40105,6 +40458,8 @@ class $$ProgramExercisesTableTableManager exerciseImageMediaIdsSnapshotJson: exerciseImageMediaIdsSnapshotJson, exerciseStepsSnapshotJson: exerciseStepsSnapshotJson, + autoStartNextTimedStepSnapshot: autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride: autoStartNextTimedStepOverride, exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot, exerciseArchivedSnapshot: exerciseArchivedSnapshot, availableTimeSnapshot: availableTimeSnapshot, @@ -44787,6 +45142,7 @@ typedef $$WorkoutTemplateExerciseOverridesTableCreateCompanionBuilder = Value targetRepsOverride, Value targetScoreOverride, Value targetScoreTimeMsOverride, + Value autoStartNextTimedStepOverride, Value rowid, }); typedef $$WorkoutTemplateExerciseOverridesTableUpdateCompanionBuilder = @@ -44809,6 +45165,7 @@ typedef $$WorkoutTemplateExerciseOverridesTableUpdateCompanionBuilder = Value targetRepsOverride, Value targetScoreOverride, Value targetScoreTimeMsOverride, + Value autoStartNextTimedStepOverride, Value rowid, }); @@ -44943,6 +45300,11 @@ class $$WorkoutTemplateExerciseOverridesTableFilterComposer builder: (column) => ColumnFilters(column), ); + ColumnFilters get autoStartNextTimedStepOverride => $composableBuilder( + column: $table.autoStartNextTimedStepOverride, + builder: (column) => ColumnFilters(column), + ); + $$WorkoutTemplateProgramsTableFilterComposer get workoutTemplateProgramId { final $$WorkoutTemplateProgramsTableFilterComposer composer = $composerBuilder( @@ -45062,6 +45424,12 @@ class $$WorkoutTemplateExerciseOverridesTableOrderingComposer builder: (column) => ColumnOrderings(column), ); + ColumnOrderings get autoStartNextTimedStepOverride => + $composableBuilder( + column: $table.autoStartNextTimedStepOverride, + builder: (column) => ColumnOrderings(column), + ); + $$WorkoutTemplateProgramsTableOrderingComposer get workoutTemplateProgramId { final $$WorkoutTemplateProgramsTableOrderingComposer composer = $composerBuilder( @@ -45171,6 +45539,12 @@ class $$WorkoutTemplateExerciseOverridesTableAnnotationComposer builder: (column) => column, ); + GeneratedColumn get autoStartNextTimedStepOverride => + $composableBuilder( + column: $table.autoStartNextTimedStepOverride, + builder: (column) => column, + ); + $$WorkoutTemplateProgramsTableAnnotationComposer get workoutTemplateProgramId { final $$WorkoutTemplateProgramsTableAnnotationComposer composer = @@ -45257,6 +45631,8 @@ class $$WorkoutTemplateExerciseOverridesTableTableManager Value targetRepsOverride = const Value.absent(), Value targetScoreOverride = const Value.absent(), Value targetScoreTimeMsOverride = const Value.absent(), + Value autoStartNextTimedStepOverride = + const Value.absent(), Value rowid = const Value.absent(), }) => WorkoutTemplateExerciseOverridesCompanion( id: id, @@ -45277,6 +45653,7 @@ class $$WorkoutTemplateExerciseOverridesTableTableManager targetRepsOverride: targetRepsOverride, targetScoreOverride: targetScoreOverride, targetScoreTimeMsOverride: targetScoreTimeMsOverride, + autoStartNextTimedStepOverride: autoStartNextTimedStepOverride, rowid: rowid, ), createCompanionCallback: @@ -45299,6 +45676,8 @@ class $$WorkoutTemplateExerciseOverridesTableTableManager Value targetRepsOverride = const Value.absent(), Value targetScoreOverride = const Value.absent(), Value targetScoreTimeMsOverride = const Value.absent(), + Value autoStartNextTimedStepOverride = + const Value.absent(), Value rowid = const Value.absent(), }) => WorkoutTemplateExerciseOverridesCompanion.insert( id: id, @@ -45319,6 +45698,7 @@ class $$WorkoutTemplateExerciseOverridesTableTableManager targetRepsOverride: targetRepsOverride, targetScoreOverride: targetScoreOverride, targetScoreTimeMsOverride: targetScoreTimeMsOverride, + autoStartNextTimedStepOverride: autoStartNextTimedStepOverride, rowid: rowid, ), withReferenceMapper: (p0) => p0 diff --git a/lib/infrastructure/local/drift_repositories.dart b/lib/infrastructure/local/drift_repositories.dart index 568c132..5085468 100644 --- a/lib/infrastructure/local/drift_repositories.dart +++ b/lib/infrastructure/local/drift_repositories.dart @@ -1881,6 +1881,7 @@ db.ExercisesCompanion _exerciseCompanion(domain.Exercise exercise) { defaultTargetReps: Value(exercise.defaultTargetReps), defaultTargetScore: Value(exercise.defaultTargetScore), defaultTargetScoreTimeMs: Value(exercise.defaultTargetScoreTimeMs), + autoStartNextTimedStep: Value(exercise.autoStartNextTimedStep), archivedAt: Value(_utcOrNull(exercise.archivedAt)), ); } @@ -1907,6 +1908,7 @@ domain.Exercise _exerciseFromRow( defaultTargetReps: row.defaultTargetReps, defaultTargetScore: row.defaultTargetScore, defaultTargetScoreTimeMs: row.defaultTargetScoreTimeMs, + autoStartNextTimedStep: row.autoStartNextTimedStep, steps: steps, archivedAt: _utcOrNull(row.archivedAt), ); @@ -2132,6 +2134,12 @@ db.ProgramExercisesCompanion _programExerciseCompanion( exerciseStepsSnapshotJson: Value( _encodeExerciseStepsSnapshot(exercise.exerciseStepsSnapshot), ), + autoStartNextTimedStepSnapshot: Value( + exercise.autoStartNextTimedStepSnapshot, + ), + autoStartNextTimedStepOverride: Value( + exercise.autoStartNextTimedStepOverride, + ), exerciseVideoMediaIdSnapshot: Value(exercise.exerciseVideoMediaIdSnapshot), exerciseArchivedSnapshot: Value(exercise.exerciseArchivedSnapshot), availableTimeSnapshot: Value(exercise.availableTimeSnapshot), @@ -2170,6 +2178,8 @@ domain.ProgramExercise _programExerciseFromRow(db.ProgramExercise row) { exerciseStepsSnapshot: _decodeExerciseStepsSnapshot( row.exerciseStepsSnapshotJson, ), + autoStartNextTimedStepSnapshot: row.autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride: row.autoStartNextTimedStepOverride, exerciseVideoMediaIdSnapshot: row.exerciseVideoMediaIdSnapshot, exerciseArchivedSnapshot: row.exerciseArchivedSnapshot, availableTimeSnapshot: row.availableTimeSnapshot, @@ -2288,6 +2298,9 @@ _workoutTemplateExerciseOverrideCompanion( targetRepsOverride: Value(override.targetRepsOverride), targetScoreOverride: Value(override.targetScoreOverride), targetScoreTimeMsOverride: Value(override.targetScoreTimeMsOverride), + autoStartNextTimedStepOverride: Value( + override.autoStartNextTimedStepOverride, + ), ); } @@ -2303,6 +2316,7 @@ domain.WorkoutTemplateExerciseOverride _workoutTemplateExerciseOverrideFromRow( targetRepsOverride: row.targetRepsOverride, targetScoreOverride: row.targetScoreOverride, targetScoreTimeMsOverride: row.targetScoreTimeMsOverride, + autoStartNextTimedStepOverride: row.autoStartNextTimedStepOverride, ); } @@ -2933,6 +2947,7 @@ Map _exercisePayload(domain.Exercise exercise) => { 'defaultTargetReps': exercise.defaultTargetReps, 'defaultTargetScore': exercise.defaultTargetScore, 'defaultTargetScoreTimeMs': exercise.defaultTargetScoreTimeMs, + 'autoStartNextTimedStep': exercise.autoStartNextTimedStep, 'steps': exercise.steps.map((step) => step.toSnapshotJson()).toList(), 'archivedAt': exercise.archivedAt?.toUtc().toIso8601String(), }; @@ -2991,6 +3006,8 @@ Map _workoutTemplatePayload(domain.WorkoutTemplate template) => 'targetRepsOverride': override.targetRepsOverride, 'targetScoreOverride': override.targetScoreOverride, 'targetScoreTimeMsOverride': override.targetScoreTimeMsOverride, + 'autoStartNextTimedStepOverride': + override.autoStartNextTimedStepOverride, }, ) .toList(), @@ -3030,6 +3047,8 @@ domain.Exercise _exerciseFromPayload(RemoteSyncedItem item) { defaultTargetReps: payload['defaultTargetReps'] as int?, defaultTargetScore: (payload['defaultTargetScore'] as num?)?.toDouble(), defaultTargetScoreTimeMs: payload['defaultTargetScoreTimeMs'] as int?, + autoStartNextTimedStep: + payload['autoStartNextTimedStep'] as bool? ?? true, steps: _stepsFromPayload(payload['steps']), archivedAt: _dateTimeFromPayload(payload['archivedAt']), ); @@ -3133,6 +3152,10 @@ List _programExercisesFromPayload( exerciseStepsSnapshot: _stepsFromPayload( map['exerciseStepsSnapshot'], ), + autoStartNextTimedStepSnapshot: + map['autoStartNextTimedStepSnapshot'] as bool? ?? true, + autoStartNextTimedStepOverride: + map['autoStartNextTimedStepOverride'] as bool?, exerciseArchivedSnapshot: map['exerciseArchivedSnapshot'] == true, availableTimeSnapshot: map['availableTimeSnapshot'] == true, availableRepsSnapshot: map['availableRepsSnapshot'] == true, @@ -3217,6 +3240,8 @@ _workoutTemplateOverridesFromPayload( targetRepsOverride: map['targetRepsOverride'] as int?, targetScoreOverride: (map['targetScoreOverride'] as num?)?.toDouble(), targetScoreTimeMsOverride: map['targetScoreTimeMsOverride'] as int?, + autoStartNextTimedStepOverride: + map['autoStartNextTimedStepOverride'] as bool?, ); }) .toList(growable: false); diff --git a/lib/infrastructure/local/tables.dart b/lib/infrastructure/local/tables.dart index 51c2583..170a117 100644 --- a/lib/infrastructure/local/tables.dart +++ b/lib/infrastructure/local/tables.dart @@ -191,6 +191,8 @@ class Exercises extends SyncableTable { IntColumn get defaultTargetReps => integer().nullable()(); RealColumn get defaultTargetScore => real().nullable()(); IntColumn get defaultTargetScoreTimeMs => integer().nullable()(); + BoolColumn get autoStartNextTimedStep => + boolean().withDefault(const Constant(true))(); DateTimeColumn get archivedAt => dateTime().nullable()(); @override @@ -296,6 +298,9 @@ class ProgramExercises extends SyncableTable { text().nullable().references(MediaAssets, #id)(); TextColumn get exerciseImageMediaIdsSnapshotJson => text().nullable()(); TextColumn get exerciseStepsSnapshotJson => text().nullable()(); + BoolColumn get autoStartNextTimedStepSnapshot => + boolean().withDefault(const Constant(true))(); + BoolColumn get autoStartNextTimedStepOverride => boolean().nullable()(); @ReferenceName('programExerciseVideoSnapshotReferences') TextColumn get exerciseVideoMediaIdSnapshot => @@ -390,6 +395,7 @@ class WorkoutTemplateExerciseOverrides extends SyncableTable { IntColumn get targetRepsOverride => integer().nullable()(); RealColumn get targetScoreOverride => real().nullable()(); IntColumn get targetScoreTimeMsOverride => integer().nullable()(); + BoolColumn get autoStartNextTimedStepOverride => boolean().nullable()(); @override List get customConstraints => [ diff --git a/test/application/use_cases_test.dart b/test/application/use_cases_test.dart index 7c25970..4bb6a3f 100644 --- a/test/application/use_cases_test.dart +++ b/test/application/use_cases_test.dart @@ -479,6 +479,129 @@ void main() { ); }); + test('program exercise snapshots step chaining setting from exercise', () async { + final exerciseRepository = _FakeExerciseRepository() + ..exercise = Exercise( + metadata: _metadata('exercise-1'), + name: 'Circuit', + hasTimeMeasure: false, + hasRepsMeasure: true, + hasScoreMeasure: false, + defaultTargetReps: 10, + autoStartNextTimedStep: false, + ); + final programRepository = _FakeProgramRepository() + ..programs.add( + Program( + metadata: _metadata('program-1'), + name: 'Programme', + defaultRestSeconds: 60, + ), + ); + final useCase = ProgramUseCases( + programRepository: programRepository, + exerciseRepository: exerciseRepository, + templateRepository: _FakeWorkoutTemplateRepository(), + clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)), + ids: _FakeIds(), + originDeviceId: 'device-1', + ); + + final snapshot = await useCase.addExercise( + programId: 'program-1', + exerciseId: 'exercise-1', + position: 0, + setsCount: 3, + enabledMeasures: const {WorkoutMeasure.reps}, + ); + + expect(snapshot.autoStartNextTimedStepSnapshot, isFalse); + expect(snapshot.autoStartNextTimedStepOverride, isNull); + expect( + snapshot.toSnapshotJson()['autoStartNextTimedStepSnapshot'], + isFalse, + ); + }); + + test('program saveConfigured preserves step chaining override', () async { + final programRepository = _FakeProgramRepository(); + final useCase = ProgramUseCases( + programRepository: programRepository, + exerciseRepository: _FakeExerciseRepository(), + templateRepository: _FakeWorkoutTemplateRepository(), + clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)), + ids: _FakeIds(), + originDeviceId: 'device-1', + ); + + final program = await useCase.saveConfigured( + name: 'Programme', + defaultRestSeconds: 60, + exercises: const [ + ProgramExerciseConfig( + exerciseNameSnapshot: 'Circuit', + availableTimeSnapshot: false, + availableRepsSnapshot: true, + availableScoreSnapshot: false, + setsCount: 3, + enabledMeasures: {WorkoutMeasure.reps}, + targetReps: 10, + autoStartNextTimedStepSnapshot: true, + autoStartNextTimedStepOverride: false, + ), + ], + ); + + expect(program.exercises.single.autoStartNextTimedStepSnapshot, isTrue); + expect(program.exercises.single.autoStartNextTimedStepOverride, isFalse); + }); + + test('workout template override preserves step chaining override', () async { + final templateRepository = _FakeWorkoutTemplateRepository(); + final useCase = WorkoutTemplateUseCases( + templateRepository: templateRepository, + programRepository: _FakeProgramRepository(), + clock: _FakeClock(DateTime.utc(2026, 7, 17, 12)), + ids: _FakeIds(), + originDeviceId: 'device-1', + ); + + final template = await useCase.saveConfigured( + name: 'Séance', + programs: [ + WorkoutTemplateProgramConfig( + clientKey: 'program-1', + programNameSnapshot: 'Programme', + defaultRestSecondsSnapshot: 60, + programSnapshotJson: jsonEncode({ + 'exercises': [ + { + 'id': 'exercise-snapshot-1', + 'exerciseNameSnapshot': 'Circuit', + 'setsCount': 3, + 'timeEnabled': false, + 'repsEnabled': true, + 'scoreEnabled': false, + }, + ], + }), + ), + ], + overrides: const [ + WorkoutTemplateExerciseOverrideConfig( + workoutTemplateProgramClientKey: 'program-1', + snapshotProgramExerciseId: 'exercise-snapshot-1', + autoStartNextTimedStepOverride: false, + ), + ], + ); + + expect( + template.overrides.single.autoStartNextTimedStepOverride, + isFalse, + ); + }); + test('delete exercise keeps existing program snapshots unchanged', () async { final exerciseRepository = _FakeExerciseRepository() ..exercise = Exercise( diff --git a/test/infrastructure/drift_repositories_test.dart b/test/infrastructure/drift_repositories_test.dart index ba2925b..bfaab8f 100644 --- a/test/infrastructure/drift_repositories_test.dart +++ b/test/infrastructure/drift_repositories_test.dart @@ -98,6 +98,100 @@ void main() { expect(restored!.defaultTargetScore, 0); }); + test('step chaining settings round-trip through drift repositories', () async { + final now = DateTime.utc(2026, 7, 17, 12); + final exercise = Exercise( + metadata: _metadata('exercise-chain-1', now), + name: 'Circuit', + hasTimeMeasure: false, + hasRepsMeasure: true, + hasScoreMeasure: false, + defaultTargetReps: 10, + autoStartNextTimedStep: false, + ); + await exerciseRepository.save(exercise); + + final restoredExercise = await exerciseRepository.findById( + exercise.metadata.id, + ); + expect(restoredExercise!.autoStartNextTimedStep, isFalse); + + final programExercise = _programExercise( + 'program-exercise-chain-1', + now, + programId: 'program-chain-1', + position: 0, + autoStartNextTimedStepSnapshot: false, + autoStartNextTimedStepOverride: true, + ); + await programRepository.save( + Program( + metadata: _metadata('program-chain-1', now), + name: 'Programme', + defaultRestSeconds: 60, + exercises: [programExercise], + ), + ); + + final restoredProgram = await programRepository.findById('program-chain-1'); + expect( + restoredProgram!.exercises.single.autoStartNextTimedStepSnapshot, + isFalse, + ); + expect( + restoredProgram.exercises.single.autoStartNextTimedStepOverride, + isTrue, + ); + + final templateProgram = WorkoutTemplateProgram( + metadata: _metadata('template-program-chain-1', now), + workoutTemplateId: 'template-chain-1', + sourceProgramId: 'program-chain-1', + position: 0, + programNameSnapshot: 'Programme', + defaultRestSecondsSnapshot: 60, + programSnapshotJson: jsonEncode({ + 'exercises': [programExercise.toSnapshotJson()], + }), + ); + await templateRepository.save( + WorkoutTemplate( + metadata: _metadata('template-chain-1', now), + name: 'Séance', + programs: [templateProgram], + overrides: [ + WorkoutTemplateExerciseOverride( + metadata: _metadata('override-chain-1', now), + workoutTemplateProgramId: templateProgram.metadata.id, + snapshotProgramExerciseId: programExercise.metadata.id, + ), + WorkoutTemplateExerciseOverride( + metadata: _metadata('override-chain-2', now), + workoutTemplateProgramId: templateProgram.metadata.id, + snapshotProgramExerciseId: 'program-exercise-chain-2', + autoStartNextTimedStepOverride: false, + ), + ], + ), + ); + + final restoredTemplate = await templateRepository.findById( + 'template-chain-1', + ); + expect( + restoredTemplate!.overrides + .singleWhere((override) => override.metadata.id == 'override-chain-1') + .autoStartNextTimedStepOverride, + isNull, + ); + expect( + restoredTemplate.overrides + .singleWhere((override) => override.metadata.id == 'override-chain-2') + .autoStartNextTimedStepOverride, + isFalse, + ); + }); + test('exercise repository round-trips configured steps', () async { final now = DateTime.utc(2026, 7, 17, 12); final exercise = Exercise( @@ -453,13 +547,18 @@ EntityMetadata _metadata(String id, DateTime now, [int localRevision = 0]) { ProgramExercise _programExercise( String id, DateTime now, { + String programId = 'program-1', required int position, + bool autoStartNextTimedStepSnapshot = true, + bool? autoStartNextTimedStepOverride, }) { return ProgramExercise( metadata: _metadata(id, now), - programId: 'program-1', + programId: programId, position: position, exerciseNameSnapshot: 'Exercise $position', + autoStartNextTimedStepSnapshot: autoStartNextTimedStepSnapshot, + autoStartNextTimedStepOverride: autoStartNextTimedStepOverride, availableTimeSnapshot: false, availableRepsSnapshot: true, availableScoreSnapshot: false,