import 'package:camera/camera.dart'; import 'package:flutter/material.dart'; class OvalCameraCapturePage extends StatefulWidget { const OvalCameraCapturePage({super.key}); @override State createState() => _OvalCameraCapturePageState(); } class _OvalCameraCapturePageState extends State { CameraController? _cameraController; bool _isCameraInitialized = false; String? _errorMessage; @override void initState() { super.initState(); _initializeCamera(); } Future _initializeCamera() async { try { // Dispose existing controller if any await _cameraController?.dispose(); _cameraController = null; // Get available cameras final cameras = await availableCameras(); // Check if cameras list is available if (cameras.isEmpty) { setState(() { _errorMessage = "لا توجد كاميرات متاحة"; _isCameraInitialized = false; }); return; } // Try to find front camera, fallback to first available camera CameraDescription? selectedCamera; try { selectedCamera = cameras.firstWhere( (cam) => cam.lensDirection == CameraLensDirection.front, ); } catch (e) { // If no front camera found, use the first available camera if (cameras.isNotEmpty) { selectedCamera = cameras.first; } else { setState(() { _errorMessage = "لا توجد كاميرات متاحة"; _isCameraInitialized = false; }); return; } } _cameraController = CameraController( selectedCamera, ResolutionPreset.medium, enableAudio: false, imageFormatGroup: ImageFormatGroup.jpeg, ); await _cameraController!.initialize(); if (!mounted) return; setState(() { _isCameraInitialized = true; _errorMessage = null; }); } catch (e) { if (!mounted) return; setState(() { _errorMessage = "خطأ في تهيئة الكاميرا: $e"; _isCameraInitialized = false; }); print("Error initializing camera: $e"); } } @override void dispose() { _cameraController?.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Color(0xff000000), body: _errorMessage != null ? Center( child: Padding( padding: const EdgeInsets.all(20.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon( Icons.camera_alt_outlined, size: 64, color: Colors.white70, ), SizedBox(height: 16), Text( _errorMessage!, style: TextStyle( color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold, ), textAlign: TextAlign.center, ), SizedBox(height: 24), ElevatedButton( onPressed: _initializeCamera, style: ElevatedButton.styleFrom( backgroundColor: Color(0xffE8001A), foregroundColor: Colors.white, padding: EdgeInsets.symmetric(horizontal: 32, vertical: 12), ), child: Text("إعادة المحاولة"), ), ], ), ), ) : _isCameraInitialized && _cameraController != null ? Stack( children: [ SizedBox(height: MediaQuery.of(context).size.height ), // Camera Preview Positioned( child: Center(child: CameraPreview(_cameraController!)), ), // Oval overlay with dimmed background Positioned.fill( child: CustomPaint( painter: _OvalOverlayPainter(), ), ), // // Capture button // Positioned( // bottom: 60, // left: 0, // right: 0, // child: Center( // child: GestureDetector( // onTap: (){}, // child: Container( // width: 72, // height: 72, // decoration: BoxDecoration( // shape: BoxShape.circle, // color: Colors.white, // boxShadow: [ // BoxShadow( // color: Colors.black26, // blurRadius: 8, // offset: Offset(0, 4), // ), // ], // ), // child: Icon(Icons.camera_alt, color: Color(0xffE8001A), size: 36), // ), // ), // ), // ), ], ) : Center(child: CircularProgressIndicator(color: Color(0xffE8001A))), ); } } class _OvalOverlayPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final width = size.width * 0.75; final height = size.height * 0.4; final center = Offset(size.width / 2, size.height / 2); final ovalRect = Rect.fromCenter( center: center, width: width, height: height, ); // Create a path for the whole screen final screenPath = Path()..addRect(Rect.fromLTWH(0, 0, size.width, size.height)); // Create a path for the oval final ovalPath = Path()..addOval(ovalRect); // Subtract the oval from the screen path final overlayPath = Path.combine(PathOperation.difference, screenPath, ovalPath); // Draw the dimmed area outside the oval with gradient final gradient = LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ Color.fromARGB(255, 41, 41, 41), // top dark gray Color.fromARGB(255, 0, 20, 15), // bottom deep green ], ); final paint = Paint() ..shader = gradient.createShader( Rect.fromLTWH(0, 0, size.width, size.height), ) ..style = PaintingStyle.fill; canvas.drawPath(overlayPath, paint); // Draw glowing circles effect (like AppBackground) - drawn after overlay // Top circle - positioned similar to AppBackground (top: -250, left: 100, right: -200) final topCircleCenter = Offset(size.width * 0.3, -250); final topCircleRadius = 150.0; // Draw multiple circles with different opacities for spread effect (spreadRadius: 160) for (int i = 0; i < 5; i++) { final spreadPaint = Paint() ..color = Color.fromARGB(69 ~/ (i + 1), 62, 254, 190) ..maskFilter = MaskFilter.blur(BlurStyle.normal, 140 - (i * 20)); canvas.drawCircle( topCircleCenter, topCircleRadius + (i * 30), spreadPaint, ); } // Bottom circle - positioned similar to AppBackground (bottom: 100, left: -140, right: -120) final bottomCircleCenter = Offset(size.width * 0.2, size.height + 100); final bottomCircleRadius = 160.0; // Draw multiple circles with different opacities for spread effect (spreadRadius: 60) for (int i = 0; i < 5; i++) { final spreadPaint = Paint() ..color = Color.fromARGB(83 ~/ (i + 1), 62, 254, 190) ..maskFilter = MaskFilter.blur(BlurStyle.normal, 180 - (i * 25)); canvas.drawCircle( bottomCircleCenter, bottomCircleRadius + (i * 40), spreadPaint, ); } // Draw oval border final borderPaint = Paint() ..color = Colors.greenAccent ..style = PaintingStyle.stroke ..strokeWidth = 4; canvas.drawOval(ovalRect, borderPaint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }