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<CaptureScreen> createState() => _CaptureScreenState();
}
class _CaptureScreenState extends State<CaptureScreen>
with WidgetsBindingObserver {
String? _previousFileName;
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
WidgetsBinding.instance.addPostFrameCallback((_) {
context.read<CameraProvider>().initialize();
});
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
final cameraProvider = context.read<CameraProvider>();
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<CameraProvider>();
_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('権限を許可する'),
),
],
),
);
}
}