Split tokens into data and state to avoid data duplication
This commit is contained in:
parent
65478d555b
commit
ece974c5d9
@ -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) => (
|
||||
<MapToken
|
||||
key={token.id}
|
||||
token={token}
|
||||
key={tokenState.id}
|
||||
token={tokens.find((token) => token.id === tokenState.tokenId)}
|
||||
tokenState={tokenState}
|
||||
tokenSizePercent={tokenSizePercent}
|
||||
className={`${mapTokenProxyClassName} ${mapTokenMenuClassName}`}
|
||||
/>
|
||||
@ -335,7 +337,7 @@ function Map({
|
||||
/>
|
||||
<TokenMenu
|
||||
tokenClassName={mapTokenMenuClassName}
|
||||
onTokenChange={onMapTokenChange}
|
||||
onTokenChange={onMapTokenStateChange}
|
||||
tokens={mapState && mapState.tokens}
|
||||
/>
|
||||
</>
|
||||
|
@ -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 (
|
||||
<Box
|
||||
style={{
|
||||
transform: `translate(${token.x * 100}%, ${token.y * 100}%)`,
|
||||
transform: `translate(${tokenState.x * 100}%, ${tokenState.y * 100}%)`,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
@ -30,7 +30,7 @@ function MapToken({ token, tokenSizePercent, className }) {
|
||||
>
|
||||
<Box
|
||||
style={{
|
||||
width: `${tokenSizePercent * (token.size || 1)}%`,
|
||||
width: `${tokenSizePercent * (tokenState.size || 1)}%`,
|
||||
}}
|
||||
sx={{
|
||||
position: "absolute",
|
||||
@ -54,11 +54,13 @@ function MapToken({ token, tokenSizePercent, className }) {
|
||||
}}
|
||||
src={imageSource}
|
||||
// pass id into the dom element which is then used by the ProxyToken
|
||||
data-id={token.id}
|
||||
data-id={tokenState.id}
|
||||
ref={imageRef}
|
||||
/>
|
||||
{token.statuses && <TokenStatus statuses={token.statuses} />}
|
||||
{token.label && <TokenLabel label={token.label} />}
|
||||
{tokenState.statuses && (
|
||||
<TokenStatus statuses={tokenState.statuses} />
|
||||
)}
|
||||
{tokenState.label && <TokenLabel label={tokenState.label} />}
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
|
@ -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,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -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 (
|
||||
<>
|
||||
<Flex sx={{ flexDirection: "column", height: "100%" }}>
|
||||
@ -336,15 +353,19 @@ function Game() {
|
||||
<Map
|
||||
map={map}
|
||||
mapState={mapState}
|
||||
onMapTokenChange={handleMapTokenChange}
|
||||
onMapTokenRemove={handleMapTokenRemove}
|
||||
tokens={tokens}
|
||||
onMapTokenStateChange={handleMapTokenStateChange}
|
||||
onMapTokenStateRemove={handleMapTokenStateRemove}
|
||||
onMapChange={handleMapChange}
|
||||
onMapStateChange={handleMapStateChange}
|
||||
onMapDraw={handleMapDraw}
|
||||
onMapDrawUndo={handleMapDrawUndo}
|
||||
onMapDrawRedo={handleMapDrawRedo}
|
||||
/>
|
||||
<Tokens onCreateMapToken={handleMapTokenChange} />
|
||||
<Tokens
|
||||
tokens={tokens}
|
||||
onCreateMapTokenState={handleMapTokenStateChange}
|
||||
/>
|
||||
</Flex>
|
||||
</Flex>
|
||||
<Banner isOpen={!!peerError} onRequestClose={() => setPeerError(null)}>
|
||||
|
Loading…
Reference in New Issue
Block a user