import React, { useRef, useState, useEffect } from "react"; import { Box, Button, Flex, Label, Input, Text } from "theme-ui"; import Modal from "../components/Modal"; import MapSelect from "../components/map/MapSelect"; import * as defaultMaps from "../maps"; const defaultMapSize = 22; function AddMapModal({ isOpen, onRequestClose, onDone }) { const [imageLoading, setImageLoading] = useState(false); const [currentMap, setCurrentMap] = useState(-1); const [maps, setMaps] = useState(Object.values(defaultMaps)); const [gridX, setGridX] = useState(defaultMapSize); const [gridY, setGridY] = useState(defaultMapSize); useEffect(() => { setMaps((prevMaps) => { const newMaps = [...prevMaps]; const changedMap = newMaps[currentMap]; if (changedMap) { changedMap.gridX = gridX; changedMap.gridY = gridY; } return newMaps; }); }, [gridX, gridY, currentMap]); const fileInputRef = useRef(); function handleImageUpload(file) { if (!file) { return; } let fileGridX = defaultMapSize; let fileGridY = defaultMapSize; if (file.name) { // Match against a regex to find the grid size in the file name // e.g. Cave 22x23 will return [["22x22", "22", "x", "23"]] const gridMatches = [...file.name.matchAll(/(\d+) ?(x|X) ?(\d+)/g)]; if (gridMatches.length > 0) { const lastMatch = gridMatches[gridMatches.length - 1]; const matchX = parseInt(lastMatch[1]); const matchY = parseInt(lastMatch[3]); if (!isNaN(matchX) && !isNaN(matchY)) { fileGridX = matchX; fileGridY = matchY; } } } const url = URL.createObjectURL(file); let image = new Image(); setImageLoading(true); image.onload = function () { setMaps((prevMaps) => { const newMaps = [ ...prevMaps, { file, gridX: fileGridX, gridY: fileGridY, width: image.width, height: image.height, source: url, }, ]; setCurrentMap(newMaps.length - 1); return newMaps; }); setGridX(fileGridX); setGridY(fileGridY); setImageLoading(false); }; image.src = url; } function openImageDialog() { if (fileInputRef.current) { fileInputRef.current.click(); } } const [dragging, setDragging] = useState(false); function handleImageDragEnter(event) { event.preventDefault(); event.stopPropagation(); setDragging(true); } function handleImageDragLeave(event) { event.preventDefault(); event.stopPropagation(); setDragging(false); } function handleImageDrop(event) { event.preventDefault(); event.stopPropagation(); const file = event.dataTransfer.files[0]; if (file && file.type.startsWith("image")) { handleImageUpload(file); } setDragging(false); } return ( { e.preventDefault(); onDone(maps[currentMap]); }} onDragEnter={handleImageDragEnter} > handleImageUpload(event.target.files[0])} type="file" accept="image/*" style={{ display: "none" }} ref={fileInputRef} /> setGridX(e.target.value)} /> setGridY(e.target.value)} /> {dragging && ( { e.preventDefault(); e.stopPropagation(); e.dataTransfer.dropEffect = "copy"; }} onDrop={handleImageDrop} > Drop map to upload )} ); } export default AddMapModal;