import { useState, useRef, useMemo } from "react"; import { motion, AnimatePresence } from "framer-motion"; import { useUI, useAudio, useConfig } from "../../context/LauncherContext"; import { ArcService } from "../../services/ArcService"; import { LocFile, LocLanguage } from "../../types/arc"; export default function LocEditorView() { const { setActiveView } = useUI(); const { playPressSound, playBackSound } = useAudio(); const { animationsEnabled } = useConfig(); const [loc, setLoc] = useState(null); const [searchTerm, setSearchTerm] = useState(""); const [selectedLocLangIdx, setSelectedLocLangIdx] = useState(0); const [notification, setNotification] = useState<{ message: string, type: "success" | "error" } | null>(null); const [isLocEditModalOpen, setIsLocEditModalOpen] = useState<{ langIdx: number, strIdx: number, isNew: boolean } | null>(null); const fileInputRef = useRef(null); const currentLocLang = useMemo(() => { if (!loc) return null; return loc.languages[selectedLocLangIdx] || null; }, [loc, selectedLocLangIdx]); const filteredLocStrings = useMemo(() => { if (!currentLocLang) return []; return currentLocLang.strings.map((s, i) => ({ ...s, originalIdx: i })) .filter(s => (s.key?.toLowerCase().includes(searchTerm.toLowerCase()) || s.value.toLowerCase().includes(searchTerm.toLowerCase()))); }, [currentLocLang, searchTerm]); const showNotification = (message: string, type: "success" | "error" = "success") => { setNotification({ message, type }); setTimeout(() => setNotification(null), 3000); }; const handleFileLoad = async (e: React.ChangeEvent) => { const file = e.target.files?.[0]; if (!file) return; playPressSound(); const buffer = await file.arrayBuffer(); try { const parsedLoc = ArcService.parseLOC(new Uint8Array(buffer)); setLoc(parsedLoc); setSelectedLocLangIdx(0); showNotification(`Loaded ${file.name}`); } catch (err) { console.error("Failed to parse LOC", err); showNotification("Failed to parse LOC", "error"); } e.target.value = ""; }; const handleSaveLoc = () => { if (!loc) return; playPressSound(); const buffer = ArcService.serializeLOC(loc); const blob = new Blob([buffer]); const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = "languages.loc"; a.click(); URL.revokeObjectURL(url); showNotification("LOC Saved Successfully"); }; const handleLocStringEdit = (langIdx: number, strIdx: number, isNew: boolean, key: string, value: string) => { if (!loc) return; playPressSound(); setLoc({ ...loc, languages: loc.languages.map((lang, lIdx) => { if (lIdx !== langIdx) return lang; if (isNew) { return { ...lang, strings: [...lang.strings, lang.isStatic ? { value } : { key, value }] }; } return { ...lang, strings: lang.strings.map((str, sIdx) => sIdx !== strIdx ? str : { ...str, ...(!lang.isStatic ? { key } : {}), value } ) }; }) }); setIsLocEditModalOpen(null); showNotification(isNew ? "String Added" : "String Updated"); }; const handleLocStringDelete = (langIdx: number, strIdx: number) => { if (!loc) return; playBackSound(); setLoc({ ...loc, languages: loc.languages.map((lang, lIdx) => lIdx !== langIdx ? lang : { ...lang, strings: lang.strings.filter((_, sIdx) => sIdx !== strIdx) } ) }); showNotification("String Deleted"); }; return (

LOC Editor

{loc && editing loaded loc}
{!loc ? (

Open a LOC file to begin editing

) : (
setSearchTerm(e.target.value)} className="flex-1 bg-black/40 border-2 border-[#373737] text-white px-4 py-2 outline-none focus:border-[#FFFF55] transition-colors" />
{filteredLocStrings.map((str) => ( ))}
Key / Index Value Actions
{currentLocLang?.isStatic ? str.originalIdx : str.key} {str.value}
)}
{notification && ( {notification.message} )} {isLocEditModalOpen && ( setIsLocEditModalOpen(null)} onConfirm={handleLocStringEdit} /> )}
); } function LocEditModal({ data, lang, onClose, onConfirm }: { data: { langIdx: number, strIdx: number, isNew: boolean }, lang: LocLanguage, onClose: () => void, onConfirm: (langIdx: number, strIdx: number, isNew: boolean, key: string, val: string) => void }) { const [key, setKey] = useState(!data.isNew ? (lang.strings[data.strIdx].key || "") : ""); const [val, setVal] = useState(!data.isNew ? lang.strings[data.strIdx].value : ""); return (

{data.isNew ? "Add" : "Edit"} String

{!lang.isStatic ? (
setKey(e.target.value)} className="w-full bg-black/40 border-2 border-[#373737] text-white px-4 py-3 outline-none focus:border-[#FFFF55] transition-colors font-mono" />
) : (
Static entry - Index: {data.isNew ? lang.strings.length : data.strIdx}
)}