import React, { useEffect, useState } from "react"; import { Button, Flex, Label } from "theme-ui"; import Modal from "../components/Modal"; import MapSettings from "../components/map/MapSettings"; import MapEditor from "../components/map/MapEditor"; import LoadingOverlay from "../components/LoadingOverlay"; import { useMapData } from "../contexts/MapDataContext"; import { isEmpty } from "../helpers/shared"; import { getGridDefaultInset } from "../helpers/grid"; import useResponsiveLayout from "../hooks/useResponsiveLayout"; function EditMapModal({ isOpen, onDone, mapId }) { const { updateMap, updateMapState, getMap, getMapFromDB, getMapStateFromDB, } = useMapData(); const [isLoading, setIsLoading] = useState(true); const [map, setMap] = useState(); const [mapState, setMapState] = useState(); // Load full map when modal is opened useEffect(() => { async function loadMap() { setIsLoading(true); let loadingMap = getMap(mapId); // Ensure file is loaded for map if (loadingMap?.type === "file" && !loadingMap?.file) { loadingMap = await getMapFromDB(mapId); } const mapState = await getMapStateFromDB(mapId); setMap(loadingMap); setMapState(mapState); setIsLoading(false); } if (isOpen && mapId) { loadMap(); } else { setMap(); setMapState(); } }, [isOpen, mapId, getMapFromDB, getMapStateFromDB, getMap]); function handleClose() { setMapSettingChanges({}); setMapStateSettingChanges({}); onDone(); } async function handleSave() { await applyMapChanges(); onDone(); } /** * Map settings */ // Local cache of map setting changes // Applied when done is clicked or map selection is changed const [mapSettingChanges, setMapSettingChanges] = useState({}); const [mapStateSettingChanges, setMapStateSettingChanges] = useState({}); function handleMapSettingsChange(key, value) { setMapSettingChanges((prevChanges) => ({ ...prevChanges, [key]: value, lastModified: Date.now(), })); } function handleMapStateSettingsChange(key, value) { setMapStateSettingChanges((prevChanges) => ({ ...prevChanges, [key]: value, })); } async function applyMapChanges() { if (!isEmpty(mapSettingChanges) || !isEmpty(mapStateSettingChanges)) { // Ensure grid values are positive let verifiedChanges = { ...mapSettingChanges }; if ("grid" in verifiedChanges && "size" in verifiedChanges.grid) { verifiedChanges.grid.size.x = verifiedChanges.grid.size.x || 1; verifiedChanges.grid.size.y = verifiedChanges.grid.size.y || 1; } // Ensure inset isn't flipped if ("grid" in verifiedChanges && "inset" in verifiedChanges.grid) { const inset = verifiedChanges.grid.inset; if ( inset.topLeft.x > inset.bottomRight.x || inset.topLeft.y > inset.bottomRight.y ) { if ("size" in verifiedChanges.grid) { verifiedChanges.grid.inset = getGridDefaultInset( { size: verifiedChanges.grid.size, type: map.grid.type }, map.width, map.height ); } else { verifiedChanges.grid.inset = getGridDefaultInset( map.grid, map.width, map.height ); } } } await updateMap(map.id, mapSettingChanges); await updateMapState(map.id, mapStateSettingChanges); setMapSettingChanges({}); setMapStateSettingChanges({}); } } const selectedMapWithChanges = map && { ...map, ...mapSettingChanges, }; const selectedMapStateWithChanges = mapState && { ...mapState, ...mapStateSettingChanges, }; const [showMoreSettings, setShowMoreSettings] = useState(true); const layout = useResponsiveLayout(); return ( {isLoading || !map ? ( ) : ( )} ); } export default EditMapModal;