import JSZip from "jszip"; import { Create40kRoster } from "./roster40k"; import { useEffect, useState, useRef } from "react"; import { Roster } from "./Roster"; import Demo0 from "./assets/Demo0.png"; import Demo1 from "./assets/Demo1.png"; function App() { const [error, setError] = useState(); const [roster, setRoster] = useState(); const [onePerPage, setOnePerPage] = useState(false); const [primaryColor, setPrimaryColor] = useState("#536766"); const uploadRef = useRef(); async function handleFileSelect(event) { const files = event?.target?.files; if (files) { const reader = new FileReader(); reader.onerror = () => { reader.abort(); setError("Failed to read roster file."); }; reader.onloadend = async () => { const content = reader.result; const xmldata = await unzip(content); parseXML(xmldata); }; reader.readAsBinaryString(files[0]); } else { let example; switch (event) { case "ultras": example = await fetch("Ultramarines Example.rosz"); break; case "chaos daemons": example = await fetch("Chaos Demons Mix.rosz"); default: break; } // load example const arrayBuffer = await example.arrayBuffer(); // Create a new Blob object from the zip file contents const zipBlob = new Blob([arrayBuffer], { type: "application/zip" }); const xmldata = await unzip(zipBlob); parseXML(xmldata); } } const unzip = async (file) => { if (file?.charAt && file.charAt(0) !== "P") { return file; } else { const jszip = new JSZip(); const zip = await jszip.loadAsync(file); return zip.file(/[^/]+\.ros/)[0].async("string"); // Get roster files that are in the root } }; function parseXML(xmldata) { const parser = new DOMParser(); const doc = parser.parseFromString(xmldata, "text/xml"); if (!doc) return; // Determine roster type (game system). const info = doc.querySelector("roster"); if (!info) return; const gameType = info.getAttribute("gameSystemName"); if (!gameType) return; const rosterName = info.getAttribute("name"); if (rosterName) { document.title = `FancyScribe ${rosterName}`; } if (gameType == "Warhammer 40,000 9th Edition") { console.log(doc); const roster = Create40kRoster(doc); console.log(roster); if (roster && roster.forces.length > 0) { setRoster(roster); setError(""); } } else { setError("No support for game type '" + gameType + "'."); } } useEffect(() => { // Check if the browser is Safari, and if so, remove the accept attribute // from the file input element. This is because Safari doesn't support // extensions on the accept attribute for input type=file // (https://caniuse.com/input-file-accept). If set, they will not allow any // file to be selected. if ( navigator.userAgent.match(/AppleWebKit.*Safari/) && !navigator.userAgent.includes("Chrome") ) { uploadRef.current?.removeAttribute("accept"); } }, []); useEffect(() => { if (roster) { setPrimaryColor(getPrimaryColor(roster.forces[0].catalog)); } }, [roster]); return (