/// First route shown after launch. Hands off to [MainShell] after a short delay. library; import 'package:flutter/material.dart'; import '../utils/constants.dart'; import 'main_shell.dart'; /// Branded splash with a fade-in logo. Replaced by the bottom-nav shell. class SplashScreen extends StatefulWidget { const SplashScreen({super.key}); @override State createState() => _SplashScreenState(); } class _SplashScreenState extends State with SingleTickerProviderStateMixin { late final AnimationController _controller; late final Animation _fade; late final Animation _scale; @override void initState() { super.initState(); _controller = AnimationController( vsync: this, duration: const Duration(milliseconds: 700), ); _fade = CurvedAnimation(parent: _controller, curve: Curves.easeOut); _scale = Tween(begin: 0.92, end: 1).animate( CurvedAnimation(parent: _controller, curve: Curves.easeOutBack), ); _controller.forward(); _goToShell(); } Future _goToShell() async { await Future.delayed(kSplashDuration); if (!mounted) return; Navigator.of(context).pushReplacement( PageRouteBuilder( pageBuilder: (_, animation, _) => FadeTransition( opacity: animation, child: const MainShell(), ), transitionDuration: const Duration(milliseconds: 400), ), ); } @override void dispose() { _controller.dispose(); super.dispose(); } @override Widget build(BuildContext context) { final colors = Theme.of(context).colorScheme; final textTheme = Theme.of(context).textTheme; return Scaffold( body: DecoratedBox( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ colors.primary, colors.primaryContainer, colors.tertiary, ], ), ), child: SafeArea( child: FadeTransition( opacity: _fade, child: ScaleTransition( scale: _scale, child: Center( child: Column( mainAxisSize: MainAxisSize.min, children: [ Container( width: 88, height: 88, decoration: BoxDecoration( color: colors.onPrimary.withValues(alpha: 0.16), borderRadius: BorderRadius.circular(24), ), child: Icon( Icons.layers_rounded, size: 44, color: colors.onPrimary, ), ), const SizedBox(height: 24), Text( kAppName, style: textTheme.displaySmall?.copyWith( color: colors.onPrimary, ), ), const SizedBox(height: 8), Text( 'A Material 3 starter template', style: textTheme.bodyLarge?.copyWith( color: colors.onPrimary.withValues(alpha: 0.85), ), ), const SizedBox(height: 40), SizedBox( width: 28, height: 28, child: CircularProgressIndicator( strokeWidth: 3, color: colors.onPrimary, ), ), ], ), ), ), ), ), ), ); } }