diff options
Diffstat (limited to 'packages/taler-wallet-webextension/src/NavigationBar.tsx')
-rw-r--r-- | packages/taler-wallet-webextension/src/NavigationBar.tsx | 116 |
1 files changed, 78 insertions, 38 deletions
diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index fe348f7fb..7fb8dad8b 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -39,7 +39,10 @@ import qrIcon from "./svg/qr_code_24px.inline.svg"; import settingsIcon from "./svg/settings_black_24dp.inline.svg"; import warningIcon from "./svg/warning_24px.inline.svg"; import { parseTalerUri, TalerUriAction } from "@gnu-taler/taler-util"; -import { useTranslationContext } from "@gnu-taler/web-util/browser"; +import { + encodeCrockForURI, + useTranslationContext, +} from "@gnu-taler/web-util/browser"; /** * List of pages used by the wallet @@ -60,10 +63,7 @@ function replaceAll( ): string { let result = pattern; for (const v in vars) { - result = result.replace( - vars[v], - !values[v] ? "" : encodeURIComponent(values[v]), - ); + result = result.replace(vars[v], !values[v] ? "" : values[v]); } return result; } @@ -94,23 +94,43 @@ function pageDefinition<T extends object>(pattern: string): PageLocation<T> { return f; } +/** + * taler action and scope info may contain + * character not suitable for URL + */ +type CrockEncodedString = string; + export const Pages = { welcome: "/welcome", balance: "/balance", - balanceHistory: pageDefinition<{ currency?: string }>( - "/balance/history/:currency?", - ), - searchHistory: pageDefinition<{ currency?: string }>( - "/search/history/:currency?", + balanceHistory: pageDefinition<{ scope?: CrockEncodedString }>( + "/balance/history/:scope?", ), - balanceDeposit: pageDefinition<{ amount: string }>( - "/balance/deposit/:amount", + searchHistory: pageDefinition<{ scope?: CrockEncodedString }>( + "/search/history/:scope?", ), balanceTransaction: pageDefinition<{ tid: string }>( "/balance/transaction/:tid", ), - sendCash: pageDefinition<{ amount?: string }>("/destination/send/:amount"), - receiveCash: pageDefinition<{ amount?: string }>("/destination/get/:amount?"), + bankManange: pageDefinition<{ scope: CrockEncodedString }>( + "/bank/manage/:scope", + ), + balanceDeposit: pageDefinition<{ + scope: CrockEncodedString; + }>("/balance/deposit/:scope"), + sendCash: pageDefinition<{ scope: CrockEncodedString; amount?: string }>( + "/destination/send/:scope/:amount?", + ), + // if no scope is specified, then exchange selection page will be shown + receiveCash: pageDefinition<{ scope?: CrockEncodedString; amount?: string }>( + "/destination/get/:scope?/:amount?", + ), + receiveCashForPurchase: pageDefinition<{ id?: string }>( + "/add-for-payment/purchase/:id", + ), + receiveCashForInvoice: pageDefinition<{ id?: string }>( + "/add-for-payment/purchase/:id", + ), dev: "/dev", exchanges: "/exchanges", @@ -127,26 +147,40 @@ export const Pages = { "/settings/exchange/add/:currency?", ), - defaultCta: pageDefinition<{ uri: string }>("/taler-uri/:uri"), - cta: pageDefinition<{ action: string }>("/cta/:action"), + defaultCta: pageDefinition<{ uri: CrockEncodedString }>("/taler-uri/:uri"), + // FIXME: mem leak problems + defaultCtaSimple: pageDefinition<{ uri: CrockEncodedString }>( + "/taler-uri-simple/:uri", + ), + cta: pageDefinition<{ action: CrockEncodedString }>("/cta/:action"), ctaPay: "/cta/pay", ctaPayTemplate: "/cta/pay/template", ctaRecovery: "/cta/recovery", ctaRefund: "/cta/refund", ctaWithdraw: "/cta/withdraw", - ctaDeposit: "/cta/deposit", + ctaDeposit: pageDefinition<{ + scope: CrockEncodedString; + account: CrockEncodedString; + }>("/cta/deposit/:scope/:account"), ctaExperiment: "/cta/experiment", ctaAddExchange: "/cta/add/exchange", - ctaInvoiceCreate: pageDefinition<{ amount?: string }>( - "/cta/invoice/create/:amount?", - ), - ctaTransferCreate: pageDefinition<{ amount?: string }>( - "/cta/transfer/create/:amount?", - ), + ctaInvoiceCreate: pageDefinition<{ + scope: CrockEncodedString; + }>("/cta/invoice/create/:scope/:amount?"), + ctaTransferCreate: pageDefinition<{ + scope: CrockEncodedString; + }>("/cta/transfer/create/:scope/:amount?"), ctaInvoicePay: "/cta/invoice/pay", ctaTransferPickup: "/cta/transfer/pickup", - ctaWithdrawManual: pageDefinition<{ amount?: string }>( - "/cta/manual-withdraw/:amount?", + + ctaWithdrawManualForScope: pageDefinition<{ + scope: CrockEncodedString; + amount?: string; + }>("/cta/scope-withdraw/:scope/:amount?"), + ctaWithdrawManual: pageDefinition<{amount?: string;}>("/cta/manual-withdraw/:amount?"), + paytoQrs: pageDefinition<{ payto: CrockEncodedString }>("/payto/qrs/:payto?"), + paytoBanks: pageDefinition<{ payto: CrockEncodedString }>( + "/payto/banks/:payto?", ), }; @@ -178,7 +212,7 @@ export function getPathnameForTalerURI(talerUri: string): string | undefined { typeof Pages[pageName] === "function" ? (Pages[pageName] as any)() : Pages[pageName]; - return `${pageString}?talerUri=${encodeURIComponent(talerUri)}`; + return `${pageString}?talerUri=${encodeCrockForURI(talerUri)}`; } export type PopupNavBarOptions = "balance" | "backup" | "dev"; @@ -195,17 +229,17 @@ export function PopupNavBar({ path }: { path?: PopupNavBarOptions }): VNode { const { i18n } = useTranslationContext(); return ( <NavigationHeader> - <a href={Pages.balance} class={path === "balance" ? "active" : ""}> + <a href={`#${Pages.balance}`} class={path === "balance" ? "active" : ""}> <i18n.Translate>Balance</i18n.Translate> </a> <EnabledBySettings name="backup"> - <a href={Pages.backup} class={path === "backup" ? "active" : ""}> + <a href={`#${Pages.backup}`} class={path === "backup" ? "active" : ""}> <i18n.Translate>Backup</i18n.Translate> </a> </EnabledBySettings> <div style={{ display: "flex", paddingTop: 4, justifyContent: "right" }}> {attentionCount > 0 ? ( - <a href={Pages.notifications}> + <a href={`#${Pages.notifications}`}> <SvgIcon title={i18n.str`Notifications`} dangerouslySetInnerHTML={{ __html: warningIcon }} @@ -215,14 +249,14 @@ export function PopupNavBar({ path }: { path?: PopupNavBarOptions }): VNode { ) : ( <Fragment /> )} - <a href={Pages.qr}> + <a href={`#${Pages.qr}`}> <SvgIcon title={i18n.str`QR Reader and Taler URI`} dangerouslySetInnerHTML={{ __html: qrIcon }} color="white" /> </a> - <a href={Pages.settings}> + <a href={`#${Pages.settings}`}> <SvgIcon title={i18n.str`Settings`} dangerouslySetInnerHTML={{ __html: settingsIcon }} @@ -250,17 +284,23 @@ export function WalletNavBar({ path }: { path?: WalletNavBarOptions }): VNode { return ( <NavigationHeaderHolder> <NavigationHeader> - <a href={Pages.balance} class={path === "balance" ? "active" : ""}> + <a + href={`#${Pages.balance}`} + class={path === "balance" ? "active" : ""} + > <i18n.Translate>Balance</i18n.Translate> </a> <EnabledBySettings name="backup"> - <a href={Pages.backup} class={path === "backup" ? "active" : ""}> + <a + href={`#${Pages.backup}`} + class={path === "backup" ? "active" : ""} + > <i18n.Translate>Backup</i18n.Translate> </a> </EnabledBySettings> {attentionCount > 0 ? ( - <a href={Pages.notifications}> + <a href={`#${Pages.notifications}`}> <i18n.Translate>Notifications</i18n.Translate> </a> ) : ( @@ -268,7 +308,7 @@ export function WalletNavBar({ path }: { path?: WalletNavBarOptions }): VNode { )} <EnabledBySettings name="advancedMode"> - <a href={Pages.dev} class={path === "dev" ? "active" : ""}> + <a href={`#${Pages.dev}`} class={path === "dev" ? "active" : ""}> <i18n.Translate>Dev tools</i18n.Translate> </a> </EnabledBySettings> @@ -276,21 +316,21 @@ export function WalletNavBar({ path }: { path?: WalletNavBarOptions }): VNode { <div style={{ display: "flex", paddingTop: 4, justifyContent: "right" }} > - <a href={Pages.searchHistory({})}> + <a href={`#${Pages.searchHistory({})}`}> <SvgIcon title={i18n.str`Search transactions`} dangerouslySetInnerHTML={{ __html: searchIcon }} color="white" /> </a> - <a href={Pages.qr}> + <a href={`#${Pages.qr}`}> <SvgIcon title={i18n.str`QR Reader and Taler URI`} dangerouslySetInnerHTML={{ __html: qrIcon }} color="white" /> </a> - <a href={Pages.settings}> + <a href={`#${Pages.settings}`}> <SvgIcon title={i18n.str`Settings`} dangerouslySetInnerHTML={{ __html: settingsIcon }} |