-
board goes here
+
- { name === "" &&
}
+ { loaded && name === "" &&
}
{ name !== "" &&
}
{ name !== "" &&
}
diff --git a/client/src/Board.css b/client/src/Board.css
index 5a91a11..1097b98 100644
--- a/client/src/Board.css
+++ b/client/src/Board.css
@@ -1,13 +1,8 @@
.Board {
display: flex;
align-self: stretch;
- position: absolute;
flex: 1;
align-items: stretch;
- right: 30rem;
- left: 0;
- top: 0;
- bottom: 11rem;
}
/* Offset 'BorderBox' such that 0,0 is the center
diff --git a/client/src/Board.js b/client/src/Board.js
index 9a0488a..fd6be4d 100644
--- a/client/src/Board.js
+++ b/client/src/Board.js
@@ -1,19 +1,153 @@
-import React, { useState } from "react";
+import React, { useEffect, useState, useContext, useRef, useMemo } from "react";
+import { assetsPath, debounce } from "./Common.js";
import "./Board.css";
+import { GlobalContext } from "./GlobalContext.js";
-const base = process.env.PUBLIC_URL;
-const assetsPath = `${base}/assets`;
+const Board = () => {
+ const { ws } = useContext(GlobalContext);
+ const board = useRef();
+ const [pipElements, setPipElements] = useState(<>>);
+ const [borderElements, setBorderElements] = useState(<>>);
+ const [tileElements, setTileElements] = useState(<>>);
+ const [cornerElements, setCornerElements] = useState(<>>);
+ const [roadElements, setRoadElements] = useState(<>>);
+ const [ signature, setSignature ] = useState("");
+ const [ robber, setRobber ] = useState(-1);
+ const [ robberName, setRobberName ] = useState([]);
+ const [ pips, setPips ] = useState([]);
+ const [ pipOrder, setPipOrder ] = useState([]);
+ const [ borders, setBorders ] = useState([]);
+ const [ borderOrder, setBorderOrder ] = useState([]);
+ const [ tiles, setTiles ] = useState([]);
+ const [ tileOrder, setTileOrder ] = useState([]);
+ const [ placements, setPlacements ] = useState(undefined);
+ const [ turn, setTurn ] = useState({});
+ const [ state, setState ] = useState("");
+ const [ color, setColor ] = useState("");
+ const [ longestRoadLength, setLongestRoadLength ] = useState(0);
+ const fields = useMemo(() => [
+ 'signature', 'robber', 'robberName',
+ 'pips', 'pipsOrder', 'borders', 'borderOrder', 'tiles', 'tileOrder',
+ 'placements', 'turn', 'state', 'color', 'longestRoadLength'
+ ], []);
+
+ const onWsMessage = (event) => {
+ const data = JSON.parse(event.data);
+ switch (data.type) {
+ case 'game-update':
+ if (data.update.signature && data.update.signature !== signature) {
+ setSignature(data.update.signature);
+ }
-const Board = ({ table, game }) => {
- const rows = [3, 4, 5, 4, 3, 2]; /* The final row of 2 is to place roads and corners */
- const [signature, setSignature] = useState("");
- const [pips, setPips] = useState(<>>);
- const [borders, setBorders] = useState(<>>);
- const [tiles, setTiles] = useState(<>>);
- const [corners, setCorners] = useState(<>>);
- const [roads, setRoads] = useState(<>>);
+ if (data.update.robber && data.update.robber !== robber) {
+ setRobber(data.update.robber);
+ }
+
+ if (data.update.robberName && data.update.robberName !== robberName) {
+ setRobberName(data.update.robberName);
+ }
- const [transform, setTransform] = useState(1);
+ if (data.update.pips) {
+ setPips(data.update.pips);
+ }
+ if (data.update.pipOrder) {
+ setPipOrder(data.update.pipOrder);
+ }
+
+ if (data.update.borders) {
+ setBorders(data.update.borders);
+ }
+ if (data.update.borderOrder) {
+ setBorderOrder(data.update.borderOrder);
+ }
+
+ if (data.update.tiles) {
+ setTiles(data.update.tiles);
+ }
+ if (data.update.tileOrder) {
+ setTileOrder(data.update.tileOrder);
+ }
+
+ if (data.update.state && data.update.state !== state) {
+ setState(data.update.state);
+ }
+ if (data.update.color && data.update.color !== color) {
+ setColor(data.update.color);
+ }
+ if (data.update.longestRoadLength
+ && data.update.longestRoadLength !== longestRoadLength) {
+ setLongestRoadLength(data.update.longestRoadLength);
+ }
+ if (data.update.turn) {
+ setTurn(data.update.turn);
+ }
+ if (data.update.placements) {
+ console.log(`placements`, data.update.placements);
+ setPlacements(data.update.placements);
+ }
+ break;
+ default:
+ break;
+ }
+ };
+
+ const refWsMessage = useRef(onWsMessage);
+ useEffect(() => { refWsMessage.current = onWsMessage; });
+
+ useEffect(() => {
+ if (!board.current) {
+ return;
+ }
+
+ const onResize = debounce(() => {
+ /* Adjust the 'transform: scale' for the BoardBox
+ * so the board fills the Board
+ *
+ * The board is H tall, and H * hexRatio wide */
+ const width = board.current.offsetWidth,
+ height = board.current.offsetHeight;
+ let _transform;
+ if (height * hexRatio > width) {
+ _transform = width / (450. * hexRatio);
+ } else {
+ _transform = height / (450.);
+ }
+
+ const boardBox = board.current.querySelector('.BoardBox');
+ if (boardBox) {
+ console.log(`Setting transofrm scale to ${_transform}`);
+ boardBox.style.transform = `scale(${_transform})`;
+ }
+ }, 250);
+
+ window.addEventListener('resize', onResize);
+ onResize();
+
+ return () => {
+ window.removeEventListener('resize', onResize);
+ }
+ }, [board]);
+
+ useEffect(() => {
+ if (!ws) {
+ return;
+ }
+ const cbMessage = e => refWsMessage.current(e);
+ ws.addEventListener('message', cbMessage);
+ return () => {
+ ws.removeEventListener('message', cbMessage);
+ }
+ }, [ws, refWsMessage]);
+
+ useEffect(() => {
+ if (!ws) {
+ return;
+ }
+ ws.send(JSON.stringify({
+ type: 'get',
+ fields
+ }));
+ }, [ws, fields]);
const
hexRatio = 1.1547,
@@ -51,10 +185,16 @@ const Board = ({ table, game }) => {
>
;
};
+ const sendPlacement = (type, index) => {
+ ws.send(JSON.stringify({
+ type, index
+ }));
+ };
+
const Road = ({road}) => {
const onClick = (event) => {
console.log(`Road clicked: ${road.index}`);
- table.placeRoad(road.index);
+ sendPlacement('place-road', road.index);
};
return {
const Corner = ({corner}) => {
const onClick = (event) => {
-// console.log(`Corner ${corner.index}:`, game.layout.corners[corner.index]);
+ let type;
if (event.currentTarget.getAttribute('data-type') === 'settlement') {
- table.placeCity(corner.index);
+ type = 'place-city';
} else {
- table.placeSettlement(corner.index);
+ type = 'place-settlement';
}
- return;
+ sendPlacement(type, corner.index);
};
return
{
const Pip = ({pip}) => {
const onClick = (event) => {
-// console.log(`Pip ${pip.index}:`, game.layout.corners[pip.index]);
- table.placeRobber(pip.index);
- return;
+ sendPlacement('place-robber', pip.index);
};
return
;
};
- const generateRoads = () => {
- let row = 0, rowCount = 0;
- let y = -2.5 + tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
- x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
+ useEffect(() => {
+ if (!signature) {
+ return;
+ }
+ const rows = [3, 4, 5, 4, 3, 2]; /* The final row of 2 is to place roads and corners */
- let index = 0;
- let road;
+ const generateRoads = () => {
+ let row = 0, rowCount = 0;
+ let y = -2.5 + tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
+ x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
+
+ let index = 0;
+ let road;
+
+ const corners = [];
+
+ for (let i = 0; i < 21; i++) {
+ const lastRow = row === rows.length - 1;
+ if (row > 2 && rowCount === 0) {
+ road = {
+ index: index++,
+ angle: -60,
+ top: y-0.5*tileHalfHeight,
+ left: x-tileHalfHeight
+ };
+ corners.push(
);
+ }
- const corners = [];
-
- for (let i = 0; i < 21; i++) {
- const lastRow = row === rows.length - 1;
- if (row > 2 && rowCount === 0) {
road = {
index: index++,
- angle: -60,
- top: y-0.5*tileHalfHeight,
- left: x-tileHalfHeight
- };
- corners.push();
- }
-
- road = {
- index: index++,
- angle: 240,
- top: y,
- left: x
- };
- corners.push();
-
- road = {
- index: index++,
- angle: -60,
- top: y-0.5*tileHalfHeight,
- left: x+tileHalfHeight
- };
- corners.push();
-
- if (!lastRow) {
- road = {
- index: index++,
- angle: 0,
+ angle: 240,
top: y,
left: x
};
corners.push();
- }
- if (++rowCount === rows[row]) {
+ road = {
+ index: index++,
+ angle: -60,
+ top: y-0.5*tileHalfHeight,
+ left: x+tileHalfHeight
+ };
+ corners.push();
+
if (!lastRow) {
road = {
index: index++,
angle: 0,
top: y,
- left: x+2.*tileHalfHeight
+ left: x
};
corners.push();
}
- if (row > 2) {
- road = {
- index: index++,
- angle: 60,
- top: y-0.5*tileHalfHeight,
- left: x+3.*tileHalfHeight
- };
- corners.push();
+ if (++rowCount === rows[row]) {
+ if (!lastRow) {
+ road = {
+ index: index++,
+ angle: 0,
+ top: y,
+ left: x+2.*tileHalfHeight
+ };
+ corners.push();
+ }
+
+ if (row > 2) {
+ road = {
+ index: index++,
+ angle: 60,
+ top: y-0.5*tileHalfHeight,
+ left: x+3.*tileHalfHeight
+ };
+ corners.push();
+ }
+
+ row++;
+ rowCount = 0;
+ y += tileHeight - 10.5;
+ x = -tileHalfHeight - (rows[row] - 1) * 0.5 * tileHeight;
+ } else {
+ x += tileHeight;
}
-
- row++;
- rowCount = 0;
- y += tileHeight - 10.5;
- x = -tileHalfHeight - (rows[row] - 1) * 0.5 * tileHeight;
- } else {
- x += tileHeight;
}
+ return corners;
}
- return corners;
- }
-
- const generateCorners = () => {
- let row = 0, rowCount = 0;
- let y = -8 + 0.5 * tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
- x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
- let index = 0;
- const corners = [];
- let corner;
+
+ const generateCorners = () => {
+ let row = 0, rowCount = 0;
+ let y = -8 + 0.5 * tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
+ x = -tileHalfHeight -(rows[row] - 1) * 0.5 * tileHeight;
+ let index = 0;
+ const corners = [];
+ let corner;
- for (let i = 0; i < 21; i++) {
- if (row > 2 && rowCount === 0) {
- corner = {
- index: index++,
- top: y-0.5*tileHalfHeight,
- left: x-tileHalfHeight
- };
- corners.push();
- }
-
- corner = {
- index: index++,
- top: y,
- left: x
- };
- corners.push();
-
- corner = {
- index: index++,
- top: y-0.5*tileHalfHeight,
- left: x+tileHalfHeight
- };
- corners.push();
-
- if (++rowCount === rows[row]) {
- corner = {
- index: index++,
- top: y,
- left: x+2.*tileHalfHeight
- };
- corners.push();
-
- if (row > 2) {
+ for (let i = 0; i < 21; i++) {
+ if (row > 2 && rowCount === 0) {
corner = {
index: index++,
top: y-0.5*tileHalfHeight,
- left: x+3.*tileHalfHeight
+ left: x-tileHalfHeight
};
corners.push();
}
-
- row++;
- rowCount = 0;
- y += tileHeight - 10.5;
- x = -tileHalfHeight - (rows[row] - 1) * 0.5 * tileHeight;
- } else {
- x += tileHeight;
- }
- }
- return corners;
- }
- const generatePips = () => {
- let row = 0, rowCount = 0;
- let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
- x = -(rows[row] - 1) * 0.5 * tileHeight;
- let index = 0;
- let pip;
- return game.pipOrder.map(order => {
- pip = {
- roll: game.pips[order].roll,
- robber: index === game.robber,
- index: index++,
- top: y,
- left: x,
- order: order
- };
- const div = ;
-
- if (++rowCount === rows[row]) {
- row++;
- rowCount = 0;
- y += tileWidth;
- x = - (rows[row] - 1) * 0.5 * tileHeight;
- } else {
- x += tileHeight;
- }
+ corner = {
+ index: index++,
+ top: y,
+ left: x
+ };
+ corners.push();
- return div;
- });
- };
-
- const generateTiles = () => {
- let row = 0, rowCount = 0;
- let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
- x = -(rows[row] - 1) * 0.5 * tileHeight;
- let index = 0;
- return game.tileOrder.map(order => {
- const tile = Object.assign({},
- game.tiles[order],
- { index: index++, left: x, top: y});
-
- let div = ;
-
- if (++rowCount === rows[row]) {
- row++;
- rowCount = 0;
- y += tileWidth;
- x = - (rows[row] - 1) * 0.5 * tileHeight;
- } else {
- x += tileHeight;
- }
+ corner = {
+ index: index++,
+ top: y-0.5*tileHalfHeight,
+ left: x+tileHalfHeight
+ };
+ corners.push();
+
+ if (++rowCount === rows[row]) {
+ corner = {
+ index: index++,
+ top: y,
+ left: x+2.*tileHalfHeight
+ };
+ corners.push();
+
+ if (row > 2) {
+ corner = {
+ index: index++,
+ top: y-0.5*tileHalfHeight,
+ left: x+3.*tileHalfHeight
+ };
+ corners.push();
+ }
- return div;
- });
- };
-
- const generateBorders = () => {
- const sides = 6;
- let side = -1;
- return game.borderOrder.map(order => {
- const border = game.borders[order];
- side++;
- let x = + Math.sin(Math.PI - side / sides * 2. * Math.PI) * radius,
- y = Math.cos(Math.PI - side / sides * 2. * Math.PI) * radius;
- let prev = (order === 0) ? 6 : order;
- const file = `borders-${order+1}.${prev}.png`;
- return ;
- });
- };
-
- /* If the game is loaded, and the signature is different,
- * regenerate everything */
- if (game && game.signature !== signature) {
- console.log(`Generate for ${game.signature}`);
- setPips(generatePips);
- setBorders(generateBorders);
- setTiles(generateTiles);
- setCorners(generateCorners);
- setRoads(generateRoads);
- setSignature(game.signature);
- } else {
- if (!game) {
- console.log(`No game in Board`);
- }
- }
-
- /* Adjust the 'transform: scale' for the BoardBox
- * so the board fills the Board
- *
- * The board is H tall, and H * hexRatio wide */
- const board = document.querySelector('.Board');
- if (board) {
- const width = board.offsetWidth,
- height = board.offsetHeight;
- let _transform;
- if (height * hexRatio > width) {
- _transform = width / (450. * hexRatio);
- } else {
- _transform = height / (450.);
- }
- if (_transform !== transform) {
- const boardBox = board.querySelector('.BoardBox');
- if (boardBox) {
- console.log(`Setting transofrm scale to ${_transform}`);
- boardBox.style.transform = `scale(${_transform})`;
+ row++;
+ rowCount = 0;
+ y += tileHeight - 10.5;
+ x = -tileHalfHeight - (rows[row] - 1) * 0.5 * tileHeight;
+ } else {
+ x += tileHeight;
+ }
}
- setTransform(_transform);
+ return corners;
}
- }
- if (game && game.turn) {
+ const generatePips = () => {
+ let row = 0, rowCount = 0;
+ let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
+ x = -(rows[row] - 1) * 0.5 * tileHeight;
+ let index = 0;
+ let pip;
+ return pipOrder.map(order => {
+ pip = {
+ roll: pips[order].roll,
+ robber: index === robber,
+ index: index++,
+ top: y,
+ left: x,
+ order: order
+ };
+ const div = ;
+
+ if (++rowCount === rows[row]) {
+ row++;
+ rowCount = 0;
+ y += tileWidth;
+ x = - (rows[row] - 1) * 0.5 * tileHeight;
+ } else {
+ x += tileHeight;
+ }
+
+ return div;
+ });
+ };
+
+ const generateTiles = () => {
+ let row = 0, rowCount = 0;
+ let y = tileHalfWidth - (rows.length - 1) * 0.5 * tileWidth,
+ x = -(rows[row] - 1) * 0.5 * tileHeight;
+ let index = 0;
+ return tileOrder.map(order => {
+ const tile = Object.assign({},
+ tiles[order],
+ { index: index++, left: x, top: y});
+
+ let div = ;
+
+ if (++rowCount === rows[row]) {
+ row++;
+ rowCount = 0;
+ y += tileWidth;
+ x = - (rows[row] - 1) * 0.5 * tileHeight;
+ } else {
+ x += tileHeight;
+ }
+
+ return div;
+ });
+ };
+
+ const generateBorders = () => {
+ const sides = 6;
+ let side = -1;
+ return borderOrder.map(order => {
+ const border = borders[order];
+ side++;
+ let x = + Math.sin(Math.PI - side / sides * 2. * Math.PI) * radius,
+ y = Math.cos(Math.PI - side / sides * 2. * Math.PI) * radius;
+ let prev = (order === 0) ? 6 : order;
+ const file = `borders-${order+1}.${prev}.png`;
+ return ;
+ });
+ };
+
+ console.log(`Generate for ${signature}`);
+ setPipElements(generatePips());
+ setBorderElements(generateBorders());
+ setTileElements(generateTiles());
+ setCornerElements(generateCorners());
+ setRoadElements(generateRoads());
+ }, [signature,
+ setPipElements, setBorderElements, setTileElements,
+ setCornerElements, setRoadElements,
+ borderImageWidth, radius, tileHalfHeight, tileHalfWidth,
+ borderImageHeight, borderOrder, borders, pipOrder, pips, robber, tileOrder, tiles,
+ tileHeight]);
+
+ if (turn) {
let nodes = document.querySelectorAll('.Active');
for (let i = 0; i < nodes.length; i++) {
nodes[i].classList.remove('Active');
}
- if (game.turn.roll) {
- nodes = document.querySelectorAll(`.Pip[data-roll="${game.turn.roll}"]`);
+ if (turn.roll) {
+ nodes = document.querySelectorAll(`.Pip[data-roll="${turn.roll}"]`);
for (let i = 0; i < nodes.length; i++) {
const index = nodes[i].getAttribute('data-index');
if (index !== null) {
@@ -397,9 +514,9 @@ const Board = ({ table, game }) => {
}
}
- if (game && game.placements) {
+ if (placements) {
/* Set color and type based on placement data from the server */
- game.placements.corners.forEach((corner, index) => {
+ placements.corners.forEach((corner, index) => {
const el = document.querySelector(`.Corner[data-index="${index}"]`);
if (!el) {
return;
@@ -412,7 +529,7 @@ const Board = ({ table, game }) => {
el.setAttribute('data-type', corner.type);
}
});
- game.placements.roads.forEach((road, index) => {
+ placements.roads.forEach((road, index) => {
const el = document.querySelector(`.Road[data-index="${index}"]`);
if (!el) {
return;
@@ -421,7 +538,7 @@ const Board = ({ table, game }) => {
el.removeAttribute('data-color');
} else {
if (road.longestRoad) {
- if (road.longestRoad === game.longestRoadLength) {
+ if (road.longestRoad === longestRoadLength) {
el.classList.add('LongestRoad');
} else {
el.classList.remove('LongestRoad');
@@ -439,10 +556,10 @@ const Board = ({ table, game }) => {
nodes[i].classList.remove('Option');
}
- /* Add 'Option' based on game.turn.limits */
- if (game.turn && game.turn.limits) {
- if (game.turn.limits['roads']) {
- game.turn.limits['roads'].forEach(index => {
+ /* Add 'Option' based on turn.limits */
+ if (turn && turn.limits) {
+ if (turn.limits['roads']) {
+ turn.limits['roads'].forEach(index => {
const el = document.querySelector(`.Road[data-index="${index}"]`);
if (!el) {
return;
@@ -450,8 +567,8 @@ const Board = ({ table, game }) => {
el.classList.add('Option');
});
}
- if (game.turn.limits['corners']) {
- game.turn.limits['corners'].forEach(index => {
+ if (turn.limits['corners']) {
+ turn.limits['corners'].forEach(index => {
const el = document.querySelector(`.Corner[data-index="${index}"]`);
if (!el) {
return;
@@ -459,8 +576,8 @@ const Board = ({ table, game }) => {
el.classList.add('Option');
});
}
- if (game.turn.limits['tiles']) {
- game.turn.limits['tiles'].forEach(index => {
+ if (turn.limits['tiles']) {
+ turn.limits['tiles'].forEach(index => {
const el = document.querySelector(`.Tile[data-index="${index}"]`);
if (!el) {
return;
@@ -468,8 +585,8 @@ const Board = ({ table, game }) => {
el.classList.add('Option');
});
}
- if (game.turn.limits['pips']) {
- game.turn.limits['pips'].forEach(index => {
+ if (turn.limits['pips']) {
+ turn.limits['pips'].forEach(index => {
const el = document.querySelector(`.Pip[data-index="${index}"]`);
if (!el) {
return;
@@ -480,63 +597,59 @@ const Board = ({ table, game }) => {
}
}
- if (game) {
- let nodes = document.querySelectorAll(`.Pip.Robber`);
- for (let i = 0; i < nodes.length; i++) {
- nodes[i].classList.remove('Robber');
- [ 'Robert', 'Roberta', 'Velocirobber' ].forEach(robberName =>
- nodes[i].classList.remove(robberName)
- );
- }
+ let nodes = document.querySelectorAll(`.Pip.Robber`);
+ for (let i = 0; i < nodes.length; i++) {
+ nodes[i].classList.remove('Robber');
+ [ 'Robert', 'Roberta', 'Velocirobber' ].forEach(robberName =>
+ nodes[i].classList.remove(robberName)
+ );
+ }
- if (game.robber !== undefined) {
- const el = document.querySelector(`.Pip[data-index="${game.robber}"]`);
- if (el) {
- el.classList.add('Robber');
- el.classList.add(game.robberName);
- }
- }
+ if (robber !== undefined) {
+ const el = document.querySelector(`.Pip[data-index="${robber}"]`);
+ if (el) {
+ el.classList.add('Robber');
+ el.classList.add(robberName);
+ }
}
const canAction = (action) => {
- return (game && game.turn && Array.isArray(game.turn.actions) && game.turn.actions.indexOf(action) !== -1);
+ return (turn && Array.isArray(turn.actions) && turn.actions.indexOf(action) !== -1);
};
const canRoad = (canAction('place-road')
- && game.turn.color === game.color
- && (game.state === 'initial-placement' || game.state === 'normal'));
+ && turn.color === color
+ && (state === 'initial-placement' || state === 'normal'));
const canCorner = ((canAction('place-settlement') || canAction('place-city'))
- && game.turn.color === game.color
- && (game.state === 'initial-placement' || game.state === 'normal'));
+ && turn.color === color
+ && (state === 'initial-placement' || state === 'normal'));
const canPip = (canAction('place-robber')
- && game.turn.color === game.color
- && (game.state === 'initial-placement' || game.state === 'normal'));
+ && turn.color === color
+ && (state === 'initial-placement' || state === 'normal'));
return (
-
+
- { borders }
+ { borderElements }
- { game && <>
-
- { tiles }
-
-
- { pips }
-
-
- { corners }
-
-
- { roads }
-
- > }
-
+
+ { tileElements }
+
+
+ { pipElements }
+
+
+ { cornerElements }
+
+
+ { roadElements }
+
+
);
};
-export default Board;
+export { Board };
diff --git a/client/src/Common.js b/client/src/Common.js
index f767044..3b23d8a 100644
--- a/client/src/Common.js
+++ b/client/src/Common.js
@@ -9,9 +9,21 @@ const getPlayerName = (sessions, color) => {
return null;
}
+
+function debounce(fn, ms) {
+ let timer
+ return _ => {
+ clearTimeout(timer)
+ timer = setTimeout(_ => {
+ timer = null
+ fn.apply(this, arguments)
+ }, ms)
+ };
+}
+
const base = process.env.PUBLIC_URL;
const assetsPath = `${base}/assets`;
const gamesPath = `${base}/games`;
-export { base, assetsPath, gamesPath, getPlayerName };
\ No newline at end of file
+export { base, debounce, assetsPath, gamesPath, getPlayerName };
\ No newline at end of file
diff --git a/client/src/MediaControl.js b/client/src/MediaControl.js
index 237e186..0fa3bbd 100644
--- a/client/src/MediaControl.js
+++ b/client/src/MediaControl.js
@@ -7,6 +7,7 @@ import VolumeUp from '@mui/icons-material/VolumeUp';
import MicOff from '@mui/icons-material/MicOff';
import Mic from '@mui/icons-material/Mic';
import { GlobalContext } from "./GlobalContext.js";
+const debug = false;
/* Proxy object so we can pass in srcObject to