From d0002431c5331b5ff65fd587b787a3404e8684ae Mon Sep 17 00:00:00 2001 From: Mitchell McCaffrey Date: Tue, 8 Sep 2020 12:35:31 +1000 Subject: [PATCH] Added fake storage shim for local and session storage --- src/contexts/AuthContext.js | 17 +++++++++++++---- src/helpers/FakeStorage.js | 23 +++++++++++++++++++++++ src/helpers/Settings.js | 16 ++++++++++++++-- 3 files changed, 50 insertions(+), 6 deletions(-) create mode 100644 src/helpers/FakeStorage.js diff --git a/src/contexts/AuthContext.js b/src/contexts/AuthContext.js index e9aced1..efa8c84 100644 --- a/src/contexts/AuthContext.js +++ b/src/contexts/AuthContext.js @@ -4,18 +4,27 @@ import shortid from "shortid"; import DatabaseContext from "./DatabaseContext"; import { getRandomMonster } from "../helpers/monsters"; +import FakeStorage from "../helpers/FakeStorage"; const AuthContext = React.createContext(); +let storage; +try { + sessionStorage.setItem("__test", "__test"); + sessionStorage.removeItem("__test"); + storage = sessionStorage; +} catch (e) { + console.warn("Session storage is disabled, no authentication will be saved"); + storage = new FakeStorage(); +} + export function AuthProvider({ children }) { const { database } = useContext(DatabaseContext); - const [password, setPassword] = useState( - sessionStorage.getItem("auth") || "" - ); + const [password, setPassword] = useState(storage.getItem("auth") || ""); useEffect(() => { - sessionStorage.setItem("auth", password); + storage.setItem("auth", password); }, [password]); const [authenticationStatus, setAuthenticationStatus] = useState("unknown"); diff --git a/src/helpers/FakeStorage.js b/src/helpers/FakeStorage.js new file mode 100644 index 0000000..d464924 --- /dev/null +++ b/src/helpers/FakeStorage.js @@ -0,0 +1,23 @@ +/** + * A faked local or session storage used when the user has disabled storage + */ +class FakeStorage { + data = {}; + key(index) { + return Object.keys(this.data)[index] || null; + } + getItem(keyName) { + return this.data[keyName] || null; + } + setItem(keyName, keyValue) { + this.data[keyName] = keyValue; + } + removeItem(keyName) { + delete this.data[keyName]; + } + clear() { + this.data = {}; + } +} + +export default FakeStorage; diff --git a/src/helpers/Settings.js b/src/helpers/Settings.js index d9ac9da..ffd029b 100644 --- a/src/helpers/Settings.js +++ b/src/helpers/Settings.js @@ -1,12 +1,24 @@ +import FakeStorage from "./FakeStorage"; + /** * An interface to a local storage back settings store with a versioning mechanism */ class Settings { name; currentVersion; + storage; constructor(name) { this.name = name; + // Try and use local storage if it is available, if not mock it with an in memory storage + try { + localStorage.setItem("__test", "__test"); + localStorage.removeItem("__test"); + this.storage = localStorage; + } catch (e) { + console.warn("Local storage is disabled, no settings will be saved"); + this.storage = new FakeStorage(); + } this.currentVersion = this.get("__version"); } @@ -18,7 +30,7 @@ class Settings { } getAll() { - return JSON.parse(localStorage.getItem(this.name)); + return JSON.parse(this.storage.getItem(this.name)); } get(key) { @@ -27,7 +39,7 @@ class Settings { } setAll(newSettings) { - localStorage.setItem( + this.storage.setItem( this.name, JSON.stringify({ ...newSettings, __version: this.currentVersion }) );