Untitled

 avatar
unknown
plain_text
8 months ago
9.2 kB
3
Indexable
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:camera/camera.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_compress/video_compress.dart';
import 'package:gal/gal.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart';

class CameraScreen extends StatefulWidget {
  @override
  _CameraScreenState createState() => _CameraScreenState();
}

class _CameraScreenState extends State<CameraScreen> {
  CameraController? _controller;
  late Future<void> _initializeControllerFuture;
  bool _isRecording = false;
  String? _recordedVideoPath;
  double _compressionProgress = 0.0;
  late Subscription _subscription;
  bool _cameraInitialized = false;
  String? _errorMessage;

  @override
  void initState() {
    super.initState();
    _subscription = VideoCompress.compressProgress$.subscribe((progress) {
      setState(() {
        _compressionProgress = progress;
      });
      debugPrint('Compression progress: $progress');
    });
    _initializeControllerFuture = _initializeCamera();
    _requestCameraPermission();
  }

  Future<void> _requestCameraPermission() async {
    final status = await Permission.camera.request();
    debugPrint('Camera permission status: ${status.isGranted}');
  }


  Future<void> _initializeCamera() async {
    try {
      debugPrint('[DEBUG] Requesting camera permission...');
      final cameraPermissionStatus = await Permission.camera.request();
      debugPrint('[DEBUG] Camera permission status: ${cameraPermissionStatus.isGranted}');

      if (!cameraPermissionStatus.isGranted) {
        _showPermissionDeniedDialog(context);
        return;
      }

      debugPrint('[DEBUG] Fetching available cameras...');
      final cameras = await availableCameras();
      debugPrint('[DEBUG] Available cameras: $cameras');

      if (cameras.isEmpty) {
        setState(() {
          _errorMessage = 'No cameras available';
        });
        return;
      }

      final firstCamera = cameras.first;
      debugPrint('[DEBUG] Initializing camera controller with: $firstCamera');
      _controller = CameraController(firstCamera, ResolutionPreset.high);

      await _controller?.initialize();
      if (!mounted) {
        return;
      }

      setState(() {
        _cameraInitialized = true;
      });
      debugPrint('[DEBUG] Camera initialized successfully');
    } catch (e) {
      debugPrint('[DEBUG] Failed to initialize camera: $e');
      setState(() {
        _errorMessage = 'Failed to initialize camera: $e';
      });
    }
  }

  void _checkPermissionStatus() async {
    final status = await Permission.camera.status;
    debugPrint('[DEBUG] Camera permission status (programmatic check): ${status.isGranted}');
  }

  @override
  void dispose() {
    _controller?.dispose();
    _subscription.unsubscribe();
    super.dispose();
  }

  Future<void> _compressAndSaveVideo(String videoPath) async {
    print('[DEBUG] Compressing video...');
    final info = await VideoCompress.compressVideo(
      videoPath,
      quality: VideoQuality.MediumQuality,
      deleteOrigin: false, // Set to true if you want to delete the original video
    );

    if (info != null && info.file != null) {
      final compressedVideoPath = info.file!.path;
      print('[DEBUG] Video compressed to $compressedVideoPath');
      await _saveVideoToGallery(compressedVideoPath);
    } else {
      print('[DEBUG] Video compression failed');
    }
  }

  Future<void> _saveVideoToGallery(String videoPath) async {
    if (await _requestStoragePermission()) {
      print('[DEBUG] Saving video to gallery...');
      final result = await Gal.putVideo(videoPath);
      print('[DEBUG] Save result');
    } else {
      print('[DEBUG] Storage permission denied');
    }
  }

  Future<bool> _requestStoragePermission() async {
    if (Platform.isIOS) {
      final status = await Permission.photos.request();
      debugPrint('[DEBUG] iOS storage permission status: ${status.isGranted}');
      return status.isGranted;
    } else {
      DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
      AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
      if (androidInfo.version.sdkInt >= 30) {
        final status = await Permission.manageExternalStorage.request();
        debugPrint('[DEBUG] Android (SDK >= 30) storage permission status: ${status.isGranted}');
        return status.isGranted;
      } else {
        final status = await Permission.storage.request();
        debugPrint('[DEBUG] Android (SDK < 30) storage permission status: ${status.isGranted}');
        return status.isGranted;
      }
    }
  }

  Future<String> _getVideoPath() async {
    final directory = await getApplicationDocumentsDirectory();
    final videoDir = Directory('${directory.path}/video_compress');
    if (!await videoDir.exists()) {
      await videoDir.create(recursive: true);
    }
    return videoDir.path;
  }

  void _showPermissionDeniedDialog(BuildContext context) {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Permission Denied'),
        content: Text('Camera permission is required to use this feature. Please enable it in the app settings.'),
        actions: [
          TextButton(
            onPressed: () {
              Navigator.of(context).pop();
            },
            child: Text('Cancel'),
          ),
          TextButton(
            onPressed: () {
              openAppSettings();
            },
            child: Text('Open Settings'),
          ),
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Take Video'),
        leading: IconButton(
          icon: const Icon(Icons.arrow_back),
          onPressed: () {
            context.go('/home'); // Navigate back
          },
        ),
      ),
      body: FutureBuilder<void>(
        future: _initializeControllerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done) {
            if (_errorMessage != null) {
              return Center(
                child: Text(_errorMessage!),
              );
            }
            return Stack(
              children: [
                _controller == null
                    ? Center(child: Text('Camera not available'))
                    : CameraPreview(_controller!),
                if (_compressionProgress > 0.0 && _compressionProgress < 100.0)
                  Center(
                    child: Column(
                      mainAxisAlignment: MainAxisAlignment.center,
                      children: [
                        CircularProgressIndicator(
                          value: _compressionProgress,
                        ),
                        const SizedBox(height: 10),
                        Text(
                          '${(_compressionProgress * 100).toStringAsFixed(1)}%',
                          style: const TextStyle(fontSize: 20),
                        ),
                      ],
                    ),
                  ),
              ],
            );
          } else if (snapshot.hasError) {
            return Center(
              child: Text('Error initializing camera: ${snapshot.error}'),
            );
          } else {
            return Center(child: CircularProgressIndicator());
          }
        },
      ),
      floatingActionButton: FutureBuilder<void>(
        future: _initializeControllerFuture,
        builder: (context, snapshot) {
          if (snapshot.connectionState == ConnectionState.done && _controller != null && _controller!.value.isInitialized) {
            return FloatingActionButton(
              onPressed: () async {
                if (_controller != null && _controller!.value.isInitialized) {
                  try {
                    if (!_isRecording) {
                      final videoPath = await _getVideoPath();
                      _recordedVideoPath = '$videoPath/recorded_video.mp4';
                      await _controller!.startVideoRecording();
                      setState(() {
                        _isRecording = true;
                      });
                      print('[DEBUG] Recording started...');
                    } else {
                      final video = await _controller!.stopVideoRecording();
                      setState(() {
                        _isRecording = false;
                      });
                      print('[DEBUG] Recording stopped. Video saved at ${video.path}');
                      if (_recordedVideoPath != null) {
                        await _compressAndSaveVideo(video.path);
                      }
                    }
                  } catch (e) {
                    print('[DEBUG] Error: $e');
                  }
                }
              },
              child: Icon(_isRecording ? Icons.stop : Icons.videocam),
            );
          } else {
            return Container(); // Or an alternative placeholder
          }
        },
      ),
    );
  }
}
Editor is loading...
Leave a Comment