summaryrefslogblamecommitdiff
path: root/frontend/src/components/LoadingScreen.tsx
blob: 5f33d000597e721f63eb6223ca64a234ac39354e (plain) (tree)
































































































































                                                                                                                                            
import React, { useEffect, useState, useRef } from 'react'

type Props = {
  onComplete: () => void
}

export const LoadingScreen: React.FC<Props> = ({ onComplete }) => {
  const [fadeOut, setFadeOut] = useState(false)
  const [mounted, setMounted] = useState(true)
  const [subtitle, setSubtitle] = useState('')
  const [animatedText, setAnimatedText] = useState('')
  const subtitleLoaded = useRef(false)

  useEffect(() => {
    console.log('Loading screen mounted - starting timer...')
    
    // Set fixed subtitle and animate it
    if (!subtitleLoaded.current) {
      subtitleLoaded.current = true
      
      const fixedSubtitle = 'Whisper of the Heart'
      setSubtitle(fixedSubtitle)
      
      // Animate text character by character
      let currentIndex = 0
      const animateText = () => {
        if (currentIndex <= fixedSubtitle.length) {
          setAnimatedText(fixedSubtitle.slice(0, currentIndex))
          currentIndex++
          setTimeout(animateText, 50) // 50ms delay between characters
        }
      }
      
      // Start animation after heart appears (1000ms = 0.2s heart delay + 0.8s heart animation)
      setTimeout(animateText, 1000)
    }
    
    // Start fade after 4 seconds (longer to show ray spinning)
    const fadeTimer = setTimeout(() => {
      console.log('4 seconds passed - Starting fade out...')
      setFadeOut(true)
    }, 4000)

    // Complete after fade finishes (4s show + 1s fade = 5s total)
    const completeTimer = setTimeout(() => {
      console.log('5 seconds passed - Loading screen completing...')
      setMounted(false)
      onComplete()
    }, 5000)

    return () => {
      console.log('Cleaning up timers...')
      clearTimeout(fadeTimer)
      clearTimeout(completeTimer)
    }
  }, []) // Empty dependency array - run once on mount

  const handleClick = () => {
    console.log('Loading screen clicked, completing early...')
    setFadeOut(true)
    setTimeout(() => {
      setMounted(false)
      onComplete()
    }, 1000)
  }

  console.log('LoadingScreen render - fadeOut:', fadeOut, 'mounted:', mounted)

  if (!mounted) return null

  return (
    <div className={`loading-screen ${fadeOut ? 'fade-out' : ''}`} onClick={handleClick}>
      <div className="loading-logo">
        <div className="heart-container">
          <div className="sun-rays loading-animate-rays">
            <svg viewBox="0 0 100 100" className="rays-svg">
              {/* Rising Sun flag style rays - triangular rays extending to edges */}
              <g transform="translate(50, 50)">
                {[...Array(16)].map((_, i) => {
                  const angle = (i * 22.5);
                  const nextAngle = ((i + 1) * 22.5);
                  const rayWidth = 11.25; // Half the angle between rays for triangular shape

                  // Create triangular ray path
                  const startAngle = angle - rayWidth;
                  const endAngle = angle + rayWidth;

                  const innerRadius = 0; // Start from center (heart center)
                  const outerRadius = 70; // Extend to screen edge

                  const x1 = Math.cos(startAngle * Math.PI / 180) * innerRadius;
                  const y1 = Math.sin(startAngle * Math.PI / 180) * innerRadius;
                  const x2 = Math.cos(endAngle * Math.PI / 180) * innerRadius;
                  const y2 = Math.sin(endAngle * Math.PI / 180) * innerRadius;
                  const x3 = Math.cos(startAngle * Math.PI / 180) * outerRadius;
                  const y3 = Math.sin(startAngle * Math.PI / 180) * outerRadius;
                  const x4 = Math.cos(endAngle * Math.PI / 180) * outerRadius;
                  const y4 = Math.sin(endAngle * Math.PI / 180) * outerRadius;

                  return (
                    <polygon
                      key={i}
                      points={`${x1},${y1} ${x2},${y2} ${x4},${y4} ${x3},${y3}`}
                      fill={i % 2 === 0 ? "#8B0000" : "#000000"}
                      opacity="0.9"
                    />
                  );
                })}
              </g>
            </svg>
          </div>
          <div className="heart-outline loading-animate-heart">
            <svg viewBox="0 0 100 100" className="heart-svg">
              <path d="M50,85 C50,85 10,60 10,35 C10,18 20,8 35,8 C42,8 50,13 50,25 C50,13 58,8 65,8 C80,8 90,18 90,35 C90,60 50,85 50,85 Z"
                    fill="#8B0000"
                    stroke="#8B0000"
                    strokeWidth="2"/>
            </svg>
          </div>
          <div className="logo-text loading-animate-text">soryu</div>
          <div className="loading-subtitle loading-animate-subtitle">{animatedText}</div>
          <div className="loading-dots loading-animate-text">
            <span>.</span><span>.</span><span>.</span>
          </div>
        </div>
      </div>
    </div>
  )
}