import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import '../widgets/app_background.dart'; class LoginAnimationScreen extends StatefulWidget { final bool isLogin; final bool isSuccess; const LoginAnimationScreen({ super.key, required this.isLogin, required this.isSuccess, }); @override State createState() => _LoginAnimationScreenState(); } class _LoginAnimationScreenState extends State with TickerProviderStateMixin { late AnimationController ringController; late AnimationController progressController; late Animation ringAnimation; late Animation progressAnimation; bool showResult = false; @override void initState() { super.initState(); ringController = AnimationController( vsync: this, duration: const Duration(seconds: 1), ); progressController = AnimationController( vsync: this, duration: const Duration(seconds: 2), ); ringAnimation = Tween( begin: 0.0, end: 1.0, ).animate(CurvedAnimation(parent: ringController, curve: Curves.easeOut)); progressAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: progressController, curve: Curves.linear), ); startAnimations(); Future.delayed(const Duration(seconds: 2), () { if (mounted) { setState(() { showResult = true; }); ringController.stop(); progressController.stop(); if (widget.isSuccess) { Future.delayed(const Duration(seconds: 2), () { if (mounted) Navigator.of(context).pop(); }); } } }); } void startAnimations() { progressController.repeat(); startPulseAnimation(); } void startPulseAnimation() { ringController.forward().then((_) { ringController.reset(); if (!showResult) startPulseAnimation(); }); } @override void dispose() { ringController.dispose(); progressController.dispose(); super.dispose(); } // FIXED: Simplified _buildIcon method that returns the appropriate SVG Widget _buildIcon() { if (!showResult) { // Loading state - fingerprint return SvgPicture.asset( "assets/images/finger_print.svg", key: const ValueKey('fingerprint'), width: 70, height: 70, placeholderBuilder: (context) => Icon( Icons.fingerprint, size: 70, color: const Color(0xFF102D25), ), ); } else if (widget.isSuccess) { // Success state - tick mark return SvgPicture.asset( "assets/images/tick.svg", key: const ValueKey('success'), width: 70, height: 70, placeholderBuilder: (context) => Icon( Icons.check_circle, size: 70, color: const Color(0xFF32C59A), ), ); } else { // Error state - error icon return SvgPicture.asset( "assets/images/error.svg", key: const ValueKey('error'), width: 70, height: 70, placeholderBuilder: (context) => Icon( Icons.error, size: 70, color: Colors.red, ), ); } } @override Widget build(BuildContext context) { return Scaffold( body: AppBackground( child: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Text( widget.isLogin ? "تسجيل الدخول" : "تسجيل خروج", style: const TextStyle( color: Colors.white, fontSize: 30, fontWeight: FontWeight.bold, decoration: TextDecoration.none, ), ), const SizedBox(height: 100), Container( width: 280, height: 400, decoration: BoxDecoration( color: const Color(0xFFEEFFFA), borderRadius: BorderRadius.circular(38), boxShadow: [ BoxShadow( color: const Color(0x34000000), blurRadius: 20, offset: const Offset(0, 10), ), ], ), child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ SizedBox( width: 160, height: 160, child: Stack( alignment: Alignment.center, children: [ Container( width: 120, height: 120, decoration: const BoxDecoration( color: Color(0xFFE5E5E5), shape: BoxShape.circle, ), ), // FIXED: AnimatedSwitcher with proper key handling AnimatedSwitcher( duration: const Duration(milliseconds: 500), child: _buildIcon(), layoutBuilder: (currentChild, previousChildren) { return Stack( alignment: Alignment.center, children: [ ...previousChildren, if (currentChild != null) currentChild, ], ); }, transitionBuilder: (child, animation) { return FadeTransition( opacity: animation, child: ScaleTransition( scale: animation, child: child, ), ); }, ), if (!showResult) Positioned.fill( child: AnimatedBuilder( animation: progressAnimation, builder: (_, __) { return CustomPaint( painter: _ProgressRingPainter( progress: progressAnimation.value, ), ); }, ), ), if (!showResult) Positioned.fill( child: AnimatedBuilder( animation: ringAnimation, builder: (_, __) { return CustomPaint( painter: _PulseRingsPainter( progress: ringAnimation.value, ), ); }, ), ), ], ), ), const SizedBox(height: 40), // Text AnimatedSwitcher with proper key handling AnimatedSwitcher( duration: const Duration(milliseconds: 500), child: showResult ? Text( widget.isSuccess ? "تم تسجيل دخولك بنجاح" : "تم رفض تسجيل الدخول ", key: ValueKey("text_${widget.isSuccess}"), style: const TextStyle( fontSize: 17, fontWeight: FontWeight.w600, decoration: TextDecoration.none, ), ) : const Text( "يتم تسجيل الدخول ...", key: ValueKey("loading_text"), style: TextStyle( fontSize: 16, decoration: TextDecoration.none, ), ), ), ], ), ), ], ), ), ), ); } } class _ProgressRingPainter extends CustomPainter { final double progress; _ProgressRingPainter({required this.progress}); @override void paint(Canvas canvas, Size size) { final center = size.center(Offset.zero); // radius slightly bigger than gray circle (60) final radius = 50.0; // background circle (very subtle) final bgPaint = Paint() ..color = const Color(0x0032C599) ..style = PaintingStyle.stroke ..strokeWidth = 3.0; canvas.drawCircle(center, radius, bgPaint); // foreground arc that animates final progressPaint = Paint() ..color = const Color(0xC40A4433) ..style = PaintingStyle.stroke ..strokeWidth = 3.0 ..strokeCap = StrokeCap.round; const startAngle = -1.5708; // -90° in radians final sweepAngle = 2 * 3.1415926 * progress; canvas.drawArc( Rect.fromCircle(center: center, radius: radius), startAngle, sweepAngle, false, progressPaint, ); } @override bool shouldRepaint(_ProgressRingPainter oldDelegate) => oldDelegate.progress != progress; } class _PulseRingsPainter extends CustomPainter { final double progress; _PulseRingsPainter({required this.progress}); @override void paint(Canvas canvas, Size size) { final center = size.center(Offset.zero); final baseRadius = 60.0; // start at grey circle final maxRadius = 130.0; // outermost ripple final ringPhases = [0.0, 0.25, 0.5]; for (final phase in ringPhases) { final ringProgress = (progress - phase).clamp(0.0, 1.0); if (ringProgress > 0) { final radius = baseRadius + (maxRadius - baseRadius) * ringProgress; final opacity = (1.0 - ringProgress) * 0.45; final paint = Paint() ..color = const Color(0xFF32C59A).withOpacity(opacity) ..style = PaintingStyle.stroke ..strokeWidth = 2; canvas.drawCircle(center, radius, paint); } } } @override bool shouldRepaint(_PulseRingsPainter oldDelegate) => oldDelegate.progress != progress; }