From d4ccad8e0a0fc992a52d3f85d4eac6f44cd6e114 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 12:07:06 +1100 Subject: [PATCH 01/37] Added bounds to grid name match --- src/helpers/map.js | 2 +- src/modals/SelectMapModal.js | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/helpers/map.js b/src/helpers/map.js index 943a2f4..a6875ba 100644 --- a/src/helpers/map.js +++ b/src/helpers/map.js @@ -39,7 +39,7 @@ const gridSizeStd = { x: 14.438842, y: 15.582376 }; const minGridSize = 10; const maxGridSize = 200; -function gridSizeVaild(x, y) { +export function gridSizeVaild(x, y) { return ( x > minGridSize && y > minGridSize && x < maxGridSize && y < maxGridSize ); diff --git a/src/modals/SelectMapModal.js b/src/modals/SelectMapModal.js index 62b67df..8f745f1 100644 --- a/src/modals/SelectMapModal.js +++ b/src/modals/SelectMapModal.js @@ -16,7 +16,7 @@ import blobToBuffer from "../helpers/blobToBuffer"; import useKeyboard from "../helpers/useKeyboard"; import { resizeImage } from "../helpers/image"; import { useSearch, useGroup, handleItemSelect } from "../helpers/select"; -import { getMapDefaultInset, getGridSize } from "../helpers/map"; +import { getMapDefaultInset, getGridSize, gridSizeVaild } from "../helpers/map"; import MapDataContext from "../contexts/MapDataContext"; import AuthContext from "../contexts/AuthContext"; @@ -120,11 +120,14 @@ function SelectMapModal({ // 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)) { + for (let match of gridMatches) { + const matchX = parseInt(match[1]); + const matchY = parseInt(match[3]); + if ( + !isNaN(matchX) && + !isNaN(matchY) && + gridSizeVaild(matchX, matchY) + ) { gridSize = { x: matchX, y: matchY }; } } From c1e67b716c7f1d49eb59ecb76252a8a013159717 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 12:07:30 +1100 Subject: [PATCH 02/37] Added exception handling to ML grid detection --- src/helpers/map.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/helpers/map.js b/src/helpers/map.js index a6875ba..cb70300 100644 --- a/src/helpers/map.js +++ b/src/helpers/map.js @@ -133,7 +133,16 @@ async function gridSizeML(image, candidates) { export async function getGridSize(image) { const candidates = dividers(image.width, image.height); - let prediction = await gridSizeML(image, candidates); + let prediction; + + // Try and use ML grid detection + // TODO: Fix possible error on Android + try { + prediction = await gridSizeML(image, candidates); + } catch (error) { + console.error(error); + } + if (!prediction) { prediction = gridSizeHeuristic(image, candidates); } From 1c79032f308bcb04547786c1814313fe32162ea3 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 12:51:37 +1100 Subject: [PATCH 03/37] Added max zoom based off of map size and normalized wheelY by window height --- src/components/map/MapEditor.js | 3 ++- src/components/map/MapInteraction.js | 2 ++ src/components/token/TokenPreview.js | 1 + src/helpers/map.js | 8 ++++++++ src/helpers/useStageInteraction.js | 10 +++++++--- 5 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/components/map/MapEditor.js b/src/components/map/MapEditor.js index fb649d8..9841020 100644 --- a/src/components/map/MapEditor.js +++ b/src/components/map/MapEditor.js @@ -6,7 +6,7 @@ import ReactResizeDetector from "react-resize-detector"; import useMapImage from "../../helpers/useMapImage"; import usePreventOverscroll from "../../helpers/usePreventOverscroll"; import useStageInteraction from "../../helpers/useStageInteraction"; -import { getMapDefaultInset } from "../../helpers/map"; +import { getMapDefaultInset, getMapMaxZoom } from "../../helpers/map"; import { MapInteractionProvider } from "../../contexts/MapInteractionContext"; import KeyboardContext from "../../contexts/KeyboardContext"; @@ -86,6 +86,7 @@ function MapEditor({ map, onSettingsChange }) { stageScale, setStageScale, stageTranslateRef, + getMapMaxZoom(map), "pan", preventMapInteraction ); diff --git a/src/components/map/MapInteraction.js b/src/components/map/MapInteraction.js index e70e447..45e156d 100644 --- a/src/components/map/MapInteraction.js +++ b/src/components/map/MapInteraction.js @@ -8,6 +8,7 @@ import useMapImage from "../../helpers/useMapImage"; import usePreventOverscroll from "../../helpers/usePreventOverscroll"; import useKeyboard from "../../helpers/useKeyboard"; import useStageInteraction from "../../helpers/useStageInteraction"; +import { getMapMaxZoom } from "../../helpers/map"; import { MapInteractionProvider } from "../../contexts/MapInteractionContext"; import MapStageContext, { @@ -88,6 +89,7 @@ function MapInteraction({ stageScale, setStageScale, stageTranslateRef, + getMapMaxZoom(map), selectedToolId, preventMapInteraction, { diff --git a/src/components/token/TokenPreview.js b/src/components/token/TokenPreview.js index 33033e4..d659908 100644 --- a/src/components/token/TokenPreview.js +++ b/src/components/token/TokenPreview.js @@ -97,6 +97,7 @@ function TokenPreview({ token }) { stageScale, setStageScale, stageTranslateRef, + 10, "pan" ); diff --git a/src/helpers/map.js b/src/helpers/map.js index cb70300..b59601b 100644 --- a/src/helpers/map.js +++ b/src/helpers/map.js @@ -152,3 +152,11 @@ export async function getGridSize(image) { return prediction; } + +export function getMapMaxZoom(map) { + if (!map) { + return 10; + } + // Return max grid size / 2 + return Math.max(Math.min(map.grid.size.x, map.grid.size.y) / 2, 5); +} diff --git a/src/helpers/useStageInteraction.js b/src/helpers/useStageInteraction.js index 21cf9a0..9ca556f 100644 --- a/src/helpers/useStageInteraction.js +++ b/src/helpers/useStageInteraction.js @@ -2,16 +2,16 @@ import { useRef } from "react"; import { useGesture } from "react-use-gesture"; import normalizeWheel from "normalize-wheel"; -const wheelZoomSpeed = -0.001; +const wheelZoomSpeed = -1; const touchZoomSpeed = 0.005; const minZoom = 0.1; -const maxZoom = 10; function useStageInteraction( layer, stageScale, onStageScaleChange, stageTranslateRef, + maxZoom = 10, tool = "pan", preventInteraction = false, gesture = {} @@ -36,7 +36,11 @@ function useStageInteraction( return; } const newScale = Math.min( - Math.max(stageScale + pixelY * wheelZoomSpeed, minZoom), + Math.max( + stageScale + + (pixelY * wheelZoomSpeed * (stageScale + 1)) / window.innerHeight, + minZoom + ), maxZoom ); onStageScaleChange(newScale); From 75c855331a7f05931e27fbbaeae2c8f219f74605 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 16:09:00 +1100 Subject: [PATCH 04/37] Upgraded database for tokens to have width and height --- src/database.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/database.js b/src/database.js index 7fc93c9..8c233fd 100644 --- a/src/database.js +++ b/src/database.js @@ -242,6 +242,32 @@ function loadVersions(db) { token.group = ""; }); }); + // v1.6.1 - Added width and height to tokens + db.version(15) + .stores({}) + .upgrade(async (tx) => { + const tokens = await Dexie.waitFor(tx.table("tokens").toArray()); + let tokenSizes = {}; + for (let token of tokens) { + const url = URL.createObjectURL(new Blob([token.file])); + let image = new Image(); + tokenSizes[token.id] = await Dexie.waitFor( + new Promise((resolve) => { + image.onload = () => { + resolve({ width: image.width, height: image.height }); + }; + image.src = url; + }) + ); + } + return tx + .table("tokens") + .toCollection() + .modify((token) => { + token.width = tokenSizes[token.id].width; + token.height = tokenSizes[token.id].height; + }); + }); } // Get the dexie database used in DatabaseContext From dddfb3d498a20dbd1dfb7899467b18157123442d Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 16:09:27 +1100 Subject: [PATCH 05/37] Added token width and height for new and default tokens --- src/modals/SelectTokensModal.js | 2 ++ src/tokens/index.js | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/modals/SelectTokensModal.js b/src/modals/SelectTokensModal.js index a15c1be..8351654 100644 --- a/src/modals/SelectTokensModal.js +++ b/src/modals/SelectTokensModal.js @@ -109,6 +109,8 @@ function SelectTokensModal({ isOpen, onRequestClose }) { category: "character", hideInSidebar: false, group: "", + width: image.width, + height: image.height, }); setImageLoading(false); resolve(); diff --git a/src/tokens/index.js b/src/tokens/index.js index f9141e4..5a16e82 100644 --- a/src/tokens/index.js +++ b/src/tokens/index.js @@ -87,6 +87,8 @@ export const tokens = Object.keys(tokenSources).map((key) => ({ defaultSize: getDefaultTokenSize(key), category: "character", hideInSidebar: false, + width: 256, + height: 256, })); export const unknownSource = unknown; From f26cbf24d22c058afb2c3503c2533c75ecb3e956 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 16:10:31 +1100 Subject: [PATCH 06/37] Refactored stage zooming to center on the mouse position --- src/components/map/MapEditor.js | 74 ++++++++------------------ src/components/map/MapInteraction.js | 57 +++++++------------- src/components/token/TokenPreview.js | 79 +++++++--------------------- src/helpers/useImageCenter.js | 71 +++++++++++++++++++++++++ src/helpers/useStageInteraction.js | 35 ++++++++---- 5 files changed, 157 insertions(+), 159 deletions(-) create mode 100644 src/helpers/useImageCenter.js diff --git a/src/components/map/MapEditor.js b/src/components/map/MapEditor.js index 9841020..d1e046a 100644 --- a/src/components/map/MapEditor.js +++ b/src/components/map/MapEditor.js @@ -1,4 +1,4 @@ -import React, { useState, useRef, useEffect, useContext } from "react"; +import React, { useState, useRef, useContext } from "react"; import { Box, IconButton } from "theme-ui"; import { Stage, Layer, Image } from "react-konva"; import ReactResizeDetector from "react-resize-detector"; @@ -6,6 +6,7 @@ import ReactResizeDetector from "react-resize-detector"; import useMapImage from "../../helpers/useMapImage"; import usePreventOverscroll from "../../helpers/usePreventOverscroll"; import useStageInteraction from "../../helpers/useStageInteraction"; +import useImageCenter from "../../helpers/useImageCenter"; import { getMapDefaultInset, getMapMaxZoom } from "../../helpers/map"; import { MapInteractionProvider } from "../../contexts/MapInteractionContext"; @@ -25,19 +26,6 @@ function MapEditor({ map, onSettingsChange }) { const [stageHeight, setStageHeight] = useState(1); const [stageScale, setStageScale] = useState(1); - const stageRatio = stageWidth / stageHeight; - const mapRatio = map ? map.width / map.height : 1; - - let mapWidth; - let mapHeight; - if (stageRatio > mapRatio) { - mapWidth = map ? stageHeight / (map.height / map.width) : stageWidth; - mapHeight = stageHeight; - } else { - mapWidth = stageWidth; - mapHeight = map ? stageWidth * (map.height / map.width) : stageHeight; - } - const defaultInset = getMapDefaultInset( map.width, map.height, @@ -46,6 +34,7 @@ function MapEditor({ map, onSettingsChange }) { ); const stageTranslateRef = useRef({ x: 0, y: 0 }); + const mapStageRef = useRef(); const mapLayerRef = useRef(); const [preventMapInteraction, setPreventMapInteraction] = useState(false); @@ -54,46 +43,32 @@ function MapEditor({ map, onSettingsChange }) { setStageHeight(height); } - // Reset map translate and scale - useEffect(() => { - const layer = mapLayerRef.current; - const containerRect = containerRef.current.getBoundingClientRect(); - if (layer) { - let newTranslate; - if (stageRatio > mapRatio) { - newTranslate = { - x: -(mapWidth - containerRect.width) / 2, - y: 0, - }; - } else { - newTranslate = { - x: 0, - y: -(mapHeight - containerRect.height) / 2, - }; - } + const containerRef = useRef(); + usePreventOverscroll(containerRef); - layer.x(newTranslate.x); - layer.y(newTranslate.y); - layer.draw(); - stageTranslateRef.current = newTranslate; - - setStageScale(1); - } - }, [map.id, mapWidth, mapHeight, stageRatio, mapRatio]); + const [mapWidth, mapHeight] = useImageCenter( + map, + mapStageRef, + stageWidth, + stageHeight, + stageTranslateRef, + setStageScale, + mapLayerRef, + containerRef, + true + ); const bind = useStageInteraction( - mapLayerRef.current, + mapStageRef.current, stageScale, setStageScale, stageTranslateRef, + mapLayerRef.current, getMapMaxZoom(map), "pan", preventMapInteraction ); - const containerRef = useRef(); - usePreventOverscroll(containerRef); - function handleGridChange(inset) { onSettingsChange("grid", { ...map.grid, @@ -129,7 +104,6 @@ function MapEditor({ map, onSettingsChange }) { map.grid.inset.topLeft.y !== defaultInset.topLeft.y || map.grid.inset.bottomRight.x !== defaultInset.bottomRight.x || map.grid.inset.bottomRight.y !== defaultInset.bottomRight.y; - return ( {showGridControls && canEditGrid && ( - - )} - {showGridControls && canEditGrid && ( - + <> + + + )} diff --git a/src/components/map/MapInteraction.js b/src/components/map/MapInteraction.js index 45e156d..b750f6d 100644 --- a/src/components/map/MapInteraction.js +++ b/src/components/map/MapInteraction.js @@ -8,6 +8,7 @@ import useMapImage from "../../helpers/useMapImage"; import usePreventOverscroll from "../../helpers/usePreventOverscroll"; import useKeyboard from "../../helpers/useKeyboard"; import useStageInteraction from "../../helpers/useStageInteraction"; +import useImageCenter from "../../helpers/useImageCenter"; import { getMapMaxZoom } from "../../helpers/map"; import { MapInteractionProvider } from "../../contexts/MapInteractionContext"; @@ -43,52 +44,41 @@ function MapInteraction({ const [stageScale, setStageScale] = useState(1); const [preventMapInteraction, setPreventMapInteraction] = useState(false); - const stageWidthRef = useRef(stageWidth); - const stageHeightRef = useRef(stageHeight); // Avoid state udpates when panning the map by using a ref and updating the konva element directly const stageTranslateRef = useRef({ x: 0, y: 0 }); - - // Reset transform when map changes - const previousMapIdRef = useRef(); - useEffect(() => { - const layer = mapLayerRef.current; - const previousMapId = previousMapIdRef.current; - if (map && layer && previousMapId !== map.id) { - const mapHeight = stageWidthRef.current * (map.height / map.width); - const newTranslate = { - x: 0, - y: -(mapHeight - stageHeightRef.current) / 2, - }; - layer.x(newTranslate.x); - layer.y(newTranslate.y); - layer.draw(); - stageTranslateRef.current = newTranslate; - - setStageScale(1); - } - previousMapIdRef.current = map && map.id; - }, [map]); + const mapStageRef = useContext(MapStageContext); + const mapLayerRef = useRef(); + const mapImageRef = useRef(); function handleResize(width, height) { setStageWidth(width); setStageHeight(height); - stageWidthRef.current = width; - stageHeightRef.current = height; } - const mapStageRef = useContext(MapStageContext); - const mapLayerRef = useRef(); - const mapImageRef = useRef(); + const containerRef = useRef(); + usePreventOverscroll(containerRef); + + const [mapWidth, mapHeight] = useImageCenter( + map, + mapStageRef, + stageWidth, + stageHeight, + stageTranslateRef, + setStageScale, + mapLayerRef, + containerRef + ); const previousSelectedToolRef = useRef(selectedToolId); const [interactionEmitter] = useState(new EventEmitter()); const bind = useStageInteraction( - mapLayerRef.current, + mapStageRef.current, stageScale, setStageScale, stageTranslateRef, + mapLayerRef.current, getMapMaxZoom(map), selectedToolId, preventMapInteraction, @@ -171,12 +161,6 @@ function MapInteraction({ } } - const containerRef = useRef(); - usePreventOverscroll(containerRef); - - const mapWidth = stageWidth; - const mapHeight = map ? stageWidth * (map.height / map.width) : stageHeight; - const auth = useContext(AuthContext); const settings = useContext(SettingsContext); @@ -208,9 +192,6 @@ function MapInteraction({ width={stageWidth} height={stageHeight} scale={{ x: stageScale, y: stageScale }} - x={stageWidth / 2} - y={stageHeight / 2} - offset={{ x: stageWidth / 2, y: stageHeight / 2 }} ref={mapStageRef} > diff --git a/src/components/token/TokenPreview.js b/src/components/token/TokenPreview.js index d659908..752a814 100644 --- a/src/components/token/TokenPreview.js +++ b/src/components/token/TokenPreview.js @@ -7,6 +7,7 @@ import useImage from "use-image"; import usePreventOverscroll from "../../helpers/usePreventOverscroll"; import useStageInteraction from "../../helpers/useStageInteraction"; import useDataSource from "../../helpers/useDataSource"; +import useImageCenter from "../../helpers/useImageCenter"; import GridOnIcon from "../../icons/GridOnIcon"; import GridOffIcon from "../../icons/GridOffIcon"; @@ -29,81 +30,43 @@ function TokenPreview({ token }) { unknownSource ); const [tokenSourceImage] = useImage(tokenSource); - const [tokenRatio, setTokenRatio] = useState(1); - - useEffect(() => { - if (tokenSourceImage) { - setTokenRatio(tokenSourceImage.width / tokenSourceImage.height); - } - }, [tokenSourceImage]); const [stageWidth, setStageWidth] = useState(1); const [stageHeight, setStageHeight] = useState(1); const [stageScale, setStageScale] = useState(1); - const stageRatio = stageWidth / stageHeight; - - let tokenWidth; - let tokenHeight; - if (stageRatio > tokenRatio) { - tokenWidth = tokenSourceImage - ? stageHeight / (tokenSourceImage.height / tokenSourceImage.width) - : stageWidth; - tokenHeight = stageHeight; - } else { - tokenWidth = stageWidth; - tokenHeight = tokenSourceImage - ? stageWidth * (tokenSourceImage.height / tokenSourceImage.width) - : stageHeight; - } - const stageTranslateRef = useRef({ x: 0, y: 0 }); - const mapLayerRef = useRef(); + const tokenStageRef = useRef(); + const tokenLayerRef = useRef(); function handleResize(width, height) { setStageWidth(width); setStageHeight(height); } - // Reset map translate and scale - useEffect(() => { - const layer = mapLayerRef.current; - const containerRect = containerRef.current.getBoundingClientRect(); - if (layer) { - let newTranslate; - if (stageRatio > tokenRatio) { - newTranslate = { - x: -(tokenWidth - containerRect.width) / 2, - y: 0, - }; - } else { - newTranslate = { - x: 0, - y: -(tokenHeight - containerRect.height) / 2, - }; - } + const containerRef = useRef(); + usePreventOverscroll(containerRef); - layer.x(newTranslate.x); - layer.y(newTranslate.y); - layer.draw(); - stageTranslateRef.current = newTranslate; - - setStageScale(1); - } - }, [token.id, tokenWidth, tokenHeight, stageRatio, tokenRatio]); + const [tokenWidth, tokenHeight] = useImageCenter( + token, + tokenStageRef, + stageWidth, + stageHeight, + stageTranslateRef, + setStageScale, + tokenLayerRef, + containerRef, + true + ); const bind = useStageInteraction( - mapLayerRef.current, + tokenStageRef.current, stageScale, setStageScale, stageTranslateRef, - 10, - "pan" + tokenLayerRef.current ); - const containerRef = useRef(); - usePreventOverscroll(containerRef); - const [showGridPreview, setShowGridPreview] = useState(true); const gridWidth = tokenWidth; const gridX = token.defaultSize; @@ -134,11 +97,9 @@ function TokenPreview({ token }) { width={stageWidth} height={stageHeight} scale={{ x: stageScale, y: stageScale }} - x={stageWidth / 2} - y={stageHeight / 2} - offset={{ x: stageWidth / 2, y: stageHeight / 2 }} + ref={tokenStageRef} > - + imageRatio) { + imageWidth = data ? stageHeight / (data.height / data.width) : stageWidth; + imageHeight = stageHeight; + } else { + imageWidth = stageWidth; + imageHeight = data ? stageWidth * (data.height / data.width) : stageHeight; + } + + // Reset data translate and scale + const previousDataIdRef = useRef(); + const previousStageRatioRef = useRef(stageRatio); + useEffect(() => { + if (!data) { + return; + } + + const layer = imageLayerRef.current; + const containerRect = containerRef.current.getBoundingClientRect(); + const previousDataId = previousDataIdRef.current; + const previousStageRatio = previousStageRatioRef.current; + + // Update when the id has changed and if responsive update when the stage changes + const shouldUpdate = responsive + ? previousDataId !== data.id || previousStageRatio !== stageRatio + : previousDataId !== data.id; + + if (layer && shouldUpdate) { + let newTranslate; + if (stageRatio > imageRatio) { + newTranslate = { + x: -(imageWidth - containerRect.width) / 2, + y: 0, + }; + } else { + newTranslate = { + x: 0, + y: -(imageHeight - containerRect.height) / 2, + }; + } + layer.position(newTranslate); + stageRef.current.position({ x: 0, y: 0 }); + stageTranslateRef.current = { x: 0, y: 0 }; + + setStageScale(1); + } + previousDataIdRef.current = data.id; + previousStageRatioRef.current = stageRatio; + }); + + return [imageWidth, imageHeight]; +} + +export default useImageCenter; diff --git a/src/helpers/useStageInteraction.js b/src/helpers/useStageInteraction.js index 9ca556f..5d7b6a8 100644 --- a/src/helpers/useStageInteraction.js +++ b/src/helpers/useStageInteraction.js @@ -7,10 +7,11 @@ const touchZoomSpeed = 0.005; const minZoom = 0.1; function useStageInteraction( - layer, + stage, stageScale, onStageScaleChange, stageTranslateRef, + layer, maxZoom = 10, tool = "pan", preventInteraction = false, @@ -43,6 +44,20 @@ function useStageInteraction( ), maxZoom ); + + const pointer = stage.getPointerPosition(); + const pointerChange = { + x: (pointer.x - stage.x()) / stageScale, + y: (pointer.y - stage.y()) / stageScale, + }; + + const newTranslate = { + x: pointer.x - pointerChange.x * newScale, + y: pointer.y - pointerChange.y * newScale, + }; + stage.position(newTranslate); + stageTranslateRef.current = newTranslate; + onStageScaleChange(newScale); gesture.onWheel && gesture.onWheel(props); }, @@ -68,12 +83,11 @@ function useStageInteraction( // Apply translate const stageTranslate = stageTranslateRef.current; const newTranslate = { - x: stageTranslate.x + originXDelta / newScale, - y: stageTranslate.y + originYDelta / newScale, + x: stageTranslate.x + originXDelta, + y: stageTranslate.y + originYDelta, }; - layer.x(newTranslate.x); - layer.y(newTranslate.y); - layer.draw(); + stage.position(newTranslate); + stage.draw(); stageTranslateRef.current = newTranslate; pinchPreviousDistanceRef.current = distance; @@ -96,12 +110,11 @@ function useStageInteraction( const stageTranslate = stageTranslateRef.current; if (tool === "pan") { const newTranslate = { - x: stageTranslate.x + dx / stageScale, - y: stageTranslate.y + dy / stageScale, + x: stageTranslate.x + dx, + y: stageTranslate.y + dy, }; - layer.x(newTranslate.x); - layer.y(newTranslate.y); - layer.draw(); + stage.position(newTranslate); + stage.draw(); stageTranslateRef.current = newTranslate; } gesture.onDrag && gesture.onDrag(props); From 1d52edc7757e9016bff28f5027997fe954ca3e49 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 16:11:00 +1100 Subject: [PATCH 07/37] Fixed unnecessary zoom speed increase --- src/helpers/useStageInteraction.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/useStageInteraction.js b/src/helpers/useStageInteraction.js index 5d7b6a8..74cc67d 100644 --- a/src/helpers/useStageInteraction.js +++ b/src/helpers/useStageInteraction.js @@ -39,7 +39,7 @@ function useStageInteraction( const newScale = Math.min( Math.max( stageScale + - (pixelY * wheelZoomSpeed * (stageScale + 1)) / window.innerHeight, + (pixelY * wheelZoomSpeed * stageScale) / window.innerHeight, minZoom ), maxZoom From c60d495a14dfde7cde7eeb2ca2807c061faa058b Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 16:11:44 +1100 Subject: [PATCH 08/37] Update comment --- src/helpers/useImageCenter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/useImageCenter.js b/src/helpers/useImageCenter.js index 9956737..3ffa355 100644 --- a/src/helpers/useImageCenter.js +++ b/src/helpers/useImageCenter.js @@ -24,7 +24,7 @@ function useImageCenter( imageHeight = data ? stageWidth * (data.height / data.width) : stageHeight; } - // Reset data translate and scale + // Reset image translate and stage scale const previousDataIdRef = useRef(); const previousStageRatioRef = useRef(stageRatio); useEffect(() => { From 611e7af3d98b7f174e7b68cc7fed28657a1412a1 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 16:39:24 +1100 Subject: [PATCH 09/37] Removed show more button for editing maps --- src/components/map/MapSettings.js | 212 +++++++++++++----------------- src/modals/EditMapModal.js | 4 - 2 files changed, 90 insertions(+), 126 deletions(-) diff --git a/src/components/map/MapSettings.js b/src/components/map/MapSettings.js index 78090aa..7d5358b 100644 --- a/src/components/map/MapSettings.js +++ b/src/components/map/MapSettings.js @@ -21,8 +21,6 @@ function MapSettings({ mapState, onSettingsChange, onStateSettingsChange, - showMore, - onShowMoreChange, }) { function handleFlagChange(event, flag) { if (event.target.checked) { @@ -131,127 +129,97 @@ function MapSettings({ my={1} /> - {showMore && ( - <> - - - - s.value === map.quality) - } - isDisabled={mapEmpty} - onChange={(option) => - onSettingsChange("quality", option.value) - } - isOptionDisabled={(option) => - mapEmpty || - (option.value !== "original" && - !map.resolutions[option.value]) - } - isSearchable={false} - /> - - - - )} - - - - - - - - - - - )} - { - e.stopPropagation(); - e.preventDefault(); - onShowMoreChange(!showMore); - }} - sx={{ - transform: `rotate(${showMore ? "180deg" : "0"})`, - alignSelf: "center", - }} - aria-label={showMore ? "Show Less" : "Show More"} - title={showMore ? "Show Less" : "Show More"} + - - + + + s.value === map.quality) + } + isDisabled={mapEmpty} + onChange={(option) => onSettingsChange("quality", option.value)} + isOptionDisabled={(option) => + mapEmpty || + (option.value !== "original" && !map.resolutions[option.value]) + } + isSearchable={false} + /> + + + + )} + + + + + + + + + ); } diff --git a/src/modals/EditMapModal.js b/src/modals/EditMapModal.js index 1a0bf0f..7db5671 100644 --- a/src/modals/EditMapModal.js +++ b/src/modals/EditMapModal.js @@ -96,8 +96,6 @@ function EditMapModal({ isOpen, onDone, map, mapState }) { ...mapStateSettingChanges, }; - const [showMoreSettings, setShowMoreSettings] = useState(false); - return ( From d6b790035ab502aeade112bd68cd323f4f6d5b09 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 20:57:01 +1100 Subject: [PATCH 10/37] Fix unused import --- src/components/map/MapSettings.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/components/map/MapSettings.js b/src/components/map/MapSettings.js index 7d5358b..3db65d5 100644 --- a/src/components/map/MapSettings.js +++ b/src/components/map/MapSettings.js @@ -1,7 +1,5 @@ import React from "react"; -import { Flex, Box, Label, Input, Checkbox, IconButton } from "theme-ui"; - -import ExpandMoreIcon from "../../icons/ExpandMoreIcon"; +import { Flex, Box, Label, Input, Checkbox } from "theme-ui"; import { isEmpty } from "../../helpers/shared"; From f9b55b4673584153e4e70f32522941fb32e56be5 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 20:57:29 +1100 Subject: [PATCH 11/37] Fixed bug with direct database update for map state --- src/network/NetworkedMapAndTokens.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/network/NetworkedMapAndTokens.js b/src/network/NetworkedMapAndTokens.js index 8a80dbd..c6efd0b 100644 --- a/src/network/NetworkedMapAndTokens.js +++ b/src/network/NetworkedMapAndTokens.js @@ -33,7 +33,9 @@ function NetworkedMapAndTokens({ session }) { } = useContext(MapLoadingContext); const { putToken, getToken, updateToken } = useContext(TokenDataContext); - const { putMap, updateMap, getMapFromDB } = useContext(MapDataContext); + const { putMap, updateMap, getMapFromDB, updateMapState } = useContext( + MapDataContext + ); const [currentMap, setCurrentMap] = useState(null); const [currentMapState, setCurrentMapState] = useState(null); @@ -53,11 +55,9 @@ function NetworkedMapAndTokens({ session }) { currentMap.owner === userId && database ) { - // Update the database directly to avoid re-renders - database - .table("states") - .update(debouncedMapState.mapId, debouncedMapState); + updateMapState(debouncedMapState.mapId, debouncedMapState); } + // eslint-disable-next-line react-hooks/exhaustive-deps }, [currentMap, debouncedMapState, userId, database]); function handleMapChange(newMap, newMapState) { From f98fc394d4493f36793049dfba16ac3f50063fc6 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Thu, 22 Oct 2020 21:15:07 +1100 Subject: [PATCH 12/37] Renamed show grid to draw grid --- src/components/map/MapSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/map/MapSettings.js b/src/components/map/MapSettings.js index 3db65d5..62eb49b 100644 --- a/src/components/map/MapSettings.js +++ b/src/components/map/MapSettings.js @@ -152,7 +152,7 @@ function MapSettings({ disabled={mapEmpty || map.type === "default"} onChange={(e) => onSettingsChange("showGrid", e.target.checked)} /> - Show Grid + Draw Grid