import { Calendar, ExternalLink } from "lucide-react"; import { useEffect, useState } from "react"; import type { SaturnEffect } from "@/lib/effects/SaturnEffect"; import { useGameStore } from "../stores/game-store"; import { useReleasesStore } from "../stores/releases-store"; export function HomeView() { const gameStore = useGameStore(); const releasesStore = useReleasesStore(); const [mouseX, setMouseX] = useState(0); const [mouseY, setMouseY] = useState(0); useEffect(() => { releasesStore.loadReleases(); }, [releasesStore.loadReleases]); const handleMouseMove = (e: React.MouseEvent) => { const x = (e.clientX / window.innerWidth) * 2 - 1; const y = (e.clientY / window.innerHeight) * 2 - 1; setMouseX(x); setMouseY(y); // Forward mouse move to SaturnEffect (if available) for parallax/rotation interactions try { const saturn = ( window as unknown as { getSaturnEffect?: () => SaturnEffect; } ).getSaturnEffect?.(); if (saturn?.handleMouseMove) { saturn.handleMouseMove(e.clientX); } } catch { /* best-effort, ignore errors from effect */ } }; const handleSaturnMouseDown = (e: React.MouseEvent) => { try { const saturn = (window as any).getSaturnEffect?.(); if (saturn?.handleMouseDown) { saturn.handleMouseDown(e.clientX); } } catch { /* ignore */ } }; const handleSaturnMouseUp = () => { try { const saturn = (window as any).getSaturnEffect?.(); if (saturn?.handleMouseUp) { saturn.handleMouseUp(); } } catch { /* ignore */ } }; const handleSaturnMouseLeave = () => { // Treat leaving the area as mouse-up for the effect try { const saturn = (window as any).getSaturnEffect?.(); if (saturn?.handleMouseUp) { saturn.handleMouseUp(); } } catch { /* ignore */ } }; const handleSaturnTouchStart = (e: React.TouchEvent) => { if (e.touches && e.touches.length === 1) { try { const clientX = e.touches[0].clientX; const saturn = (window as any).getSaturnEffect?.(); if (saturn?.handleTouchStart) { saturn.handleTouchStart(clientX); } } catch { /* ignore */ } } }; const handleSaturnTouchMove = (e: React.TouchEvent) => { if (e.touches && e.touches.length === 1) { try { const clientX = e.touches[0].clientX; const saturn = (window as any).getSaturnEffect?.(); if (saturn?.handleTouchMove) { saturn.handleTouchMove(clientX); } } catch { /* ignore */ } } }; const handleSaturnTouchEnd = () => { try { const saturn = (window as any).getSaturnEffect?.(); if (saturn?.handleTouchEnd) { saturn.handleTouchEnd(); } } catch { /* ignore */ } }; const formatDate = (dateString: string) => { return new Date(dateString).toLocaleDateString(undefined, { year: "numeric", month: "long", day: "numeric", }); }; const escapeHtml = (unsafe: string) => { return unsafe .replace(/&/g, "&") .replace(//g, ">") .replace(/"/g, """) .replace(/'/g, "'"); }; const formatBody = (body: string) => { if (!body) return ""; let processed = escapeHtml(body); const emojiMap: Record = { ":tada:": "🎉", ":sparkles:": "✨", ":bug:": "🐛", ":memo:": "📝", ":rocket:": "🚀", ":white_check_mark:": "✅", ":construction:": "🚧", ":recycle:": "♻️", ":wrench:": "🔧", ":package:": "📦", ":arrow_up:": "⬆️", ":arrow_down:": "⬇️", ":warning:": "⚠️", ":fire:": "🔥", ":heart:": "❤️", ":star:": "⭐", ":zap:": "⚡", ":art:": "🎨", ":lipstick:": "💄", ":globe_with_meridians:": "🌐", }; processed = processed.replace( /:[a-z0-9_]+:/g, (match) => emojiMap[match] || match, ); processed = processed.replace(/`([0-9a-f]{7,40})`/g, (_match, hash) => { return `${hash.substring( 0, 7, )}`; }); processed = processed.replace( /@([a-zA-Z0-9-]+)/g, '@$1', ); return processed .split("\n") .map((line) => { line = line.trim(); const formatLine = (text: string) => text .replace( /\*\*(.*?)\*\*/g, '$1', ) .replace( /(?$1', ) .replace( /`([^`]+)`/g, '$1', ) .replace( /\[(.*?)\]\((.*?)\)/g, '$1', ); if (line.startsWith("- ") || line.startsWith("* ")) { return `
  • ${formatLine( line.substring(2), )}
  • `; } if (line.startsWith("##")) { return `

    ${line.replace( /^#+\s+/, "", )}

    `; } if (line.startsWith("#")) { return `

    ${line.replace( /^#+\s+/, "", )}

    `; } if (line.startsWith("> ")) { return `
    ${formatLine( line.substring(2), )}
    `; } if (line === "") return '
    '; return `

    ${formatLine(line)}

    `; }) .join(""); }; return (
    {/* Hero Section (Full Height) - Interactive area */}
    {/* 3D Floating Hero Text */}
    Launcher Active

    MINECRAFT

    Java Edition
    Latest Release{" "} {gameStore.latestRelease?.id || "..."}
    {/* Action Area */}
    > Ready to launch session.
    {/* Scroll Hint */} {!releasesStore.isLoading && releasesStore.releases.length > 0 && (
    Scroll for Updates Scroll for Updates
    )}
    {/* Changelog / Updates Section */}

    LATEST UPDATES

    {releasesStore.isLoading ? (
    {Array(3) .fill(0) .map((_, i) => (
    ))}
    ) : releasesStore.error ? (
    Failed to load updates: {releasesStore.error}
    ) : releasesStore.releases.length === 0 ? (
    No releases found.
    ) : (
    {releasesStore.releases.map((release, index) => (
    {/* Timeline Dot */}

    {release.name || release.tagName}

    {formatDate(release.publishedAt)}
    ))}
    )}
    ); }