import 'package:file_picker/file_picker.dart'; import 'package:flutter/widgets.dart'; class UploadedFile { final PlatformFile file; final TextEditingController controller; UploadedFile({required this.file}) : controller = TextEditingController( text: file.extension != null ? file.name.replaceAll('.${file.extension}', '') : file.name, ); String get label => controller.text; void dispose() => controller.dispose(); } class MultiFileUploadService { MultiFileUploadService._(); static final MultiFileUploadService _instance = MultiFileUploadService._(); factory MultiFileUploadService() => _instance; final List _files = []; // Expose as unmodifiable but containing UploadedFile objects List get files => List.unmodifiable(_files); // Allowed extensions static const allowedExtensions = ['pdf', 'png', 'jpg', 'jpeg', 'heic']; Future pickFiles({int maxFileSizeInMB = 3}) async { final result = await FilePicker.platform.pickFiles( allowMultiple: true, withData: true, type: FileType.custom, allowedExtensions: allowedExtensions, ); if (result != null) { for (final pf in result.files) { final ext = pf.extension?.toLowerCase() ?? ''; final sizeInMB = (pf.size / (1024 * 1024)); if (!allowedExtensions.contains(ext)) { return "Unsupported file format: ${pf.name}"; } if (sizeInMB > maxFileSizeInMB) { return "File too large (${pf.name}). Max $maxFileSizeInMB MB allowed."; } // Wrap PlatformFile in our UploadedFile model _files.add(UploadedFile(file: pf)); } } return null; } void removeFileAt(int index) { if (index >= 0 && index < _files.length) { _files[index].dispose(); _files.removeAt(index); } } void clearAll() { for (final f in _files) { f.dispose(); } _files.clear(); } }