import 'package:camera/camera.dart'; import 'package:flutter/foundation.dart'; import 'package:mini_tias/services/file_service.dart'; import 'package:mini_tias/services/permission_service.dart'; import 'package:mini_tias/services/raw_capture_service.dart'; /// カメラの初期化・プレビュー制御・撮影実行・ライフサイクルを管理する. class CameraProvider extends ChangeNotifier { final PermissionService _permissionService = PermissionService(); final FileService _fileService = FileService(); final RawCaptureService _rawCaptureService = RawCaptureService(); CameraController? _controller; bool _isInitialized = false; String? _errorMessage; bool _permissionDenied = false; bool _permissionPermanentlyDenied = false; String? _lastSavedFileName; bool _isSaving = false; CameraController? get controller => _controller; bool get isInitialized => _isInitialized; String? get errorMessage => _errorMessage; bool get permissionDenied => _permissionDenied; bool get permissionPermanentlyDenied => _permissionPermanentlyDenied; String? get lastSavedFileName => _lastSavedFileName; bool get isSaving => _isSaving; /// カメラを初期化する. Future initialize() async { final granted = await _permissionService.requestCamera(); if (!granted) { _permissionDenied = true; _permissionPermanentlyDenied = await _permissionService .isCameraPermanentlyDenied(); _errorMessage = 'カメラの権限が必要です'; notifyListeners(); return; } _permissionDenied = false; _permissionPermanentlyDenied = false; try { final cameras = await availableCameras(); final frontCamera = cameras.firstWhere( (c) => c.lensDirection == CameraLensDirection.front, ); _controller = CameraController( frontCamera, ResolutionPreset.max, enableAudio: false, ); await _controller!.initialize(); await _controller!.setFlashMode(FlashMode.off); _isInitialized = true; _errorMessage = null; } catch (e) { _errorMessage = 'カメラの初期化に失敗しました: $e'; _isInitialized = false; } notifyListeners(); } /// Camera2 API でフル解像度 YUV キャプチャし,PNG で保存する. /// /// プレビューを一時停止 → Camera2 でキャプチャ → プレビュー再開. Future takePicture() async { if (!_isInitialized || _isSaving) return; _isSaving = true; _isInitialized = false; notifyListeners(); try { // ストレージ権限の確認 final storageGranted = await _permissionService.requestStorage(); if (!storageGranted) { _errorMessage = 'ストレージの権限が必要です'; _isSaving = false; notifyListeners(); return; } // プレビューを停止してカメラを解放 await _controller?.dispose(); _controller = null; // カメラが完全に解放されるまで待つ await Future.delayed(const Duration(milliseconds: 500)); // Camera2 API でフル解像度 YUV キャプチャ final yuvData = await _rawCaptureService.captureFullResolutionYuv(); // PNG に変換して保存 final savedPath = await _fileService.saveImageFromYuvData(yuvData); // MediaStore に登録(PC から MTP で見えるようにする) await _rawCaptureService.scanFile(savedPath); _lastSavedFileName = savedPath.split('/').last; _errorMessage = null; } catch (e) { _errorMessage = '撮影に失敗しました: $e'; _lastSavedFileName = null; } _isSaving = false; notifyListeners(); // プレビューを再開 await initialize(); } /// カメラリソースを解放する. void disposeCamera() { _controller?.dispose(); _controller = null; _isInitialized = false; notifyListeners(); } /// アプリの設定画面を開く(権限が永久拒否された場合). Future openSettings() async { await _permissionService.openSettings(); } @override void dispose() { _controller?.dispose(); super.dispose(); } }