import 'dart:typed_data'; import 'package:image_picker/image_picker.dart'; /// 待上传的一张原始图(选择器产物,压缩前形态)。 /// /// 只持有内存字节:不落磁盘副本、不携带原始文件路径,配合压缩层剥离 /// EXIF(含 GPS)的隐私纪律(03 号评估 §4.1)。 class PickedMediaImage { const PickedMediaImage({required this.bytes, this.name}); /// 原始字节(供压缩层消费与格内缩略预览)。 final Uint8List bytes; /// 原始文件名(仅诊断用途,不参与上传——objectKey 由服务端生成)。 final String? name; } /// 图片选择抽象:MediaUploader 只依赖本接口,单测注入假实现, /// widget 测试无需平台通道。 abstract class MediaImagePicker { /// 拉起系统选择器,最多返回 [limit] 张;用户取消返回空列表。 Future> pickImages({required int limit}); } /// 基于 image_picker 的系统选择器实现(03 号评估 §4.1 选型:官方维护、 /// pickMultiImage 多选,M3 不引入重型相册组件)。 class SystemMediaImagePicker implements MediaImagePicker { SystemMediaImagePicker({ImagePicker? picker}) : _picker = picker ?? ImagePicker(); final ImagePicker _picker; @override Future> pickImages({required int limit}) async { // 仅剩一个空位时用单选(pickMultiImage 的 limit 在部分平台要求 ≥2)。 final files = limit <= 1 ? [?await _picker.pickImage(source: ImageSource.gallery)] : await _picker.pickMultiImage(limit: limit); final images = []; for (final file in files.take(limit)) { images.add( PickedMediaImage(bytes: await file.readAsBytes(), name: file.name), ); } return images; } }