From ece974c5d9adfd8973d0963cc5c82ecf458996d7 Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Fri, 24 Apr 2020 18:39:11 +1000 Subject: [PATCH] Split tokens into data and state to avoid data duplication --- src/components/map/Map.js | 24 +++++++++++---------- src/components/map/MapToken.js | 14 ++++++------ src/components/token/Tokens.js | 25 +++++++--------------- src/routes/Game.js | 39 ++++++++++++++++++++++++++-------- 4 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/components/map/Map.js b/src/components/map/Map.js index 922a86c..b213f8f 100644 --- a/src/components/map/Map.js +++ b/src/components/map/Map.js @@ -21,8 +21,9 @@ const maxZoom = 5; function Map({ map, mapState, - onMapTokenChange, - onMapTokenRemove, + tokens, + onMapTokenStateChange, + onMapTokenStateRemove, onMapChange, onMapStateChange, onMapDraw, @@ -31,13 +32,13 @@ function Map({ }) { const mapSource = useDataSource(map, defaultMapSources); - function handleProxyDragEnd(isOnMap, token) { - if (isOnMap && onMapTokenChange) { - onMapTokenChange(token); + function handleProxyDragEnd(isOnMap, tokenState) { + if (isOnMap && onMapTokenStateChange) { + onMapTokenStateChange(tokenState); } - if (!isOnMap && onMapTokenRemove) { - onMapTokenRemove(token); + if (!isOnMap && onMapTokenStateRemove) { + onMapTokenStateRemove(tokenState); } } @@ -240,10 +241,11 @@ function Map({ }} > {mapState && - Object.values(mapState.tokens).map((token) => ( + Object.values(mapState.tokens).map((tokenState) => ( token.id === tokenState.tokenId)} + tokenState={tokenState} tokenSizePercent={tokenSizePercent} className={`${mapTokenProxyClassName} ${mapTokenMenuClassName}`} /> @@ -335,7 +337,7 @@ function Map({ /> diff --git a/src/components/map/MapToken.js b/src/components/map/MapToken.js index 3fdceb0..6d8309a 100644 --- a/src/components/map/MapToken.js +++ b/src/components/map/MapToken.js @@ -9,7 +9,7 @@ import useDataSource from "../../helpers/useDataSource"; import { tokenSources } from "../../tokens"; -function MapToken({ token, tokenSizePercent, className }) { +function MapToken({ token, tokenState, tokenSizePercent, className }) { const imageSource = useDataSource(token, tokenSources); const imageRef = useRef(); @@ -19,7 +19,7 @@ function MapToken({ token, tokenSizePercent, className }) { return ( - {token.statuses && } - {token.label && } + {tokenState.statuses && ( + + )} + {tokenState.label && } diff --git a/src/components/token/Tokens.js b/src/components/token/Tokens.js index 94865a5..becf119 100644 --- a/src/components/token/Tokens.js +++ b/src/components/token/Tokens.js @@ -1,10 +1,8 @@ -import React, { useState, useEffect } from "react"; +import React, { useState } from "react"; import { Box } from "theme-ui"; import shortid from "shortid"; import SimpleBar from "simplebar-react"; -import { tokens as defaultTokens } from "../../tokens"; - import ListToken from "./ListToken"; import ProxyToken from "./ProxyToken"; import NumberInput from "../NumberInput"; @@ -13,27 +11,20 @@ import { fromEntries } from "../../helpers/shared"; const listTokenClassName = "list-token"; -function Tokens({ onCreateMapToken }) { - const [tokens, setTokens] = useState([]); - useEffect(() => { - const defaultTokensWithIds = []; - for (let defaultToken of defaultTokens) { - defaultTokensWithIds.push({ ...defaultToken, id: defaultToken.name }); - } - setTokens(defaultTokensWithIds); - }, []); - +function Tokens({ onCreateMapTokenState, tokens }) { const [tokenSize, setTokenSize] = useState(1); function handleProxyDragEnd(isOnMap, token) { - if (isOnMap && onCreateMapToken) { - // Give the token an id - onCreateMapToken({ - ...token, + if (isOnMap && onCreateMapTokenState) { + // Create a token state from the dragged token + onCreateMapTokenState({ id: shortid.generate(), + tokenId: token.id, size: tokenSize, label: "", statuses: [], + x: token.x, + y: token.y, }); } } diff --git a/src/routes/Game.js b/src/routes/Game.js index 248071b..1789f50 100644 --- a/src/routes/Game.js +++ b/src/routes/Game.js @@ -19,6 +19,8 @@ import AuthModal from "../modals/AuthModal"; import AuthContext from "../contexts/AuthContext"; +import { tokens as defaultTokens } from "../tokens"; + function Game() { const { id: gameId } = useParams(); const { authenticationStatus, userId } = useContext(AuthContext); @@ -70,7 +72,7 @@ function Game() { } } - async function handleMapTokenChange(token) { + async function handleMapTokenStateChange(token) { if (mapState === null) { return; } @@ -83,18 +85,18 @@ function Game() { })); for (let peer of Object.values(peers)) { const data = { [token.id]: token }; - peer.connection.send({ id: "tokenEdit", data }); + peer.connection.send({ id: "tokenStateEdit", data }); } } - function handleMapTokenRemove(token) { + function handleMapTokenStateRemove(token) { setMapState((prevMapState) => { const { [token.id]: old, ...rest } = prevMapState.tokens; return { ...prevMapState, tokens: rest }; }); for (let peer of Object.values(peers)) { const data = { [token.id]: token }; - peer.connection.send({ id: "tokenRemove", data }); + peer.connection.send({ id: "tokenStateRemove", data }); } } @@ -196,13 +198,13 @@ function Game() { if (data.id === "mapState") { setMapState(data.data); } - if (data.id === "tokenEdit") { + if (data.id === "tokenStateEdit") { setMapState((prevMapState) => ({ ...prevMapState, tokens: { ...prevMapState.tokens, ...data.data }, })); } - if (data.id === "tokenRemove") { + if (data.id === "tokenStateRemove") { setMapState((prevMapState) => ({ ...prevMapState, tokens: omit(prevMapState.tokens, Object.keys(data.data)), @@ -317,6 +319,21 @@ function Game() { } }, [stream, peers, handleStreamEnd]); + /** + * Token data + */ + const [tokens, setTokens] = useState([]); + useEffect(() => { + const defaultTokensWithIds = []; + for (let defaultToken of defaultTokens) { + defaultTokensWithIds.push({ + ...defaultToken, + id: `__default-${defaultToken.name}`, + }); + } + setTokens(defaultTokensWithIds); + }, []); + return ( <> @@ -336,15 +353,19 @@ function Game() { - + setPeerError(null)}>