Save previous board position to localstorage
This commit is contained in:
parent
4bfa239246
commit
dac997448d
5 changed files with 86 additions and 20 deletions
14
package-lock.json
generated
14
package-lock.json
generated
|
@ -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",
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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}
|
||||
/>
|
||||
<SessionRestoreDim />
|
||||
{isMaster && <AutoSaveSession />}
|
||||
</>
|
||||
);
|
||||
|
|
64
src/views/SessionRestoreDim.jsx
Normal file
64
src/views/SessionRestoreDim.jsx
Normal file
|
@ -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;
|
Loading…
Reference in a new issue