diff --git a/website/src/App.tsx b/website/src/App.tsx index b638c548..19b803d0 100644 --- a/website/src/App.tsx +++ b/website/src/App.tsx @@ -3,6 +3,7 @@ import { Mgba } from "./mgba"; import { BindingsControl, DefaultBindingsSet, Bindings } from "./bindings"; import { styled } from "styled-components"; import { useOnKeyUp } from "./useOnKeyUp.hook"; +import { useLocalStorage } from "./useLocalStorage.hook"; const BindingsDialog = styled.dialog` border-radius: 5px; @@ -21,8 +22,14 @@ const CloseButton = styled.button` `; function App() { - const [volume, setVolume] = useState(1.0); - const [bindings, setBindings] = useState(DefaultBindingsSet()); + const [volumeState, setVolume] = useState(1.0); + const [bindingsState, setBindings] = useState(DefaultBindingsSet()); + + const { volume, bindings } = useLocalStorage( + { volume: volumeState, bindings: bindingsState }, + "agbrswebplayer" + ); + const [paused, setPaused] = useState(false); const [showBindings, setShowBindings] = useState(false); diff --git a/website/src/useLocalStorage.hook.ts b/website/src/useLocalStorage.hook.ts new file mode 100644 index 00000000..4cd87fe8 --- /dev/null +++ b/website/src/useLocalStorage.hook.ts @@ -0,0 +1,36 @@ +import { useRef, useLayoutEffect, useEffect } from "react"; + +export const useLocalStorage = (currentValue: T, appName: string): T => { + const initialValue = useRef(); + + const isFirstRun = !initialValue.current; + + useLayoutEffect(() => { + if (!initialValue.current) { + try { + const storageValue = localStorage.getItem(appName); + if (storageValue) { + initialValue.current = JSON.parse(storageValue); + } else { + initialValue.current = currentValue; + } + } catch { + initialValue.current = currentValue; + } + } + }, []); + + useEffect(() => { + try { + if (initialValue.current && currentValue) { + localStorage.setItem(appName, JSON.stringify(currentValue)); + } + } catch {} + }, [currentValue]); + + if (isFirstRun) { + return initialValue.current ?? currentValue; + } else { + return currentValue; + } +};