From ced66c5807575cd29f6aa5632e8ad02b38c8448a Mon Sep 17 00:00:00 2001 From: ivar Date: Sun, 28 Apr 2024 22:37:30 +0200 Subject: WIP new frontend --- code/frontend/src/utils/persistent-store.ts | 110 ++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 code/frontend/src/utils/persistent-store.ts (limited to 'code/frontend/src/utils/persistent-store.ts') diff --git a/code/frontend/src/utils/persistent-store.ts b/code/frontend/src/utils/persistent-store.ts new file mode 100644 index 0000000..d880464 --- /dev/null +++ b/code/frontend/src/utils/persistent-store.ts @@ -0,0 +1,110 @@ +import {browser} from "$app/environment"; +import {writable as _writable, readable as _readable} from "svelte/store"; +import type {Writable, Readable, StartStopNotifier} from "svelte/store"; + +enum StoreType { + SESSION = 0, + LOCAL = 1 +} + +interface StoreOptions { + store?: StoreType; +} + +interface WritableStoreInit { + name: string, + initialState: T, + options?: StoreOptions +} + +interface ReadableStoreInit { + name: string, + initialState: T, + callback: StartStopNotifier, + options?: StoreOptions +} + +function get_store(type: StoreType): Storage { + if (!browser) return undefined; + switch (type) { + case StoreType.SESSION: + return window.sessionStorage; + case StoreType.LOCAL: + return window.localStorage; + } +} + +function prepared_store_value(value: any): string { + try { + return JSON.stringify(value); + } catch (e) { + console.error(e); + return "__INVALID__"; + } +} + +function get_store_value(init: WritableStoreInit | ReadableStoreInit): any { + try { + const storage = get_store(init.options.store); + if (!storage) return; + const value = storage.getItem(init.name); + if (!value) return false; + return JSON.parse(value); + } catch (e) { + console.error(e); + return {__INVALID__: true}; + } +} + +function hydrate(store: Writable, init: WritableStoreInit | ReadableStoreInit): void { + const value = get_store_value(init); + if (value && store.set) store.set(value); +} + +function subscribe(store: Writable | Readable, init: WritableStoreInit | ReadableStoreInit): void { + const storage = get_store(init.options.store); + if (!storage) return; + if (!store.subscribe) return; + store.subscribe((state: any) => { + storage.setItem(init.name, prepared_store_value(state)); + }); +} + +function create_writable_persistent(init: WritableStoreInit): Writable { + if (!browser) { + console.warn("Persistent store is only available in the browser"); + return; + } + if (init.options === undefined) throw new Error("init is a required parameter"); + console.debug("Creating writable store with options: ", init); + const store = _writable(init.initialState); + hydrate(store, init); + subscribe(store, init); + return store; +} + +function create_readable_persistent(init: ReadableStoreInit): Readable { + if (!browser) { + console.warning("Persistent store is only available in the browser"); + return; + } + if (init.options === undefined) throw new Error("init is a required parameter"); + console.debug("Creating readable store with options: ", init); + const store = _readable(init.initialState, init.callback); + // hydrate(store, options); + subscribe(store, init); + return store; +} + +export { + create_writable_persistent, + create_readable_persistent, + StoreType, +}; + +export type { + WritableStoreInit as WritableStore, + ReadableStoreInit as ReadableStore, + StoreOptions, +}; + -- cgit v1.3