import 'package:image_picker/image_picker.dart'; import 'my_data.dart'; /// 사진을 어디서 가져오는가 — Figma `374:15486` 「앨범 항목」과 카메라 칸. enum PhotoSource { gallery, camera } /// 사진 한 장을 고르는 일. 화면이 이 함수를 주입받는다. /// /// 플러그인을 화면 안에서 직접 부르면 위젯 테스트가 플랫폼 채널을 타서 돌지 /// 않는다. 고르는 일만 밖으로 빼면 화면은 「골라진 사진」만 다루면 된다. typedef PhotoPicker = Future Function(PhotoSource source); /// 기본 구현 — `image_picker`. /// /// 앨범·카메라 권한 문구는 iOS `Info.plist` 의 `NSPhotoLibraryUsageDescription`· /// `NSCameraUsageDescription` 에 이미 들어가 있다(BUILD.md 「권한 사용 문구 6종」). /// 문구가 없으면 권한을 묻는 순간 앱이 종료되므로 여기서 다시 확인해 둔다. Future pickPhotoWithPlugin(PhotoSource source) async { final file = await ImagePicker().pickImage( source: source == PhotoSource.camera ? ImageSource.camera : ImageSource.gallery, ); if (file == null) return null; final bytes = await file.readAsBytes(); return PickedPhoto( bytes: bytes, // 플러그인이 종류를 주지 않는 기기가 있어 확장자로 물러난다. contentType: file.mimeType ?? _typeOfName(file.name), name: file.name, ); } String _typeOfName(String name) { final lower = name.toLowerCase(); if (lower.endsWith('.png')) return 'image/png'; if (lower.endsWith('.webp')) return 'image/webp'; if (lower.endsWith('.gif')) return 'image/gif'; if (lower.endsWith('.jpg') || lower.endsWith('.jpeg')) return 'image/jpeg'; // 모르는 확장자는 지어내지 않는다. `checkProfilePhoto` 가 형식으로 거른다. return 'application/octet-stream'; }