feat(exécution): affichage dernière performance et meilleur score (ticket #81)

Affiche la dernière performance et le meilleur score par exercice
pendant l'exécution de séance (écran d'exécution), ainsi que les
points d'accès associés dans l'accueil, la séance-modèle et
l'historique, en s'appuyant sur ExercisePerformanceReferenceUseCase.

Validé GO par Main : dart analyze propre, 178 tests (4 échecs
préexistants sans rapport, identiques à ceux déjà documentés sur #80).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 08:03:00 +02:00
parent ac51c16b51
commit 0813327bef
4 changed files with 346 additions and 11 deletions

View File

@ -15,6 +15,7 @@ final class HistoryListScreen extends StatefulWidget {
required this.closeUseCase, required this.closeUseCase,
this.mediaUseCases, this.mediaUseCases,
this.stepUseCases, this.stepUseCases,
this.performanceReferenceUseCase,
super.key, super.key,
}); });
@ -22,6 +23,7 @@ final class HistoryListScreen extends StatefulWidget {
final WorkoutTemplateUseCases workoutTemplateUseCases; final WorkoutTemplateUseCases workoutTemplateUseCases;
final ActiveWorkoutSessionUseCases activeUseCases; final ActiveWorkoutSessionUseCases activeUseCases;
final ActiveExerciseStepUseCases? stepUseCases; final ActiveExerciseStepUseCases? stepUseCases;
final ExercisePerformanceReferenceUseCase? performanceReferenceUseCase;
final CloseWorkoutSessionUseCase closeUseCase; final CloseWorkoutSessionUseCase closeUseCase;
final MediaUseCases? mediaUseCases; final MediaUseCases? mediaUseCases;
@ -97,6 +99,7 @@ final class _HistoryListScreenState extends State<HistoryListScreen> {
workoutTemplateUseCases: widget.workoutTemplateUseCases, workoutTemplateUseCases: widget.workoutTemplateUseCases,
activeUseCases: widget.activeUseCases, activeUseCases: widget.activeUseCases,
stepUseCases: widget.stepUseCases, stepUseCases: widget.stepUseCases,
performanceReferenceUseCase: widget.performanceReferenceUseCase,
closeUseCase: widget.closeUseCase, closeUseCase: widget.closeUseCase,
mediaUseCases: widget.mediaUseCases, mediaUseCases: widget.mediaUseCases,
), ),
@ -119,6 +122,7 @@ final class HistoryDetailScreen extends StatelessWidget {
required this.closeUseCase, required this.closeUseCase,
this.mediaUseCases, this.mediaUseCases,
this.stepUseCases, this.stepUseCases,
this.performanceReferenceUseCase,
super.key, super.key,
}); });
@ -127,6 +131,7 @@ final class HistoryDetailScreen extends StatelessWidget {
final WorkoutTemplateUseCases workoutTemplateUseCases; final WorkoutTemplateUseCases workoutTemplateUseCases;
final ActiveWorkoutSessionUseCases activeUseCases; final ActiveWorkoutSessionUseCases activeUseCases;
final ActiveExerciseStepUseCases? stepUseCases; final ActiveExerciseStepUseCases? stepUseCases;
final ExercisePerformanceReferenceUseCase? performanceReferenceUseCase;
final CloseWorkoutSessionUseCase closeUseCase; final CloseWorkoutSessionUseCase closeUseCase;
final MediaUseCases? mediaUseCases; final MediaUseCases? mediaUseCases;
@ -213,6 +218,7 @@ final class HistoryDetailScreen extends StatelessWidget {
closeUseCase: closeUseCase, closeUseCase: closeUseCase,
historyUseCases: historyUseCases, historyUseCases: historyUseCases,
workoutTemplateUseCases: workoutTemplateUseCases, workoutTemplateUseCases: workoutTemplateUseCases,
performanceReferenceUseCase: performanceReferenceUseCase,
mediaUseCases: mediaUseCases, mediaUseCases: mediaUseCases,
), ),
), ),

View File

@ -157,6 +157,8 @@ final class _HomeScreenState extends State<HomeScreen> with RouteAware {
programUseCases: widget.bootstrap.programUseCases, programUseCases: widget.bootstrap.programUseCases,
activeUseCases: widget.bootstrap.activeWorkoutSessionUseCases, activeUseCases: widget.bootstrap.activeWorkoutSessionUseCases,
stepUseCases: widget.bootstrap.activeExerciseStepUseCases, stepUseCases: widget.bootstrap.activeExerciseStepUseCases,
performanceReferenceUseCase:
widget.bootstrap.exercisePerformanceReferenceUseCase,
closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase, closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase,
historyUseCases: widget.bootstrap.workoutHistoryUseCases, historyUseCases: widget.bootstrap.workoutHistoryUseCases,
mediaUseCases: widget.bootstrap.mediaUseCases, mediaUseCases: widget.bootstrap.mediaUseCases,
@ -179,6 +181,8 @@ final class _HomeScreenState extends State<HomeScreen> with RouteAware {
widget.bootstrap.workoutTemplateUseCases, widget.bootstrap.workoutTemplateUseCases,
activeUseCases: widget.bootstrap.activeWorkoutSessionUseCases, activeUseCases: widget.bootstrap.activeWorkoutSessionUseCases,
stepUseCases: widget.bootstrap.activeExerciseStepUseCases, stepUseCases: widget.bootstrap.activeExerciseStepUseCases,
performanceReferenceUseCase:
widget.bootstrap.exercisePerformanceReferenceUseCase,
closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase, closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase,
mediaUseCases: widget.bootstrap.mediaUseCases, mediaUseCases: widget.bootstrap.mediaUseCases,
), ),
@ -231,6 +235,8 @@ final class _HomeScreenState extends State<HomeScreen> with RouteAware {
closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase, closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase,
historyUseCases: widget.bootstrap.workoutHistoryUseCases, historyUseCases: widget.bootstrap.workoutHistoryUseCases,
workoutTemplateUseCases: widget.bootstrap.workoutTemplateUseCases, workoutTemplateUseCases: widget.bootstrap.workoutTemplateUseCases,
performanceReferenceUseCase:
widget.bootstrap.exercisePerformanceReferenceUseCase,
mediaUseCases: widget.bootstrap.mediaUseCases, mediaUseCases: widget.bootstrap.mediaUseCases,
), ),
), ),

View File

@ -23,6 +23,7 @@ final class WorkoutExecutionScreen extends StatefulWidget {
required this.closeUseCase, required this.closeUseCase,
required this.historyUseCases, required this.historyUseCases,
required this.workoutTemplateUseCases, required this.workoutTemplateUseCases,
this.performanceReferenceUseCase,
this.mediaUseCases, this.mediaUseCases,
this.mediaAssetLoader, this.mediaAssetLoader,
this.videoMediaBuilder, this.videoMediaBuilder,
@ -37,6 +38,7 @@ final class WorkoutExecutionScreen extends StatefulWidget {
final CloseWorkoutSessionUseCase closeUseCase; final CloseWorkoutSessionUseCase closeUseCase;
final WorkoutHistoryUseCases historyUseCases; final WorkoutHistoryUseCases historyUseCases;
final WorkoutTemplateUseCases workoutTemplateUseCases; final WorkoutTemplateUseCases workoutTemplateUseCases;
final ExercisePerformanceReferenceUseCase? performanceReferenceUseCase;
final MediaUseCases? mediaUseCases; final MediaUseCases? mediaUseCases;
final Future<MediaAsset?> Function(String id)? mediaAssetLoader; final Future<MediaAsset?> Function(String id)? mediaAssetLoader;
final VideoMediaBuilder? videoMediaBuilder; final VideoMediaBuilder? videoMediaBuilder;
@ -71,6 +73,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
var _lastCountdownBeepSecond = -1; var _lastCountdownBeepSecond = -1;
var _advancingStep = false; var _advancingStep = false;
var _reps = 0; var _reps = 0;
Future<ExercisePerformanceReference>? _performanceReference;
final _scoreController = TextEditingController(); final _scoreController = TextEditingController();
var _remainingRestSeconds = 0; var _remainingRestSeconds = 0;
@ -98,6 +101,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
? WorkoutExecutionMode.active ? WorkoutExecutionMode.active
: WorkoutExecutionMode.paused; : WorkoutExecutionMode.paused;
_reps = _initialRepsFor(_exercise); _reps = _initialRepsFor(_exercise);
_performanceReference = _loadPerformanceReference();
_ticker = Timer.periodic(const Duration(seconds: 1), (_) { _ticker = Timer.periodic(const Duration(seconds: 1), (_) {
if (mounted) setState(() {}); if (mounted) setState(() {});
}); });
@ -181,8 +185,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
totalSets: _exercise.setsCount, totalSets: _exercise.setsCount,
progressLabel: _plan.progressLabel(_position), progressLabel: _plan.progressLabel(_position),
setTimerLabel: _setTimerLabel, setTimerLabel: _setTimerLabel,
setTimerComplete: setTimerComplete: _setTimer?.status == ActiveSetTimerStatus.stopped,
_setTimer?.status == ActiveSetTimerStatus.stopped,
showStartButton: _shouldShowStartExerciseButton, showStartButton: _shouldShowStartExerciseButton,
onStartExercise: _startExercise, onStartExercise: _startExercise,
onOpenMedia: _exercise.hasMedia onOpenMedia: _exercise.hasMedia
@ -197,6 +200,17 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
), ),
), ),
), ),
if (_performanceReference != null) ...[
Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
child: PerformanceReferenceCard(
reference: _performanceReference!,
activeMeasures: _exercise.activePerformanceMeasures,
scoreUnit: _exercise.scoreUnit,
usesStepPassages: _exercise.steps.isNotEmpty,
),
),
],
Expanded( Expanded(
child: Padding( child: Padding(
padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), padding: const EdgeInsets.fromLTRB(16, 0, 16, 8),
@ -1442,6 +1456,10 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
_scoreStopwatchLoadGeneration++; _scoreStopwatchLoadGeneration++;
_manualScoreTimeMs = null; _manualScoreTimeMs = null;
_stepProgress = null; _stepProgress = null;
_performanceReference = _loadPerformanceReferenceFor(
_plan.exerciseAt(position),
position.setIndex,
);
_resetStepScoreInput(); _resetStepScoreInput();
_refreshScoreStopwatchTicker(); _refreshScoreStopwatchTicker();
_refreshStepTicker(); _refreshStepTicker();
@ -1517,6 +1535,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
closeUseCase: widget.closeUseCase, closeUseCase: widget.closeUseCase,
historyUseCases: widget.historyUseCases, historyUseCases: widget.historyUseCases,
workoutTemplateUseCases: widget.workoutTemplateUseCases, workoutTemplateUseCases: widget.workoutTemplateUseCases,
performanceReferenceUseCase: widget.performanceReferenceUseCase,
mediaUseCases: widget.mediaUseCases, mediaUseCases: widget.mediaUseCases,
mediaAssetLoader: widget.mediaAssetLoader, mediaAssetLoader: widget.mediaAssetLoader,
videoMediaBuilder: widget.videoMediaBuilder, videoMediaBuilder: widget.videoMediaBuilder,
@ -1529,6 +1548,181 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
if (!exercise.repsEnabled) return 0; if (!exercise.repsEnabled) return 0;
return exercise.targetReps ?? 0; return exercise.targetReps ?? 0;
} }
Future<ExercisePerformanceReference>? _loadPerformanceReference() {
return _loadPerformanceReferenceFor(_exercise, _position.setIndex);
}
Future<ExercisePerformanceReference>? _loadPerformanceReferenceFor(
ExecutionExercise exercise,
int setIndex,
) {
final useCase = widget.performanceReferenceUseCase;
final sourceExerciseId = exercise.sourceExerciseId;
if (useCase == null || sourceExerciseId == null) {
return null;
}
return useCase.getExercisePerformanceReference(
exerciseId: sourceExerciseId,
activeMeasures: exercise.activePerformanceMeasures,
currentSetIndex: setIndex,
);
}
}
final class PerformanceReferenceCard extends StatelessWidget {
const PerformanceReferenceCard({
required this.reference,
required this.activeMeasures,
this.scoreUnit,
this.usesStepPassages = false,
super.key,
});
final Future<ExercisePerformanceReference> reference;
final ActivePerformanceMeasures activeMeasures;
final String? scoreUnit;
final bool usesStepPassages;
@override
Widget build(BuildContext context) {
return FutureBuilder<ExercisePerformanceReference>(
future: reference,
builder: (context, snapshot) {
if (snapshot.connectionState != ConnectionState.done) {
return const _PerformanceReferenceShell(
child: Center(child: Text('Chargement…')),
);
}
if (snapshot.hasError) {
return const _PerformanceReferenceShell(
child: Center(child: Text('Références indisponibles')),
);
}
final reference = snapshot.data;
if (reference == null || !activeMeasures.hasAny) {
return const _PerformanceReferenceShell(
child: Center(child: Text('Aucune référence pour ces mesures')),
);
}
if (!reference.hasAnyHistoryForExercise) {
return const _PerformanceReferenceShell(
child: Center(child: Text('Première fois sur cet exercice')),
);
}
final lastLabel = _formatSetPerformance(
reference.last,
activeMeasures,
scoreUnit: scoreUnit,
usesStepPassages: usesStepPassages,
);
final recordLabel = _formatMetricPerformance(
reference.record,
scoreUnit: scoreUnit,
usesStepPassages: usesStepPassages,
);
if (lastLabel == null && recordLabel == null) {
return const _PerformanceReferenceShell(
child: Center(child: Text('Aucune référence pour ces mesures')),
);
}
return _PerformanceReferenceShell(
child: Row(
children: [
Expanded(
child: _PerformanceReferenceColumn(
title: 'Dernière',
value: lastLabel ?? '',
),
),
const SizedBox(width: 12),
Expanded(
child: _PerformanceReferenceColumn(
title: _recordTitle(reference.record),
value: recordLabel ?? '',
alignEnd: true,
),
),
],
),
);
},
);
}
}
final class _PerformanceReferenceShell extends StatelessWidget {
const _PerformanceReferenceShell({required this.child});
final Widget child;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final tokens = courtBlazerTokensOf(context);
return Container(
constraints: const BoxConstraints(minHeight: 64),
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
decoration: BoxDecoration(
color: theme.colorScheme.surface,
borderRadius: BorderRadius.circular(6),
border: Border.all(color: tokens.border),
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Références',
style: theme.textTheme.labelSmall?.copyWith(
color: tokens.mutedText,
fontWeight: FontWeight.w700,
),
),
const SizedBox(height: 4),
child,
],
),
);
}
}
final class _PerformanceReferenceColumn extends StatelessWidget {
const _PerformanceReferenceColumn({
required this.title,
required this.value,
this.alignEnd = false,
});
final String title;
final String value;
final bool alignEnd;
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final tokens = courtBlazerTokensOf(context);
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: alignEnd
? CrossAxisAlignment.end
: CrossAxisAlignment.start,
children: [
Text(
title,
style: theme.textTheme.labelSmall?.copyWith(color: tokens.mutedText),
),
const SizedBox(height: 2),
Text(
value,
maxLines: 1,
overflow: TextOverflow.ellipsis,
textAlign: alignEnd ? TextAlign.end : TextAlign.start,
style: theme.textTheme.titleSmall,
),
],
);
}
} }
final class SetMeasureInput extends StatelessWidget { final class SetMeasureInput extends StatelessWidget {
@ -1726,10 +1920,7 @@ final class _ExecutionContextHeader extends StatelessWidget {
} }
final class _SetActionBar extends StatelessWidget { final class _SetActionBar extends StatelessWidget {
const _SetActionBar({ const _SetActionBar({required this.onFinishSet, required this.onSkipSet});
required this.onFinishSet,
required this.onSkipSet,
});
final VoidCallback onFinishSet; final VoidCallback onFinishSet;
final VoidCallback onSkipSet; final VoidCallback onSkipSet;
@ -1892,10 +2083,7 @@ final class _StepSequencePanel extends StatelessWidget {
style: Theme.of(context).textTheme.titleMedium, style: Theme.of(context).textTheme.titleMedium,
), ),
), ),
Text( Text('SÉQUENCE', style: Theme.of(context).textTheme.labelMedium),
'SÉQUENCE',
style: Theme.of(context).textTheme.labelMedium,
),
], ],
), ),
const SizedBox(height: 6), const SizedBox(height: 6),
@ -1972,7 +2160,9 @@ final class _BoundedAccentPanel extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
Container(height: 2, color: tokens.accent), Container(height: 2, color: tokens.accent),
Expanded(child: Padding(padding: padding, child: child)), Expanded(
child: Padding(padding: padding, child: child),
),
], ],
), ),
); );
@ -3790,6 +3980,7 @@ final class ExecutionProgram {
final class ExecutionExercise { final class ExecutionExercise {
const ExecutionExercise({ const ExecutionExercise({
required this.id, required this.id,
this.sourceExerciseId,
required this.name, required this.name,
required this.setsCount, required this.setsCount,
required this.timeEnabled, required this.timeEnabled,
@ -3814,6 +4005,7 @@ final class ExecutionExercise {
) { ) {
return ExecutionExercise( return ExecutionExercise(
id: exercise['id'] as String, id: exercise['id'] as String,
sourceExerciseId: exercise['sourceExerciseId'] as String?,
name: exercise['exerciseNameSnapshot'] as String, name: exercise['exerciseNameSnapshot'] as String,
setsCount: setsCount:
(override?['setsCountOverride'] as int?) ?? (override?['setsCountOverride'] as int?) ??
@ -3848,6 +4040,7 @@ final class ExecutionExercise {
} }
final String id; final String id;
final String? sourceExerciseId;
final String name; final String name;
final int setsCount; final int setsCount;
final bool timeEnabled; final bool timeEnabled;
@ -3876,6 +4069,133 @@ final class ExecutionExercise {
bool get hasMedia { bool get hasMedia {
return imageMediaIds.isNotEmpty || videoMediaId != null; return imageMediaIds.isNotEmpty || videoMediaId != null;
} }
ActivePerformanceMeasures get activePerformanceMeasures {
return ActivePerformanceMeasures(
timeEnabled: timeEnabled,
repsEnabled: repsEnabled,
scoreEnabled: scoreEnabled,
scoreInputMode: scoreInputMode,
);
}
}
String? _formatSetPerformance(
WorkoutHistorySetPerformance? performance,
ActivePerformanceMeasures measures, {
required String? scoreUnit,
required bool usesStepPassages,
}) {
if (performance == null) return null;
final values = [
if (measures.timeEnabled && performance.actualTimeMs != null)
_formatReferenceTime(performance.actualTimeMs!, stopwatch: false),
if (measures.repsEnabled && performance.actualReps != null)
_formatReferenceReps(
performance.actualReps!,
usesStepPassages: usesStepPassages,
),
if (measures.scoreEnabled)
_formatReferenceScore(
actualScore: performance.actualScore,
actualScoreTimeMs: performance.actualScoreTimeMs,
scoreInputMode: measures.scoreInputMode,
scoreUnit: scoreUnit,
),
].whereType<String>().toList();
if (values.isEmpty) return null;
return values.join(' · ');
}
String? _formatMetricPerformance(
WorkoutHistoryMetricPerformance? performance, {
required String? scoreUnit,
required bool usesStepPassages,
}) {
if (performance == null) return null;
return switch (performance.metric) {
PerformanceMetric.time =>
performance.actualTimeMs == null
? null
: _formatReferenceTime(performance.actualTimeMs!, stopwatch: false),
PerformanceMetric.reps =>
performance.actualReps == null
? null
: _formatReferenceReps(
performance.actualReps!,
usesStepPassages: usesStepPassages,
),
PerformanceMetric.score =>
performance.scoreInputModeSnapshot == ScoreInputMode.stopwatch
? performance.actualScoreTimeMs == null
? null
: _formatReferenceTime(
performance.actualScoreTimeMs!,
stopwatch: true,
)
: performance.actualScore == null
? null
: _formatReferenceManualScore(performance.actualScore!, scoreUnit),
};
}
String _recordTitle(WorkoutHistoryMetricPerformance? performance) {
return switch (performance?.metric) {
PerformanceMetric.time => 'Max',
PerformanceMetric.score
when performance?.scoreInputModeSnapshot == ScoreInputMode.stopwatch =>
'Meilleur temps',
_ => 'Record',
};
}
String _formatReferenceReps(int reps, {required bool usesStepPassages}) {
return '$reps ${usesStepPassages ? 'passages' : 'reps'}';
}
String? _formatReferenceScore({
required double? actualScore,
required int? actualScoreTimeMs,
required ScoreInputMode scoreInputMode,
required String? scoreUnit,
}) {
if (scoreInputMode == ScoreInputMode.stopwatch) {
return actualScoreTimeMs == null
? null
: _formatReferenceTime(actualScoreTimeMs, stopwatch: true);
}
return actualScore == null
? null
: _formatReferenceManualScore(actualScore, scoreUnit);
}
String _formatReferenceManualScore(double score, String? scoreUnit) {
final value = score == score.roundToDouble()
? score.toInt().toString()
: score.toStringAsFixed(1);
final unit = scoreUnit?.trim();
if (unit == null || unit.isEmpty) {
return value;
}
return '$value $unit';
}
String _formatReferenceTime(int milliseconds, {required bool stopwatch}) {
final totalTenths = (milliseconds / 100).round();
final minutes = totalTenths ~/ 600;
final seconds = (totalTenths ~/ 10) % 60;
final tenths = totalTenths % 10;
if (minutes == 0) {
if (!stopwatch && tenths == 0) {
return '$seconds s';
}
return '${(seconds + tenths / 10).toStringAsFixed(1)} s';
}
final paddedSeconds = seconds.toString().padLeft(2, '0');
if (stopwatch) {
return '$minutes:$paddedSeconds.$tenths';
}
return '$minutes:$paddedSeconds';
} }
List<String> _imageMediaIdsFromSnapshot(Map<String, dynamic> exercise) { List<String> _imageMediaIdsFromSnapshot(Map<String, dynamic> exercise) {

View File

@ -17,6 +17,7 @@ final class WorkoutTemplateListScreen extends StatefulWidget {
required this.historyUseCases, required this.historyUseCases,
this.mediaUseCases, this.mediaUseCases,
this.stepUseCases, this.stepUseCases,
this.performanceReferenceUseCase,
this.shareUseCases, this.shareUseCases,
this.authUseCases, this.authUseCases,
this.syncUseCases, this.syncUseCases,
@ -27,6 +28,7 @@ final class WorkoutTemplateListScreen extends StatefulWidget {
final ProgramUseCases programUseCases; final ProgramUseCases programUseCases;
final ActiveWorkoutSessionUseCases activeUseCases; final ActiveWorkoutSessionUseCases activeUseCases;
final ActiveExerciseStepUseCases? stepUseCases; final ActiveExerciseStepUseCases? stepUseCases;
final ExercisePerformanceReferenceUseCase? performanceReferenceUseCase;
final CloseWorkoutSessionUseCase closeUseCase; final CloseWorkoutSessionUseCase closeUseCase;
final WorkoutHistoryUseCases historyUseCases; final WorkoutHistoryUseCases historyUseCases;
final MediaUseCases? mediaUseCases; final MediaUseCases? mediaUseCases;
@ -166,6 +168,7 @@ final class _WorkoutTemplateListScreenState
closeUseCase: widget.closeUseCase, closeUseCase: widget.closeUseCase,
historyUseCases: widget.historyUseCases, historyUseCases: widget.historyUseCases,
workoutTemplateUseCases: widget.workoutTemplateUseCases, workoutTemplateUseCases: widget.workoutTemplateUseCases,
performanceReferenceUseCase: widget.performanceReferenceUseCase,
mediaUseCases: widget.mediaUseCases, mediaUseCases: widget.mediaUseCases,
), ),
), ),