import React, { useEffect, useState, useRef } from 'react'; import { View, StyleSheet, Animated, Easing, Dimensions } from 'react-native'; import Text from '../atoms/Text'; import { MaterialCommunityIcons } from '@expo/vector-icons'; type LoadingContext = 'character' | 'story' | 'image' | 'saving' | 'loading' | 'cuddly_toy'; const magicalPhrases: Record = { character: [ 'Zauberstaub wird gesammelt...', 'Charaktere erwachen zum Leben...', 'Magische Eigenschaften werden geformt...', 'Persönlichkeit wird erschaffen...', 'Die Geschichte deines Charakters beginnt...', 'Kreative Funken fliegen...', 'Charakterzüge werden verfeinert...', ], cuddly_toy: [ 'Dein Kuscheltier wird zum Leben erweckt...', 'Magische Verwandlung beginnt...', 'Persönlichkeit wird erschaffen...', 'Charakter nimmt Gestalt an...', 'Zauberhafte Details werden hinzugefügt...', 'Fast fertig, gleich ist es soweit...', 'Letzte magische Berührungen...', ], story: [ 'Märchenwelten öffnen sich...', 'Magische Tinte fließt...', 'Geschichten weben sich...', 'Abenteuer entfalten sich...', 'Zauberhafte Momente entstehen...', 'Fantasie nimmt Gestalt an...', 'Worte tanzen auf Seiten...', ], image: [ 'Bilder werden zum Leben erweckt...', 'Farben und Formen verschmelzen...', 'Künstliche Kreativität entfaltet sich...', 'Visuelle Magie wird erschaffen...', 'Digitale Leinwand wird bemalt...', ], saving: [ 'Deine Kreation wird gesichert...', 'Magische Speicherung läuft...', 'Daten werden in Sternenstaub verwandelt...', 'Fortschritt wird konserviert...', ], loading: [ 'Daten werden aus dem Äther geholt...', 'Magische Verbindungen werden hergestellt...', 'Informationen materialisieren sich...', 'Digitale Schätze werden geborgen...', ], }; interface MagicalLoadingScreenProps { context: LoadingContext; } export default function MagicalLoadingScreen({ context }: MagicalLoadingScreenProps) { const phrases = magicalPhrases[context]; const [currentPhrase, setCurrentPhrase] = useState(0); const [animations] = useState(() => ({ sparkleRotation: new Animated.Value(0), sparkleScale: new Animated.Value(0.3), glowOpacity: new Animated.Value(0.4), textOpacity: new Animated.Value(1), })); const textOpacityRef = useRef(animations.textOpacity); useEffect(() => { const startAnimations = () => { // Rotation Animation Animated.loop( Animated.timing(animations.sparkleRotation, { toValue: 1, duration: 4000, easing: Easing.linear, useNativeDriver: true, }) ).start(); // Scale Animation Animated.loop( Animated.sequence([ Animated.timing(animations.sparkleScale, { toValue: 1, duration: 1500, easing: Easing.bezier(0.4, 0, 0.2, 1), useNativeDriver: true, }), Animated.timing(animations.sparkleScale, { toValue: 0.3, duration: 1500, easing: Easing.bezier(0.4, 0, 0.2, 1), useNativeDriver: true, }), ]) ).start(); // Glow Animation Animated.loop( Animated.sequence([ Animated.timing(animations.glowOpacity, { toValue: 1, duration: 1000, easing: Easing.bezier(0.4, 0, 0.2, 1), useNativeDriver: true, }), Animated.timing(animations.glowOpacity, { toValue: 0.4, duration: 1000, easing: Easing.bezier(0.4, 0, 0.2, 1), useNativeDriver: true, }), ]) ).start(); }; startAnimations(); // Phrase rotation with fade effect const interval = setInterval(() => { // Fade out - slower animation (800ms instead of 500ms) Animated.timing(textOpacityRef.current, { toValue: 0, duration: 800, easing: Easing.ease, useNativeDriver: true, }).start(() => { // Change phrase when fully faded out setCurrentPhrase((prev) => (prev + 1) % phrases.length); // Fade in - slower animation (800ms instead of 500ms) Animated.timing(textOpacityRef.current, { toValue: 1, duration: 800, easing: Easing.ease, useNativeDriver: true, }).start(); }); }, 6000); // Longer display time (6000ms instead of 4000ms) return () => clearInterval(interval); }, [phrases]); const spin = animations.sparkleRotation.interpolate({ inputRange: [0, 1], outputRange: ['0deg', '360deg'], }); return ( {phrases[currentPhrase]} Die Verarbeitung dauert circa eine Minute, du kannst die App auch schließen. ); } const styles = StyleSheet.create({ container: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, backgroundColor: '#000000', justifyContent: 'center', alignItems: 'center', zIndex: 1000, }, content: { alignItems: 'center', justifyContent: 'center', }, sparkleContainer: { marginBottom: 20, }, loadingText: { color: '#FFD700', fontSize: 20, textAlign: 'center', marginTop: 20, fontFamily: 'serif', fontWeight: 'bold', // Text fetter machen minHeight: 60, // Fixed height to prevent layout shifts during text changes minWidth: 280, // Minimum width to maintain consistent layout paddingHorizontal: 20, // Additional padding within the text component lineHeight: 30, // Increased line height for better readability }, infoContainer: { position: 'absolute', bottom: 40, left: 0, right: 0, alignItems: 'center', paddingHorizontal: 20, }, infoText: { color: 'rgba(255, 255, 255, 0.7)', fontSize: 14, textAlign: 'center', fontFamily: 'system', maxWidth: 300, }, });