Newer
Older
MiniTias / lib / screens / capture_screen.dart
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('権限を許可する'),
            ),
        ],
      ),
    );
  }
}