diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/context')
-rw-r--r-- | packages/taler-wallet-webextension/src/context/alert.ts | 98 | ||||
-rw-r--r-- | packages/taler-wallet-webextension/src/context/devContext.ts | 17 |
2 files changed, 89 insertions, 26 deletions
diff --git a/packages/taler-wallet-webextension/src/context/alert.ts b/packages/taler-wallet-webextension/src/context/alert.ts index cc98ec1e0..e67d94671 100644 --- a/packages/taler-wallet-webextension/src/context/alert.ts +++ b/packages/taler-wallet-webextension/src/context/alert.ts @@ -19,19 +19,26 @@ * @author Sebastian Javier Marchano (sebasjm) */ -import { TranslatedString } from "@gnu-taler/taler-util"; +import { TalerErrorDetail, TranslatedString } from "@gnu-taler/taler-util"; import { ComponentChildren, createContext, h, VNode } from "preact"; import { useContext, useState } from "preact/hooks"; +import { HookError } from "../hooks/useAsyncAsHook.js"; +import { SafeHandler, withSafe } from "../mui/handlers.js"; +import { BackgroundError } from "../wxApi.js"; export type AlertType = "info" | "warning" | "error" | "success"; -export interface Alert { +export interface InfoAlert { message: TranslatedString; description: TranslatedString | VNode; - type: AlertType; + type: "info" | "warning" | "success"; } -export interface ErrorAlert extends Alert { +export type Alert = InfoAlert | ErrorAlert; + +export interface ErrorAlert { + message: TranslatedString; + description: TranslatedString | VNode; type: "error"; context: object; cause: any; @@ -41,10 +48,14 @@ type Type = { alerts: Alert[]; pushAlert: (n: Alert) => void; removeAlert: (n: Alert) => void; + pushAlertOnError: <T>(h: (p: T) => Promise<void>) => SafeHandler<T>; }; const initial: Type = { alerts: [], + pushAlertOnError: () => { + throw Error("alert context not initialized"); + }, pushAlert: () => { null; }, @@ -80,8 +91,17 @@ export const AlertProvider = ({ children }: Props): VNode => { setAlerts((ns: AlertWithDate[]) => ns.filter((n) => n !== alert)); }; + function pushAlertOnError<T>( + handler: (p: T) => Promise<void>, + ): SafeHandler<T> { + return withSafe(handler, (e) => { + const a = alertFromError(e.message as TranslatedString, e); + pushAlert(a); + }); + } + return h(Context.Provider, { - value: { alerts, pushAlert, removeAlert }, + value: { alerts, pushAlert, removeAlert, pushAlertOnError }, children, }); }; @@ -90,29 +110,71 @@ export const useAlertContext = (): Type => useContext(Context); export function alertFromError( message: TranslatedString, - error: unknown, + error: HookError, ...context: any[] -): ErrorAlert { - let description = "" as TranslatedString; +): ErrorAlert; - const isObject = typeof error === "object" && - error !== null; - const hasMessage = - isObject && - "message" in error && - typeof error.message === "string"; +export function alertFromError( + message: TranslatedString, + error: Error, + ...context: any[] +): ErrorAlert; - if (hasMessage) { - description = error.message as TranslatedString; +export function alertFromError( + message: TranslatedString, + error: TalerErrorDetail, + ...context: any[] +): ErrorAlert; + +export function alertFromError( + message: TranslatedString, + error: HookError | TalerErrorDetail | Error, + ...context: any[] +): ErrorAlert { + let description: TranslatedString; + let cause: any; + + if (typeof error === "object" && error !== null) { + if ("code" in error) { + //TalerErrorDetail + description = (error.hint ?? + `Error code: ${error.code}`) as TranslatedString; + cause = { + details: error, + }; + } else if ("hasError" in error) { + //HookError + description = error.message as TranslatedString; + if (error.type === "taler") { + cause = { + details: error.details, + }; + } + } else { + if (error instanceof BackgroundError) { + description = (error.errorDetail.hint ?? + `Error code: ${error.errorDetail.code}`) as TranslatedString; + cause = { + details: error.errorDetail, + stack: error.stack, + }; + } else { + description = error.message as TranslatedString; + cause = { + stack: error.stack, + }; + } + } } else { - description = `Unknown error: ${String(error)}` as TranslatedString; + description = "" as TranslatedString; + cause = error; } return { type: "error", message, description, - cause: error, + cause, context, }; } diff --git a/packages/taler-wallet-webextension/src/context/devContext.ts b/packages/taler-wallet-webextension/src/context/devContext.ts index 99301df52..e2ad2914b 100644 --- a/packages/taler-wallet-webextension/src/context/devContext.ts +++ b/packages/taler-wallet-webextension/src/context/devContext.ts @@ -22,16 +22,15 @@ import { createContext, h, VNode } from "preact"; import { useContext } from "preact/hooks"; import { useWalletDevMode } from "../hooks/useWalletDevMode.js"; -import { ToggleHandler } from "../mui/handlers.js"; interface Type { devMode: boolean; - devModeToggle: ToggleHandler; + toggle: () => Promise<void>; } const Context = createContext<Type>({ devMode: false, - devModeToggle: { - button: {}, + toggle: async () => { + null; }, }); @@ -47,9 +46,8 @@ export const DevContextProviderForTesting = ({ return h(Context.Provider, { value: { devMode: !!value, - devModeToggle: { - value, - button: {}, + toggle: async () => { + null; }, }, children, @@ -58,7 +56,10 @@ export const DevContextProviderForTesting = ({ export const DevContextProvider = ({ children }: { children: any }): VNode => { const devModeToggle = useWalletDevMode(); - const value: Type = { devMode: !!devModeToggle.value, devModeToggle }; + const value: Type = { + devMode: !!devModeToggle.value, + toggle: devModeToggle.toggle, + }; //support for function as children, useful for getting the value right away children = children.length === 1 && typeof children === "function" |