22222
This commit is contained in:
@@ -1,8 +1,11 @@
|
||||
import 'package:camera/camera.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'dart:async';
|
||||
|
||||
class OvalCameraCapturePage extends StatefulWidget {
|
||||
const OvalCameraCapturePage({super.key});
|
||||
final bool isLogin;
|
||||
const OvalCameraCapturePage({super.key, this.isLogin = true});
|
||||
|
||||
@override
|
||||
State<OvalCameraCapturePage> createState() => _OvalCameraCapturePageState();
|
||||
@@ -12,6 +15,8 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
|
||||
CameraController? _cameraController;
|
||||
bool _isCameraInitialized = false;
|
||||
String? _errorMessage;
|
||||
bool _isSuccess = false;
|
||||
Timer? _timer;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@@ -27,7 +32,7 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
|
||||
|
||||
// Get available cameras
|
||||
final cameras = await availableCameras();
|
||||
|
||||
|
||||
// Check if cameras list is available
|
||||
if (cameras.isEmpty) {
|
||||
setState(() {
|
||||
@@ -64,16 +69,31 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
|
||||
);
|
||||
|
||||
await _cameraController!.initialize();
|
||||
|
||||
|
||||
if (!mounted) return;
|
||||
|
||||
|
||||
setState(() {
|
||||
_isCameraInitialized = true;
|
||||
_errorMessage = null;
|
||||
});
|
||||
|
||||
_timer = Timer(const Duration(seconds: 3), () {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_isSuccess = true;
|
||||
});
|
||||
|
||||
// Auto-close after 2 seconds
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
if (mounted) {
|
||||
Navigator.of(context).pop();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
|
||||
|
||||
setState(() {
|
||||
_errorMessage = "خطأ في تهيئة الكاميرا: $e";
|
||||
_isCameraInitialized = false;
|
||||
@@ -82,11 +102,10 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_cameraController?.dispose();
|
||||
_timer?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@@ -95,88 +114,151 @@ class _OvalCameraCapturePageState extends State<OvalCameraCapturePage> {
|
||||
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,
|
||||
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,
|
||||
),
|
||||
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),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
_errorMessage!,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
child: Text("إعادة المحاولة"),
|
||||
),
|
||||
],
|
||||
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
|
||||
)
|
||||
: _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(),
|
||||
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()),
|
||||
),
|
||||
|
||||
// Top Text
|
||||
Positioned(
|
||||
top: 100,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Center(
|
||||
child: Text(
|
||||
widget.isLogin ? "تسجيل الدخول" : "تسجيل خروج",
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.bold,
|
||||
fontFamily:
|
||||
'Cairo', // Assuming Cairo font based on Arabic text
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
// // 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))),
|
||||
),
|
||||
|
||||
// Bottom Text and Logo
|
||||
Positioned(
|
||||
bottom: 80,
|
||||
left: 0,
|
||||
right: 0,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
_isSuccess
|
||||
? (widget.isLogin
|
||||
? "تم تسجيل دخولك بنجاح"
|
||||
: "تم تسجيل خروجك بنجاح")
|
||||
: (widget.isLogin
|
||||
? "يتم تسجيل الدخول ..."
|
||||
: "يتم تسجيل الخروج ..."),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
// Logo
|
||||
SizedBox(
|
||||
height: _isSuccess ? 80 : 60,
|
||||
width: _isSuccess ? 80 : 60,
|
||||
child: SvgPicture.asset(
|
||||
_isSuccess
|
||||
? 'assets/images/logSuccess.svg'
|
||||
: 'assets/images/logLoading.svg',
|
||||
// ignore: deprecated_member_use
|
||||
color: Colors.white,
|
||||
fit: BoxFit.contain,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// // 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)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -194,11 +276,16 @@ class _OvalOverlayPainter extends CustomPainter {
|
||||
);
|
||||
|
||||
// Create a path for the whole screen
|
||||
final screenPath = Path()..addRect(Rect.fromLTWH(0, 0, size.width, size.height));
|
||||
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);
|
||||
final overlayPath = Path.combine(
|
||||
PathOperation.difference,
|
||||
screenPath,
|
||||
ovalPath,
|
||||
);
|
||||
|
||||
// Draw the dimmed area outside the oval with gradient
|
||||
final gradient = LinearGradient(
|
||||
@@ -209,11 +296,12 @@ class _OvalOverlayPainter extends CustomPainter {
|
||||
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;
|
||||
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
|
||||
@@ -222,9 +310,10 @@ class _OvalOverlayPainter extends CustomPainter {
|
||||
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));
|
||||
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),
|
||||
@@ -237,9 +326,10 @@ class _OvalOverlayPainter extends CustomPainter {
|
||||
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));
|
||||
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),
|
||||
@@ -248,13 +338,14 @@ class _OvalOverlayPainter extends CustomPainter {
|
||||
}
|
||||
|
||||
// Draw oval border
|
||||
final borderPaint = Paint()
|
||||
..color = Colors.greenAccent
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 4;
|
||||
final borderPaint =
|
||||
Paint()
|
||||
..color = Colors.greenAccent
|
||||
..style = PaintingStyle.stroke
|
||||
..strokeWidth = 4;
|
||||
canvas.drawOval(ovalRect, borderPaint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user