use new local storage api
This commit is contained in:
parent
d4dd82eda1
commit
be9d3dad83
@ -14,11 +14,20 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
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 {
|
import {
|
||||||
ErrorType,
|
ErrorType,
|
||||||
HttpError,
|
HttpError,
|
||||||
RequestError,
|
RequestError,
|
||||||
|
buildStorageKey,
|
||||||
useLocalStorage,
|
useLocalStorage,
|
||||||
} from "@gnu-taler/web-util/browser";
|
} from "@gnu-taler/web-util/browser";
|
||||||
import {
|
import {
|
||||||
@ -51,6 +60,26 @@ interface LoggedOut {
|
|||||||
status: "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 {
|
export function getInitialBackendBaseURL(): string {
|
||||||
const overrideUrl =
|
const overrideUrl =
|
||||||
typeof localStorage !== "undefined"
|
typeof localStorage !== "undefined"
|
||||||
@ -79,29 +108,27 @@ export interface BackendStateHandler {
|
|||||||
logOut(): void;
|
logOut(): void;
|
||||||
logIn(info: BackendCredentials): void;
|
logIn(info: BackendCredentials): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const BACKEND_STATE_KEY = buildStorageKey(
|
||||||
|
"backend-state",
|
||||||
|
codecForBackendState(),
|
||||||
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return getters and setters for
|
* Return getters and setters for
|
||||||
* login credentials and backend's
|
* login credentials and backend's
|
||||||
* base URL.
|
* base URL.
|
||||||
*/
|
*/
|
||||||
export function useBackendState(): BackendStateHandler {
|
export function useBackendState(): BackendStateHandler {
|
||||||
const { value, update } = useLocalStorage(
|
const { value: state, update } = useLocalStorage(
|
||||||
"backend-state",
|
BACKEND_STATE_KEY,
|
||||||
JSON.stringify(defaultState),
|
defaultState,
|
||||||
);
|
);
|
||||||
|
|
||||||
let parsed;
|
|
||||||
try {
|
|
||||||
parsed = JSON.parse(value!);
|
|
||||||
} catch {
|
|
||||||
parsed = undefined;
|
|
||||||
}
|
|
||||||
const state: BackendState = !parsed?.status ? defaultState : parsed;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
logOut() {
|
logOut() {
|
||||||
update(JSON.stringify({ ...defaultState }));
|
update(defaultState);
|
||||||
},
|
},
|
||||||
logIn(info) {
|
logIn(info) {
|
||||||
//admin is defined by the username
|
//admin is defined by the username
|
||||||
@ -110,7 +137,7 @@ export function useBackendState(): BackendStateHandler {
|
|||||||
...info,
|
...info,
|
||||||
isUserAdministrator: info.username === "admin",
|
isUserAdministrator: info.username === "admin",
|
||||||
};
|
};
|
||||||
update(JSON.stringify(nextState));
|
update(nextState);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { StateUpdater } from "preact/hooks";
|
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);
|
export type ValueOrFunction<T> = T | ((p: T) => T);
|
||||||
|
|
||||||
const calculateRootPath = () => {
|
const calculateRootPath = () => {
|
||||||
@ -31,11 +32,14 @@ const calculateRootPath = () => {
|
|||||||
return rootPath;
|
return rootPath;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const BACKEND_URL_KEY = buildStorageKey("backend-url");
|
||||||
|
const TRIED_LOGIN_KEY = buildStorageKey("tried-login", codecForBoolean());
|
||||||
|
|
||||||
export function useBackendURL(
|
export function useBackendURL(
|
||||||
url?: string,
|
url?: string,
|
||||||
): [string, boolean, StateUpdater<string>, () => void] {
|
): [string, boolean, StateUpdater<string>, () => void] {
|
||||||
const { value, update: setter } = useLocalStorage(
|
const { value, update: setter } = useLocalStorage(
|
||||||
"backend-url",
|
BACKEND_URL_KEY,
|
||||||
url || calculateRootPath(),
|
url || calculateRootPath(),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -43,10 +47,10 @@ export function useBackendURL(
|
|||||||
value: triedToLog,
|
value: triedToLog,
|
||||||
update: setTriedToLog,
|
update: setTriedToLog,
|
||||||
reset: resetBackend,
|
reset: resetBackend,
|
||||||
} = useLocalStorage("tried-login");
|
} = useLocalStorage(TRIED_LOGIN_KEY);
|
||||||
|
|
||||||
const checkedSetter = (v: ValueOrFunction<string>) => {
|
const checkedSetter = (v: ValueOrFunction<string>) => {
|
||||||
setTriedToLog("yes");
|
setTriedToLog(true);
|
||||||
const computedValue =
|
const computedValue =
|
||||||
v instanceof Function ? v(value) : v.replace(/\/$/, "");
|
v instanceof Function ? v(value) : v.replace(/\/$/, "");
|
||||||
return setter(computedValue);
|
return setter(computedValue);
|
||||||
|
@ -14,36 +14,44 @@
|
|||||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
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 {
|
interface Settings {
|
||||||
currentWithdrawalOperationId: string | undefined;
|
currentWithdrawalOperationId: string | undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const codecForSettings = (): Codec<Settings> =>
|
||||||
|
buildCodecForObject<Settings>()
|
||||||
|
.property("currentWithdrawalOperationId", codecOptional(codecForString()))
|
||||||
|
.build("Settings");
|
||||||
|
|
||||||
const defaultSettings: Settings = {
|
const defaultSettings: Settings = {
|
||||||
currentWithdrawalOperationId: undefined,
|
currentWithdrawalOperationId: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
function parse_json_or_undefined<T>(str: string | undefined): T | undefined {
|
const DEMOBANK_SETTINGS_KEY = buildStorageKey(
|
||||||
if (str === undefined) return undefined;
|
"demobank-settings",
|
||||||
try {
|
codecForSettings(),
|
||||||
return JSON.parse(str);
|
);
|
||||||
} catch {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useSettings(): [
|
export function useSettings(): [
|
||||||
Readonly<Settings>,
|
Readonly<Settings>,
|
||||||
<T extends keyof Settings>(key: T, value: Settings[T]) => void,
|
<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]) {
|
function updateField<T extends keyof Settings>(k: T, v: Settings[T]) {
|
||||||
const newValue = { ...parsed, [k]: v };
|
const newValue = { ...value, [k]: v };
|
||||||
const json = JSON.stringify(newValue);
|
update(newValue);
|
||||||
update(json);
|
|
||||||
}
|
}
|
||||||
return [parsed, updateField];
|
return [value, updateField];
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user