opvault.js/packages/web/src/utils/localStorage.ts
2022-02-21 03:54:04 -05:00

83 lines
2.1 KiB
TypeScript

import { useCallback, useEffect, useState } from "react"
export enum Key {
LAST_VAULT_PATH = "app.state.last_vault_path",
RECENTLY_OPENED_VAULTS = "app.state.recently_opened_vaults",
PREFERRED_LOCALE = "app.config.locale",
ENABLE_AUTO_LOCK = "app.config.enable_auto_lock",
AUTO_LOCK_AFTER = "app.config.auto_lock_after",
UI_FONT = "app.config.font.ui",
MONOSPACE_FONT = "app.config.font.monospace",
}
interface StoredData {
[Key.LAST_VAULT_PATH]: string
[Key.RECENTLY_OPENED_VAULTS]: string[]
[Key.PREFERRED_LOCALE]: string
[Key.ENABLE_AUTO_LOCK]: boolean
[Key.AUTO_LOCK_AFTER]: number
[Key.UI_FONT]: string
[Key.MONOSPACE_FONT]: string
}
const events = new Map(Object.values(Key).map(key => [key, new Set()])) as {
get<K extends Key>(key: K): Set<(value: StoredData[Key]) => void>
}
export function useStorage<K extends Key>(key: K) {
const [state, setState] = useState(get(key)!)
useEffect(() => {
events.get(key).add(setState as any)
return () => {
events.get(key).delete(setState as any)
}
}, [key])
const setState2 = useCallback(
(value: ((value: StoredData[K]) => StoredData[K]) | StoredData[K]) => {
set(key, value)
},
[key]
)
return [state, setState2] as const
}
export function get<K extends Key>(key: K): StoredData[K] | undefined {
try {
const value = localStorage.getItem(key)
return value == null ? undefined : (JSON.parse(value!) as StoredData[K])
} catch {}
}
export function set<K extends Key>(
key: K,
value: ((value: StoredData[K]) => StoredData[K]) | StoredData[K]
) {
try {
if (typeof value === "function") {
value = value(get(key)!)
}
localStorage.setItem(key, JSON.stringify(value))
events.get(key).forEach(fn => fn(value as StoredData[K]))
} catch (e) {
console.error(e)
}
}
export function remove(key: Key) {
try {
localStorage.removeItem(key)
} catch {}
}
const defaults: typeof set = (key, value) => {
if (!(key in localStorage)) {
set(key, value)
}
}
defaults(Key.ENABLE_AUTO_LOCK, true)
defaults(Key.AUTO_LOCK_AFTER, 180)
defaults(Key.RECENTLY_OPENED_VAULTS, [])
defaults(Key.UI_FONT, "")
defaults(Key.MONOSPACE_FONT, "")