import 'dart:async'; import 'dart:io'; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:pulse/Notifier/auth_provider.dart'; import 'package:pulse/Screens/authScreen/LoginScreen.dart'; import 'package:pulse/Screens/home_screen.dart'; import 'package:pulse/utils/SharedpreferencesService.dart'; import 'package:pulse/utils/customSnackBar.dart'; import 'package:flutter_svg/svg.dart'; class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override State createState() => _SplashScreenState(); } class _SplashScreenState extends State with SingleTickerProviderStateMixin { final _prefs = SharedPreferencesService.instance; double _opacity = 0.0; double _scale = 0.8; double _progressValue = 0.0; late AnimationController _controller; late Animation _animation; Timer? _connectivityTimer; bool _progressCheckCompleted = false; bool _hasInternet = true; @override void initState() { super.initState(); // Initialize connectivity check _initConnectivity(); // Animation controller for pulse effect _controller = AnimationController( duration: const Duration(seconds: 2), vsync: this, )..repeat(reverse: true); _animation = Tween(begin: 0.95, end: 1.05).animate( CurvedAnimation(parent: _controller, curve: Curves.easeInOut), ); // Start fade-in and scale animation Future.delayed(const Duration(milliseconds: 200), () { setState(() { _opacity = 1.0; _scale = 1.0; }); }); // Simulate progress animation _simulateProgress(); } Future _initConnectivity() async { try { // Initial connectivity check await _checkConnectivity(); // Use periodic checks instead of stream _connectivityTimer = Timer.periodic(const Duration(seconds: 3), (timer) { _checkConnectivity(); }); } catch (e) { debugPrint("Connectivity initialization error: $e"); _updateConnectionStatus(false); } } Future _checkConnectivity() async { try { // Method 1: Using connectivity_plus final connectivity = Connectivity(); final results = await connectivity.checkConnectivity(); final hasInternet = results.any((result) => result != ConnectivityResult.none); // Method 2: Fallback with socket test 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 { // Dismiss the warning snackbar if internet is restored ScaffoldMessenger.of(context).hideCurrentSnackBar(); if (!_progressCheckCompleted) { _startLoginCheck(); } } } void _showNoInternetSnackbar() { if (mounted) { WidgetsBinding.instance.addPostFrameCallback((_) { // Hide any existing snackbar ScaffoldMessenger.of(context).hideCurrentSnackBar(); // Show custom snackbar with all required params CustomSnackBar.show( context: context, title: "Connection Error", message: "No internet connection! Please connect to the internet.", icon: Icons.wifi_off, backgroundColor: Colors.redAccent, ); }); } } void _simulateProgress() { Timer.periodic(const Duration(milliseconds: 30), (timer) { if (_progressValue < 1.0) { setState(() { _progressValue += 0.02; }); } else { timer.cancel(); if (_hasInternet && !_progressCheckCompleted) { _startLoginCheck(); } } }); } void _startLoginCheck() { if (_progressCheckCompleted) return; _progressCheckCompleted = true; _checkLoginStatus(); } Future _checkLoginStatus() async { await Future.delayed(const Duration(seconds: 3)); final sessionId = await _prefs.getString("sessionId"); final staffId = await _prefs.getString("staffId"); debugPrint("✅ Direct session restore $sessionId"); debugPrint("✅ Direct staff restore $staffId"); if (sessionId != null && staffId != null && sessionId.isNotEmpty) { // Direct session restore Navigator.pushReplacement( context, MaterialPageRoute( builder: (_) => HomeScreen( sessionId: sessionId, staffId: staffId, ), ), ); return; } final email = await _prefs.getString("email"); final password = await _prefs.getString("password"); if (email != null && password != null) { final loginProvider = Provider.of(context, listen: false); await loginProvider.loginUser( context, csrfToken: "2fb317d960000fe130fb0e99cee97aa9", email: email, password: password, ); if (loginProvider.isLoggedIn) { Navigator.pushReplacement( context, MaterialPageRoute( builder: (_) => HomeScreen( sessionId: loginProvider.sessionId!, staffId: loginProvider.staffId.toString(), ), ), ); return; } } // Default → Login screen Navigator.pushReplacement( context, MaterialPageRoute(builder: (_) => const LoginScreen()), ); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFF1e293b), // Theme color applied body: Stack( children: [ // Background gradient overlay Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ const Color(0xFF1e293b).withOpacity(0.9), const Color(0xFF1e293b).withOpacity(0.95), const Color(0xFF1e293b), ], stops: const [0.0, 0.5, 1.0], ), ), ), // Subtle background pattern Opacity( opacity: 0.03, child: Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage("assets/images/pulse_logo.png"), repeat: ImageRepeat.repeat, scale: 8.0, ), ), ), ), Center( child: AnimatedOpacity( opacity: _opacity, duration: const Duration(seconds: 1), curve: Curves.easeInOut, child: AnimatedScale( scale: _scale, duration: const Duration(seconds: 1), curve: Curves.easeOutBack, child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ // Pulse animation container AnimatedBuilder( animation: _animation, builder: (context, child) { return Transform.scale( scale: _animation.value, child: Container( padding: const EdgeInsets.all(20), decoration: BoxDecoration( borderRadius: BorderRadius.circular(15), color: Colors.white.withOpacity(0.1), shape: BoxShape.rectangle, boxShadow: [ BoxShadow( color: Colors.white.withOpacity(0.1), blurRadius: 20, spreadRadius: 5, ), ], ), child: Container( padding: const EdgeInsets.all(15), decoration: BoxDecoration( borderRadius: BorderRadius.circular(12), color: const Color(0xFF1e293b), shape: BoxShape.rectangle, boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.3), blurRadius: 10, offset: const Offset(0, 5), ), ], ), child: SvgPicture.asset( "assets/svg/pulse_logo_ic.svg", height: 75, //filterQuality: FilterQuality.high, ), ), ), ); }, ), const SizedBox(height: 40), // App name with gradient text ShaderMask( shaderCallback: (bounds) { return LinearGradient( colors: [ Colors.white, Colors.white.withOpacity(0.8), ], ).createShader(bounds); }, child: Text( "PULSE", style: TextStyle( fontSize: 36, fontWeight: FontWeight.w800, letterSpacing: 2.0, color: Colors.white, ), ), ), const SizedBox(height: 8), // Tagline Text( "Enterprise Resource Planning", style: TextStyle( fontSize: 14, fontWeight: FontWeight.w300, color: Colors.white.withOpacity(0.7), letterSpacing: 1.2, ), ), const SizedBox(height: 50), // Animated progress bar Container( width: 200, height: 4, decoration: BoxDecoration( color: Colors.white.withOpacity(0.2), borderRadius: BorderRadius.circular(2), ), child: Stack( children: [ // Background Container( decoration: BoxDecoration( color: Colors.white.withOpacity(0.1), borderRadius: BorderRadius.circular(2), ), ), // Progress AnimatedContainer( duration: const Duration(milliseconds: 200), width: 200 * _progressValue, decoration: BoxDecoration( gradient: LinearGradient( colors: [ Colors.white, Colors.white.withOpacity(0.8), ], ), borderRadius: BorderRadius.circular(2), boxShadow: [ BoxShadow( color: Colors.white.withOpacity(0.5), blurRadius: 4, spreadRadius: 1, ), ], ), ), ], ), ), const SizedBox(height: 20), // Loading text with dots animation Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Text( "Loading", style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 14, ), ), SizedBox(width: 4), _buildLoadingDots(), ], ), const SizedBox(height: 30), // Version info Text( "Version 1.0.0", style: TextStyle( color: Colors.white.withOpacity(0.5), fontSize: 12, ), ), ], ), ), ), ), // Bottom company info Positioned( bottom: 30, left: 0, right: 0, child: Column( children: [ Text( "Powered by", style: TextStyle( color: Colors.white.withOpacity(0.4), fontSize: 12, ), ), const SizedBox(height: 4), Text( "Avantech Web Grid", style: TextStyle( color: Colors.white.withOpacity(0.6), fontSize: 14, fontWeight: FontWeight.w500, ), ), ], ), ), ], ), ); } Widget _buildLoadingDots() { return TweenAnimationBuilder( tween: Tween(begin: 0.0, end: 1.0), duration: const Duration(milliseconds: 1500), builder: (context, value, child) { int visibleDots = (value * 3).ceil(); return Row( children: List.generate(3, (index) { return Opacity( opacity: index < visibleDots ? 1.0 : 0.3, child: Text( ".", style: TextStyle( color: Colors.white.withOpacity(0.8), fontSize: 20, fontWeight: FontWeight.bold, ), ), ); }), ); }, ); } }