import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:gen_service/Screens/HomeScreen.dart'; import '../Utility/CustomSnackbar.dart'; import '../Utility/SharedpreferencesService.dart'; import 'authScreen/LoginScreen.dart'; class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override State createState() => _SplashScreenState(); } class _SplashScreenState extends State with SingleTickerProviderStateMixin { late AnimationController _controller; late Animation _fadeAnimation; late Animation _scaleAnimation; late Animation _slideAnimation; late Animation _rotationAnimation; late Animation _gradientAnimation; late Animation _particleAnimation; final prefs = SharedPreferencesService.instance; Timer? _connectivityTimer; bool _progressCheckCompleted = false; bool _hasInternet = true; @override void initState() { super.initState(); // Initialize connectivity check _initConnectivity(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 2000), ); // Enhanced animations _fadeAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.0, 0.8, curve: Curves.easeInOut), ), ); _scaleAnimation = Tween(begin: 0.3, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.1, 0.7, curve: Curves.elasticOut), ), ); _slideAnimation = Tween( begin: const Offset(0, 1.0), end: Offset.zero, ).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.2, 0.8, curve: Curves.easeOutBack), ), ); _rotationAnimation = Tween(begin: -0.5, end: 0.0).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.0, 0.5, curve: Curves.easeInOut), ), ); _gradientAnimation = ColorTween( begin: const Color(0xFF1487C9), end: const Color(0xFF26BAE7), ).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.0, 1.0, curve: Curves.easeInOut), ), ); _particleAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation( parent: _controller, curve: const Interval(0.3, 1.0, curve: Curves.easeInOut), ), ); // Start animations _controller.forward(); // Navigate after delay Timer(const Duration(seconds: 3), () { _checkAccountAndNavigate(); }); } Future _checkAccountAndNavigate() async { try { final String? savedAccId = await prefs.getString("accId"); if (savedAccId != null && savedAccId.isNotEmpty) { _navigateToDashboard(); } else { _navigateToLogin(); } } catch (e) { debugPrint("Error checking account ID: $e"); _navigateToLogin(); } } Future _navigateToDashboard() async { final String? savedAccId = await prefs.getString("accId"); final String? savedSessionId = await prefs.getString("session_id"); if (savedAccId != null && savedAccId.isNotEmpty) { Navigator.pushReplacement( context, PageRouteBuilder( pageBuilder: (_, __, ___) => HomeScreen( accId: savedAccId, sessionId: savedSessionId.toString(), ), transitionsBuilder: (_, animation, __, child) { return FadeTransition( opacity: animation, child: child, ); }, transitionDuration: const Duration(milliseconds: 800), ), ); } else { _navigateToLogin(); } } void _navigateToLogin() { Navigator.pushReplacement( context, PageRouteBuilder( pageBuilder: (_, __, ___) => const LoginScreen(), transitionsBuilder: (_, animation, __, child) { return FadeTransition( opacity: animation, child: child, ); }, transitionDuration: const Duration(milliseconds: 800), ), ); } Future _initConnectivity() async { try { _checkConnectivity(); _connectivityTimer = Timer.periodic(const Duration(seconds: 3), (timer) { _checkConnectivity(); }); } catch (e) { debugPrint("Connectivity initialization error: $e"); _updateConnectionStatus(false); } } Future _checkConnectivity() async { try { final connectivity = Connectivity(); final results = await connectivity.checkConnectivity(); final hasInternet = results.any((element) => element == ConnectivityResult.wifi || element == ConnectivityResult.mobile); if (hasInternet) { try { final result = await InternetAddress.lookup('google.com'); final socketCheck = result.isNotEmpty && result[0].rawAddress.isNotEmpty; _updateConnectionStatus(socketCheck); } catch (e) { _updateConnectionStatus(false); } } else { _updateConnectionStatus(false); } } catch (e) { debugPrint("Connectivity check error: $e"); _updateConnectionStatus(false); } } void _updateConnectionStatus(bool hasInternet) { if (mounted) { setState(() { _hasInternet = hasInternet; }); } if (!hasInternet) { _showNoInternetSnackbar(); } else { ScaffoldMessenger.of(context).hideCurrentSnackBar(); } } void _showNoInternetSnackbar() { if (mounted) { WidgetsBinding.instance.addPostFrameCallback((_) { ScaffoldMessenger.of(context).hideCurrentSnackBar(); CustomSnackBar.showError( context: context, message: "No internet connection! Please connect to the internet.", action: SnackBarAction( label: "RETRY", onPressed: _checkConnectivity, ), ); }); } } @override void dispose() { _controller.dispose(); _connectivityTimer?.cancel(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: AnimatedBuilder( animation: _gradientAnimation, builder: (context, child) { return Container( decoration: BoxDecoration( gradient: RadialGradient( center: Alignment.topLeft, radius: 1.5, colors: [ _gradientAnimation.value!, _gradientAnimation.value!.withOpacity(0.9), const Color(0xFF1487C9), ], stops: const [0.0, 0.6, 1.0], ), ), child: Stack( children: [ // Animated background particles ..._buildParticles(), // Floating geometric shapes Positioned( top: 100, right: 50, child: AnimatedBuilder( animation: _particleAnimation, builder: (context, child) { return Transform.translate( offset: Offset(0, 20 * _particleAnimation.value), child: Opacity( opacity: 0.1, child: Container( width: 60, height: 60, decoration: BoxDecoration( shape: BoxShape.circle, border: Border.all( color: Colors.white, width: 2, ), ), ), ), ); }, ), ), Positioned( bottom: 150, left: 40, child: AnimatedBuilder( animation: _particleAnimation, builder: (context, child) { return Transform.rotate( angle: _particleAnimation.value * 2 * 3.14159, child: Opacity( opacity: 0.08, child: Container( width: 40, height: 40, decoration: BoxDecoration( borderRadius: BorderRadius.circular(10), border: Border.all( color: Colors.white, width: 1.5, ), ), ), ), ); }, ), ), // Main content Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Logo container with enhanced styling AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.translate( offset: _slideAnimation.value * 200, child: Transform.scale( scale: _scaleAnimation.value, child: Opacity( opacity: _fadeAnimation.value, child: Container( padding: const EdgeInsets.all(25), decoration: BoxDecoration( borderRadius: BorderRadius.circular(30), color: Colors.white.withOpacity(0.15), boxShadow: [ BoxShadow( color: Colors.white.withOpacity(0.3), blurRadius: 20, spreadRadius: 2, offset: const Offset(0, 10), ), BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 10, offset: const Offset(0, 5), ), ], border: Border.all( color: Colors.white.withOpacity(0.3), width: 1, ), ), child: Stack( children: [ // Background glow Container( width: 140, height: 140, decoration: BoxDecoration( shape: BoxShape.circle, gradient: RadialGradient( colors: [ Colors.white.withOpacity(0.3), Colors.transparent, ], ), ), ), // Logo RotationTransition( turns: _rotationAnimation, child: SizedBox( height: 170, width: 170, child: SvgPicture.asset( "assets/svg/genesis_logo_2io.svg", color: Color(0xFF4076FF), ), ), ), ], ), ), ), ), ); }, ), const SizedBox(height: 40), // App name with enhanced typography AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.translate( offset: _slideAnimation.value * 100, child: Opacity( opacity: _fadeAnimation.value, child: Column( children: [ Text( "Gen Services", style: TextStyle( fontSize: 36, fontWeight: FontWeight.w900, color: Colors.white, letterSpacing: 2.0, shadows: [ Shadow( blurRadius: 10, color: Colors.black.withOpacity(0.3), offset: const Offset(2, 2), ), ], ), ), const SizedBox(height: 8), Text( "Premium Service Solutions", style: TextStyle( fontSize: 14, fontWeight: FontWeight.w300, color: Colors.white.withOpacity(0.8), letterSpacing: 3.0, ), ), ], ), ), ); }, ), const SizedBox(height: 60), // Enhanced loading indicator AnimatedBuilder( animation: _controller, builder: (context, child) { return Opacity( opacity: _fadeAnimation.value, child: Column( children: [ // Dots loading animation Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(3, (index) { return AnimatedContainer( duration: const Duration(milliseconds: 500), margin: const EdgeInsets.symmetric(horizontal: 4), width: 12, height: 12, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white.withOpacity( _controller.value > (index + 1) * 0.25 ? 1.0 : 0.3, ), boxShadow: [ BoxShadow( color: Colors.white.withOpacity(0.5), blurRadius: 8, spreadRadius: 1, ), ], ), ); }), ), const SizedBox(height: 20), Text( "Loading...", style: TextStyle( fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white.withOpacity(0.7), letterSpacing: 1.0, ), ), ], ), ); }, ), const SizedBox(height: 80), // Powered by section AnimatedBuilder( animation: _controller, builder: (context, child) { return Opacity( opacity: _fadeAnimation.value, child: Transform.translate( offset: _slideAnimation.value * 50, child: Container( padding: const EdgeInsets.symmetric( horizontal: 20, vertical: 12), decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(20), border: Border.all( color: Colors.white.withOpacity(0.2), ), ), child: Column( children: [ Text( "Powered by", style: TextStyle( fontSize: 12, fontWeight: FontWeight.w400, color: Colors.white.withOpacity(0.7), letterSpacing: 1.0, ), ), const SizedBox(height: 4), Text( "Avantect Web Grid", style: TextStyle( fontSize: 16, fontWeight: FontWeight.w600, color: Colors.white, letterSpacing: 1.0, ), ), ], ), ), ), ); }, ), ], ), ), // Bottom wave with enhanced design Positioned( bottom: 0, left: 0, right: 0, child: AnimatedBuilder( animation: _controller, builder: (context, child) { return Transform.translate( offset: Offset(0, 50 * (1 - _controller.value)), child: Opacity( opacity: _fadeAnimation.value, child: CustomPaint( size: Size(MediaQuery.of(context).size.width, 120), painter: _EnhancedWavePainter(), ), ), ); }, ), ), ], ), ); }, ), ); } List _buildParticles() { return List.generate(8, (index) { return Positioned( left: (index * 50.0) % MediaQuery.of(context).size.width, top: (index * 70.0) % MediaQuery.of(context).size.height, child: AnimatedBuilder( animation: _particleAnimation, builder: (context, child) { return Transform.translate( offset: Offset(0, 30 * _particleAnimation.value * (index.isEven ? 1 : -1)), child: Opacity( opacity: 0.1 + (0.05 * (index % 3)), child: Container( width: 8 + (index % 3) * 4, height: 8 + (index % 3) * 4, decoration: BoxDecoration( shape: BoxShape.circle, color: Colors.white, boxShadow: [ BoxShadow( color: Colors.white.withOpacity(0.5), blurRadius: 10, spreadRadius: 2, ), ], ), ), ), ); }, ), ); }); } } class _EnhancedWavePainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.white.withOpacity(0.15) ..style = PaintingStyle.fill; final path = Path(); // Create multiple waves for depth path.moveTo(0, size.height * 0.6); // First wave path.quadraticBezierTo( size.width * 0.25, size.height * 0.4, size.width * 0.5, size.height * 0.6, ); path.quadraticBezierTo( size.width * 0.75, size.height * 0.8, size.width, size.height * 0.6, ); path.lineTo(size.width, size.height); path.lineTo(0, size.height); path.close(); canvas.drawPath(path, paint); // Second smaller wave for depth final secondPaint = Paint() ..color = Colors.white.withOpacity(0.08) ..style = PaintingStyle.fill; final secondPath = Path(); secondPath.moveTo(0, size.height * 0.7); secondPath.quadraticBezierTo( size.width * 0.3, size.height * 0.5, size.width * 0.6, size.height * 0.7, ); secondPath.quadraticBezierTo( size.width * 0.8, size.height * 0.85, size.width, size.height * 0.7, ); secondPath.lineTo(size.width, size.height); secondPath.lineTo(0, size.height); secondPath.close(); canvas.drawPath(secondPath, secondPaint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; }