diff --git a/package-lock.json b/package-lock.json
index 8def707..4f5102f 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -39,7 +39,7 @@
"react-query": "^3.13.4",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
- "react-sync-board": "^0.4.4",
+ "react-sync-board": "^0.4.5",
"react-toastify": "^6.1.0",
"react-useportal": "^1.0.14",
"recoil": "^0.3.1",
@@ -11667,9 +11667,9 @@
}
},
"node_modules/react-sync-board": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/react-sync-board/-/react-sync-board-0.4.4.tgz",
- "integrity": "sha512-jwxwn33lB8EmiKPAIG4XlsKKFhPD0WjVZI1SeUBlmWuvNmGxt1UFUCl5dLmtaVLmzeArNTBVrb9EP52WO/Ci7A==",
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/react-sync-board/-/react-sync-board-0.4.5.tgz",
+ "integrity": "sha512-YsffM8deD3kZpX2S8wWYUtufyhSOd0scxcED61UgDqztYOdrfQY7vobERwvH3vLWa+xN9/BY0rBcctuqMA1Bdg==",
"dependencies": {
"@emotion/react": "^11.4.0",
"@emotion/styled": "^11.3.0",
@@ -23186,9 +23186,9 @@
}
},
"react-sync-board": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/react-sync-board/-/react-sync-board-0.4.4.tgz",
- "integrity": "sha512-jwxwn33lB8EmiKPAIG4XlsKKFhPD0WjVZI1SeUBlmWuvNmGxt1UFUCl5dLmtaVLmzeArNTBVrb9EP52WO/Ci7A==",
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/react-sync-board/-/react-sync-board-0.4.5.tgz",
+ "integrity": "sha512-YsffM8deD3kZpX2S8wWYUtufyhSOd0scxcED61UgDqztYOdrfQY7vobERwvH3vLWa+xN9/BY0rBcctuqMA1Bdg==",
"requires": {
"@emotion/react": "^11.4.0",
"@emotion/styled": "^11.3.0",
diff --git a/package.json b/package.json
index bc8ebba..8737c78 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,7 @@
"react-query": "^3.13.4",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
- "react-sync-board": "^0.4.4",
+ "react-sync-board": "^0.4.5",
"react-toastify": "^6.1.0",
"react-useportal": "^1.0.14",
"recoil": "^0.3.1",
diff --git a/src/hooks/useLocalStorage.js b/src/hooks/useLocalStorage.js
index dbd8aa8..0586f87 100644
--- a/src/hooks/useLocalStorage.js
+++ b/src/hooks/useLocalStorage.js
@@ -3,8 +3,8 @@ import { atomFamily, useRecoilState } from "recoil";
const getFromLocalStorage = (key) => {
const item = window.localStorage.getItem(key);
- if (item === undefined) {
- return undefined;
+ if (item === null) {
+ return null;
}
return JSON.parse(item);
};
@@ -25,7 +25,7 @@ const useLocalStorage = (key, initialValue) => {
// Get from local storage by key
const item = window.localStorage.getItem(key);
- if (item === undefined) {
+ if (item === null) {
// If missing we add it
window.localStorage.setItem(key, JSON.stringify(initialValue));
setStoredValue([true, initialValue]);
@@ -44,21 +44,21 @@ const useLocalStorage = (key, initialValue) => {
const setValue = React.useCallback(
(value) => {
try {
- // Allow value to be a function so we have same API as useState
- const valueToStore =
- value instanceof Function ? value(storedValue) : value;
-
// Save state
- setStoredValue([true, valueToStore]);
+ setStoredValue(([, prev]) => {
+ // Allow value to be a function so we have same API as useState
+ const valueToStore = value instanceof Function ? value(prev) : value;
- // Save to local storage
- window.localStorage.setItem(key, JSON.stringify(valueToStore));
+ // Save to local storage
+ window.localStorage.setItem(key, JSON.stringify(valueToStore));
+ return [true, valueToStore];
+ });
} catch (error) {
// A more advanced implementation would handle the error case
console.log(error);
}
},
- [key, setStoredValue, storedValue]
+ [key, setStoredValue]
);
// React on other tab modifications
@@ -74,7 +74,7 @@ const useLocalStorage = (key, initialValue) => {
};
}, [key, setStoredValue]);
- return [storedValue === undefined ? initialValue : storedValue, setValue];
+ return [storedValue === null ? initialValue : storedValue, setValue];
};
export default useLocalStorage;
diff --git a/src/views/Session.jsx b/src/views/Session.jsx
index 4c67b62..71e31cd 100644
--- a/src/views/Session.jsx
+++ b/src/views/Session.jsx
@@ -6,6 +6,7 @@ import { BoardWrapper, useWire } from "react-sync-board";
import { itemTemplates, itemLibrary, premadeItems } from "../gameComponents";
import BoardView from "./BoardView";
+import SessionRestoreDim from "./SessionRestoreDim";
import Waiter from "../ui/Waiter";
import { uid } from "../utils";
@@ -159,6 +160,7 @@ export const Session = () => {
mediaLibraries={mediaLibraries}
itemLibraries={itemLibraries}
/>
+
{isMaster && }
>
);
diff --git a/src/views/SessionRestoreDim.jsx b/src/views/SessionRestoreDim.jsx
new file mode 100644
index 0000000..a9de394
--- /dev/null
+++ b/src/views/SessionRestoreDim.jsx
@@ -0,0 +1,64 @@
+import React from "react";
+import useAsyncEffect from "use-async-effect";
+import { useBoardPosition } from "react-sync-board";
+
+import useSession from "../hooks/useSession";
+
+import useLocalStorage from "../hooks/useLocalStorage";
+
+// 150 days max for session dim
+const MAX_SESSION_DIM_RETENTION = 1000 * 60 * 60 * 24 * 150;
+
+export const SessionRestoreDim = () => {
+ const { sessionLoaded, sessionId } = useSession();
+
+ const [sessionDimensions, setSessionDimensions] = useLocalStorage(
+ "sessionDimensions",
+ {}
+ );
+ const { getDim, setDim } = useBoardPosition();
+
+ /**
+ * Load the previous dimension for this session if exists
+ */
+ React.useEffect(() => {
+ if (sessionLoaded) {
+ if (sessionDimensions[sessionId]) {
+ setTimeout(() => {
+ const dim = { ...sessionDimensions[sessionId], timestamp: undefined };
+ setDim(() => dim);
+ }, 500);
+ }
+ const now = Date.now();
+
+ const newDim = Object.fromEntries(
+ Object.entries(sessionDimensions).filter(([, { timestamp }]) => {
+ return timestamp && now - timestamp < MAX_SESSION_DIM_RETENTION;
+ })
+ );
+ setSessionDimensions(newDim);
+ }
+ // We want to set dimension only when session is loaded
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [sessionLoaded]);
+
+ /**
+ * Save board dimension in localstorage every 2 seconds for next visit
+ */
+ useAsyncEffect((isMounted) => {
+ const interval = setInterval(async () => {
+ const currentDim = await getDim();
+ if (isMounted) {
+ setSessionDimensions((prev) => ({
+ ...prev,
+ [sessionId]: { ...currentDim, timestamp: Date.now() },
+ }));
+ }
+ }, 2000);
+ return () => clearInterval(interval);
+ }, []);
+
+ return null;
+};
+
+export default SessionRestoreDim;