diff options
Diffstat (limited to 'packages/demobank-ui/src')
-rw-r--r-- | packages/demobank-ui/src/hooks/backend.ts | 55 | ||||
-rw-r--r-- | packages/demobank-ui/src/hooks/index.ts | 12 | ||||
-rw-r--r-- | packages/demobank-ui/src/hooks/settings.ts | 38 |
3 files changed, 72 insertions, 33 deletions
diff --git a/packages/demobank-ui/src/hooks/backend.ts b/packages/demobank-ui/src/hooks/backend.ts index 83df53a1a..f7c255ead 100644 --- a/packages/demobank-ui/src/hooks/backend.ts +++ b/packages/demobank-ui/src/hooks/backend.ts @@ -14,11 +14,20 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { canonicalizeBaseUrl } from "@gnu-taler/taler-util"; +import { + Codec, + buildCodecForObject, + buildCodecForUnion, + canonicalizeBaseUrl, + codecForBoolean, + codecForConstString, + codecForString, +} from "@gnu-taler/taler-util"; import { ErrorType, HttpError, RequestError, + buildStorageKey, useLocalStorage, } from "@gnu-taler/web-util/browser"; import { @@ -51,6 +60,26 @@ interface LoggedOut { status: "loggedOut"; } +export const codecForBackendStateLoggedIn = (): Codec<LoggedIn> => + buildCodecForObject<LoggedIn>() + .property("status", codecForConstString("loggedIn")) + .property("username", codecForString()) + .property("password", codecForString()) + .property("isUserAdministrator", codecForBoolean()) + .build("BackendState.LoggedIn"); + +export const codecForBackendStateLoggedOut = (): Codec<LoggedOut> => + buildCodecForObject<LoggedOut>() + .property("status", codecForConstString("loggedOut")) + .build("BackendState.LoggedOut"); + +export const codecForBackendState = (): Codec<BackendState> => + buildCodecForUnion<BackendState>() + .discriminateOn("status") + .alternative("loggedIn", codecForBackendStateLoggedIn()) + .alternative("loggedOut", codecForBackendStateLoggedOut()) + .build("BackendState"); + export function getInitialBackendBaseURL(): string { const overrideUrl = typeof localStorage !== "undefined" @@ -79,29 +108,27 @@ export interface BackendStateHandler { logOut(): void; logIn(info: BackendCredentials): void; } + +const BACKEND_STATE_KEY = buildStorageKey( + "backend-state", + codecForBackendState(), +); + /** * Return getters and setters for * login credentials and backend's * base URL. */ export function useBackendState(): BackendStateHandler { - const { value, update } = useLocalStorage( - "backend-state", - JSON.stringify(defaultState), + const { value: state, update } = useLocalStorage( + BACKEND_STATE_KEY, + defaultState, ); - let parsed; - try { - parsed = JSON.parse(value!); - } catch { - parsed = undefined; - } - const state: BackendState = !parsed?.status ? defaultState : parsed; - return { state, logOut() { - update(JSON.stringify({ ...defaultState })); + update(defaultState); }, logIn(info) { //admin is defined by the username @@ -110,7 +137,7 @@ export function useBackendState(): BackendStateHandler { ...info, isUserAdministrator: info.username === "admin", }; - update(JSON.stringify(nextState)); + update(nextState); }, }; } diff --git a/packages/demobank-ui/src/hooks/index.ts b/packages/demobank-ui/src/hooks/index.ts index 44b0598e6..e9c68812c 100644 --- a/packages/demobank-ui/src/hooks/index.ts +++ b/packages/demobank-ui/src/hooks/index.ts @@ -20,7 +20,8 @@ */ import { StateUpdater } from "preact/hooks"; -import { useLocalStorage } from "@gnu-taler/web-util/browser"; +import { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser"; +import { codecForBoolean } from "@gnu-taler/taler-util"; export type ValueOrFunction<T> = T | ((p: T) => T); const calculateRootPath = () => { @@ -31,11 +32,14 @@ const calculateRootPath = () => { return rootPath; }; +const BACKEND_URL_KEY = buildStorageKey("backend-url"); +const TRIED_LOGIN_KEY = buildStorageKey("tried-login", codecForBoolean()); + export function useBackendURL( url?: string, ): [string, boolean, StateUpdater<string>, () => void] { const { value, update: setter } = useLocalStorage( - "backend-url", + BACKEND_URL_KEY, url || calculateRootPath(), ); @@ -43,10 +47,10 @@ export function useBackendURL( value: triedToLog, update: setTriedToLog, reset: resetBackend, - } = useLocalStorage("tried-login"); + } = useLocalStorage(TRIED_LOGIN_KEY); const checkedSetter = (v: ValueOrFunction<string>) => { - setTriedToLog("yes"); + setTriedToLog(true); const computedValue = v instanceof Function ? v(value) : v.replace(/\/$/, ""); return setter(computedValue); diff --git a/packages/demobank-ui/src/hooks/settings.ts b/packages/demobank-ui/src/hooks/settings.ts index 325b583f9..46b31bf2a 100644 --- a/packages/demobank-ui/src/hooks/settings.ts +++ b/packages/demobank-ui/src/hooks/settings.ts @@ -14,36 +14,44 @@ GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> */ -import { useLocalStorage } from "@gnu-taler/web-util/browser"; +import { + Codec, + buildCodecForObject, + codecForString, + codecOptional, +} from "@gnu-taler/taler-util"; +import { buildStorageKey, useLocalStorage } from "@gnu-taler/web-util/browser"; interface Settings { currentWithdrawalOperationId: string | undefined; } +export const codecForSettings = (): Codec<Settings> => + buildCodecForObject<Settings>() + .property("currentWithdrawalOperationId", codecOptional(codecForString())) + .build("Settings"); + const defaultSettings: Settings = { currentWithdrawalOperationId: undefined, }; -function parse_json_or_undefined<T>(str: string | undefined): T | undefined { - if (str === undefined) return undefined; - try { - return JSON.parse(str); - } catch { - return undefined; - } -} +const DEMOBANK_SETTINGS_KEY = buildStorageKey( + "demobank-settings", + codecForSettings(), +); export function useSettings(): [ Readonly<Settings>, <T extends keyof Settings>(key: T, value: Settings[T]) => void, ] { - const { value, update } = useLocalStorage("demobank-settings"); + const { value, update } = useLocalStorage( + DEMOBANK_SETTINGS_KEY, + defaultSettings, + ); - const parsed: Settings = parse_json_or_undefined(value) ?? defaultSettings; function updateField<T extends keyof Settings>(k: T, v: Settings[T]) { - const newValue = { ...parsed, [k]: v }; - const json = JSON.stringify(newValue); - update(json); + const newValue = { ...value, [k]: v }; + update(newValue); } - return [parsed, updateField]; + return [value, updateField]; } |