diff --git a/src/docs/faq/maps.md b/src/docs/faq/maps.md index 0c0b2cd..d5cada1 100644 --- a/src/docs/faq/maps.md +++ b/src/docs/faq/maps.md @@ -14,7 +14,7 @@ This means that the token hasn’t loaded in just yet. If they still haven’t l ### How big can my maps be? -Owlbear Rodeo doesn't impose a limit on map sizes but keep in mind the larger the map you upload the longer it will take for your players to load. We recommend trying to keep your maps under 10MB in size and under 8000px on the largest edge in resolution. If you accidently upload a map that is too big you can use the quality option in the map's settings to lower the size without needing to re-upload your map. +Owlbear Rodeo has a map size limit of 50MB but keep in mind the larger the map you upload the longer it will take for your players to load. We recommend trying to keep your maps under 10MB in size and under 8000px on the largest edge in resolution. If you accidently upload a map that is too big you can use the quality option in the map's settings to lower the size without needing to re-upload your map. ### Where are my maps stored? diff --git a/src/modals/SelectMapModal.js b/src/modals/SelectMapModal.js index 80dc8d3..bfcc3f1 100644 --- a/src/modals/SelectMapModal.js +++ b/src/modals/SelectMapModal.js @@ -2,6 +2,7 @@ import React, { useRef, useState } from "react"; import { Button, Flex, Label } from "theme-ui"; import shortid from "shortid"; import Case from "case"; +import { useToasts } from "react-toast-notifications"; import EditMapModal from "./EditMapModal"; import EditGroupModal from "./EditGroupModal"; @@ -56,6 +57,8 @@ function SelectMapModal({ // The map currently being view in the map screen currentMap, }) { + const { addToast } = useToasts(); + const { userId } = useAuth(); const { ownedMaps, @@ -106,19 +109,55 @@ function SelectMapModal({ const fileInputRef = useRef(); const [isLoading, setIsLoading] = useState(false); + const [isLargeImageWarningModalOpen, setShowLargeImageWarning] = useState( + false + ); + const largeImageWarningFiles = useRef(); + async function handleImagesUpload(files) { if (navigator.storage) { // Attempt to enable persistant storage await navigator.storage.persist(); } - for (let file of files) { - await handleImageUpload(file); - } // Set file input to null to allow adding the same image 2 times in a row if (fileInputRef.current) { fileInputRef.current.value = null; } + + let mapFiles = []; + for (let file of files) { + if (file.size > 5e7) { + addToast(`Unable to import map ${file.name} as it is over 50MB`); + } else { + mapFiles.push(file); + } + } + + // Any file greater than 20MB + if (mapFiles.some((file) => file.size > 2e7)) { + largeImageWarningFiles.current = mapFiles; + setShowLargeImageWarning(true); + return; + } + + for (let file of mapFiles) { + await handleImageUpload(file); + } + } + + function handleLargeImageWarningCancel() { + largeImageWarningFiles.current = undefined; + setShowLargeImageWarning(false); + } + + async function handleLargeImageWarningConfirm() { + setShowLargeImageWarning(false); + const files = largeImageWarningFiles.current; + for (let file of files) { + await handleImageUpload(file); + } + largeImageWarningFiles.current = undefined; } async function handleImageUpload(file) { @@ -486,6 +525,14 @@ function SelectMapModal({ }`} description="This operation cannot be undone." /> + ); } diff --git a/src/modals/SelectTokensModal.js b/src/modals/SelectTokensModal.js index 2627a81..1a640cc 100644 --- a/src/modals/SelectTokensModal.js +++ b/src/modals/SelectTokensModal.js @@ -2,6 +2,7 @@ import React, { useRef, useState } from "react"; import { Flex, Label, Button } from "theme-ui"; import shortid from "shortid"; import Case from "case"; +import { useToasts } from "react-toast-notifications"; import EditTokenModal from "./EditTokenModal"; import EditGroupModal from "./EditGroupModal"; @@ -25,6 +26,8 @@ import { useKeyboard, useBlur } from "../contexts/KeyboardContext"; import shortcuts from "../shortcuts"; function SelectTokensModal({ isOpen, onRequestClose }) { + const { addToast } = useToasts(); + const { userId } = useAuth(); const { ownedTokens, @@ -70,6 +73,11 @@ function SelectTokensModal({ isOpen, onRequestClose }) { const fileInputRef = useRef(); const [isLoading, setIsLoading] = useState(false); + const [isLargeImageWarningModalOpen, setShowLargeImageWarning] = useState( + false + ); + const largeImageWarningFiles = useRef(); + function openImageDialog() { if (fileInputRef.current) { fileInputRef.current.click(); @@ -82,13 +90,44 @@ function SelectTokensModal({ isOpen, onRequestClose }) { await navigator.storage.persist(); } - for (let file of files) { - await handleImageUpload(file); - } // Set file input to null to allow adding the same image 2 times in a row if (fileInputRef.current) { fileInputRef.current.value = null; } + + let tokenFiles = []; + for (let file of files) { + if (file.size > 5e7) { + addToast(`Unable to import token ${file.name} as it is over 50MB`); + } else { + tokenFiles.push(file); + } + } + + // Any file greater than 20MB + if (tokenFiles.some((file) => file.size > 2e7)) { + largeImageWarningFiles.current = tokenFiles; + setShowLargeImageWarning(true); + return; + } + + for (let file of tokenFiles) { + await handleImageUpload(file); + } + } + + function handleLargeImageWarningCancel() { + largeImageWarningFiles.current = undefined; + setShowLargeImageWarning(false); + } + + async function handleLargeImageWarningConfirm() { + setShowLargeImageWarning(false); + const files = largeImageWarningFiles.current; + for (let file of files) { + await handleImageUpload(file); + } + largeImageWarningFiles.current = undefined; } async function handleImageUpload(file) { @@ -314,6 +353,14 @@ function SelectTokensModal({ isOpen, onRequestClose }) { }`} description="This operation cannot be undone." /> + ); }