import 'dart:math'; import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../utils/farb_theme.dart'; import '../services/melo_logger.dart'; /// Animierte Ladeanzeige mit Easter Eggs für Melo class MeloLoader extends StatefulWidget { final String titel; final String? subtitle; const MeloLoader({super.key, required this.titel, this.subtitle}); @override State createState() => _MeloLoaderState(); } class _MeloLoaderState extends State with TickerProviderStateMixin { late AnimationController _pulsCtrl; late AnimationController _equalCtrl; late Animation _pulsAnim; int _downloadCount = 0; String? _easterEgg; static const _easterEggs = [ '🎵 Baka hat dich programmiert!', '🔥 Melo > Spotify. Change my mind.', '💀 Dieser Download kostet dich 5 Jahre Lebenszeit.', '🎸 Fun Fact: Dieser Song wurde von einem Server-Proxy gerettet!', '🐧 Linux > Windows. (Server-Fakt)', '🍎 SideStore > iLoader. Immer.', '🛡️ Geschützt von Caddy + Basic Auth.', '🤫 Melo ist besser als YouTube Music.', '⚡ Server: Aingrad, Netcup RS 1000.', '💾 yt-dlp 2026.03.17 – Updates sind wichtig.', '🎯 Der Proxy läuft auf Systemd – stabil.', '🧠 Dustin hat das selbst gecoded!', '📱 iOS + Android + Linux = schon 3/5!', '🐛 Crash-Logs auf crash.baka-net.de', '🎵 Navidrome: musik.baka-net.de', '🗿 Du hast den Stein der Weisen gefunden.', '🧙 Die Antwort ist 42.', '⚔️ SDS Origin Guide im Vault.', ]; @override void initState() { super.initState(); _pulsCtrl = AnimationController( vsync: this, duration: const Duration(milliseconds: 1200), )..repeat(reverse: true); _pulsAnim = Tween(begin: 0.6, end: 1.0).animate( CurvedAnimation(parent: _pulsCtrl, curve: Curves.easeInOut), ); _equalCtrl = AnimationController( vsync: this, duration: const Duration(milliseconds: 600), )..repeat(); _ladeCount(); } Future _ladeCount() async { try { final prefs = await SharedPreferences.getInstance(); _downloadCount = prefs.getInt('dl_count') ?? 0; _downloadCount++; await prefs.setInt('dl_count', _downloadCount); MeloLogger().aktion('dl_count', {'c': _downloadCount}); if (_downloadCount % 10 == 0 && mounted) { final rng = Random(_downloadCount * 7); final msg = _easterEggs[rng.nextInt(_easterEggs.length)]; setState(() => _easterEgg = msg); } } catch (_) {} } @override void dispose() { _pulsCtrl.dispose(); _equalCtrl.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Column( mainAxisSize: MainAxisSize.min, children: [ SizedBox( height: 40, child: AnimatedBuilder( animation: _equalCtrl, builder: (_, __) => Row( mainAxisAlignment: MainAxisAlignment.center, children: List.generate(5, (i) { final phase = (i * 0.4 + _equalCtrl.value * 2 * pi); final h = (sin(phase).abs() * 24 + 8); return Container( width: 4, height: h, margin: const EdgeInsets.symmetric(horizontal: 3), decoration: BoxDecoration( color: MeloTheme.rot.withValues(alpha: _pulsAnim.value), borderRadius: BorderRadius.circular(2), ), ); }), ), ), ), const SizedBox(height: 12), FadeTransition( opacity: _pulsAnim, child: Text( widget.titel, textAlign: TextAlign.center, style: const TextStyle(color: Colors.white, fontSize: 15), ), ), if (widget.subtitle != null) ...[ const SizedBox(height: 4), Text(widget.subtitle!, textAlign: TextAlign.center, style: const TextStyle(color: Colors.grey, fontSize: 12)), ], if (_easterEgg != null) ...[ const SizedBox(height: 16), Container( padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), decoration: BoxDecoration( color: MeloTheme.dunkel1, borderRadius: BorderRadius.circular(8), border: Border.all(color: MeloTheme.rot.withValues(alpha: 0.3)), ), child: Row( mainAxisSize: MainAxisSize.min, children: [ const Text('🥚', style: TextStyle(fontSize: 16)), const SizedBox(width: 8), Flexible( child: Text( _easterEgg!, style: const TextStyle(color: MeloTheme.rot, fontSize: 12), ), ), ], ), ), ], ], ); } }