import 'package:auto_route/auto_route.dart'; import 'package:flutter/material.dart'; import '../../../common/theme/theme.dart'; import '../../components/assets/assets.gen.dart'; import '../../router/app_router.gr.dart'; @RoutePage() class SplashPage extends StatefulWidget { const SplashPage({super.key}); @override State createState() => _SplashPageState(); } class _SplashPageState extends State with TickerProviderStateMixin { late AnimationController _logoController; late AnimationController _versionController; late AnimationController _backgroundController; late Animation _logoAnimation; late Animation _versionAnimation; late Animation _backgroundAnimation; @override void initState() { super.initState(); // Initialize animation controllers _logoController = AnimationController( duration: const Duration(milliseconds: 1200), vsync: this, ); _versionController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, ); _backgroundController = AnimationController( duration: const Duration(milliseconds: 1500), vsync: this, ); // Create animations _logoAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _logoController, curve: Curves.elasticOut), ); _versionAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _versionController, curve: Curves.easeInOut), ); _backgroundAnimation = Tween(begin: 0.0, end: 1.0).animate( CurvedAnimation(parent: _backgroundController, curve: Curves.easeInOut), ); // Start animations _startAnimations(); } void _startAnimations() async { // Start background animation immediately _backgroundController.forward(); // Wait a bit, then start logo animation await Future.delayed(const Duration(milliseconds: 300)); if (mounted) _logoController.forward(); // Start version animation after logo starts await Future.delayed(const Duration(milliseconds: 600)); if (mounted) _versionController.forward(); // Navigate to home screen after all animations complete await Future.delayed(const Duration(milliseconds: 2000)); if (mounted) { _navigateToHome(); } } void _navigateToHome() { // Uncomment dan sesuaikan dengan route yang ada context.router.replace(const LoginRoute()); } @override void dispose() { _logoController.dispose(); _versionController.dispose(); _backgroundController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( body: AnimatedBuilder( animation: Listenable.merge([ _logoController, _versionController, _backgroundController, ]), builder: (context, child) { // Clamp values to prevent opacity errors final logoOpacity = _logoAnimation.value.clamp(0.0, 1.0); final versionOpacity = _versionAnimation.value.clamp(0.0, 1.0); final backgroundOpacity = _backgroundAnimation.value.clamp(0.0, 1.0); return Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [ AppColor.primaryWithOpacity(backgroundOpacity), AppColor.primaryWithOpacity(backgroundOpacity * 0.8), ], ), ), child: Stack( children: [ // Logo di tengah Center( child: Transform.scale( scale: logoOpacity, child: Opacity( opacity: logoOpacity, child: Container( width: 150, height: 150, decoration: BoxDecoration( boxShadow: [ BoxShadow( color: Colors.black.withOpacity(0.1), blurRadius: 30, offset: const Offset(0, 15), ), ], ), child: ClipRRect( borderRadius: BorderRadius.circular(AppValue.radius), child: Assets.images.logo.image(fit: BoxFit.cover), ), ), ), ), ), // Version di bagian bawah Positioned( bottom: 60, left: 0, right: 0, child: Transform.translate( offset: Offset(0, 20 * (1 - versionOpacity)), child: Opacity( opacity: versionOpacity, child: Text( 'Version 1.0.0', style: AppStyle.md.copyWith(color: AppColor.textLight), textAlign: TextAlign.center, ), ), ), ), ], ), ); }, ), ); } }