aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/context
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-webextension/src/context')
-rw-r--r--packages/taler-wallet-webextension/src/context/alert.ts98
-rw-r--r--packages/taler-wallet-webextension/src/context/devContext.ts17
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"