import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:mini_tias/providers/camera_provider.dart'; import 'package:mini_tias/widgets/camera_preview.dart'; import 'package:mini_tias/widgets/shutter_button.dart'; /// 撮影画面.カメラプレビューとシャッターボタンを表示する. class CaptureScreen extends StatefulWidget { const CaptureScreen({super.key}); @override State createState() => _CaptureScreenState(); } class _CaptureScreenState extends State with WidgetsBindingObserver { String? _previousFileName; @override void initState() { super.initState(); WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addPostFrameCallback((_) { context.read().initialize(); }); } @override void dispose() { WidgetsBinding.instance.removeObserver(this); super.dispose(); } @override void didChangeAppLifecycleState(AppLifecycleState state) { final cameraProvider = context.read(); if (state == AppLifecycleState.paused) { cameraProvider.disposeCamera(); } else if (state == AppLifecycleState.resumed) { cameraProvider.initialize(); } } void _showSaveResult(CameraProvider cameraProvider) { final fileName = cameraProvider.lastSavedFileName; if (fileName != null && fileName != _previousFileName) { _previousFileName = fileName; WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('保存しました: $fileName'), duration: const Duration(seconds: 2), behavior: SnackBarBehavior.floating, margin: EdgeInsets.only( bottom: MediaQuery.of(context).size.height / 2, left: 16, right: 16, ), ), ); }); } final error = cameraProvider.errorMessage; if (error != null && !cameraProvider.isInitialized) return; if (error != null && !cameraProvider.isSaving) { WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text(error), backgroundColor: Colors.red), ); }); } } @override Widget build(BuildContext context) { final cameraProvider = context.watch(); _showSaveResult(cameraProvider); if (cameraProvider.permissionDenied) { return _buildPermissionDenied(cameraProvider); } if (cameraProvider.errorMessage != null && !cameraProvider.isInitialized) { return Center(child: Text(cameraProvider.errorMessage!)); } if (!cameraProvider.isInitialized) { return const Center(child: CircularProgressIndicator()); } return Stack( children: [ Positioned.fill( child: CameraPreviewWidget(controller: cameraProvider.controller!), ), // 保存中インジケーター if (cameraProvider.isSaving) const Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ CircularProgressIndicator(color: Colors.white), SizedBox(height: 12), Text( '保存中...', style: TextStyle(color: Colors.white, fontSize: 16), ), ], ), ), // シャッターボタン(画面下部中央) Positioned( left: 0, right: 0, bottom: 24, child: Center( child: ShutterButton( onPressed: cameraProvider.isSaving ? () {} : () => cameraProvider.takePicture(), ), ), ), ], ); } Widget _buildPermissionDenied(CameraProvider cameraProvider) { return Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text(cameraProvider.errorMessage ?? 'カメラの権限が必要です'), const SizedBox(height: 16), if (cameraProvider.permissionPermanentlyDenied) ElevatedButton( onPressed: () => cameraProvider.openSettings(), child: const Text('設定画面を開く'), ) else ElevatedButton( onPressed: () => cameraProvider.initialize(), child: const Text('権限を許可する'), ), ], ), ); } }