feat(exercice): affichage des médias pendant l'exécution (ticket #36)
Expose la galerie d'images d'exercice (backend du ticket #35) pendant l'exécution de séance sur workout_execution_screen.dart et program_screen.dart, avec les ajustements domain/use cases/repositories nécessaires. flutter analyze propre, 67/67 tests verts, build APK debug validé. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -439,6 +439,7 @@ final class ProgramUseCases {
|
|||||||
exerciseNameSnapshot: input.exerciseNameSnapshot,
|
exerciseNameSnapshot: input.exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot: input.exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot: input.exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot: input.exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot: input.exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshot: input.exerciseImageMediaIdsSnapshot,
|
||||||
exerciseVideoMediaIdSnapshot: input.exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot: input.exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot: input.exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot: input.exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot: input.availableTimeSnapshot,
|
availableTimeSnapshot: input.availableTimeSnapshot,
|
||||||
@ -555,6 +556,7 @@ final class ProgramExerciseConfig {
|
|||||||
required this.exerciseNameSnapshot,
|
required this.exerciseNameSnapshot,
|
||||||
this.exerciseDescriptionSnapshot,
|
this.exerciseDescriptionSnapshot,
|
||||||
this.exerciseImageMediaIdSnapshot,
|
this.exerciseImageMediaIdSnapshot,
|
||||||
|
this.exerciseImageMediaIdsSnapshot = const [],
|
||||||
this.exerciseVideoMediaIdSnapshot,
|
this.exerciseVideoMediaIdSnapshot,
|
||||||
this.exerciseArchivedSnapshot = false,
|
this.exerciseArchivedSnapshot = false,
|
||||||
required this.availableTimeSnapshot,
|
required this.availableTimeSnapshot,
|
||||||
@ -577,6 +579,7 @@ final class ProgramExerciseConfig {
|
|||||||
final String exerciseNameSnapshot;
|
final String exerciseNameSnapshot;
|
||||||
final String? exerciseDescriptionSnapshot;
|
final String? exerciseDescriptionSnapshot;
|
||||||
final String? exerciseImageMediaIdSnapshot;
|
final String? exerciseImageMediaIdSnapshot;
|
||||||
|
final List<String> exerciseImageMediaIdsSnapshot;
|
||||||
final String? exerciseVideoMediaIdSnapshot;
|
final String? exerciseVideoMediaIdSnapshot;
|
||||||
final bool exerciseArchivedSnapshot;
|
final bool exerciseArchivedSnapshot;
|
||||||
final bool availableTimeSnapshot;
|
final bool availableTimeSnapshot;
|
||||||
@ -1501,6 +1504,8 @@ List<ProgramExercise> _repositionProgramExercises(
|
|||||||
exercises[index].exerciseDescriptionSnapshot,
|
exercises[index].exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot:
|
exerciseImageMediaIdSnapshot:
|
||||||
exercises[index].exerciseImageMediaIdSnapshot,
|
exercises[index].exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshot:
|
||||||
|
exercises[index].exerciseImageMediaIdsSnapshot,
|
||||||
exerciseVideoMediaIdSnapshot:
|
exerciseVideoMediaIdSnapshot:
|
||||||
exercises[index].exerciseVideoMediaIdSnapshot,
|
exercises[index].exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot: exercises[index].exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot: exercises[index].exerciseArchivedSnapshot,
|
||||||
|
|||||||
@ -303,6 +303,7 @@ final class ProgramExercise {
|
|||||||
required String exerciseNameSnapshot,
|
required String exerciseNameSnapshot,
|
||||||
this.exerciseDescriptionSnapshot,
|
this.exerciseDescriptionSnapshot,
|
||||||
this.exerciseImageMediaIdSnapshot,
|
this.exerciseImageMediaIdSnapshot,
|
||||||
|
List<String> exerciseImageMediaIdsSnapshot = const [],
|
||||||
this.exerciseVideoMediaIdSnapshot,
|
this.exerciseVideoMediaIdSnapshot,
|
||||||
this.exerciseArchivedSnapshot = false,
|
this.exerciseArchivedSnapshot = false,
|
||||||
required this.availableTimeSnapshot,
|
required this.availableTimeSnapshot,
|
||||||
@ -323,6 +324,12 @@ final class ProgramExercise {
|
|||||||
}) : exerciseNameSnapshot = _nonBlank(
|
}) : exerciseNameSnapshot = _nonBlank(
|
||||||
exerciseNameSnapshot,
|
exerciseNameSnapshot,
|
||||||
'Exercise snapshot name',
|
'Exercise snapshot name',
|
||||||
|
),
|
||||||
|
exerciseImageMediaIdsSnapshot = _validatedImageMediaIds(
|
||||||
|
exerciseImageMediaIdsSnapshot.isEmpty &&
|
||||||
|
exerciseImageMediaIdSnapshot != null
|
||||||
|
? [exerciseImageMediaIdSnapshot]
|
||||||
|
: exerciseImageMediaIdsSnapshot,
|
||||||
) {
|
) {
|
||||||
_requireNonNegative(position, 'Position');
|
_requireNonNegative(position, 'Position');
|
||||||
_requirePositive(setsCount, 'Sets count');
|
_requirePositive(setsCount, 'Sets count');
|
||||||
@ -360,6 +367,7 @@ final class ProgramExercise {
|
|||||||
final String exerciseNameSnapshot;
|
final String exerciseNameSnapshot;
|
||||||
final String? exerciseDescriptionSnapshot;
|
final String? exerciseDescriptionSnapshot;
|
||||||
final String? exerciseImageMediaIdSnapshot;
|
final String? exerciseImageMediaIdSnapshot;
|
||||||
|
final List<String> exerciseImageMediaIdsSnapshot;
|
||||||
final String? exerciseVideoMediaIdSnapshot;
|
final String? exerciseVideoMediaIdSnapshot;
|
||||||
final bool exerciseArchivedSnapshot;
|
final bool exerciseArchivedSnapshot;
|
||||||
final bool availableTimeSnapshot;
|
final bool availableTimeSnapshot;
|
||||||
@ -405,6 +413,7 @@ final class ProgramExercise {
|
|||||||
exerciseNameSnapshot: exercise.name,
|
exerciseNameSnapshot: exercise.name,
|
||||||
exerciseDescriptionSnapshot: exercise.description,
|
exerciseDescriptionSnapshot: exercise.description,
|
||||||
exerciseImageMediaIdSnapshot: exercise.imageMediaId,
|
exerciseImageMediaIdSnapshot: exercise.imageMediaId,
|
||||||
|
exerciseImageMediaIdsSnapshot: exercise.imageMediaIds,
|
||||||
exerciseVideoMediaIdSnapshot: exercise.videoMediaId,
|
exerciseVideoMediaIdSnapshot: exercise.videoMediaId,
|
||||||
exerciseArchivedSnapshot: exercise.archivedAt != null,
|
exerciseArchivedSnapshot: exercise.archivedAt != null,
|
||||||
availableTimeSnapshot: exercise.hasTimeMeasure,
|
availableTimeSnapshot: exercise.hasTimeMeasure,
|
||||||
@ -432,6 +441,8 @@ final class ProgramExercise {
|
|||||||
'exerciseNameSnapshot': exerciseNameSnapshot,
|
'exerciseNameSnapshot': exerciseNameSnapshot,
|
||||||
'exerciseDescriptionSnapshot': exerciseDescriptionSnapshot,
|
'exerciseDescriptionSnapshot': exerciseDescriptionSnapshot,
|
||||||
'exerciseImageMediaIdSnapshot': exerciseImageMediaIdSnapshot,
|
'exerciseImageMediaIdSnapshot': exerciseImageMediaIdSnapshot,
|
||||||
|
'exerciseImageMediaIdsSnapshot': exerciseImageMediaIdsSnapshot,
|
||||||
|
'imageMediaIdsSnapshot': exerciseImageMediaIdsSnapshot,
|
||||||
'exerciseVideoMediaIdSnapshot': exerciseVideoMediaIdSnapshot,
|
'exerciseVideoMediaIdSnapshot': exerciseVideoMediaIdSnapshot,
|
||||||
'exerciseArchivedSnapshot': exerciseArchivedSnapshot,
|
'exerciseArchivedSnapshot': exerciseArchivedSnapshot,
|
||||||
'availableTimeSnapshot': availableTimeSnapshot,
|
'availableTimeSnapshot': availableTimeSnapshot,
|
||||||
|
|||||||
@ -37,7 +37,7 @@ final class AppDatabase extends _$AppDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 5;
|
int get schemaVersion => 6;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration {
|
MigrationStrategy get migration {
|
||||||
@ -67,6 +67,9 @@ final class AppDatabase extends _$AppDatabase {
|
|||||||
if (from < 5) {
|
if (from < 5) {
|
||||||
await _migrateToSchema5(migrator);
|
await _migrateToSchema5(migrator);
|
||||||
}
|
}
|
||||||
|
if (from < 6) {
|
||||||
|
await _migrateToSchema6();
|
||||||
|
}
|
||||||
await _createIndexes();
|
await _createIndexes();
|
||||||
},
|
},
|
||||||
beforeOpen: (details) async {
|
beforeOpen: (details) async {
|
||||||
@ -250,4 +253,11 @@ extension on AppDatabase {
|
|||||||
'WHERE image_media_id IS NOT NULL',
|
'WHERE image_media_id IS NOT NULL',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _migrateToSchema6() async {
|
||||||
|
await customStatement(
|
||||||
|
'ALTER TABLE program_exercises ADD COLUMN '
|
||||||
|
'exercise_image_media_ids_snapshot_json TEXT',
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11148,6 +11148,17 @@ class $ProgramExercisesTable extends ProgramExercises
|
|||||||
'REFERENCES media_assets (id)',
|
'REFERENCES media_assets (id)',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
static const VerificationMeta _exerciseImageMediaIdsSnapshotJsonMeta =
|
||||||
|
const VerificationMeta('exerciseImageMediaIdsSnapshotJson');
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<String> exerciseImageMediaIdsSnapshotJson =
|
||||||
|
GeneratedColumn<String>(
|
||||||
|
'exercise_image_media_ids_snapshot_json',
|
||||||
|
aliasedName,
|
||||||
|
true,
|
||||||
|
type: DriftSqlType.string,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
);
|
||||||
static const VerificationMeta _exerciseVideoMediaIdSnapshotMeta =
|
static const VerificationMeta _exerciseVideoMediaIdSnapshotMeta =
|
||||||
const VerificationMeta('exerciseVideoMediaIdSnapshot');
|
const VerificationMeta('exerciseVideoMediaIdSnapshot');
|
||||||
@override
|
@override
|
||||||
@ -11380,6 +11391,7 @@ class $ProgramExercisesTable extends ProgramExercises
|
|||||||
exerciseNameSnapshot,
|
exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshotJson,
|
||||||
exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot,
|
availableTimeSnapshot,
|
||||||
@ -11557,6 +11569,15 @@ class $ProgramExercisesTable extends ProgramExercises
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('exercise_image_media_ids_snapshot_json')) {
|
||||||
|
context.handle(
|
||||||
|
_exerciseImageMediaIdsSnapshotJsonMeta,
|
||||||
|
exerciseImageMediaIdsSnapshotJson.isAcceptableOrUnknown(
|
||||||
|
data['exercise_image_media_ids_snapshot_json']!,
|
||||||
|
_exerciseImageMediaIdsSnapshotJsonMeta,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
if (data.containsKey('exercise_video_media_id_snapshot')) {
|
if (data.containsKey('exercise_video_media_id_snapshot')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_exerciseVideoMediaIdSnapshotMeta,
|
_exerciseVideoMediaIdSnapshotMeta,
|
||||||
@ -11795,6 +11816,10 @@ class $ProgramExercisesTable extends ProgramExercises
|
|||||||
DriftSqlType.string,
|
DriftSqlType.string,
|
||||||
data['${effectivePrefix}exercise_image_media_id_snapshot'],
|
data['${effectivePrefix}exercise_image_media_id_snapshot'],
|
||||||
),
|
),
|
||||||
|
exerciseImageMediaIdsSnapshotJson: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.string,
|
||||||
|
data['${effectivePrefix}exercise_image_media_ids_snapshot_json'],
|
||||||
|
),
|
||||||
exerciseVideoMediaIdSnapshot: attachedDatabase.typeMapping.read(
|
exerciseVideoMediaIdSnapshot: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.string,
|
DriftSqlType.string,
|
||||||
data['${effectivePrefix}exercise_video_media_id_snapshot'],
|
data['${effectivePrefix}exercise_video_media_id_snapshot'],
|
||||||
@ -11890,6 +11915,7 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
final String exerciseNameSnapshot;
|
final String exerciseNameSnapshot;
|
||||||
final String? exerciseDescriptionSnapshot;
|
final String? exerciseDescriptionSnapshot;
|
||||||
final String? exerciseImageMediaIdSnapshot;
|
final String? exerciseImageMediaIdSnapshot;
|
||||||
|
final String? exerciseImageMediaIdsSnapshotJson;
|
||||||
final String? exerciseVideoMediaIdSnapshot;
|
final String? exerciseVideoMediaIdSnapshot;
|
||||||
final bool exerciseArchivedSnapshot;
|
final bool exerciseArchivedSnapshot;
|
||||||
final bool availableTimeSnapshot;
|
final bool availableTimeSnapshot;
|
||||||
@ -11925,6 +11951,7 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
required this.exerciseNameSnapshot,
|
required this.exerciseNameSnapshot,
|
||||||
this.exerciseDescriptionSnapshot,
|
this.exerciseDescriptionSnapshot,
|
||||||
this.exerciseImageMediaIdSnapshot,
|
this.exerciseImageMediaIdSnapshot,
|
||||||
|
this.exerciseImageMediaIdsSnapshotJson,
|
||||||
this.exerciseVideoMediaIdSnapshot,
|
this.exerciseVideoMediaIdSnapshot,
|
||||||
required this.exerciseArchivedSnapshot,
|
required this.exerciseArchivedSnapshot,
|
||||||
required this.availableTimeSnapshot,
|
required this.availableTimeSnapshot,
|
||||||
@ -11981,6 +12008,11 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (!nullToAbsent || exerciseImageMediaIdsSnapshotJson != null) {
|
||||||
|
map['exercise_image_media_ids_snapshot_json'] = Variable<String>(
|
||||||
|
exerciseImageMediaIdsSnapshotJson,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (!nullToAbsent || exerciseVideoMediaIdSnapshot != null) {
|
if (!nullToAbsent || exerciseVideoMediaIdSnapshot != null) {
|
||||||
map['exercise_video_media_id_snapshot'] = Variable<String>(
|
map['exercise_video_media_id_snapshot'] = Variable<String>(
|
||||||
exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot,
|
||||||
@ -12056,6 +12088,10 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
exerciseImageMediaIdSnapshot == null && nullToAbsent
|
exerciseImageMediaIdSnapshot == null && nullToAbsent
|
||||||
? const Value.absent()
|
? const Value.absent()
|
||||||
: Value(exerciseImageMediaIdSnapshot),
|
: Value(exerciseImageMediaIdSnapshot),
|
||||||
|
exerciseImageMediaIdsSnapshotJson:
|
||||||
|
exerciseImageMediaIdsSnapshotJson == null && nullToAbsent
|
||||||
|
? const Value.absent()
|
||||||
|
: Value(exerciseImageMediaIdsSnapshotJson),
|
||||||
exerciseVideoMediaIdSnapshot:
|
exerciseVideoMediaIdSnapshot:
|
||||||
exerciseVideoMediaIdSnapshot == null && nullToAbsent
|
exerciseVideoMediaIdSnapshot == null && nullToAbsent
|
||||||
? const Value.absent()
|
? const Value.absent()
|
||||||
@ -12124,6 +12160,9 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
exerciseImageMediaIdSnapshot: serializer.fromJson<String?>(
|
exerciseImageMediaIdSnapshot: serializer.fromJson<String?>(
|
||||||
json['exerciseImageMediaIdSnapshot'],
|
json['exerciseImageMediaIdSnapshot'],
|
||||||
),
|
),
|
||||||
|
exerciseImageMediaIdsSnapshotJson: serializer.fromJson<String?>(
|
||||||
|
json['exerciseImageMediaIdsSnapshotJson'],
|
||||||
|
),
|
||||||
exerciseVideoMediaIdSnapshot: serializer.fromJson<String?>(
|
exerciseVideoMediaIdSnapshot: serializer.fromJson<String?>(
|
||||||
json['exerciseVideoMediaIdSnapshot'],
|
json['exerciseVideoMediaIdSnapshot'],
|
||||||
),
|
),
|
||||||
@ -12186,6 +12225,9 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
'exerciseImageMediaIdSnapshot': serializer.toJson<String?>(
|
'exerciseImageMediaIdSnapshot': serializer.toJson<String?>(
|
||||||
exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot,
|
||||||
),
|
),
|
||||||
|
'exerciseImageMediaIdsSnapshotJson': serializer.toJson<String?>(
|
||||||
|
exerciseImageMediaIdsSnapshotJson,
|
||||||
|
),
|
||||||
'exerciseVideoMediaIdSnapshot': serializer.toJson<String?>(
|
'exerciseVideoMediaIdSnapshot': serializer.toJson<String?>(
|
||||||
exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot,
|
||||||
),
|
),
|
||||||
@ -12230,6 +12272,7 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
String? exerciseNameSnapshot,
|
String? exerciseNameSnapshot,
|
||||||
Value<String?> exerciseDescriptionSnapshot = const Value.absent(),
|
Value<String?> exerciseDescriptionSnapshot = const Value.absent(),
|
||||||
Value<String?> exerciseImageMediaIdSnapshot = const Value.absent(),
|
Value<String?> exerciseImageMediaIdSnapshot = const Value.absent(),
|
||||||
|
Value<String?> exerciseImageMediaIdsSnapshotJson = const Value.absent(),
|
||||||
Value<String?> exerciseVideoMediaIdSnapshot = const Value.absent(),
|
Value<String?> exerciseVideoMediaIdSnapshot = const Value.absent(),
|
||||||
bool? exerciseArchivedSnapshot,
|
bool? exerciseArchivedSnapshot,
|
||||||
bool? availableTimeSnapshot,
|
bool? availableTimeSnapshot,
|
||||||
@ -12275,6 +12318,9 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot.present
|
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot.present
|
||||||
? exerciseImageMediaIdSnapshot.value
|
? exerciseImageMediaIdSnapshot.value
|
||||||
: this.exerciseImageMediaIdSnapshot,
|
: this.exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshotJson: exerciseImageMediaIdsSnapshotJson.present
|
||||||
|
? exerciseImageMediaIdsSnapshotJson.value
|
||||||
|
: this.exerciseImageMediaIdsSnapshotJson,
|
||||||
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot.present
|
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot.present
|
||||||
? exerciseVideoMediaIdSnapshot.value
|
? exerciseVideoMediaIdSnapshot.value
|
||||||
: this.exerciseVideoMediaIdSnapshot,
|
: this.exerciseVideoMediaIdSnapshot,
|
||||||
@ -12347,6 +12393,10 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
exerciseImageMediaIdSnapshot: data.exerciseImageMediaIdSnapshot.present
|
exerciseImageMediaIdSnapshot: data.exerciseImageMediaIdSnapshot.present
|
||||||
? data.exerciseImageMediaIdSnapshot.value
|
? data.exerciseImageMediaIdSnapshot.value
|
||||||
: this.exerciseImageMediaIdSnapshot,
|
: this.exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshotJson:
|
||||||
|
data.exerciseImageMediaIdsSnapshotJson.present
|
||||||
|
? data.exerciseImageMediaIdsSnapshotJson.value
|
||||||
|
: this.exerciseImageMediaIdsSnapshotJson,
|
||||||
exerciseVideoMediaIdSnapshot: data.exerciseVideoMediaIdSnapshot.present
|
exerciseVideoMediaIdSnapshot: data.exerciseVideoMediaIdSnapshot.present
|
||||||
? data.exerciseVideoMediaIdSnapshot.value
|
? data.exerciseVideoMediaIdSnapshot.value
|
||||||
: this.exerciseVideoMediaIdSnapshot,
|
: this.exerciseVideoMediaIdSnapshot,
|
||||||
@ -12421,6 +12471,9 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
..write(
|
..write(
|
||||||
'exerciseImageMediaIdSnapshot: $exerciseImageMediaIdSnapshot, ',
|
'exerciseImageMediaIdSnapshot: $exerciseImageMediaIdSnapshot, ',
|
||||||
)
|
)
|
||||||
|
..write(
|
||||||
|
'exerciseImageMediaIdsSnapshotJson: $exerciseImageMediaIdsSnapshotJson, ',
|
||||||
|
)
|
||||||
..write(
|
..write(
|
||||||
'exerciseVideoMediaIdSnapshot: $exerciseVideoMediaIdSnapshot, ',
|
'exerciseVideoMediaIdSnapshot: $exerciseVideoMediaIdSnapshot, ',
|
||||||
)
|
)
|
||||||
@ -12463,6 +12516,7 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
exerciseNameSnapshot,
|
exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshotJson,
|
||||||
exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot,
|
availableTimeSnapshot,
|
||||||
@ -12504,6 +12558,8 @@ class ProgramExercise extends DataClass implements Insertable<ProgramExercise> {
|
|||||||
this.exerciseDescriptionSnapshot &&
|
this.exerciseDescriptionSnapshot &&
|
||||||
other.exerciseImageMediaIdSnapshot ==
|
other.exerciseImageMediaIdSnapshot ==
|
||||||
this.exerciseImageMediaIdSnapshot &&
|
this.exerciseImageMediaIdSnapshot &&
|
||||||
|
other.exerciseImageMediaIdsSnapshotJson ==
|
||||||
|
this.exerciseImageMediaIdsSnapshotJson &&
|
||||||
other.exerciseVideoMediaIdSnapshot ==
|
other.exerciseVideoMediaIdSnapshot ==
|
||||||
this.exerciseVideoMediaIdSnapshot &&
|
this.exerciseVideoMediaIdSnapshot &&
|
||||||
other.exerciseArchivedSnapshot == this.exerciseArchivedSnapshot &&
|
other.exerciseArchivedSnapshot == this.exerciseArchivedSnapshot &&
|
||||||
@ -12542,6 +12598,7 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
final Value<String> exerciseNameSnapshot;
|
final Value<String> exerciseNameSnapshot;
|
||||||
final Value<String?> exerciseDescriptionSnapshot;
|
final Value<String?> exerciseDescriptionSnapshot;
|
||||||
final Value<String?> exerciseImageMediaIdSnapshot;
|
final Value<String?> exerciseImageMediaIdSnapshot;
|
||||||
|
final Value<String?> exerciseImageMediaIdsSnapshotJson;
|
||||||
final Value<String?> exerciseVideoMediaIdSnapshot;
|
final Value<String?> exerciseVideoMediaIdSnapshot;
|
||||||
final Value<bool> exerciseArchivedSnapshot;
|
final Value<bool> exerciseArchivedSnapshot;
|
||||||
final Value<bool> availableTimeSnapshot;
|
final Value<bool> availableTimeSnapshot;
|
||||||
@ -12578,6 +12635,7 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
this.exerciseNameSnapshot = const Value.absent(),
|
this.exerciseNameSnapshot = const Value.absent(),
|
||||||
this.exerciseDescriptionSnapshot = const Value.absent(),
|
this.exerciseDescriptionSnapshot = const Value.absent(),
|
||||||
this.exerciseImageMediaIdSnapshot = const Value.absent(),
|
this.exerciseImageMediaIdSnapshot = const Value.absent(),
|
||||||
|
this.exerciseImageMediaIdsSnapshotJson = const Value.absent(),
|
||||||
this.exerciseVideoMediaIdSnapshot = const Value.absent(),
|
this.exerciseVideoMediaIdSnapshot = const Value.absent(),
|
||||||
this.exerciseArchivedSnapshot = const Value.absent(),
|
this.exerciseArchivedSnapshot = const Value.absent(),
|
||||||
this.availableTimeSnapshot = const Value.absent(),
|
this.availableTimeSnapshot = const Value.absent(),
|
||||||
@ -12615,6 +12673,7 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
required String exerciseNameSnapshot,
|
required String exerciseNameSnapshot,
|
||||||
this.exerciseDescriptionSnapshot = const Value.absent(),
|
this.exerciseDescriptionSnapshot = const Value.absent(),
|
||||||
this.exerciseImageMediaIdSnapshot = const Value.absent(),
|
this.exerciseImageMediaIdSnapshot = const Value.absent(),
|
||||||
|
this.exerciseImageMediaIdsSnapshotJson = const Value.absent(),
|
||||||
this.exerciseVideoMediaIdSnapshot = const Value.absent(),
|
this.exerciseVideoMediaIdSnapshot = const Value.absent(),
|
||||||
this.exerciseArchivedSnapshot = const Value.absent(),
|
this.exerciseArchivedSnapshot = const Value.absent(),
|
||||||
required bool availableTimeSnapshot,
|
required bool availableTimeSnapshot,
|
||||||
@ -12667,6 +12726,7 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
Expression<String>? exerciseNameSnapshot,
|
Expression<String>? exerciseNameSnapshot,
|
||||||
Expression<String>? exerciseDescriptionSnapshot,
|
Expression<String>? exerciseDescriptionSnapshot,
|
||||||
Expression<String>? exerciseImageMediaIdSnapshot,
|
Expression<String>? exerciseImageMediaIdSnapshot,
|
||||||
|
Expression<String>? exerciseImageMediaIdsSnapshotJson,
|
||||||
Expression<String>? exerciseVideoMediaIdSnapshot,
|
Expression<String>? exerciseVideoMediaIdSnapshot,
|
||||||
Expression<bool>? exerciseArchivedSnapshot,
|
Expression<bool>? exerciseArchivedSnapshot,
|
||||||
Expression<bool>? availableTimeSnapshot,
|
Expression<bool>? availableTimeSnapshot,
|
||||||
@ -12708,6 +12768,9 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
'exercise_description_snapshot': exerciseDescriptionSnapshot,
|
'exercise_description_snapshot': exerciseDescriptionSnapshot,
|
||||||
if (exerciseImageMediaIdSnapshot != null)
|
if (exerciseImageMediaIdSnapshot != null)
|
||||||
'exercise_image_media_id_snapshot': exerciseImageMediaIdSnapshot,
|
'exercise_image_media_id_snapshot': exerciseImageMediaIdSnapshot,
|
||||||
|
if (exerciseImageMediaIdsSnapshotJson != null)
|
||||||
|
'exercise_image_media_ids_snapshot_json':
|
||||||
|
exerciseImageMediaIdsSnapshotJson,
|
||||||
if (exerciseVideoMediaIdSnapshot != null)
|
if (exerciseVideoMediaIdSnapshot != null)
|
||||||
'exercise_video_media_id_snapshot': exerciseVideoMediaIdSnapshot,
|
'exercise_video_media_id_snapshot': exerciseVideoMediaIdSnapshot,
|
||||||
if (exerciseArchivedSnapshot != null)
|
if (exerciseArchivedSnapshot != null)
|
||||||
@ -12755,6 +12818,7 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
Value<String>? exerciseNameSnapshot,
|
Value<String>? exerciseNameSnapshot,
|
||||||
Value<String?>? exerciseDescriptionSnapshot,
|
Value<String?>? exerciseDescriptionSnapshot,
|
||||||
Value<String?>? exerciseImageMediaIdSnapshot,
|
Value<String?>? exerciseImageMediaIdSnapshot,
|
||||||
|
Value<String?>? exerciseImageMediaIdsSnapshotJson,
|
||||||
Value<String?>? exerciseVideoMediaIdSnapshot,
|
Value<String?>? exerciseVideoMediaIdSnapshot,
|
||||||
Value<bool>? exerciseArchivedSnapshot,
|
Value<bool>? exerciseArchivedSnapshot,
|
||||||
Value<bool>? availableTimeSnapshot,
|
Value<bool>? availableTimeSnapshot,
|
||||||
@ -12794,6 +12858,9 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
exerciseDescriptionSnapshot ?? this.exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot ?? this.exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot:
|
exerciseImageMediaIdSnapshot:
|
||||||
exerciseImageMediaIdSnapshot ?? this.exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot ?? this.exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshotJson:
|
||||||
|
exerciseImageMediaIdsSnapshotJson ??
|
||||||
|
this.exerciseImageMediaIdsSnapshotJson,
|
||||||
exerciseVideoMediaIdSnapshot:
|
exerciseVideoMediaIdSnapshot:
|
||||||
exerciseVideoMediaIdSnapshot ?? this.exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot ?? this.exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot:
|
exerciseArchivedSnapshot:
|
||||||
@ -12883,6 +12950,11 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
exerciseImageMediaIdSnapshot.value,
|
exerciseImageMediaIdSnapshot.value,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (exerciseImageMediaIdsSnapshotJson.present) {
|
||||||
|
map['exercise_image_media_ids_snapshot_json'] = Variable<String>(
|
||||||
|
exerciseImageMediaIdsSnapshotJson.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
if (exerciseVideoMediaIdSnapshot.present) {
|
if (exerciseVideoMediaIdSnapshot.present) {
|
||||||
map['exercise_video_media_id_snapshot'] = Variable<String>(
|
map['exercise_video_media_id_snapshot'] = Variable<String>(
|
||||||
exerciseVideoMediaIdSnapshot.value,
|
exerciseVideoMediaIdSnapshot.value,
|
||||||
@ -12974,6 +13046,9 @@ class ProgramExercisesCompanion extends UpdateCompanion<ProgramExercise> {
|
|||||||
..write(
|
..write(
|
||||||
'exerciseImageMediaIdSnapshot: $exerciseImageMediaIdSnapshot, ',
|
'exerciseImageMediaIdSnapshot: $exerciseImageMediaIdSnapshot, ',
|
||||||
)
|
)
|
||||||
|
..write(
|
||||||
|
'exerciseImageMediaIdsSnapshotJson: $exerciseImageMediaIdsSnapshotJson, ',
|
||||||
|
)
|
||||||
..write(
|
..write(
|
||||||
'exerciseVideoMediaIdSnapshot: $exerciseVideoMediaIdSnapshot, ',
|
'exerciseVideoMediaIdSnapshot: $exerciseVideoMediaIdSnapshot, ',
|
||||||
)
|
)
|
||||||
@ -25793,6 +25868,7 @@ typedef $$ProgramExercisesTableCreateCompanionBuilder =
|
|||||||
required String exerciseNameSnapshot,
|
required String exerciseNameSnapshot,
|
||||||
Value<String?> exerciseDescriptionSnapshot,
|
Value<String?> exerciseDescriptionSnapshot,
|
||||||
Value<String?> exerciseImageMediaIdSnapshot,
|
Value<String?> exerciseImageMediaIdSnapshot,
|
||||||
|
Value<String?> exerciseImageMediaIdsSnapshotJson,
|
||||||
Value<String?> exerciseVideoMediaIdSnapshot,
|
Value<String?> exerciseVideoMediaIdSnapshot,
|
||||||
Value<bool> exerciseArchivedSnapshot,
|
Value<bool> exerciseArchivedSnapshot,
|
||||||
required bool availableTimeSnapshot,
|
required bool availableTimeSnapshot,
|
||||||
@ -25831,6 +25907,7 @@ typedef $$ProgramExercisesTableUpdateCompanionBuilder =
|
|||||||
Value<String> exerciseNameSnapshot,
|
Value<String> exerciseNameSnapshot,
|
||||||
Value<String?> exerciseDescriptionSnapshot,
|
Value<String?> exerciseDescriptionSnapshot,
|
||||||
Value<String?> exerciseImageMediaIdSnapshot,
|
Value<String?> exerciseImageMediaIdSnapshot,
|
||||||
|
Value<String?> exerciseImageMediaIdsSnapshotJson,
|
||||||
Value<String?> exerciseVideoMediaIdSnapshot,
|
Value<String?> exerciseVideoMediaIdSnapshot,
|
||||||
Value<bool> exerciseArchivedSnapshot,
|
Value<bool> exerciseArchivedSnapshot,
|
||||||
Value<bool> availableTimeSnapshot,
|
Value<bool> availableTimeSnapshot,
|
||||||
@ -26019,6 +26096,12 @@ class $$ProgramExercisesTableFilterComposer
|
|||||||
builder: (column) => ColumnFilters(column),
|
builder: (column) => ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ColumnFilters<String> get exerciseImageMediaIdsSnapshotJson =>
|
||||||
|
$composableBuilder(
|
||||||
|
column: $table.exerciseImageMediaIdsSnapshotJson,
|
||||||
|
builder: (column) => ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
ColumnFilters<bool> get exerciseArchivedSnapshot => $composableBuilder(
|
ColumnFilters<bool> get exerciseArchivedSnapshot => $composableBuilder(
|
||||||
column: $table.exerciseArchivedSnapshot,
|
column: $table.exerciseArchivedSnapshot,
|
||||||
builder: (column) => ColumnFilters(column),
|
builder: (column) => ColumnFilters(column),
|
||||||
@ -26271,6 +26354,12 @@ class $$ProgramExercisesTableOrderingComposer
|
|||||||
builder: (column) => ColumnOrderings(column),
|
builder: (column) => ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ColumnOrderings<String> get exerciseImageMediaIdsSnapshotJson =>
|
||||||
|
$composableBuilder(
|
||||||
|
column: $table.exerciseImageMediaIdsSnapshotJson,
|
||||||
|
builder: (column) => ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
ColumnOrderings<bool> get exerciseArchivedSnapshot => $composableBuilder(
|
ColumnOrderings<bool> get exerciseArchivedSnapshot => $composableBuilder(
|
||||||
column: $table.exerciseArchivedSnapshot,
|
column: $table.exerciseArchivedSnapshot,
|
||||||
builder: (column) => ColumnOrderings(column),
|
builder: (column) => ColumnOrderings(column),
|
||||||
@ -26511,6 +26600,12 @@ class $$ProgramExercisesTableAnnotationComposer
|
|||||||
builder: (column) => column,
|
builder: (column) => column,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
GeneratedColumn<String> get exerciseImageMediaIdsSnapshotJson =>
|
||||||
|
$composableBuilder(
|
||||||
|
column: $table.exerciseImageMediaIdsSnapshotJson,
|
||||||
|
builder: (column) => column,
|
||||||
|
);
|
||||||
|
|
||||||
GeneratedColumn<bool> get exerciseArchivedSnapshot => $composableBuilder(
|
GeneratedColumn<bool> get exerciseArchivedSnapshot => $composableBuilder(
|
||||||
column: $table.exerciseArchivedSnapshot,
|
column: $table.exerciseArchivedSnapshot,
|
||||||
builder: (column) => column,
|
builder: (column) => column,
|
||||||
@ -26736,6 +26831,8 @@ class $$ProgramExercisesTableTableManager
|
|||||||
const Value.absent(),
|
const Value.absent(),
|
||||||
Value<String?> exerciseImageMediaIdSnapshot =
|
Value<String?> exerciseImageMediaIdSnapshot =
|
||||||
const Value.absent(),
|
const Value.absent(),
|
||||||
|
Value<String?> exerciseImageMediaIdsSnapshotJson =
|
||||||
|
const Value.absent(),
|
||||||
Value<String?> exerciseVideoMediaIdSnapshot =
|
Value<String?> exerciseVideoMediaIdSnapshot =
|
||||||
const Value.absent(),
|
const Value.absent(),
|
||||||
Value<bool> exerciseArchivedSnapshot = const Value.absent(),
|
Value<bool> exerciseArchivedSnapshot = const Value.absent(),
|
||||||
@ -26773,6 +26870,8 @@ class $$ProgramExercisesTableTableManager
|
|||||||
exerciseNameSnapshot: exerciseNameSnapshot,
|
exerciseNameSnapshot: exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot: exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot: exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshotJson:
|
||||||
|
exerciseImageMediaIdsSnapshotJson,
|
||||||
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot: exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot: exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot: availableTimeSnapshot,
|
availableTimeSnapshot: availableTimeSnapshot,
|
||||||
@ -26813,6 +26912,8 @@ class $$ProgramExercisesTableTableManager
|
|||||||
const Value.absent(),
|
const Value.absent(),
|
||||||
Value<String?> exerciseImageMediaIdSnapshot =
|
Value<String?> exerciseImageMediaIdSnapshot =
|
||||||
const Value.absent(),
|
const Value.absent(),
|
||||||
|
Value<String?> exerciseImageMediaIdsSnapshotJson =
|
||||||
|
const Value.absent(),
|
||||||
Value<String?> exerciseVideoMediaIdSnapshot =
|
Value<String?> exerciseVideoMediaIdSnapshot =
|
||||||
const Value.absent(),
|
const Value.absent(),
|
||||||
Value<bool> exerciseArchivedSnapshot = const Value.absent(),
|
Value<bool> exerciseArchivedSnapshot = const Value.absent(),
|
||||||
@ -26850,6 +26951,8 @@ class $$ProgramExercisesTableTableManager
|
|||||||
exerciseNameSnapshot: exerciseNameSnapshot,
|
exerciseNameSnapshot: exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot: exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot: exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshotJson:
|
||||||
|
exerciseImageMediaIdsSnapshotJson,
|
||||||
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot: exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot: exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot: availableTimeSnapshot,
|
availableTimeSnapshot: availableTimeSnapshot,
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
|
|
||||||
import '../../application/application.dart';
|
import '../../application/application.dart';
|
||||||
@ -1208,6 +1210,9 @@ db.ProgramExercisesCompanion _programExerciseCompanion(
|
|||||||
exerciseNameSnapshot: Value(exercise.exerciseNameSnapshot),
|
exerciseNameSnapshot: Value(exercise.exerciseNameSnapshot),
|
||||||
exerciseDescriptionSnapshot: Value(exercise.exerciseDescriptionSnapshot),
|
exerciseDescriptionSnapshot: Value(exercise.exerciseDescriptionSnapshot),
|
||||||
exerciseImageMediaIdSnapshot: Value(exercise.exerciseImageMediaIdSnapshot),
|
exerciseImageMediaIdSnapshot: Value(exercise.exerciseImageMediaIdSnapshot),
|
||||||
|
exerciseImageMediaIdsSnapshotJson: Value(
|
||||||
|
_encodeImageMediaIdsSnapshot(exercise.exerciseImageMediaIdsSnapshot),
|
||||||
|
),
|
||||||
exerciseVideoMediaIdSnapshot: Value(exercise.exerciseVideoMediaIdSnapshot),
|
exerciseVideoMediaIdSnapshot: Value(exercise.exerciseVideoMediaIdSnapshot),
|
||||||
exerciseArchivedSnapshot: Value(exercise.exerciseArchivedSnapshot),
|
exerciseArchivedSnapshot: Value(exercise.exerciseArchivedSnapshot),
|
||||||
availableTimeSnapshot: Value(exercise.availableTimeSnapshot),
|
availableTimeSnapshot: Value(exercise.availableTimeSnapshot),
|
||||||
@ -1239,6 +1244,10 @@ domain.ProgramExercise _programExerciseFromRow(db.ProgramExercise row) {
|
|||||||
exerciseNameSnapshot: row.exerciseNameSnapshot,
|
exerciseNameSnapshot: row.exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot: row.exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot: row.exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot: row.exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot: row.exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshot: _decodeImageMediaIdsSnapshot(
|
||||||
|
row.exerciseImageMediaIdsSnapshotJson,
|
||||||
|
row.exerciseImageMediaIdSnapshot,
|
||||||
|
),
|
||||||
exerciseVideoMediaIdSnapshot: row.exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot: row.exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot: row.exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot: row.exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot: row.availableTimeSnapshot,
|
availableTimeSnapshot: row.availableTimeSnapshot,
|
||||||
@ -1766,6 +1775,29 @@ domain.ActiveScoreStopwatchStatus _scoreStopwatchStatusFromDb(String value) =>
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
String? _encodeImageMediaIdsSnapshot(List<String> imageMediaIds) {
|
||||||
|
return imageMediaIds.isEmpty ? null : jsonEncode(imageMediaIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> _decodeImageMediaIdsSnapshot(
|
||||||
|
String? encoded,
|
||||||
|
String? fallbackImageMediaId,
|
||||||
|
) {
|
||||||
|
if (encoded == null || encoded.trim().isEmpty) {
|
||||||
|
return [if (fallbackImageMediaId != null) fallbackImageMediaId];
|
||||||
|
}
|
||||||
|
final decoded = jsonDecode(encoded);
|
||||||
|
if (decoded is! List) {
|
||||||
|
throw const domain.DomainException(
|
||||||
|
'Invalid exercise image media ids snapshot.',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return decoded
|
||||||
|
.whereType<String>()
|
||||||
|
.where((id) => id.trim().isNotEmpty)
|
||||||
|
.toList(growable: false);
|
||||||
|
}
|
||||||
|
|
||||||
domain.ActiveWorkoutStatus _activeStatusFromDb(String value) => switch (value) {
|
domain.ActiveWorkoutStatus _activeStatusFromDb(String value) => switch (value) {
|
||||||
'running' => domain.ActiveWorkoutStatus.running,
|
'running' => domain.ActiveWorkoutStatus.running,
|
||||||
'paused' => domain.ActiveWorkoutStatus.paused,
|
'paused' => domain.ActiveWorkoutStatus.paused,
|
||||||
|
|||||||
@ -128,6 +128,7 @@ class ProgramExercises extends SyncableTable {
|
|||||||
@ReferenceName('programExerciseImageSnapshotReferences')
|
@ReferenceName('programExerciseImageSnapshotReferences')
|
||||||
TextColumn get exerciseImageMediaIdSnapshot =>
|
TextColumn get exerciseImageMediaIdSnapshot =>
|
||||||
text().nullable().references(MediaAssets, #id)();
|
text().nullable().references(MediaAssets, #id)();
|
||||||
|
TextColumn get exerciseImageMediaIdsSnapshotJson => text().nullable()();
|
||||||
|
|
||||||
@ReferenceName('programExerciseVideoSnapshotReferences')
|
@ReferenceName('programExerciseVideoSnapshotReferences')
|
||||||
TextColumn get exerciseVideoMediaIdSnapshot =>
|
TextColumn get exerciseVideoMediaIdSnapshot =>
|
||||||
|
|||||||
@ -870,6 +870,7 @@ final class _ProgramExerciseDraft {
|
|||||||
required this.exerciseNameSnapshot,
|
required this.exerciseNameSnapshot,
|
||||||
this.exerciseDescriptionSnapshot,
|
this.exerciseDescriptionSnapshot,
|
||||||
this.exerciseImageMediaIdSnapshot,
|
this.exerciseImageMediaIdSnapshot,
|
||||||
|
this.exerciseImageMediaIdsSnapshot = const [],
|
||||||
this.exerciseVideoMediaIdSnapshot,
|
this.exerciseVideoMediaIdSnapshot,
|
||||||
this.exerciseArchivedSnapshot = false,
|
this.exerciseArchivedSnapshot = false,
|
||||||
required this.availableTimeSnapshot,
|
required this.availableTimeSnapshot,
|
||||||
@ -897,6 +898,7 @@ final class _ProgramExerciseDraft {
|
|||||||
exerciseNameSnapshot: exercise.name,
|
exerciseNameSnapshot: exercise.name,
|
||||||
exerciseDescriptionSnapshot: exercise.description,
|
exerciseDescriptionSnapshot: exercise.description,
|
||||||
exerciseImageMediaIdSnapshot: exercise.imageMediaId,
|
exerciseImageMediaIdSnapshot: exercise.imageMediaId,
|
||||||
|
exerciseImageMediaIdsSnapshot: exercise.imageMediaIds,
|
||||||
exerciseVideoMediaIdSnapshot: exercise.videoMediaId,
|
exerciseVideoMediaIdSnapshot: exercise.videoMediaId,
|
||||||
exerciseArchivedSnapshot: exercise.archivedAt != null,
|
exerciseArchivedSnapshot: exercise.archivedAt != null,
|
||||||
availableTimeSnapshot: exercise.hasTimeMeasure,
|
availableTimeSnapshot: exercise.hasTimeMeasure,
|
||||||
@ -927,6 +929,7 @@ final class _ProgramExerciseDraft {
|
|||||||
exerciseNameSnapshot: exercise.exerciseNameSnapshot,
|
exerciseNameSnapshot: exercise.exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot: exercise.exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot: exercise.exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot: exercise.exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot: exercise.exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshot: exercise.exerciseImageMediaIdsSnapshot,
|
||||||
exerciseVideoMediaIdSnapshot: exercise.exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot: exercise.exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot: exercise.exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot: exercise.exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot: exercise.availableTimeSnapshot,
|
availableTimeSnapshot: exercise.availableTimeSnapshot,
|
||||||
@ -955,6 +958,7 @@ final class _ProgramExerciseDraft {
|
|||||||
final String exerciseNameSnapshot;
|
final String exerciseNameSnapshot;
|
||||||
final String? exerciseDescriptionSnapshot;
|
final String? exerciseDescriptionSnapshot;
|
||||||
final String? exerciseImageMediaIdSnapshot;
|
final String? exerciseImageMediaIdSnapshot;
|
||||||
|
final List<String> exerciseImageMediaIdsSnapshot;
|
||||||
final String? exerciseVideoMediaIdSnapshot;
|
final String? exerciseVideoMediaIdSnapshot;
|
||||||
final bool exerciseArchivedSnapshot;
|
final bool exerciseArchivedSnapshot;
|
||||||
final bool availableTimeSnapshot;
|
final bool availableTimeSnapshot;
|
||||||
@ -979,6 +983,7 @@ final class _ProgramExerciseDraft {
|
|||||||
exerciseNameSnapshot: exerciseNameSnapshot,
|
exerciseNameSnapshot: exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot: exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot: exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshot: exerciseImageMediaIdsSnapshot,
|
||||||
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot: exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot: exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot: availableTimeSnapshot,
|
availableTimeSnapshot: availableTimeSnapshot,
|
||||||
@ -1006,6 +1011,7 @@ final class _ProgramExerciseDraft {
|
|||||||
exerciseNameSnapshot: exerciseNameSnapshot,
|
exerciseNameSnapshot: exerciseNameSnapshot,
|
||||||
exerciseDescriptionSnapshot: exerciseDescriptionSnapshot,
|
exerciseDescriptionSnapshot: exerciseDescriptionSnapshot,
|
||||||
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot,
|
exerciseImageMediaIdSnapshot: exerciseImageMediaIdSnapshot,
|
||||||
|
exerciseImageMediaIdsSnapshot: exerciseImageMediaIdsSnapshot,
|
||||||
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot,
|
exerciseVideoMediaIdSnapshot: exerciseVideoMediaIdSnapshot,
|
||||||
exerciseArchivedSnapshot: exerciseArchivedSnapshot,
|
exerciseArchivedSnapshot: exerciseArchivedSnapshot,
|
||||||
availableTimeSnapshot: availableTimeSnapshot,
|
availableTimeSnapshot: availableTimeSnapshot,
|
||||||
|
|||||||
@ -130,6 +130,20 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
Text(_exercise.name, style: Theme.of(context).textTheme.headlineMedium),
|
Text(_exercise.name, style: Theme.of(context).textTheme.headlineMedium),
|
||||||
|
if (_exercise.hasMedia) ...[
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerLeft,
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Voir les médias de l’exercice',
|
||||||
|
child: OutlinedButton.icon(
|
||||||
|
onPressed: () => _openExerciseMedia(_exercise),
|
||||||
|
icon: const Icon(Icons.perm_media_outlined),
|
||||||
|
label: const Text('Voir médias'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
SetMeasureInput(
|
SetMeasureInput(
|
||||||
exercise: _exercise,
|
exercise: _exercise,
|
||||||
@ -183,6 +197,19 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
|||||||
fontSize: 30,
|
fontSize: 30,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (nextExercise.hasMedia) ...[
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
Center(
|
||||||
|
child: Tooltip(
|
||||||
|
message: 'Voir les médias de l’exercice',
|
||||||
|
child: OutlinedButton.icon(
|
||||||
|
onPressed: () => _openExerciseMedia(nextExercise),
|
||||||
|
icon: const Icon(Icons.perm_media_outlined),
|
||||||
|
label: const Text('Voir médias'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Row(
|
Row(
|
||||||
@ -282,6 +309,23 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _openExerciseMedia(ExecutionExercise exercise) async {
|
||||||
|
if (!exercise.hasMedia) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await showModalBottomSheet<void>(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
useSafeArea: true,
|
||||||
|
builder: (context) => _ExerciseMediaSheet(
|
||||||
|
exercise: exercise,
|
||||||
|
restRemainingSeconds: _mode == WorkoutExecutionMode.rest
|
||||||
|
? _remainingRestSeconds
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
bool get _canPauseFromNavigation {
|
bool get _canPauseFromNavigation {
|
||||||
return _mode == WorkoutExecutionMode.active ||
|
return _mode == WorkoutExecutionMode.active ||
|
||||||
_mode == WorkoutExecutionMode.rest;
|
_mode == WorkoutExecutionMode.rest;
|
||||||
@ -816,6 +860,228 @@ final class _RestPlanBanner extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum _MediaSheetSection { images, video }
|
||||||
|
|
||||||
|
final class _ExerciseMediaSheet extends StatefulWidget {
|
||||||
|
const _ExerciseMediaSheet({
|
||||||
|
required this.exercise,
|
||||||
|
this.restRemainingSeconds,
|
||||||
|
});
|
||||||
|
|
||||||
|
final ExecutionExercise exercise;
|
||||||
|
final int? restRemainingSeconds;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_ExerciseMediaSheet> createState() => _ExerciseMediaSheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
final class _ExerciseMediaSheetState extends State<_ExerciseMediaSheet> {
|
||||||
|
late final PageController _pageController;
|
||||||
|
late _MediaSheetSection _section;
|
||||||
|
var _imageIndex = 0;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_pageController = PageController();
|
||||||
|
_section = widget.exercise.imageMediaIds.isNotEmpty
|
||||||
|
? _MediaSheetSection.images
|
||||||
|
: _MediaSheetSection.video;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_pageController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final exercise = widget.exercise;
|
||||||
|
final hasImages = exercise.imageMediaIds.isNotEmpty;
|
||||||
|
final hasVideo = exercise.videoMediaId != null;
|
||||||
|
return SizedBox(
|
||||||
|
height: MediaQuery.of(context).size.height * 0.95,
|
||||||
|
child: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text('Médias de l’exercice'),
|
||||||
|
Text(exercise.name, style: Theme.of(context).textTheme.bodySmall),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
tooltip: 'Fermer',
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
icon: const Icon(Icons.close),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: ListView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
children: [
|
||||||
|
if (widget.restRemainingSeconds != null) ...[
|
||||||
|
_RestPlanBanner(remainingSeconds: widget.restRemainingSeconds!),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
if (hasImages && hasVideo) ...[
|
||||||
|
Wrap(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
ChoiceChip(
|
||||||
|
label: const Text('Images'),
|
||||||
|
selected: _section == _MediaSheetSection.images,
|
||||||
|
onSelected: (_) {
|
||||||
|
setState(() => _section = _MediaSheetSection.images);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ChoiceChip(
|
||||||
|
label: const Text('Vidéo'),
|
||||||
|
selected: _section == _MediaSheetSection.video,
|
||||||
|
onSelected: (_) {
|
||||||
|
setState(() => _section = _MediaSheetSection.video);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
if (_section == _MediaSheetSection.images && hasImages)
|
||||||
|
_ImageMediaGallery(
|
||||||
|
imageMediaIds: exercise.imageMediaIds,
|
||||||
|
pageController: _pageController,
|
||||||
|
currentIndex: _imageIndex,
|
||||||
|
onPageChanged: (index) => setState(() => _imageIndex = index),
|
||||||
|
)
|
||||||
|
else if (hasVideo)
|
||||||
|
_VideoMediaPanel(videoMediaId: exercise.videoMediaId!),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class _ImageMediaGallery extends StatelessWidget {
|
||||||
|
const _ImageMediaGallery({
|
||||||
|
required this.imageMediaIds,
|
||||||
|
required this.pageController,
|
||||||
|
required this.currentIndex,
|
||||||
|
required this.onPageChanged,
|
||||||
|
});
|
||||||
|
|
||||||
|
final List<String> imageMediaIds;
|
||||||
|
final PageController pageController;
|
||||||
|
final int currentIndex;
|
||||||
|
final ValueChanged<int> onPageChanged;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CourtBlazerAccentPanel(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: Text(
|
||||||
|
'${currentIndex + 1}/${imageMediaIds.length}',
|
||||||
|
style: Theme.of(context).textTheme.labelLarge?.copyWith(
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 12),
|
||||||
|
SizedBox(
|
||||||
|
height: 320,
|
||||||
|
child: PageView.builder(
|
||||||
|
controller: pageController,
|
||||||
|
itemCount: imageMediaIds.length,
|
||||||
|
onPageChanged: onPageChanged,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
return _ImageMediaPage(
|
||||||
|
mediaAssetId: imageMediaIds[index],
|
||||||
|
index: index,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class _ImageMediaPage extends StatelessWidget {
|
||||||
|
const _ImageMediaPage({required this.mediaAssetId, required this.index});
|
||||||
|
|
||||||
|
final String mediaAssetId;
|
||||||
|
final int index;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final tokens = courtBlazerTokensOf(context);
|
||||||
|
return Container(
|
||||||
|
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
borderRadius: BorderRadius.circular(6),
|
||||||
|
border: Border.all(color: tokens.border),
|
||||||
|
color: Theme.of(context).colorScheme.surface,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.image_outlined,
|
||||||
|
size: 64,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text(
|
||||||
|
'Image ${index + 1}',
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(mediaAssetId, style: Theme.of(context).textTheme.bodySmall),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final class _VideoMediaPanel extends StatelessWidget {
|
||||||
|
const _VideoMediaPanel({required this.videoMediaId});
|
||||||
|
|
||||||
|
final String videoMediaId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return CourtBlazerAccentPanel(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: SizedBox(
|
||||||
|
height: 260,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Icons.play_circle_outline,
|
||||||
|
size: 64,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Text('Vidéo', style: Theme.of(context).textTheme.titleMedium),
|
||||||
|
const SizedBox(height: 4),
|
||||||
|
Text(videoMediaId, style: Theme.of(context).textTheme.bodySmall),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final class _WorkoutPlanSetTile extends StatelessWidget {
|
final class _WorkoutPlanSetTile extends StatelessWidget {
|
||||||
const _WorkoutPlanSetTile({
|
const _WorkoutPlanSetTile({
|
||||||
required this.position,
|
required this.position,
|
||||||
@ -1364,6 +1630,8 @@ final class ExecutionExercise {
|
|||||||
required this.repsEnabled,
|
required this.repsEnabled,
|
||||||
required this.scoreEnabled,
|
required this.scoreEnabled,
|
||||||
required this.restSeconds,
|
required this.restSeconds,
|
||||||
|
this.imageMediaIds = const [],
|
||||||
|
this.videoMediaId,
|
||||||
this.scoreInputMode = ScoreInputMode.manual,
|
this.scoreInputMode = ScoreInputMode.manual,
|
||||||
this.scoreLabel,
|
this.scoreLabel,
|
||||||
this.targetTimeSeconds,
|
this.targetTimeSeconds,
|
||||||
@ -1386,6 +1654,10 @@ final class ExecutionExercise {
|
|||||||
repsEnabled: exercise['repsEnabled'] as bool,
|
repsEnabled: exercise['repsEnabled'] as bool,
|
||||||
scoreEnabled: exercise['scoreEnabled'] as bool,
|
scoreEnabled: exercise['scoreEnabled'] as bool,
|
||||||
restSeconds: exercise['restSecondsOverride'] as int? ?? 0,
|
restSeconds: exercise['restSecondsOverride'] as int? ?? 0,
|
||||||
|
imageMediaIds: _imageMediaIdsFromSnapshot(exercise),
|
||||||
|
videoMediaId:
|
||||||
|
exercise['videoMediaIdSnapshot'] as String? ??
|
||||||
|
exercise['exerciseVideoMediaIdSnapshot'] as String?,
|
||||||
scoreInputMode: _scoreInputModeFromSnapshot(
|
scoreInputMode: _scoreInputModeFromSnapshot(
|
||||||
exercise['scoreInputModeSnapshot'],
|
exercise['scoreInputModeSnapshot'],
|
||||||
),
|
),
|
||||||
@ -1410,6 +1682,8 @@ final class ExecutionExercise {
|
|||||||
final bool repsEnabled;
|
final bool repsEnabled;
|
||||||
final bool scoreEnabled;
|
final bool scoreEnabled;
|
||||||
final int restSeconds;
|
final int restSeconds;
|
||||||
|
final List<String> imageMediaIds;
|
||||||
|
final String? videoMediaId;
|
||||||
final ScoreInputMode scoreInputMode;
|
final ScoreInputMode scoreInputMode;
|
||||||
final String? scoreLabel;
|
final String? scoreLabel;
|
||||||
final int? targetTimeSeconds;
|
final int? targetTimeSeconds;
|
||||||
@ -1420,6 +1694,26 @@ final class ExecutionExercise {
|
|||||||
bool get manualScoreEnabled {
|
bool get manualScoreEnabled {
|
||||||
return scoreEnabled && scoreInputMode == ScoreInputMode.manual;
|
return scoreEnabled && scoreInputMode == ScoreInputMode.manual;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get hasMedia {
|
||||||
|
return imageMediaIds.isNotEmpty || videoMediaId != null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> _imageMediaIdsFromSnapshot(Map<String, dynamic> exercise) {
|
||||||
|
final imageMediaIds =
|
||||||
|
exercise['imageMediaIdsSnapshot'] ??
|
||||||
|
exercise['exerciseImageMediaIdsSnapshot'];
|
||||||
|
if (imageMediaIds is List) {
|
||||||
|
return imageMediaIds
|
||||||
|
.whereType<String>()
|
||||||
|
.where((id) => id.trim().isNotEmpty)
|
||||||
|
.toList(growable: false);
|
||||||
|
}
|
||||||
|
final imageMediaId = exercise['exerciseImageMediaIdSnapshot'] as String?;
|
||||||
|
return [
|
||||||
|
if (imageMediaId != null && imageMediaId.trim().isNotEmpty) imageMediaId,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
ScoreInputMode _scoreInputModeFromSnapshot(Object? value) {
|
ScoreInputMode _scoreInputModeFromSnapshot(Object? value) {
|
||||||
|
|||||||
@ -225,6 +225,66 @@ void main() {
|
|||||||
expect(updated.imageMediaId, 'media-1');
|
expect(updated.imageMediaId, 'media-1');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('program exercise snapshot keeps the full image gallery', () async {
|
||||||
|
final exerciseRepository = _FakeExerciseRepository()
|
||||||
|
..exercise = Exercise(
|
||||||
|
metadata: _metadata('exercise-1'),
|
||||||
|
name: 'Squat',
|
||||||
|
imageMediaIds: const ['media-1', 'media-2', 'media-3'],
|
||||||
|
videoMediaId: 'video-1',
|
||||||
|
hasTimeMeasure: false,
|
||||||
|
hasRepsMeasure: true,
|
||||||
|
hasScoreMeasure: false,
|
||||||
|
defaultTargetReps: 10,
|
||||||
|
);
|
||||||
|
final programRepository = _FakeProgramRepository()
|
||||||
|
..programs.add(
|
||||||
|
Program(
|
||||||
|
metadata: _metadata('program-1'),
|
||||||
|
name: 'Jambes',
|
||||||
|
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.exerciseImageMediaIdSnapshot, 'media-1');
|
||||||
|
expect(snapshot.exerciseImageMediaIdsSnapshot, [
|
||||||
|
'media-1',
|
||||||
|
'media-2',
|
||||||
|
'media-3',
|
||||||
|
]);
|
||||||
|
expect(snapshot.exerciseVideoMediaIdSnapshot, 'video-1');
|
||||||
|
expect(snapshot.toSnapshotJson()['imageMediaIdsSnapshot'], [
|
||||||
|
'media-1',
|
||||||
|
'media-2',
|
||||||
|
'media-3',
|
||||||
|
]);
|
||||||
|
expect(
|
||||||
|
programRepository
|
||||||
|
.programs
|
||||||
|
.single
|
||||||
|
.exercises
|
||||||
|
.single
|
||||||
|
.exerciseImageMediaIdsSnapshot,
|
||||||
|
snapshot.exerciseImageMediaIdsSnapshot,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
test('delete exercise removes it from referencing programs', () async {
|
test('delete exercise removes it from referencing programs', () async {
|
||||||
final exerciseRepository = _FakeExerciseRepository()
|
final exerciseRepository = _FakeExerciseRepository()
|
||||||
..exercise = Exercise(
|
..exercise = Exercise(
|
||||||
|
|||||||
@ -116,6 +116,131 @@ void main() {
|
|||||||
expect(find.text('Pas de repos'), findsOneWidget);
|
expect(find.text('Pas de repos'), findsOneWidget);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('le bouton médias est absent sans média', (tester) async {
|
||||||
|
final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12));
|
||||||
|
final session = ActiveWorkoutSession(
|
||||||
|
metadata: _metadata('session-1'),
|
||||||
|
sourceWorkoutTemplateId: 'template-1',
|
||||||
|
status: ActiveWorkoutStatus.running,
|
||||||
|
startedAt: DateTime.utc(2026, 7, 17, 12),
|
||||||
|
lastPersistedAt: DateTime.utc(2026, 7, 17, 12),
|
||||||
|
elapsedActiveMs: 0,
|
||||||
|
currentProgramIndex: 0,
|
||||||
|
currentExerciseIndex: 0,
|
||||||
|
currentSetIndex: 0,
|
||||||
|
resolvedTemplateSnapshotJson: _sessionSnapshot(),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: WorkoutExecutionScreen(
|
||||||
|
initialSession: session,
|
||||||
|
activeUseCases: _activeUseCases(
|
||||||
|
_FakeActiveSessionRepository(),
|
||||||
|
clock,
|
||||||
|
),
|
||||||
|
closeUseCase: _closeUseCase(_FakeActiveSessionRepository(), clock),
|
||||||
|
historyUseCases: _historyUseCases(clock),
|
||||||
|
workoutTemplateUseCases: _workoutTemplateUseCases(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.text('Voir médias'), findsNothing);
|
||||||
|
expect(find.byTooltip('Voir les médias de l’exercice'), findsNothing);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('le bouton médias ouvre la sheet si médias présents', (
|
||||||
|
tester,
|
||||||
|
) async {
|
||||||
|
final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12));
|
||||||
|
final session = ActiveWorkoutSession(
|
||||||
|
metadata: _metadata('session-1'),
|
||||||
|
sourceWorkoutTemplateId: 'template-1',
|
||||||
|
status: ActiveWorkoutStatus.running,
|
||||||
|
startedAt: DateTime.utc(2026, 7, 17, 12),
|
||||||
|
lastPersistedAt: DateTime.utc(2026, 7, 17, 12),
|
||||||
|
elapsedActiveMs: 0,
|
||||||
|
currentProgramIndex: 0,
|
||||||
|
currentExerciseIndex: 0,
|
||||||
|
currentSetIndex: 0,
|
||||||
|
resolvedTemplateSnapshotJson: _sessionSnapshot(
|
||||||
|
imageMediaIds: const ['image-1'],
|
||||||
|
videoMediaId: 'video-1',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: WorkoutExecutionScreen(
|
||||||
|
initialSession: session,
|
||||||
|
activeUseCases: _activeUseCases(
|
||||||
|
_FakeActiveSessionRepository(),
|
||||||
|
clock,
|
||||||
|
),
|
||||||
|
closeUseCase: _closeUseCase(_FakeActiveSessionRepository(), clock),
|
||||||
|
historyUseCases: _historyUseCases(clock),
|
||||||
|
workoutTemplateUseCases: _workoutTemplateUseCases(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(find.byTooltip('Voir les médias de l’exercice'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(find.text('Voir médias'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.text('Médias de l’exercice'), findsOneWidget);
|
||||||
|
expect(find.text('Images'), findsOneWidget);
|
||||||
|
expect(find.text('Vidéo'), findsOneWidget);
|
||||||
|
expect(find.text('1/1'), findsOneWidget);
|
||||||
|
expect(find.text('Image 1'), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('la galerie médias navigue entre les images', (tester) async {
|
||||||
|
final clock = _FakeClock(DateTime.utc(2026, 7, 17, 12));
|
||||||
|
final session = ActiveWorkoutSession(
|
||||||
|
metadata: _metadata('session-1'),
|
||||||
|
sourceWorkoutTemplateId: 'template-1',
|
||||||
|
status: ActiveWorkoutStatus.running,
|
||||||
|
startedAt: DateTime.utc(2026, 7, 17, 12),
|
||||||
|
lastPersistedAt: DateTime.utc(2026, 7, 17, 12),
|
||||||
|
elapsedActiveMs: 0,
|
||||||
|
currentProgramIndex: 0,
|
||||||
|
currentExerciseIndex: 0,
|
||||||
|
currentSetIndex: 0,
|
||||||
|
resolvedTemplateSnapshotJson: _sessionSnapshot(
|
||||||
|
imageMediaIds: const ['image-1', 'image-2', 'image-3'],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.pumpWidget(
|
||||||
|
MaterialApp(
|
||||||
|
home: WorkoutExecutionScreen(
|
||||||
|
initialSession: session,
|
||||||
|
activeUseCases: _activeUseCases(
|
||||||
|
_FakeActiveSessionRepository(),
|
||||||
|
clock,
|
||||||
|
),
|
||||||
|
closeUseCase: _closeUseCase(_FakeActiveSessionRepository(), clock),
|
||||||
|
historyUseCases: _historyUseCases(clock),
|
||||||
|
workoutTemplateUseCases: _workoutTemplateUseCases(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tap(find.text('Voir médias'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.text('1/3'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.drag(find.byType(PageView), const Offset(-400, 0));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.text('2/3'), findsOneWidget);
|
||||||
|
expect(find.text('Image 2'), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
testWidgets('un repos actif est repris avec le temps restant recalculé', (
|
testWidgets('un repos actif est repris avec le temps restant recalculé', (
|
||||||
tester,
|
tester,
|
||||||
) async {
|
) async {
|
||||||
@ -559,6 +684,8 @@ String _sessionSnapshot({
|
|||||||
double targetScore = 80,
|
double targetScore = 80,
|
||||||
String scoreUnit = 'kg',
|
String scoreUnit = 'kg',
|
||||||
ScoreInputMode scoreInputMode = ScoreInputMode.manual,
|
ScoreInputMode scoreInputMode = ScoreInputMode.manual,
|
||||||
|
List<String> imageMediaIds = const [],
|
||||||
|
String? videoMediaId,
|
||||||
}) {
|
}) {
|
||||||
return jsonEncode({
|
return jsonEncode({
|
||||||
'name': 'Séance jambes',
|
'name': 'Séance jambes',
|
||||||
@ -582,6 +709,10 @@ String _sessionSnapshot({
|
|||||||
'scoreLabelSnapshot': 'Score',
|
'scoreLabelSnapshot': 'Score',
|
||||||
'scoreUnitSnapshot': scoreUnit,
|
'scoreUnitSnapshot': scoreUnit,
|
||||||
'restSecondsOverride': restSeconds,
|
'restSecondsOverride': restSeconds,
|
||||||
|
'exerciseImageMediaIdsSnapshot': imageMediaIds,
|
||||||
|
'imageMediaIdsSnapshot': imageMediaIds,
|
||||||
|
'exerciseVideoMediaIdSnapshot': videoMediaId,
|
||||||
|
'videoMediaIdSnapshot': videoMediaId,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
|||||||
Reference in New Issue
Block a user