diff --git a/src/contexts/MapDataContext.js b/src/contexts/MapDataContext.js
index bdd6193..433eb9b 100644
--- a/src/contexts/MapDataContext.js
+++ b/src/contexts/MapDataContext.js
@@ -54,10 +54,7 @@ export function MapDataProvider({ children }) {
}
async function loadMaps() {
- let storedMaps = await database
- .table("maps")
- .where({ owner: userId })
- .toArray();
+ let storedMaps = await database.table("maps").toArray();
const sortedMaps = storedMaps.sort((a, b) => b.created - a.created);
const defaultMapsWithIds = await getDefaultMaps();
const allMaps = [...sortedMaps, ...defaultMapsWithIds];
@@ -129,14 +126,37 @@ export function MapDataProvider({ children }) {
});
}
+ async function putMap(map) {
+ await database.table("maps").put(map);
+ setMaps((prevMaps) => {
+ const newMaps = [...prevMaps];
+ const i = newMaps.findIndex((m) => m.id === map.id);
+ if (i > -1) {
+ newMaps[i] = { ...newMaps[i], ...map };
+ } else {
+ newMaps.unshift(map);
+ }
+ return newMaps;
+ });
+ }
+
+ function getMap(mapId) {
+ return maps.find((map) => map.id === mapId);
+ }
+
+ const ownedMaps = maps.filter((map) => map.owner === userId);
+
const value = {
maps,
+ ownedMaps,
mapStates,
addMap,
removeMap,
resetMap,
updateMap,
updateMapState,
+ putMap,
+ getMap,
};
return (
{children}
diff --git a/src/contexts/TokenDataContext.js b/src/contexts/TokenDataContext.js
index e28aa0d..096d006 100644
--- a/src/contexts/TokenDataContext.js
+++ b/src/contexts/TokenDataContext.js
@@ -68,11 +68,21 @@ export function TokenDataProvider({ children }) {
}
async function putToken(token) {
- if (tokens.includes((t) => t.id === token.id)) {
- await updateToken(token.id, token);
- } else {
- await addToken(token);
- }
+ await database.table("tokens").put(token);
+ setTokens((prevTokens) => {
+ const newTokens = [...prevTokens];
+ const i = newTokens.findIndex((t) => t.id === token.id);
+ if (i > -1) {
+ newTokens[i] = { ...newTokens[i], ...token };
+ } else {
+ newTokens.unshift(token);
+ }
+ return newTokens;
+ });
+ }
+
+ function getToken(tokenId) {
+ return tokens.find((token) => token.id === tokenId);
}
const ownedTokens = tokens.filter((token) => token.owner === userId);
@@ -84,6 +94,7 @@ export function TokenDataProvider({ children }) {
removeToken,
updateToken,
putToken,
+ getToken,
};
return (
diff --git a/src/modals/SelectMapModal.js b/src/modals/SelectMapModal.js
index 9a84cee..91de48a 100644
--- a/src/modals/SelectMapModal.js
+++ b/src/modals/SelectMapModal.js
@@ -30,7 +30,7 @@ function SelectMapModal({
}) {
const { userId } = useContext(AuthContext);
const {
- maps,
+ ownedMaps,
mapStates,
addMap,
removeMap,
@@ -44,7 +44,7 @@ function SelectMapModal({
// The map selected in the modal
const [selectedMapId, setSelectedMapId] = useState(null);
- const selectedMap = maps.find((map) => map.id === selectedMapId);
+ const selectedMap = ownedMaps.find((map) => map.id === selectedMapId);
const selectedMapState = mapStates.find(
(state) => state.mapId === selectedMapId
);
@@ -189,7 +189,7 @@ function SelectMapModal({
Select or import a map
{
if (
debouncedMapState &&
debouncedMapState.mapId &&
- map &&
- map.owner === userId &&
+ currentMap &&
+ currentMap.owner === userId &&
database
) {
+ // Update the database directly to avoid re-renders
database
.table("states")
.update(debouncedMapState.mapId, debouncedMapState);
}
- }, [map, debouncedMapState, userId, database]);
+ }, [currentMap, debouncedMapState, userId, database]);
function handleMapChange(newMap, newMapState) {
- setMapState(newMapState);
- setMap(newMap);
+ setCurrentMapState(newMapState);
+ setCurrentMap(newMap);
for (let peer of Object.values(peers)) {
// Clear the map so the new map state isn't shown on an old map
peer.connection.send({ id: "map", data: null });
@@ -110,14 +113,14 @@ function Game() {
}
function handleMapStateChange(newMapState) {
- setMapState(newMapState);
+ setCurrentMapState(newMapState);
for (let peer of Object.values(peers)) {
peer.connection.send({ id: "mapState", data: newMapState });
}
}
function addMapDrawActions(actions, indexKey, actionsKey) {
- setMapState((prevMapState) => {
+ setCurrentMapState((prevMapState) => {
const newActions = [
...prevMapState[actionsKey].slice(0, prevMapState[indexKey] + 1),
...actions,
@@ -133,11 +136,11 @@ function Game() {
function updateDrawActionIndex(change, indexKey, actionsKey, peerId) {
const newIndex = Math.min(
- Math.max(mapState[indexKey] + change, -1),
- mapState[actionsKey].length - 1
+ Math.max(currentMapState[indexKey] + change, -1),
+ currentMapState[actionsKey].length - 1
);
- setMapState((prevMapState) => ({
+ setCurrentMapState((prevMapState) => ({
...prevMapState,
[indexKey]: newIndex,
}));
@@ -206,10 +209,27 @@ function Game() {
* Token state
*/
+ // Get all tokens from a token state and send it to a peer
+ function sendTokensToPeer(peer, state) {
+ let sentTokens = {};
+ for (let tokenState of Object.values(state.tokens)) {
+ if (
+ tokenState.tokenType === "file" &&
+ !(tokenState.tokenId in sentTokens)
+ ) {
+ sentTokens[tokenState.tokenId] = true;
+ const token = getToken(tokenState.tokenId);
+ // Omit file from token peer will request file if needed
+ const { file, ...rest } = token;
+ peer.connection.send({ id: "token", data: rest });
+ }
+ }
+ }
+
async function handleMapTokenStateCreate(tokenState) {
// If file type token send the token to the other peers
if (tokenState.tokenType === "file") {
- const token = await database.table("tokens").get(tokenState.tokenId);
+ const token = getToken(tokenState.tokenId);
const { file, ...rest } = token;
for (let peer of Object.values(peers)) {
peer.connection.send({ id: "token", data: rest });
@@ -219,10 +239,10 @@ function Game() {
}
function handleMapTokenStateChange(tokenState) {
- if (mapState === null) {
+ if (currentMapState === null) {
return;
}
- setMapState((prevMapState) => ({
+ setCurrentMapState((prevMapState) => ({
...prevMapState,
tokens: {
...prevMapState.tokens,
@@ -236,7 +256,7 @@ function Game() {
}
function handleMapTokenStateRemove(tokenState) {
- setMapState((prevMapState) => {
+ setCurrentMapState((prevMapState) => {
const { [tokenState.id]: old, ...rest } = prevMapState.tokens;
return { ...prevMapState, tokens: rest };
});
@@ -273,58 +293,37 @@ function Game() {
* Peer handlers
*/
- const { putToken } = useContext(TokenDataContext);
-
- function sendTokensToPeer(peer, state) {
- let sentTokens = {};
- for (let tokenState of Object.values(state.tokens)) {
- if (
- tokenState.tokenType === "file" &&
- !(tokenState.tokenId in sentTokens)
- ) {
- sentTokens[tokenState.tokenId] = true;
- database
- .table("tokens")
- .get(tokenState.tokenId)
- .then((token) => {
- const { file, ...rest } = token;
- peer.connection.send({ id: "token", data: rest });
- });
- }
- }
- }
+ const { putToken, getToken } = useContext(TokenDataContext);
+ const { putMap, getMap } = useContext(MapDataContext);
function handlePeerData({ data, peer }) {
if (data.id === "sync") {
- if (mapState) {
- peer.connection.send({ id: "mapState", data: mapState });
- sendTokensToPeer(peer, mapState);
+ if (currentMapState) {
+ peer.connection.send({ id: "mapState", data: currentMapState });
+ sendTokensToPeer(peer, currentMapState);
}
- if (map) {
- sendMapDataToPeer(peer, map);
+ if (currentMap) {
+ sendMapDataToPeer(peer, currentMap);
}
}
if (data.id === "map") {
const newMap = data.data;
// If is a file map check cache and request the full file if outdated
if (newMap && newMap.type === "file") {
- database
- .table("maps")
- .get(newMap.id)
- .then((cachedMap) => {
- if (cachedMap && cachedMap.lastModified === newMap.lastModified) {
- setMap(cachedMap);
- } else {
- setMapLoading(true);
- peer.connection.send({ id: "mapRequest" });
- }
- });
+ const cachedMap = getMap(newMap.id);
+ if (cachedMap && cachedMap.lastModified === newMap.lastModified) {
+ setCurrentMap(cachedMap);
+ } else {
+ setMapLoading(true);
+ peer.connection.send({ id: "mapRequest", data: newMap.id });
+ }
} else {
- setMap(newMap);
+ setCurrentMap(newMap);
}
}
// Send full map data including file
if (data.id === "mapRequest") {
+ const map = getMap(data.data);
peer.connection.send({ id: "mapResponse", data: map });
}
// A new map response with a file attached
@@ -332,47 +331,35 @@ function Game() {
setMapLoading(false);
if (data.data && data.data.type === "file") {
const newMap = { ...data.data, file: data.data.file };
- // Store in db
- database
- .table("maps")
- .put(newMap)
- .then(() => {
- setMap(newMap);
- });
+ putMap(newMap).then(() => {
+ setCurrentMap(newMap);
+ });
} else {
- setMap(data.data);
+ setCurrentMap(data.data);
}
}
if (data.id === "mapState") {
- setMapState(data.data);
+ setCurrentMapState(data.data);
}
if (data.id === "token") {
const newToken = data.data;
if (newToken && newToken.type === "file") {
- database
- .table("tokens")
- .get(newToken.id)
- .then((cachedToken) => {
- if (
- !cachedToken ||
- cachedToken.lastModified !== newToken.lastModified
- ) {
- setMapLoading(true);
- peer.connection.send({
- id: "tokenRequest",
- data: newToken.id,
- });
- }
+ const cachedToken = getToken(newToken.id);
+ if (
+ !cachedToken ||
+ cachedToken.lastModified !== newToken.lastModified
+ ) {
+ setMapLoading(true);
+ peer.connection.send({
+ id: "tokenRequest",
+ data: newToken.id,
});
+ }
}
}
if (data.id === "tokenRequest") {
- database
- .table("tokens")
- .get(data.data)
- .then((token) => {
- peer.connection.send({ id: "tokenResponse", data: token });
- });
+ const token = getToken(data.data);
+ peer.connection.send({ id: "tokenResponse", data: token });
}
if (data.id === "tokenResponse") {
setMapLoading(false);
@@ -382,13 +369,13 @@ function Game() {
}
}
if (data.id === "tokenStateEdit") {
- setMapState((prevMapState) => ({
+ setCurrentMapState((prevMapState) => ({
...prevMapState,
tokens: { ...prevMapState.tokens, ...data.data },
}));
}
if (data.id === "tokenStateRemove") {
- setMapState((prevMapState) => ({
+ setCurrentMapState((prevMapState) => ({
...prevMapState,
tokens: omit(prevMapState.tokens, Object.keys(data.data)),
}));
@@ -403,7 +390,7 @@ function Game() {
addMapDrawActions(data.data, "mapDrawActionIndex", "mapDrawActions");
}
if (data.id === "mapDrawIndex") {
- setMapState((prevMapState) => ({
+ setCurrentMapState((prevMapState) => ({
...prevMapState,
mapDrawActionIndex: data.data,
}));
@@ -412,7 +399,7 @@ function Game() {
addMapDrawActions(data.data, "fogDrawActionIndex", "fogDrawActions");
}
if (data.id === "mapFogIndex") {
- setMapState((prevMapState) => ({
+ setCurrentMapState((prevMapState) => ({
...prevMapState,
fogDrawActionIndex: data.data,
}));
@@ -532,8 +519,8 @@ function Game() {
onStreamEnd={handleStreamEnd}
/>