import 'dart:ui' as ui;
import 'dart:math' as math;
import 'package:flutter/[Link]';
import 'package:google_fonts/google_fonts.dart';
import 'package:lunita_app/lib/widgets/animated_background.dart';
import 'package:lunita_app/lib/widgets/audio_manager.dart';
import 'package:lunita_app/lib/screens/message_sequence.dart';
class WelcomeScreen extends StatefulWidget {
const WelcomeScreen({[Link]});
@override
State<WelcomeScreen> createState() => _WelcomeScreenState();
}
class _WelcomeScreenState extends State<WelcomeScreen>
with TickerProviderStateMixin {
late final AnimationController _buttonScaleController;
late final AnimationController _glowController;
late final Animation<double> _buttonScaleAnim;
late final AnimationController _entryAnimationController;
late final Animation<double> _vignetteOpacityAnim;
late final Animation<double> _buttonOpacityAnim;
static const _vignetteInitialDelay = Duration(milliseconds: 300);
static const _vignetteFadeDuration = Duration(milliseconds: 2000);
static const _delayBeforeButtonAppears = Duration(milliseconds: 500);
static const _buttonFadeInDuration = Duration(milliseconds: 3000); // ← FADE IN
LENTO
final double baseButtonBorderRadius = 28.0;
final double buttonGlassTintOpacity = 0.55;
final double baseButtonBlurSigma = 6.0;
final Color buttonBorderBaseColor = [Link];
final double baseButtonPaddingHorizontal = 48.0;
final double baseButtonPaddingVertical = 20.0;
final double baseFontSize = 20.0;
final double baseLetterSpacing = 0.25;
@override
void initState() {
[Link]();
[Link]();
final totalEntryDuration = Duration(
milliseconds: _vignetteInitialDelay.inMilliseconds +
_vignetteFadeDuration.inMilliseconds +
_delayBeforeButtonAppears.inMilliseconds +
_buttonFadeInDuration.inMilliseconds,
);
_entryAnimationController = AnimationController(
vsync: this,
duration: totalEntryDuration,
);
_vignetteOpacityAnim = Tween<double>(begin: 1.0, end: 0.0).animate(
CurvedAnimation(
parent: _entryAnimationController,
curve: Interval(
_vignetteInitialDelay.inMilliseconds / [Link],
(_vignetteInitialDelay.inMilliseconds +
_vignetteFadeDuration.inMilliseconds) /
[Link],
curve: [Link],
),
),
);
final buttonStartTime = _vignetteInitialDelay.inMilliseconds +
_vignetteFadeDuration.inMilliseconds +
_delayBeforeButtonAppears.inMilliseconds;
_buttonOpacityAnim = Tween<double>(begin: 0.0, end: 1.0).animate(
CurvedAnimation(
parent: _entryAnimationController,
curve: Interval(
buttonStartTime / [Link],
1.0,
curve: [Link], // ← CURVA SUAVE Y ETÉREA
),
),
);
_buttonScaleController = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 3000),
);
_glowController = AnimationController(
vsync: this,
duration: const Duration(seconds: 6),
)..repeat();
_buttonScaleAnim = TweenSequence<double>([
TweenSequenceItem(tween: Tween(begin: 1.0, end: 1.05), weight: 50),
TweenSequenceItem(tween: Tween(begin: 1.05, end: 1.0), weight: 50),
]).animate(CurvedAnimation(
parent: _buttonScaleController,
curve: [Link],
));
_entryAnimationController.forward().whenComplete(() {
if (mounted) {
_buttonScaleController.repeat();
}
});
}
@override
void dispose() {
_buttonScaleController.dispose();
_glowController.dispose();
_entryAnimationController.dispose();
[Link]();
}
@override
Widget build(BuildContext context) {
final screenWidth = [Link](context).[Link];
final scaleFactor = screenWidth / 375.0;
final dynamicButtonBorderRadius =
(baseButtonBorderRadius * scaleFactor).clamp(20.0, 40.0);
final dynamicPaddingH =
(baseButtonPaddingHorizontal * scaleFactor).clamp(25.0, 70.0);
final dynamicPaddingV =
(baseButtonPaddingVertical * scaleFactor).clamp(12.0, 35.0);
final dynamicFontSize = (baseFontSize * scaleFactor).clamp(16.0, 28.0);
final dynamicLetterSpacing =
(baseLetterSpacing * scaleFactor).clamp(0.15, 0.4);
final blurSigma = baseButtonBlurSigma;
final buttonGlassTint =
[Link](buttonGlassTintOpacity);
return Scaffold(
body: Stack(
fit: [Link],
children: [
const AnimatedBackground(),
AnimatedBuilder(
animation: _vignetteOpacityAnim,
builder: (context, child) => Opacity(
opacity: _vignetteOpacityAnim.value,
child: child,
),
child: Container(color: [Link]),
),
Center(
child: AnimatedBuilder(
animation: _buttonOpacityAnim,
builder: (context, child) => Opacity(
opacity: _buttonOpacityAnim.value,
child: child,
),
child: ScaleTransition(
scale: _buttonScaleAnim,
child: AnimatedBuilder(
animation: _glowController,
builder: (_, child) {
return CustomPaint(
painter: _AnimatedGlowBorderPainter(
progress: _glowController.value,
radius: dynamicButtonBorderRadius,
baseColor: buttonBorderBaseColor,
),
child: ClipRRect(
borderRadius:
[Link](dynamicButtonBorderRadius),
child: BackdropFilter(
filter: [Link](
sigmaX: blurSigma,
sigmaY: blurSigma,
),
child: ElevatedButton(
onPressed: () {
_buttonScaleController.stop();
_glowController.stop();
if (!mounted) return;
[Link](context).pushReplacement(
PageRouteBuilder(
pageBuilder: (context, animation,
secondaryAnimation) =>
const MessageSequence(),
transitionsBuilder: (context, animation,
secondaryAnimation, child) =>
FadeTransition(
opacity: animation, child: child),
transitionDuration:
const Duration(milliseconds: 1200),
),
);
},
style: [Link](
backgroundColor: buttonGlassTint,
foregroundColor: [Link],
padding: [Link](
horizontal: dynamicPaddingH,
vertical: dynamicPaddingV,
),
shape: RoundedRectangleBorder(
borderRadius: [Link](
dynamicButtonBorderRadius),
),
elevation: 0,
shadowColor: [Link],
),
child: [Link](
scaleX: 1.05,
scaleY: 1.0,
child: Text(
"Entrar",
style: [Link](
fontSize: dynamicFontSize,
color: [Link](0.75),
fontWeight: FontWeight.w400,
letterSpacing: dynamicLetterSpacing,
shadows: [
Shadow(
blurRadius:
(2.0 * scaleFactor).clamp(1.0, 4.0),
color: [Link](0.25),
offset: Offset(
(0.5 * scaleFactor).clamp(0.2, 1.0),
(0.5 * scaleFactor).clamp(0.2, 1.0),
),
),
Shadow(
blurRadius:
(4.0 * scaleFactor).clamp(2.0, 8.0),
color: [Link](0.15),
),
],
),
),
),
),
),
),
);
},
),
),
),
),
],
),
);
}
}
class _AnimatedGlowBorderPainter extends CustomPainter {
final double progress;
final double radius;
final Color baseColor;
_AnimatedGlowBorderPainter({
required [Link],
required [Link],
required [Link],
});
@override
void paint(Canvas canvas, Size size) {
final rect = [Link] & size;
final rrect = [Link](rect, [Link](radius));
final glowGradient = SweepGradient(
startAngle: 0,
endAngle: [Link] * 2,
center: [Link],
colors: [
[Link],
[Link](0.2),
[Link](0.4),
[Link](0.2),
[Link],
],
stops: const [0.0, 0.3, 0.5, 0.7, 1.0],
transform: GradientRotation(progress * [Link] * 2),
);
final glowPaint = Paint()
..shader = [Link](rect)
..style = [Link]
..strokeWidth = 2.2;
[Link](rrect, glowPaint);
}
@override
bool shouldRepaint(covariant _AnimatedGlowBorderPainter old) =>
[Link] != progress;
}