Files
flutter/lib/widgets/add_exercise/preview_images.dart
Branislav Nohaj c00246dedb Add image source selection and preview improvements
Add dialog for camera/gallery selection and improve preview widget
with edit mode toggle. Preview now supports add-more callback and
can be displayed in read-only mode.
2025-10-04 16:13:02 +02:00

111 lines
3.2 KiB
Dart

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:wger/providers/add_exercise.dart';
/// Widget to preview selected exercise images
///
/// Displays images in a horizontal scrollable list with thumbnails.
/// Each image shows a preview thumbnail and optionally a delete button.
/// Can optionally include an "add more" button at the end of the list.
class PreviewExerciseImages extends StatelessWidget {
final List<File> selectedImages;
final VoidCallback? onAddMore;
final bool allowEdit;
const PreviewExerciseImages({
Key? key,
required this.selectedImages,
this.onAddMore,
this.allowEdit = true,
}) : super(key: key);
@override
Widget build(BuildContext context) {
// Calculate item count: images + optional "add more" button
final itemCount = selectedImages.length + (allowEdit && onAddMore != null ? 1 : 0);
return SizedBox(
height: 120,
child: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: itemCount,
itemBuilder: (context, index) {
// Show "add more" button at the end (only if editing is allowed)
if (index == selectedImages.length) {
return _buildAddMoreButton(context);
}
// Show image thumbnail
final image = selectedImages[index];
return _buildImageCard(context, image);
},
),
);
}
Widget _buildImageCard(BuildContext context, File image) {
return Container(
width: 120,
margin: const EdgeInsets.only(right: 8),
child: Stack(
children: [
// Image thumbnail
ClipRRect(
borderRadius: BorderRadius.circular(8),
child: Image.file(
image,
width: 120,
height: 120,
fit: BoxFit.cover,
),
),
// Delete button overlay (only shown if editing is allowed)
if (allowEdit)
Positioned(
top: 4,
right: 4,
child: IconButton(
icon: const Icon(Icons.close),
color: Colors.white,
iconSize: 20,
style: IconButton.styleFrom(
backgroundColor: Colors.black.withOpacity(0.6),
padding: const EdgeInsets.all(4),
),
onPressed: () {
context.read<AddExerciseProvider>().removeExercise(image.path);
},
),
),
],
),
);
}
Widget _buildAddMoreButton(BuildContext context) {
return GestureDetector(
onTap: onAddMore,
child: Container(
width: 120,
height: 120,
margin: const EdgeInsets.only(right: 8),
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surfaceVariant,
borderRadius: BorderRadius.circular(8),
border: Border.all(
color: Theme.of(context).colorScheme.outline,
width: 2,
style: BorderStyle.solid,
),
),
child: Icon(
Icons.add,
size: 48,
color: Theme.of(context).colorScheme.onSurfaceVariant,
),
),
);
}
}