Corrige l'affichage des images (#41) et de la vidéo (#42) dans le carrousel de médias, et le format du chrono de score qui n'affichait que les secondes (#43) sur workout_execution_screen.dart. Ajoute la dépendance video_player (2.13.0) pour la lecture vidéo. Ajuste home_screen.dart, history_screen.dart et workout_template_screen.dart en conséquence. flutter analyze propre, flutter test 77/77 vert (plus aucun hang), pub get résolu. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@ -13,6 +13,7 @@ final class HistoryListScreen extends StatefulWidget {
|
||||
required this.workoutTemplateUseCases,
|
||||
required this.activeUseCases,
|
||||
required this.closeUseCase,
|
||||
this.mediaUseCases,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@ -20,6 +21,7 @@ final class HistoryListScreen extends StatefulWidget {
|
||||
final WorkoutTemplateUseCases workoutTemplateUseCases;
|
||||
final ActiveWorkoutSessionUseCases activeUseCases;
|
||||
final CloseWorkoutSessionUseCase closeUseCase;
|
||||
final MediaUseCases? mediaUseCases;
|
||||
|
||||
@override
|
||||
State<HistoryListScreen> createState() => _HistoryListScreenState();
|
||||
@ -93,6 +95,7 @@ final class _HistoryListScreenState extends State<HistoryListScreen> {
|
||||
workoutTemplateUseCases: widget.workoutTemplateUseCases,
|
||||
activeUseCases: widget.activeUseCases,
|
||||
closeUseCase: widget.closeUseCase,
|
||||
mediaUseCases: widget.mediaUseCases,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -111,6 +114,7 @@ final class HistoryDetailScreen extends StatelessWidget {
|
||||
required this.workoutTemplateUseCases,
|
||||
required this.activeUseCases,
|
||||
required this.closeUseCase,
|
||||
this.mediaUseCases,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@ -119,6 +123,7 @@ final class HistoryDetailScreen extends StatelessWidget {
|
||||
final WorkoutTemplateUseCases workoutTemplateUseCases;
|
||||
final ActiveWorkoutSessionUseCases activeUseCases;
|
||||
final CloseWorkoutSessionUseCase closeUseCase;
|
||||
final MediaUseCases? mediaUseCases;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -191,6 +196,7 @@ final class HistoryDetailScreen extends StatelessWidget {
|
||||
closeUseCase: closeUseCase,
|
||||
historyUseCases: historyUseCases,
|
||||
workoutTemplateUseCases: workoutTemplateUseCases,
|
||||
mediaUseCases: mediaUseCases,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -154,6 +154,7 @@ final class _HomeScreenState extends State<HomeScreen> with RouteAware {
|
||||
activeUseCases: widget.bootstrap.activeWorkoutSessionUseCases,
|
||||
closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase,
|
||||
historyUseCases: widget.bootstrap.workoutHistoryUseCases,
|
||||
mediaUseCases: widget.bootstrap.mediaUseCases,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -170,6 +171,7 @@ final class _HomeScreenState extends State<HomeScreen> with RouteAware {
|
||||
widget.bootstrap.workoutTemplateUseCases,
|
||||
activeUseCases: widget.bootstrap.activeWorkoutSessionUseCases,
|
||||
closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase,
|
||||
mediaUseCases: widget.bootstrap.mediaUseCases,
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -188,6 +190,7 @@ final class _HomeScreenState extends State<HomeScreen> with RouteAware {
|
||||
closeUseCase: widget.bootstrap.closeWorkoutSessionUseCase,
|
||||
historyUseCases: widget.bootstrap.workoutHistoryUseCases,
|
||||
workoutTemplateUseCases: widget.bootstrap.workoutTemplateUseCases,
|
||||
mediaUseCases: widget.bootstrap.mediaUseCases,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:video_player/video_player.dart';
|
||||
|
||||
import '../application/application.dart';
|
||||
import '../domain/domain.dart';
|
||||
@ -10,6 +12,8 @@ import 'theme.dart';
|
||||
|
||||
enum WorkoutExecutionMode { active, rest, paused, finished }
|
||||
|
||||
typedef VideoMediaBuilder = Widget Function(BuildContext context, MediaAsset asset);
|
||||
|
||||
final class WorkoutExecutionScreen extends StatefulWidget {
|
||||
const WorkoutExecutionScreen({
|
||||
required this.initialSession,
|
||||
@ -17,6 +21,9 @@ final class WorkoutExecutionScreen extends StatefulWidget {
|
||||
required this.closeUseCase,
|
||||
required this.historyUseCases,
|
||||
required this.workoutTemplateUseCases,
|
||||
this.mediaUseCases,
|
||||
this.mediaAssetLoader,
|
||||
this.videoMediaBuilder,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@ -25,6 +32,9 @@ final class WorkoutExecutionScreen extends StatefulWidget {
|
||||
final CloseWorkoutSessionUseCase closeUseCase;
|
||||
final WorkoutHistoryUseCases historyUseCases;
|
||||
final WorkoutTemplateUseCases workoutTemplateUseCases;
|
||||
final MediaUseCases? mediaUseCases;
|
||||
final Future<MediaAsset?> Function(String id)? mediaAssetLoader;
|
||||
final VideoMediaBuilder? videoMediaBuilder;
|
||||
|
||||
@override
|
||||
State<WorkoutExecutionScreen> createState() => _WorkoutExecutionScreenState();
|
||||
@ -36,6 +46,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
late WorkoutExecutionMode _mode;
|
||||
Timer? _ticker;
|
||||
Timer? _restTicker;
|
||||
Timer? _scoreStopwatchTicker;
|
||||
WorkoutHistory? _completedHistory;
|
||||
String? _activeRestStateId;
|
||||
ActiveScoreStopwatchState? _scoreStopwatch;
|
||||
@ -73,6 +84,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
void dispose() {
|
||||
_ticker?.cancel();
|
||||
_restTicker?.cancel();
|
||||
_scoreStopwatchTicker?.cancel();
|
||||
_scoreController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
@ -339,10 +351,20 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
restRemainingSeconds: _mode == WorkoutExecutionMode.rest
|
||||
? _remainingRestSeconds
|
||||
: null,
|
||||
mediaAssetLoader: _loadMediaAsset,
|
||||
videoMediaBuilder: widget.videoMediaBuilder,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<MediaAsset?> _loadMediaAsset(String id) {
|
||||
final loader = widget.mediaAssetLoader;
|
||||
if (loader != null) return loader(id);
|
||||
final mediaUseCases = widget.mediaUseCases;
|
||||
if (mediaUseCases == null) return Future<MediaAsset?>.value();
|
||||
return mediaUseCases.findById(id);
|
||||
}
|
||||
|
||||
int get _scoreStopwatchElapsedMs {
|
||||
final manual = _manualScoreTimeMs;
|
||||
if (manual != null) {
|
||||
@ -359,6 +381,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
if (!_exercise.stopwatchScoreEnabled) {
|
||||
_scoreStopwatch = null;
|
||||
_manualScoreTimeMs = null;
|
||||
_refreshScoreStopwatchTicker();
|
||||
return;
|
||||
}
|
||||
final state = await widget.activeUseCases.findScoreStopwatch(
|
||||
@ -369,6 +392,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() => _scoreStopwatch = state);
|
||||
_refreshScoreStopwatchTicker();
|
||||
}
|
||||
|
||||
Future<void> _startScoreStopwatch() async {
|
||||
@ -383,6 +407,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
_scoreStopwatch = state;
|
||||
_manualScoreTimeMs = null;
|
||||
});
|
||||
_refreshScoreStopwatchTicker();
|
||||
}
|
||||
|
||||
Future<ActiveScoreStopwatchState?> _stopScoreStopwatch() async {
|
||||
@ -396,6 +421,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
);
|
||||
if (!mounted) return stopped;
|
||||
setState(() => _scoreStopwatch = stopped);
|
||||
_refreshScoreStopwatchTicker();
|
||||
return stopped;
|
||||
}
|
||||
|
||||
@ -411,6 +437,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
_scoreStopwatch = state;
|
||||
_manualScoreTimeMs = null;
|
||||
});
|
||||
_refreshScoreStopwatchTicker();
|
||||
}
|
||||
|
||||
Future<void> _resetScoreStopwatch() async {
|
||||
@ -445,6 +472,23 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
_scoreStopwatch = null;
|
||||
_manualScoreTimeMs = null;
|
||||
});
|
||||
_refreshScoreStopwatchTicker();
|
||||
}
|
||||
|
||||
void _refreshScoreStopwatchTicker() {
|
||||
final shouldTick =
|
||||
_scoreStopwatch?.status == ActiveScoreStopwatchStatus.running;
|
||||
if (!shouldTick) {
|
||||
_scoreStopwatchTicker?.cancel();
|
||||
_scoreStopwatchTicker = null;
|
||||
return;
|
||||
}
|
||||
if (_scoreStopwatchTicker != null) return;
|
||||
_scoreStopwatchTicker = Timer.periodic(const Duration(milliseconds: 100), (
|
||||
_,
|
||||
) {
|
||||
if (mounted) setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _editScoreStopwatchTime() async {
|
||||
@ -575,6 +619,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
_scoreStopwatch = null;
|
||||
_manualScoreTimeMs = null;
|
||||
});
|
||||
_refreshScoreStopwatchTicker();
|
||||
}
|
||||
if (!skipped &&
|
||||
_exercise.stopwatchScoreEnabled &&
|
||||
@ -767,6 +812,7 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
_activeRestStateId = null;
|
||||
_scoreStopwatch = null;
|
||||
_manualScoreTimeMs = null;
|
||||
_refreshScoreStopwatchTicker();
|
||||
_seriesStartedAt = DateTime.now().toUtc();
|
||||
_session = await widget.activeUseCases.updateProgress(
|
||||
sessionId: _session.metadata.id,
|
||||
@ -836,6 +882,9 @@ final class _WorkoutExecutionScreenState extends State<WorkoutExecutionScreen> {
|
||||
closeUseCase: widget.closeUseCase,
|
||||
historyUseCases: widget.historyUseCases,
|
||||
workoutTemplateUseCases: widget.workoutTemplateUseCases,
|
||||
mediaUseCases: widget.mediaUseCases,
|
||||
mediaAssetLoader: widget.mediaAssetLoader,
|
||||
videoMediaBuilder: widget.videoMediaBuilder,
|
||||
),
|
||||
),
|
||||
);
|
||||
@ -1256,10 +1305,14 @@ enum _MediaSheetSection { images, video }
|
||||
final class _ExerciseMediaSheet extends StatefulWidget {
|
||||
const _ExerciseMediaSheet({
|
||||
required this.exercise,
|
||||
required this.mediaAssetLoader,
|
||||
this.videoMediaBuilder,
|
||||
this.restRemainingSeconds,
|
||||
});
|
||||
|
||||
final ExecutionExercise exercise;
|
||||
final Future<MediaAsset?> Function(String id) mediaAssetLoader;
|
||||
final VideoMediaBuilder? videoMediaBuilder;
|
||||
final int? restRemainingSeconds;
|
||||
|
||||
@override
|
||||
@ -1346,9 +1399,14 @@ final class _ExerciseMediaSheetState extends State<_ExerciseMediaSheet> {
|
||||
pageController: _pageController,
|
||||
currentIndex: _imageIndex,
|
||||
onPageChanged: (index) => setState(() => _imageIndex = index),
|
||||
mediaAssetLoader: widget.mediaAssetLoader,
|
||||
)
|
||||
else if (hasVideo)
|
||||
_VideoMediaPanel(videoMediaId: exercise.videoMediaId!),
|
||||
_VideoMediaPanel(
|
||||
videoMediaId: exercise.videoMediaId!,
|
||||
mediaAssetLoader: widget.mediaAssetLoader,
|
||||
videoMediaBuilder: widget.videoMediaBuilder,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -1362,12 +1420,14 @@ final class _ImageMediaGallery extends StatelessWidget {
|
||||
required this.pageController,
|
||||
required this.currentIndex,
|
||||
required this.onPageChanged,
|
||||
required this.mediaAssetLoader,
|
||||
});
|
||||
|
||||
final List<String> imageMediaIds;
|
||||
final PageController pageController;
|
||||
final int currentIndex;
|
||||
final ValueChanged<int> onPageChanged;
|
||||
final Future<MediaAsset?> Function(String id) mediaAssetLoader;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -1396,6 +1456,7 @@ final class _ImageMediaGallery extends StatelessWidget {
|
||||
return _ImageMediaPage(
|
||||
mediaAssetId: imageMediaIds[index],
|
||||
index: index,
|
||||
mediaAssetLoader: mediaAssetLoader,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -1407,10 +1468,15 @@ final class _ImageMediaGallery extends StatelessWidget {
|
||||
}
|
||||
|
||||
final class _ImageMediaPage extends StatelessWidget {
|
||||
const _ImageMediaPage({required this.mediaAssetId, required this.index});
|
||||
const _ImageMediaPage({
|
||||
required this.mediaAssetId,
|
||||
required this.index,
|
||||
required this.mediaAssetLoader,
|
||||
});
|
||||
|
||||
final String mediaAssetId;
|
||||
final int index;
|
||||
final Future<MediaAsset?> Function(String id) mediaAssetLoader;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -1422,57 +1488,203 @@ final class _ImageMediaPage extends StatelessWidget {
|
||||
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),
|
||||
],
|
||||
child: FutureBuilder<MediaAsset?>(
|
||||
future: mediaAssetLoader(mediaAssetId),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
}
|
||||
final asset = snapshot.data;
|
||||
if (asset == null || asset.kind != MediaKind.image) {
|
||||
return _MissingMediaPlaceholder(
|
||||
icon: Icons.broken_image_outlined,
|
||||
title: 'Image indisponible',
|
||||
subtitle: mediaAssetId,
|
||||
);
|
||||
}
|
||||
return ClipRRect(
|
||||
borderRadius: BorderRadius.circular(6),
|
||||
child: Image.file(
|
||||
_fileFromLocalUri(asset.localUri),
|
||||
key: ValueKey('exercise-image-${asset.metadata.id}'),
|
||||
fit: BoxFit.contain,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return _MissingMediaPlaceholder(
|
||||
icon: Icons.broken_image_outlined,
|
||||
title: 'Image introuvable',
|
||||
subtitle: asset.metadata.id,
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final class _VideoMediaPanel extends StatelessWidget {
|
||||
const _VideoMediaPanel({required this.videoMediaId});
|
||||
const _VideoMediaPanel({
|
||||
required this.videoMediaId,
|
||||
required this.mediaAssetLoader,
|
||||
this.videoMediaBuilder,
|
||||
});
|
||||
|
||||
final String videoMediaId;
|
||||
final Future<MediaAsset?> Function(String id) mediaAssetLoader;
|
||||
final VideoMediaBuilder? videoMediaBuilder;
|
||||
|
||||
@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),
|
||||
],
|
||||
),
|
||||
child: FutureBuilder<MediaAsset?>(
|
||||
future: mediaAssetLoader(videoMediaId),
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return const SizedBox(
|
||||
height: 260,
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
final asset = snapshot.data;
|
||||
if (asset == null || asset.kind != MediaKind.video) {
|
||||
return SizedBox(
|
||||
height: 260,
|
||||
child: _MissingMediaPlaceholder(
|
||||
icon: Icons.videocam_off_outlined,
|
||||
title: 'Vidéo indisponible',
|
||||
subtitle: videoMediaId,
|
||||
),
|
||||
);
|
||||
}
|
||||
final builder = videoMediaBuilder;
|
||||
if (builder != null) {
|
||||
return builder(context, asset);
|
||||
}
|
||||
return _VideoPlayerSurface(asset: asset);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final class _VideoPlayerSurface extends StatefulWidget {
|
||||
const _VideoPlayerSurface({required this.asset});
|
||||
|
||||
final MediaAsset asset;
|
||||
|
||||
@override
|
||||
State<_VideoPlayerSurface> createState() => _VideoPlayerSurfaceState();
|
||||
}
|
||||
|
||||
final class _VideoPlayerSurfaceState extends State<_VideoPlayerSurface> {
|
||||
late final VideoPlayerController _controller;
|
||||
late final Future<void> _initialize;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_controller = VideoPlayerController.file(
|
||||
_fileFromLocalUri(widget.asset.localUri),
|
||||
);
|
||||
_initialize = _controller.initialize().then((_) {
|
||||
if (mounted) setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<void>(
|
||||
future: _initialize,
|
||||
builder: (context, snapshot) {
|
||||
if (snapshot.connectionState != ConnectionState.done) {
|
||||
return const SizedBox(
|
||||
height: 260,
|
||||
child: Center(child: CircularProgressIndicator()),
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError || !_controller.value.isInitialized) {
|
||||
return SizedBox(
|
||||
height: 260,
|
||||
child: _MissingMediaPlaceholder(
|
||||
icon: Icons.videocam_off_outlined,
|
||||
title: 'Vidéo introuvable',
|
||||
subtitle: widget.asset.metadata.id,
|
||||
),
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: _controller.value.aspectRatio,
|
||||
child: VideoPlayer(_controller),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
IconButton.filled(
|
||||
tooltip: _controller.value.isPlaying ? 'Pause' : 'Lecture',
|
||||
onPressed: () async {
|
||||
if (_controller.value.isPlaying) {
|
||||
await _controller.pause();
|
||||
} else {
|
||||
await _controller.play();
|
||||
}
|
||||
if (mounted) setState(() {});
|
||||
},
|
||||
icon: Icon(
|
||||
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final class _MissingMediaPlaceholder extends StatelessWidget {
|
||||
const _MissingMediaPlaceholder({
|
||||
required this.icon,
|
||||
required this.title,
|
||||
required this.subtitle,
|
||||
});
|
||||
|
||||
final IconData icon;
|
||||
final String title;
|
||||
final String subtitle;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(icon, size: 64, color: Theme.of(context).colorScheme.primary),
|
||||
const SizedBox(height: 16),
|
||||
Text(title, style: Theme.of(context).textTheme.titleMedium),
|
||||
const SizedBox(height: 4),
|
||||
Text(subtitle, style: Theme.of(context).textTheme.bodySmall),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File _fileFromLocalUri(String localUri) {
|
||||
final uri = Uri.tryParse(localUri);
|
||||
if (uri != null && uri.hasScheme) {
|
||||
return File.fromUri(uri);
|
||||
}
|
||||
return File(localUri);
|
||||
}
|
||||
|
||||
final class _WorkoutPlanSetTile extends StatelessWidget {
|
||||
const _WorkoutPlanSetTile({
|
||||
required this.position,
|
||||
|
||||
@ -13,6 +13,7 @@ final class WorkoutTemplateListScreen extends StatefulWidget {
|
||||
required this.activeUseCases,
|
||||
required this.closeUseCase,
|
||||
required this.historyUseCases,
|
||||
this.mediaUseCases,
|
||||
super.key,
|
||||
});
|
||||
|
||||
@ -21,6 +22,7 @@ final class WorkoutTemplateListScreen extends StatefulWidget {
|
||||
final ActiveWorkoutSessionUseCases activeUseCases;
|
||||
final CloseWorkoutSessionUseCase closeUseCase;
|
||||
final WorkoutHistoryUseCases historyUseCases;
|
||||
final MediaUseCases? mediaUseCases;
|
||||
|
||||
@override
|
||||
State<WorkoutTemplateListScreen> createState() =>
|
||||
@ -141,6 +143,7 @@ final class _WorkoutTemplateListScreenState
|
||||
closeUseCase: widget.closeUseCase,
|
||||
historyUseCases: widget.historyUseCases,
|
||||
workoutTemplateUseCases: widget.workoutTemplateUseCases,
|
||||
mediaUseCases: widget.mediaUseCases,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user