import 'package:flutter/material.dart'; import 'dart:math' as math; import '../../utils/colors.dart'; import '../../utils/theme_notifier.dart'; class AnimatedBackground extends StatefulWidget { final Widget child; final bool isZenMode; final Function()? onShake; const AnimatedBackground({ super.key, required this.child, this.isZenMode = false, this.onShake, }); @override State createState() => _AnimatedBackgroundState(); } class _AnimatedBackgroundState extends State with TickerProviderStateMixin { late AnimationController _controller1; late AnimationController _controller2; late AnimationController _controller3; late AnimationController _shakeController; bool _isShaking = false; @override void initState() { super.initState(); // Create multiple animation controllers for layered effects (optimized for performance) _controller1 = AnimationController( duration: const Duration(seconds: 60), // Slower animations for better performance vsync: this, )..repeat(); _controller2 = AnimationController( duration: const Duration(seconds: 80), // Slower animations for better performance vsync: this, )..repeat(); _controller3 = AnimationController( duration: const Duration(seconds: 100), // Much slower for better performance vsync: this, )..repeat(); // Shake effect controller _shakeController = AnimationController( duration: const Duration(milliseconds: 800), vsync: this, ); } @override void dispose() { _controller1.dispose(); _controller2.dispose(); _controller3.dispose(); _shakeController.dispose(); super.dispose(); } void triggerShake() { if (!_isShaking) { _isShaking = true; _shakeController.forward().then((_) { _shakeController.reset(); _isShaking = false; }); widget.onShake?.call(); } } @override Widget build(BuildContext context) { return ThemeAwareBuilder( builder: (context, theme) { return Stack( children: [ // Base background Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ ZenColors.currentAppBackground, ZenColors.currentSecondaryBackground, ], ), ), ), // Animated gradient layers (reduced to 2 for better performance) ...List.generate(2, (index) => _buildAnimatedLayer(index)), // Content overlay widget.child, ], ); }, ); } Widget _buildAnimatedLayer(int layerIndex) { AnimationController controller; List colors; switch (layerIndex) { case 0: controller = _controller1; colors = widget.isZenMode ? ZenColors.zenModeColors : ZenColors.animationLayer1; break; case 1: controller = _controller2; colors = ZenColors.animationLayer2; break; default: controller = _controller3; colors = ZenColors.animationLayer3; } return AnimatedBuilder( animation: Listenable.merge([controller, _shakeController]), builder: (context, child) { // Add shake effect double shakeIntensity = 0.0; if (_isShaking) { shakeIntensity = math.sin(_shakeController.value * math.pi * 8) * (1 - _shakeController.value) * 10; // Decay over time } return Transform.translate( offset: Offset( shakeIntensity * (math.Random().nextDouble() - 0.5) * 2, shakeIntensity * (math.Random().nextDouble() - 0.5) * 2, ), child: Transform.rotate( angle: controller.value * 2 * math.pi, child: Container( decoration: BoxDecoration( gradient: RadialGradient( center: Alignment( math.sin(controller.value * 2 * math.pi) * 0.5, math.cos(controller.value * 2 * math.pi) * 0.5, ), radius: 1.5 + math.sin(controller.value * math.pi) * 0.5 + (shakeIntensity * 0.1), // Shake affects radius too colors: colors, ), ), ), ), ); }, ); } }