summaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/wallet
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-webextension/src/wallet')
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Application.tsx853
-rw-r--r--packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx6
-rw-r--r--packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts7
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx16
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Settings.tsx183
-rw-r--r--packages/taler-wallet-webextension/src/wallet/Transaction.tsx15
6 files changed, 567 insertions, 513 deletions
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx
index ff8cf0314..5c75b734b 100644
--- a/packages/taler-wallet-webextension/src/wallet/Application.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx
@@ -20,15 +20,21 @@
* @author sebasjm
*/
+import { TranslatedString } from "@gnu-taler/taler-util";
import {
- TalerUriAction,
- TranslatedString,
- parseTalerUri,
-} from "@gnu-taler/taler-util";
+ TranslationProvider,
+ useTranslationContext,
+} from "@gnu-taler/web-util/lib/index.browser";
import { createHashHistory } from "history";
-import { ComponentChildren, Fragment, h, VNode } from "preact";
-import { route, Route, Router } from "preact-router";
+import { ComponentChildren, Fragment, VNode, h } from "preact";
+import { Route, Router, route } from "preact-router";
import { useEffect } from "preact/hooks";
+import {
+ Pages,
+ WalletNavBar,
+ WalletNavBarOptions,
+ getPathnameForTalerURI,
+} from "../NavigationBar.js";
import { AlertView, CurrentAlerts } from "../components/CurrentAlerts.js";
import { LogoHeader } from "../components/LogoHeader.js";
import PendingTransactions from "../components/PendingTransactions.js";
@@ -39,12 +45,7 @@ import {
WalletBox,
} from "../components/styled/index.js";
import { AlertProvider } from "../context/alert.js";
-import { DevContextProvider } from "../context/devContext.js";
import { IoCProviderForRuntime } from "../context/iocContext.js";
-import {
- TranslationProvider,
- useTranslationContext,
-} from "@gnu-taler/web-util/lib/index.browser";
import { DepositPage as DepositPageCTA } from "../cta/Deposit/index.js";
import { InvoiceCreatePage } from "../cta/InvoiceCreate/index.js";
import { InvoicePayPage } from "../cta/InvoicePay/index.js";
@@ -59,12 +60,7 @@ import {
WithdrawPageFromParams,
WithdrawPageFromURI,
} from "../cta/Withdraw/index.js";
-import {
- Pages,
- WalletNavBar,
- WalletNavBarOptions,
- getPathnameForTalerURI,
-} from "../NavigationBar.js";
+import { strings } from "../i18n/strings.js";
import { platform } from "../platform/foreground.js";
import CloseIcon from "../svg/close_24px.svg";
import { AddBackupProviderPage } from "./AddBackupProvider/index.js";
@@ -80,7 +76,6 @@ import { QrReaderPage } from "./QrReader.js";
import { SettingsPage } from "./Settings.js";
import { TransactionPage } from "./Transaction.js";
import { WelcomePage } from "./Welcome.js";
-import { strings } from "../i18n/strings.js";
export function Application(): VNode {
const { i18n } = useTranslationContext();
@@ -91,433 +86,421 @@ export function Application(): VNode {
}
return (
<TranslationProvider source={strings}>
- <DevContextProvider>
- <IoCProviderForRuntime>
- <Router history={hash_history}>
- <Route
- path={Pages.welcome}
- component={() => (
- <WalletTemplate>
- <WelcomePage />
- </WalletTemplate>
- )}
- />
+ <IoCProviderForRuntime>
+ <Router history={hash_history}>
+ <Route
+ path={Pages.welcome}
+ component={() => (
+ <WalletTemplate>
+ <WelcomePage />
+ </WalletTemplate>
+ )}
+ />
- <Route
- path={Pages.qr}
- component={() => (
- <WalletTemplate goToTransaction={redirectToTxInfo}>
- <QrReaderPage
- onDetected={(talerActionUrl: string) => {
- platform.openWalletURIFromPopup(talerActionUrl);
- }}
- />
- </WalletTemplate>
- )}
- />
+ <Route
+ path={Pages.qr}
+ component={() => (
+ <WalletTemplate goToTransaction={redirectToTxInfo}>
+ <QrReaderPage
+ onDetected={(talerActionUrl: string) => {
+ platform.openWalletURIFromPopup(talerActionUrl);
+ }}
+ />
+ </WalletTemplate>
+ )}
+ />
- <Route
- path={Pages.settings}
- component={() => (
- <WalletTemplate goToTransaction={redirectToTxInfo}>
- <SettingsPage />
- </WalletTemplate>
- )}
- />
- <Route
- path={Pages.notifications}
- component={() => (
- <WalletTemplate>
- <NotificationsPage />
- </WalletTemplate>
- )}
- />
- {/**
- * SETTINGS
- */}
- <Route
- path={Pages.settingsExchangeAdd.pattern}
- component={() => (
- <WalletTemplate>
- <ExchangeAddPage onBack={() => redirectTo(Pages.balance)} />
- </WalletTemplate>
- )}
- />
+ <Route
+ path={Pages.settings}
+ component={() => (
+ <WalletTemplate goToTransaction={redirectToTxInfo}>
+ <SettingsPage />
+ </WalletTemplate>
+ )}
+ />
+ <Route
+ path={Pages.notifications}
+ component={() => (
+ <WalletTemplate>
+ <NotificationsPage />
+ </WalletTemplate>
+ )}
+ />
+ {/**
+ * SETTINGS
+ */}
+ <Route
+ path={Pages.settingsExchangeAdd.pattern}
+ component={() => (
+ <WalletTemplate>
+ <ExchangeAddPage onBack={() => redirectTo(Pages.balance)} />
+ </WalletTemplate>
+ )}
+ />
- <Route
- path={Pages.balanceHistory.pattern}
- component={({ currency }: { currency?: string }) => (
- <WalletTemplate
- path="balance"
- goToTransaction={redirectToTxInfo}
- >
- <HistoryPage
- currency={currency}
- goToWalletDeposit={(currency: string) =>
- redirectTo(Pages.sendCash({ amount: `${currency}:0` }))
- }
- goToWalletManualWithdraw={(currency?: string) =>
- redirectTo(
- Pages.receiveCash({
- amount: !currency ? undefined : `${currency}:0`,
- }),
- )
- }
- />
- </WalletTemplate>
- )}
- />
- <Route
- path={Pages.sendCash.pattern}
- component={({ amount }: { amount?: string }) => (
- <WalletTemplate path="balance">
- <DestinationSelectionPage
- type="send"
- amount={amount}
- goToWalletBankDeposit={(amount: string) =>
- redirectTo(Pages.balanceDeposit({ amount }))
- }
- goToWalletWalletSend={(amount: string) =>
- redirectTo(Pages.ctaTransferCreate({ amount }))
- }
- />
- </WalletTemplate>
- )}
- />
- <Route
- path={Pages.receiveCash.pattern}
- component={({ amount }: { amount?: string }) => (
- <WalletTemplate path="balance">
- <DestinationSelectionPage
- type="get"
- amount={amount}
- goToWalletManualWithdraw={(amount?: string) =>
- redirectTo(Pages.ctaWithdrawManual({ amount }))
- }
- goToWalletWalletInvoice={(amount?: string) =>
- redirectTo(Pages.ctaInvoiceCreate({ amount }))
- }
- />
- </WalletTemplate>
- )}
- />
+ <Route
+ path={Pages.balanceHistory.pattern}
+ component={({ currency }: { currency?: string }) => (
+ <WalletTemplate path="balance" goToTransaction={redirectToTxInfo}>
+ <HistoryPage
+ currency={currency}
+ goToWalletDeposit={(currency: string) =>
+ redirectTo(Pages.sendCash({ amount: `${currency}:0` }))
+ }
+ goToWalletManualWithdraw={(currency?: string) =>
+ redirectTo(
+ Pages.receiveCash({
+ amount: !currency ? undefined : `${currency}:0`,
+ }),
+ )
+ }
+ />
+ </WalletTemplate>
+ )}
+ />
+ <Route
+ path={Pages.sendCash.pattern}
+ component={({ amount }: { amount?: string }) => (
+ <WalletTemplate path="balance">
+ <DestinationSelectionPage
+ type="send"
+ amount={amount}
+ goToWalletBankDeposit={(amount: string) =>
+ redirectTo(Pages.balanceDeposit({ amount }))
+ }
+ goToWalletWalletSend={(amount: string) =>
+ redirectTo(Pages.ctaTransferCreate({ amount }))
+ }
+ />
+ </WalletTemplate>
+ )}
+ />
+ <Route
+ path={Pages.receiveCash.pattern}
+ component={({ amount }: { amount?: string }) => (
+ <WalletTemplate path="balance">
+ <DestinationSelectionPage
+ type="get"
+ amount={amount}
+ goToWalletManualWithdraw={(amount?: string) =>
+ redirectTo(Pages.ctaWithdrawManual({ amount }))
+ }
+ goToWalletWalletInvoice={(amount?: string) =>
+ redirectTo(Pages.ctaInvoiceCreate({ amount }))
+ }
+ />
+ </WalletTemplate>
+ )}
+ />
- <Route
- path={Pages.balanceTransaction.pattern}
- component={({ tid }: { tid: string }) => (
- <WalletTemplate path="balance">
- <TransactionPage
- tid={tid}
- goToWalletHistory={(currency?: string) =>
- redirectTo(Pages.balanceHistory({ currency }))
- }
- />
- </WalletTemplate>
- )}
- />
+ <Route
+ path={Pages.balanceTransaction.pattern}
+ component={({ tid }: { tid: string }) => (
+ <WalletTemplate path="balance">
+ <TransactionPage
+ tid={tid}
+ goToWalletHistory={(currency?: string) =>
+ redirectTo(Pages.balanceHistory({ currency }))
+ }
+ />
+ </WalletTemplate>
+ )}
+ />
- <Route
- path={Pages.balanceDeposit.pattern}
- component={({ amount }: { amount: string }) => (
- <WalletTemplate path="balance">
- <DepositPage
- amount={amount}
- onCancel={(currency: string) => {
- redirectTo(Pages.balanceHistory({ currency }));
- }}
- onSuccess={(currency: string) => {
- redirectTo(Pages.balanceHistory({ currency }));
- }}
- />
- </WalletTemplate>
- )}
- />
+ <Route
+ path={Pages.balanceDeposit.pattern}
+ component={({ amount }: { amount: string }) => (
+ <WalletTemplate path="balance">
+ <DepositPage
+ amount={amount}
+ onCancel={(currency: string) => {
+ redirectTo(Pages.balanceHistory({ currency }));
+ }}
+ onSuccess={(currency: string) => {
+ redirectTo(Pages.balanceHistory({ currency }));
+ }}
+ />
+ </WalletTemplate>
+ )}
+ />
- <Route
- path={Pages.backup}
- component={() => (
- <WalletTemplate
- path="backup"
- goToTransaction={redirectToTxInfo}
- >
- <BackupPage
- onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
- />
- </WalletTemplate>
- )}
- />
- <Route
- path={Pages.backupProviderDetail.pattern}
- component={({ pid }: { pid: string }) => (
- <WalletTemplate>
- <ProviderDetailPage
- pid={pid}
- onPayProvider={(uri: string) =>
- redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
- }
- onWithdraw={(amount: string) =>
- redirectTo(Pages.receiveCash({ amount }))
- }
- onBack={() => redirectTo(Pages.backup)}
- />
- </WalletTemplate>
- )}
- />
- <Route
- path={Pages.backupProviderAdd}
- component={() => (
- <WalletTemplate>
- <AddBackupProviderPage
- onPaymentRequired={(uri: string) =>
- redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
- }
- onComplete={(pid: string) =>
- redirectTo(Pages.backupProviderDetail({ pid }))
- }
- onBack={() => redirectTo(Pages.backup)}
- />
- </WalletTemplate>
- )}
- />
+ <Route
+ path={Pages.backup}
+ component={() => (
+ <WalletTemplate path="backup" goToTransaction={redirectToTxInfo}>
+ <BackupPage
+ onAddProvider={() => redirectTo(Pages.backupProviderAdd)}
+ />
+ </WalletTemplate>
+ )}
+ />
+ <Route
+ path={Pages.backupProviderDetail.pattern}
+ component={({ pid }: { pid: string }) => (
+ <WalletTemplate>
+ <ProviderDetailPage
+ pid={pid}
+ onPayProvider={(uri: string) =>
+ redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
+ }
+ onWithdraw={(amount: string) =>
+ redirectTo(Pages.receiveCash({ amount }))
+ }
+ onBack={() => redirectTo(Pages.backup)}
+ />
+ </WalletTemplate>
+ )}
+ />
+ <Route
+ path={Pages.backupProviderAdd}
+ component={() => (
+ <WalletTemplate>
+ <AddBackupProviderPage
+ onPaymentRequired={(uri: string) =>
+ redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`)
+ }
+ onComplete={(pid: string) =>
+ redirectTo(Pages.backupProviderDetail({ pid }))
+ }
+ onBack={() => redirectTo(Pages.backup)}
+ />
+ </WalletTemplate>
+ )}
+ />
- {/**
- * DEV
- */}
- <Route
- path={Pages.dev}
- component={() => (
- <WalletTemplate path="dev" goToTransaction={redirectToTxInfo}>
- <DeveloperPage />
- </WalletTemplate>
- )}
- />
+ {/**
+ * DEV
+ */}
+ <Route
+ path={Pages.dev}
+ component={() => (
+ <WalletTemplate path="dev" goToTransaction={redirectToTxInfo}>
+ <DeveloperPage />
+ </WalletTemplate>
+ )}
+ />
- {/**
- * CALL TO ACTION
- */}
- <Route
- path={Pages.defaultCta.pattern}
- component={({ uri }: { uri: string }) => {
- const path = getPathnameForTalerURI(uri);
- if (!path) {
- return (
- <CallToActionTemplate title={i18n.str`Taler URI handler`}>
- <AlertView
- alert={{
- type: "warning",
- message: i18n.str`Could not found a handler for the Taler URI`,
- description: i18n.str`The uri read in the path parameter is not valid: "${uri}"`,
- }}
- />
- </CallToActionTemplate>
- );
- }
- return <Redirect to={path} />;
- }}
- />
- <Route
- path={Pages.ctaPay}
- component={({ talerUri }: { talerUri: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash payment`}>
- <PaymentPage
- talerPayUri={decodeURIComponent(talerUri)}
- goToWalletManualWithdraw={(amount?: string) =>
- redirectTo(Pages.receiveCash({ amount }))
- }
- cancel={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaPayTemplate}
- component={({ talerUri }: { talerUri: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash payment`}>
- <PaymentTemplatePage
- talerTemplateUri={decodeURIComponent(talerUri)}
- goToWalletManualWithdraw={(amount?: string) =>
- redirectTo(Pages.receiveCash({ amount }))
- }
- cancel={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaRefund}
- component={({ talerUri }: { talerUri: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash refund`}>
- <RefundPage
- talerRefundUri={decodeURIComponent(talerUri)}
- cancel={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaTips}
- component={({ talerUri }: { talerUri: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash tip`}>
- <TipPage
- talerTipUri={decodeURIComponent(talerUri)}
- onCancel={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaWithdraw}
- component={({ talerUri }: { talerUri: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
- <WithdrawPageFromURI
- talerWithdrawUri={decodeURIComponent(talerUri)}
- cancel={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaWithdrawManual.pattern}
- component={({ amount }: { amount: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
- <WithdrawPageFromParams
- amount={amount}
- cancel={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaDeposit}
- component={({
- amount,
- talerUri,
- }: {
- amount: string;
- talerUri: string;
- }) => (
- <CallToActionTemplate title={i18n.str`Digital cash deposit`}>
- <DepositPageCTA
- amountStr={amount}
- talerDepositUri={decodeURIComponent(talerUri)}
- cancel={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaInvoiceCreate.pattern}
- component={({ amount }: { amount: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
- <InvoiceCreatePage
- amount={amount}
- onClose={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaTransferCreate.pattern}
- component={({ amount }: { amount: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
- <TransferCreatePage
- amount={amount}
- onClose={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaInvoicePay}
- component={({ talerUri }: { talerUri: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
- <InvoicePayPage
- talerPayPullUri={decodeURIComponent(talerUri)}
- goToWalletManualWithdraw={(amount?: string) =>
- redirectTo(Pages.receiveCash({ amount }))
- }
- onClose={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaTransferPickup}
- component={({ talerUri }: { talerUri: string }) => (
- <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
- <TransferPickupPage
- talerPayPushUri={decodeURIComponent(talerUri)}
- onClose={() => redirectTo(Pages.balance)}
- onSuccess={(tid: string) =>
- redirectTo(Pages.balanceTransaction({ tid }))
- }
- />
- </CallToActionTemplate>
- )}
- />
- <Route
- path={Pages.ctaRecovery}
- component={({
- talerRecoveryUri,
- }: {
- talerRecoveryUri: string;
- }) => (
- <CallToActionTemplate title={i18n.str`Digital cash recovery`}>
- <RecoveryPage
- talerRecoveryUri={decodeURIComponent(talerRecoveryUri)}
- onCancel={() => redirectTo(Pages.balance)}
- onSuccess={() => redirectTo(Pages.backup)}
- />
- </CallToActionTemplate>
- )}
- />
+ {/**
+ * CALL TO ACTION
+ */}
+ <Route
+ path={Pages.defaultCta.pattern}
+ component={({ uri }: { uri: string }) => {
+ const path = getPathnameForTalerURI(uri);
+ if (!path) {
+ return (
+ <CallToActionTemplate title={i18n.str`Taler URI handler`}>
+ <AlertView
+ alert={{
+ type: "warning",
+ message: i18n.str`Could not found a handler for the Taler URI`,
+ description: i18n.str`The uri read in the path parameter is not valid: "${uri}"`,
+ }}
+ />
+ </CallToActionTemplate>
+ );
+ }
+ return <Redirect to={path} />;
+ }}
+ />
+ <Route
+ path={Pages.ctaPay}
+ component={({ talerUri }: { talerUri: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash payment`}>
+ <PaymentPage
+ talerPayUri={decodeURIComponent(talerUri)}
+ goToWalletManualWithdraw={(amount?: string) =>
+ redirectTo(Pages.receiveCash({ amount }))
+ }
+ cancel={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaPayTemplate}
+ component={({ talerUri }: { talerUri: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash payment`}>
+ <PaymentTemplatePage
+ talerTemplateUri={decodeURIComponent(talerUri)}
+ goToWalletManualWithdraw={(amount?: string) =>
+ redirectTo(Pages.receiveCash({ amount }))
+ }
+ cancel={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaRefund}
+ component={({ talerUri }: { talerUri: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash refund`}>
+ <RefundPage
+ talerRefundUri={decodeURIComponent(talerUri)}
+ cancel={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaTips}
+ component={({ talerUri }: { talerUri: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash tip`}>
+ <TipPage
+ talerTipUri={decodeURIComponent(talerUri)}
+ onCancel={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaWithdraw}
+ component={({ talerUri }: { talerUri: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
+ <WithdrawPageFromURI
+ talerWithdrawUri={decodeURIComponent(talerUri)}
+ cancel={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaWithdrawManual.pattern}
+ component={({ amount }: { amount: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash withdrawal`}>
+ <WithdrawPageFromParams
+ amount={amount}
+ cancel={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaDeposit}
+ component={({
+ amount,
+ talerUri,
+ }: {
+ amount: string;
+ talerUri: string;
+ }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash deposit`}>
+ <DepositPageCTA
+ amountStr={amount}
+ talerDepositUri={decodeURIComponent(talerUri)}
+ cancel={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaInvoiceCreate.pattern}
+ component={({ amount }: { amount: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
+ <InvoiceCreatePage
+ amount={amount}
+ onClose={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaTransferCreate.pattern}
+ component={({ amount }: { amount: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
+ <TransferCreatePage
+ amount={amount}
+ onClose={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaInvoicePay}
+ component={({ talerUri }: { talerUri: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash invoice`}>
+ <InvoicePayPage
+ talerPayPullUri={decodeURIComponent(talerUri)}
+ goToWalletManualWithdraw={(amount?: string) =>
+ redirectTo(Pages.receiveCash({ amount }))
+ }
+ onClose={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaTransferPickup}
+ component={({ talerUri }: { talerUri: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash transfer`}>
+ <TransferPickupPage
+ talerPayPushUri={decodeURIComponent(talerUri)}
+ onClose={() => redirectTo(Pages.balance)}
+ onSuccess={(tid: string) =>
+ redirectTo(Pages.balanceTransaction({ tid }))
+ }
+ />
+ </CallToActionTemplate>
+ )}
+ />
+ <Route
+ path={Pages.ctaRecovery}
+ component={({ talerRecoveryUri }: { talerRecoveryUri: string }) => (
+ <CallToActionTemplate title={i18n.str`Digital cash recovery`}>
+ <RecoveryPage
+ talerRecoveryUri={decodeURIComponent(talerRecoveryUri)}
+ onCancel={() => redirectTo(Pages.balance)}
+ onSuccess={() => redirectTo(Pages.backup)}
+ />
+ </CallToActionTemplate>
+ )}
+ />
- {/**
- * NOT FOUND
- * all redirects should be at the end
- */}
- <Route
- path={Pages.balance}
- component={() => <Redirect to={Pages.balanceHistory({})} />}
- />
+ {/**
+ * NOT FOUND
+ * all redirects should be at the end
+ */}
+ <Route
+ path={Pages.balance}
+ component={() => <Redirect to={Pages.balanceHistory({})} />}
+ />
- <Route
- default
- component={() => <Redirect to={Pages.balanceHistory({})} />}
- />
- </Router>
- </IoCProviderForRuntime>
- </DevContextProvider>
+ <Route
+ default
+ component={() => <Redirect to={Pages.balanceHistory({})} />}
+ />
+ </Router>
+ </IoCProviderForRuntime>
</TranslationProvider>
);
}
diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
index 7f239f33d..8416e17e9 100644
--- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection/views.tsx
@@ -17,7 +17,7 @@
import { styled } from "@linaria/react";
import { Fragment, h, VNode } from "preact";
import { AmountField } from "../../components/AmountField.js";
-import { JustInDevMode } from "../../components/JustInDevMode.js";
+import { EnabledBySettings } from "../../components/EnabledBySettings.js";
import { SelectList } from "../../components/SelectList.js";
import {
Input,
@@ -300,11 +300,11 @@ export function ReadySendView({
required
handler={amountHandler}
/>
- <JustInDevMode>
+ <EnabledBySettings name="advanceMode">
<Button onClick={sendAll.onClick}>
<i18n.Translate>Send all</i18n.Translate>
</Button>
- </JustInDevMode>
+ </EnabledBySettings>
</Grid>
<Grid container spacing={1} columns={1}>
diff --git a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
index 1f8ab4883..641b47cd7 100644
--- a/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
+++ b/packages/taler-wallet-webextension/src/wallet/ManageAccount/state.ts
@@ -23,10 +23,10 @@ import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
import { useState } from "preact/hooks";
import { alertFromError, useAlertContext } from "../../context/alert.js";
import { useBackendContext } from "../../context/backend.js";
-import { useDevContext } from "../../context/devContext.js";
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { useAsyncAsHook } from "../../hooks/useAsyncAsHook.js";
import { AccountByType, Props, State } from "./index.js";
+import { useSettings } from "../../hooks/useSettings.js";
export function useComponentState({
currency,
@@ -39,12 +39,11 @@ export function useComponentState({
const hook = useAsyncAsHook(() =>
api.wallet.call(WalletApiOperation.ListKnownBankAccounts, { currency }),
);
- const { devMode } = useDevContext();
const accountType: Record<string, string> = {
iban: "IBAN",
- // "x-taler-bank": "Taler Bank",
};
- if (devMode) {
+ const [settings] = useSettings();
+ if (settings.extendedAccountTypes) {
accountType["bitcoin"] = "Bitcoin";
accountType["x-taler-bank"] = "Taler Bank";
}
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
index 53bc577d4..89d92b82c 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.stories.tsx
@@ -47,27 +47,27 @@ const version = {
export const AllOff = tests.createExample(TestedComponent, {
deviceName: "this-is-the-device-name",
- devModeToggle: { value: false, button: {} },
+ advanceToggle: { value: false, button: {} },
autoOpenToggle: { value: false, button: {} },
- clipboardToggle: { value: false, button: {} },
+ langToggle: { value: false, button: {} },
setDeviceName: () => Promise.resolve(),
...version,
});
export const OneChecked = tests.createExample(TestedComponent, {
deviceName: "this-is-the-device-name",
- devModeToggle: { value: false, button: {} },
+ advanceToggle: { value: false, button: {} },
autoOpenToggle: { value: false, button: {} },
- clipboardToggle: { value: false, button: {} },
+ langToggle: { value: false, button: {} },
setDeviceName: () => Promise.resolve(),
...version,
});
export const WithOneExchange = tests.createExample(TestedComponent, {
deviceName: "this-is-the-device-name",
- devModeToggle: { value: false, button: {} },
+ advanceToggle: { value: false, button: {} },
autoOpenToggle: { value: false, button: {} },
- clipboardToggle: { value: false, button: {} },
+ langToggle: { value: false, button: {} },
setDeviceName: () => Promise.resolve(),
knownExchanges: [
{
@@ -89,9 +89,9 @@ export const WithExchangeInDifferentState = tests.createExample(
TestedComponent,
{
deviceName: "this-is-the-device-name",
- devModeToggle: { value: false, button: {} },
+ advanceToggle: { value: false, button: {} },
autoOpenToggle: { value: false, button: {} },
- clipboardToggle: { value: false, button: {} },
+ langToggle: { value: false, button: {} },
setDeviceName: () => Promise.resolve(),
knownExchanges: [
{
diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
index ae3a6e688..62a6c55ff 100644
--- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx
@@ -17,12 +17,15 @@
import {
ExchangeListItem,
ExchangeTosStatus,
+ TranslatedString,
WalletCoreVersion,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
-import { Fragment, h, VNode } from "preact";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
+import { Fragment, VNode, h } from "preact";
+import { Pages } from "../NavigationBar.js";
import { Checkbox } from "../components/Checkbox.js";
-import { JustInDevMode } from "../components/JustInDevMode.js";
+import { EnabledBySettings } from "../components/EnabledBySettings.js";
import { Part } from "../components/Part.js";
import { SelectList } from "../components/SelectList.js";
import {
@@ -35,25 +38,20 @@ import {
} from "../components/styled/index.js";
import { useAlertContext } from "../context/alert.js";
import { useBackendContext } from "../context/backend.js";
-import { useDevContext } from "../context/devContext.js";
-import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
-import { useSettings } from "../hooks/useSettings.js";
import { useBackupDeviceName } from "../hooks/useBackupDeviceName.js";
import { useClipboardPermissions } from "../hooks/useClipboardPermissions.js";
+import { useSettings } from "../hooks/useSettings.js";
import { ToggleHandler } from "../mui/handlers.js";
-import { Pages } from "../NavigationBar.js";
import { platform } from "../platform/foreground.js";
+import { Settings } from "../platform/api.js";
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
export function SettingsPage(): VNode {
const [settings, updateSettings] = useSettings();
- const clipboardToggle = useClipboardPermissions();
- const { devMode, toggle } = useDevContext();
const { safely } = useAlertContext();
const { name, update } = useBackupDeviceName();
- const { pushAlertOnError } = useAlertContext();
const webex = platform.getWalletWebExVersion();
const api = useBackendContext();
@@ -76,16 +74,24 @@ export function SettingsPage(): VNode {
value: settings.injectTalerSupport,
button: {
onClick: safely("update support injection", async () => {
- console.log("click", settings.injectTalerSupport);
updateSettings("injectTalerSupport", !settings.injectTalerSupport);
}),
},
}}
- clipboardToggle={clipboardToggle}
- devModeToggle={{
- value: devMode,
+ advanceToggle={{
+ value: settings.advanceMode,
button: {
- onClick: pushAlertOnError(toggle),
+ onClick: safely("update advance mode", async () => {
+ updateSettings("advanceMode", !settings.advanceMode);
+ }),
+ },
+ }}
+ langToggle={{
+ value: settings.langSelector,
+ button: {
+ onClick: safely("update lang selector", async () => {
+ updateSettings("langSelector", !settings.langSelector);
+ }),
},
}}
webexVersion={{
@@ -101,8 +107,8 @@ export interface ViewProps {
deviceName: string;
setDeviceName: (s: string) => Promise<void>;
autoOpenToggle: ToggleHandler;
- clipboardToggle: ToggleHandler;
- devModeToggle: ToggleHandler;
+ advanceToggle: ToggleHandler;
+ langToggle: ToggleHandler;
knownExchanges: Array<ExchangeListItem>;
coreVersion: WalletCoreVersion | undefined;
webexVersion: {
@@ -114,8 +120,8 @@ export interface ViewProps {
export function SettingsView({
knownExchanges,
autoOpenToggle,
- clipboardToggle,
- devModeToggle,
+ advanceToggle,
+ langToggle,
coreVersion,
webexVersion,
}: ViewProps): VNode {
@@ -204,45 +210,19 @@ export function SettingsView({
</LinkPrimary>
</div>
- <JustInDevMode>
- <SubTitle>
- <i18n.Translate>Display</i18n.Translate>
- </SubTitle>
- <Input>
- <SelectList
- label={<i18n.Translate>Current Language</i18n.Translate>}
- list={supportedLang}
- name="lang"
- value={lang}
- onChange={(v) => changeLanguage(v)}
- />
- </Input>
- </JustInDevMode>
- <SubTitle>
- <i18n.Translate>Version</i18n.Translate>
- </SubTitle>
- {coreVersion && (
- <Part
- title={i18n.str`Wallet Core`}
- text={
- <span>
- {coreVersion.version}{" "}
- <JustInDevMode>{coreVersion.hash}</JustInDevMode>
- </span>
- }
- />
- )}
<Part
title={i18n.str`Web Extension`}
text={
<span>
{webexVersion.version}{" "}
- <JustInDevMode>{webexVersion.hash}</JustInDevMode>
+ <EnabledBySettings name="advanceMode">
+ {webexVersion.hash}
+ </EnabledBySettings>
</span>
}
/>
{coreVersion && (
- <JustInDevMode>
+ <EnabledBySettings name="advanceMode">
<Part
title={i18n.str`Exchange compatibility`}
text={<span>{coreVersion.exchange}</span>}
@@ -255,18 +235,42 @@ export function SettingsView({
title={i18n.str`Bank compatibility`}
text={<span>{coreVersion.bank}</span>}
/>
- </JustInDevMode>
+ </EnabledBySettings>
)}
<SubTitle>
- <i18n.Translate>Troubleshooting</i18n.Translate>
+ <i18n.Translate>Advance mode</i18n.Translate>
</SubTitle>
<Checkbox
- label={i18n.str`Developer mode`}
+ label={i18n.str`Enable advance mode`}
name="devMode"
- description={i18n.str`More options and information useful for debugging`}
- enabled={devModeToggle.value!}
- onToggle={devModeToggle.button.onClick!}
+ description={i18n.str`Show more information and options in the UI`}
+ enabled={advanceToggle.value!}
+ onToggle={advanceToggle.button.onClick!}
+ />
+ <EnabledBySettings name="advanceMode">
+ <AdvanceSettings />
+ </EnabledBySettings>
+ <Checkbox
+ label={i18n.str`Lang selector`}
+ name="langSelector"
+ description={i18n.str`Allows to manually change the language of the UI. Otherwise it will be automatically selected by your browser configuration.`}
+ enabled={langToggle.value!}
+ onToggle={langToggle.button.onClick!}
/>
+ <EnabledBySettings name="langSelector">
+ <SubTitle>
+ <i18n.Translate>Display</i18n.Translate>
+ </SubTitle>
+ <Input>
+ <SelectList
+ label={<i18n.Translate>Current Language</i18n.Translate>}
+ list={supportedLang}
+ name="lang"
+ value={lang}
+ onChange={(v) => changeLanguage(v)}
+ />
+ </Input>
+ </EnabledBySettings>
<SubTitle>
<i18n.Translate>Navigator</i18n.Translate>
</SubTitle>
@@ -283,6 +287,77 @@ export function SettingsView({
enabled={autoOpenToggle.value!}
onToggle={autoOpenToggle.button.onClick!}
/>
+ <SubTitle>
+ <i18n.Translate>Version</i18n.Translate>
+ </SubTitle>
+ {coreVersion && (
+ <Part
+ title={i18n.str`Wallet Core`}
+ text={
+ <span>
+ {coreVersion.version}{" "}
+ <EnabledBySettings name="advanceMode">
+ {coreVersion.hash}
+ </EnabledBySettings>
+ </span>
+ }
+ />
+ )}
+ </section>
+ </Fragment>
+ );
+}
+
+type Info = { label: TranslatedString; description: TranslatedString };
+type Options = {
+ [k in keyof Settings]?: Info;
+};
+function AdvanceSettings(): VNode {
+ const [settings, updateSettings] = useSettings();
+ const { i18n } = useTranslationContext();
+ const o: Options = {
+ backup: {
+ label: i18n.str`Show backup feature`,
+ description: i18n.str`Backup integration still in beta.`,
+ },
+ deleteActiveTransactions: {
+ label: i18n.str`Show delete active transaction`,
+ description: i18n.str`Deleting active transaction is not safe and you may loose your coins.`,
+ },
+ extendedAccountTypes: {
+ label: i18n.str`Show more account types on deposit`,
+ description: i18n.str`Extends the UI to more payment target types.`,
+ },
+ showJsonOnError: {
+ label: i18n.str`Show JSON on error`,
+ description: i18n.str`Print more information about the error. Useful for debugging.`,
+ },
+ walletAllowHttp: {
+ label: i18n.str`Allow HTTP connections`,
+ description: i18n.str`Using HTTP connection may be faster but unsafe (wallet restart required)`,
+ },
+ walletBatchWithdrawal: {
+ label: i18n.str`Allow batch withdrawals`,
+ description: i18n.str`Using the batch withdrawal API allows faster withdrawals (wallet restart required)`,
+ },
+ };
+ return (
+ <Fragment>
+ <section>
+ {Object.entries(o).map(([name, { label, description }]) => {
+ const settingsName = name as keyof Settings;
+ return (
+ <Checkbox
+ label={label}
+ name={name}
+ description={description}
+ enabled={settings[settingsName]}
+ onToggle={async () => {
+ updateSettings(settingsName, !settings[settingsName]);
+ }}
+ />
+ );
+ })}
</section>
</Fragment>
);
diff --git a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
index 1ef0f0b79..9bcae8997 100644
--- a/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
+++ b/packages/taler-wallet-webextension/src/wallet/Transaction.tsx
@@ -34,6 +34,7 @@ import {
WithdrawalType,
} from "@gnu-taler/taler-util";
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { styled } from "@linaria/react";
import { differenceInSeconds, isPast } from "date-fns";
import { ComponentChildren, Fragment, h, VNode } from "preact";
@@ -43,7 +44,6 @@ import { Amount } from "../components/Amount.js";
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType.js";
import { CopyButton } from "../components/CopyButton.js";
import { AlertView, ErrorAlertView } from "../components/CurrentAlerts.js";
-import { JustInDevMode } from "../components/JustInDevMode.js";
import { Loading } from "../components/Loading.js";
import { Kind, Part, PartCollapsible, PartPayto } from "../components/Part.js";
import { QR } from "../components/QR.js";
@@ -61,12 +61,12 @@ import {
import { Time } from "../components/Time.js";
import { alertFromError, useAlertContext } from "../context/alert.js";
import { useBackendContext } from "../context/backend.js";
-import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { SafeHandler } from "../mui/handlers.js";
import { Pages } from "../NavigationBar.js";
import { assertUnreachable } from "../utils/index.js";
+import { EnabledBySettings } from "../components/EnabledBySettings.js";
interface Props {
tid: string;
@@ -359,18 +359,15 @@ function TransactionTemplate({
<i18n.Translate>Cancel</i18n.Translate>
</Button>
) : (
- //WORKAROUND
- //Able to delete tx in dev mode
- //FIXME: remove this when DD37 is implemented
- <JustInDevMode>
+ <EnabledBySettings name="deleteActiveTransactions">
<Button
variant="contained"
color="error"
onClick={doCheckBeforeForget as SafeHandler<void>}
>
- <i18n.Translate>Forget</i18n.Translate>
+ <i18n.Translate>Delete</i18n.Translate>
</Button>
- </JustInDevMode>
+ </EnabledBySettings>
)
) : (
<Button
@@ -378,7 +375,7 @@ function TransactionTemplate({
color="error"
onClick={doCheckBeforeForget as SafeHandler<void>}
>
- <i18n.Translate>Forget</i18n.Translate>
+ <i18n.Translate>Delete</i18n.Translate>
</Button>
)}
</div>