import { useState, useEffect, useRef, memo } from "react"; import { motion } from "framer-motion"; import { TauriService } from "../../services/TauriService"; import CustomTUModal from "../modals/CustomTUModal"; import { useUI, useConfig, useAudio, useGame } from "../../context/LauncherContext"; const VersionsView = memo(function VersionsView() { const { setActiveView } = useUI(); const { profile: selectedProfile, setProfile: setSelectedProfile } = useConfig(); const { playPressSound, playBackSound, playSfx } = useAudio(); const { editions, installs: installedVersions, toggleInstall, handleUninstall: onUninstall, deleteCustomEdition: onDeleteEdition, addCustomEdition: onAddEdition, updateCustomEdition: onUpdateEdition, downloadingId, downloadProgress } = useGame(); const [focusRow, setFocusRow] = useState(0); const [focusCol, setFocusCol] = useState(0); const [isImportModalOpen, setIsImportModalOpen] = useState(false); const [editingEdition, setEditingEdition] = useState(null); const containerRef = useRef(null); const ITEM_COUNT = editions.length + 2; useEffect(() => { const handleKeyDown = (e: KeyboardEvent) => { if (document.activeElement?.tagName === "INPUT") return; if (e.key === "Escape" || e.key === "Backspace") { playBackSound(); setActiveView("main"); return; } if (e.key === "ArrowDown") { setFocusRow((prev) => (prev >= ITEM_COUNT - 1 ? 0 : prev + 1)); setFocusCol(0); } else if (e.key === "ArrowUp") { setFocusRow((prev) => (prev <= 0 ? ITEM_COUNT - 1 : prev - 1)); setFocusCol(0); } else if (e.key === "ArrowRight") { if (focusRow < editions.length) { const id = editions[focusRow].id; const isInstalled = installedVersions.includes(id); const isCustom = id.startsWith("custom_"); let maxCol = 1; if (isInstalled) maxCol = 3; if (isCustom) maxCol = isInstalled ? 5 : 3; setFocusCol((prev) => (prev < maxCol ? prev + 1 : prev)); } } else if (e.key === "ArrowLeft") { setFocusCol((prev) => (prev > 0 ? prev - 1 : prev)); } else if (e.key === "Enter") { if (focusRow < editions.length) { const edition = editions[focusRow]; const isInstalled = installedVersions.includes(edition.id); const isCustom = edition.id.startsWith("custom_"); if (focusCol === 0) { if (isInstalled) { playPressSound(); setSelectedProfile(edition.id); } else if (!downloadingId) { playPressSound(); toggleInstall(edition.id); } } else if (focusCol === 1 && !downloadingId) { playPressSound(); toggleInstall(edition.id); } else if (focusCol === 2) { if (isInstalled) { playPressSound(); TauriService.openInstanceFolder(edition.id); } else if (isCustom) { playPressSound(); setEditingEdition(edition); setIsImportModalOpen(true); } } else if (focusCol === 3) { if (isInstalled) { playBackSound(); onUninstall(edition.id); } else if (isCustom) { playBackSound(); onDeleteEdition(edition.id); } } else if (focusCol === 4) { if (isCustom) { playPressSound(); setEditingEdition(edition); setIsImportModalOpen(true); } } else if (focusCol === 5) { if (isCustom) { playBackSound(); onDeleteEdition(edition.id); } } } else if (focusRow === editions.length) { playPressSound(); setIsImportModalOpen(true); } else { playBackSound(); setActiveView("main"); } } }; window.addEventListener("keydown", handleKeyDown); return () => window.removeEventListener("keydown", handleKeyDown); }, [ focusRow, focusCol, editions, installedVersions, playPressSound, playBackSound, setSelectedProfile, setActiveView, toggleInstall, onUninstall, onDeleteEdition, ITEM_COUNT, ]); useEffect(() => { const el = containerRef.current?.querySelector( `[data-row="${focusRow}"][data-col="${focusCol}"]`, ) as HTMLElement; if (el) el.focus(); }, [focusRow, focusCol]); return (

Versions

{editions.map((edition: any, i: number) => { const isInstalled = installedVersions.includes(edition.id); const isSelected = selectedProfile === edition.id; const isRowFocused = focusRow === i; const isCustom = edition.id.startsWith("custom_"); return (
{ setFocusRow(i); setFocusCol(0); }} onClick={() => { if (isInstalled) { playPressSound(); setSelectedProfile(edition.id); } else { toggleInstall(edition.id); } }} className="flex-1 p-4 flex items-center cursor-pointer outline-none pl-6 text-left relative" >
{edition.name} {isCustom && ( Custom )}
{edition.desc}
{!isInstalled ? ( ) : ( <> )} {isCustom && ( <> )}
); })}
{ setIsImportModalOpen(false); setEditingEdition(null); }} onImport={(ed: any) => { if (editingEdition) { onUpdateEdition(editingEdition.id, ed); } else { const id = onAddEdition(ed); setSelectedProfile(id); } }} playSfx={playSfx} editingEdition={editingEdition} />
); }); export default VersionsView;