From 2779086a32a62d6d16b7813c2ca4944dc02c4d93 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 26 Jun 2023 14:23:32 -0300 Subject: support for exchange-withdraw call to action, pending use case when the user need to specify the amount --- .../src/NavigationBar.tsx | 9 +++++-- .../src/cta/Withdraw/index.ts | 21 ++++++++++----- .../src/cta/Withdraw/state.ts | 31 ++++++++++++++++++++-- .../src/cta/Withdraw/views.tsx | 9 +++++++ .../src/platform/chrome.ts | 1 + .../src/popup/TalerActionFound.tsx | 1 + .../src/wallet/Application.tsx | 9 ++++++- .../src/wallet/Settings.tsx | 11 +++----- 8 files changed, 74 insertions(+), 18 deletions(-) diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index dd2d31c3d..231418861 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -84,7 +84,7 @@ function pageDefinition(pattern: string): PageLocation { return { ...prev, [name]: cur }; }, {} as Record); - const f = (values: T): string => replaceAll(pattern, vars, values); + const f = (values: T): string => replaceAll(pattern, vars, values ?? {}); f.pattern = pattern; return f; } @@ -152,6 +152,7 @@ const talerUriActionToPageName: { [TalerUriAction.PayPush]: "ctaTransferPickup", [TalerUriAction.Restore]: "ctaRecovery", [TalerUriAction.PayTemplate]: "ctaPayTemplate", + [TalerUriAction.WithdrawExchange]: "ctaWithdrawManual", [TalerUriAction.DevExperiment]: undefined, [TalerUriAction.Exchange]: undefined, [TalerUriAction.Auditor]: undefined, @@ -166,7 +167,11 @@ export function getPathnameForTalerURI(talerUri: string): string | undefined { if (!pageName) { return undefined; } - return `${Pages[pageName]}?talerUri=${encodeURIComponent(talerUri)}`; + const pageString: string = + typeof Pages[pageName] === "function" + ? (Pages[pageName] as any)() + : Pages[pageName]; + return `${pageString}?talerUri=${encodeURIComponent(talerUri)}`; } export type PopupNavBarOptions = "balance" | "backup" | "dev"; diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts index 45c37ba5c..ae4b3c436 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts @@ -16,20 +16,19 @@ import { AmountJson, ExchangeListItem } from "@gnu-taler/taler-util"; import { Loading } from "../../components/Loading.js"; -import { HookError } from "../../hooks/useAsyncAsHook.js"; import { State as SelectExchangeState } from "../../hooks/useSelectedExchange.js"; import { ButtonHandler, SelectFieldHandler } from "../../mui/handlers.js"; -import { compose, StateViewMap } from "../../utils/index.js"; +import { StateViewMap, compose } from "../../utils/index.js"; import { useComponentStateFromParams, useComponentStateFromURI, } from "./state.js"; +import { ErrorAlertView } from "../../components/CurrentAlerts.js"; +import { ErrorAlert } from "../../context/alert.js"; import { ExchangeSelectionPage } from "../../wallet/ExchangeSelection/index.js"; import { NoExchangesView } from "../../wallet/ExchangeSelection/views.js"; -import { SuccessView } from "./views.js"; -import { ErrorAlert } from "../../context/alert.js"; -import { ErrorAlertView } from "../../components/CurrentAlerts.js"; +import { SelectAmountView, SuccessView } from "./views.js"; export interface PropsFromURI { talerWithdrawUri: string | undefined; @@ -38,6 +37,7 @@ export interface PropsFromURI { } export interface PropsFromParams { + talerExchangeWithdrawUri: string; amount: string; cancel: () => Promise; onSuccess: (txid: string) => Promise; @@ -48,6 +48,7 @@ export type State = | State.LoadingUriError | SelectExchangeState.NoExchangeFound | SelectExchangeState.Selecting + | State.SelectAmount | State.Success; export namespace State { @@ -60,6 +61,13 @@ export namespace State { error: ErrorAlert; } + export interface SelectAmount { + status: "select-amount"; + error: undefined; + currentExchange: ExchangeListItem; + currency: string; + } + export type Success = { status: "success"; error: undefined; @@ -84,13 +92,14 @@ export namespace State { const viewMapping: StateViewMap = { loading: Loading, error: ErrorAlertView, + "select-amount": SelectAmountView, "no-exchange-found": NoExchangesView, "selecting-exchange": ExchangeSelectionPage, success: SuccessView, }; export const WithdrawPageFromURI = compose( - "WithdrawPageFromURI", + "WithdrawPageFromURI_Withdraw", (p: PropsFromURI) => useComponentStateFromURI(p), viewMapping, ); diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts index 717d3ba6b..f19f32ec0 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts @@ -18,9 +18,12 @@ import { AmountJson, Amounts, + ExchangeFullDetails, ExchangeListItem, ExchangeTosStatus, TalerError, + parseWithdrawExchangeUri, + stringifyWithdrawUri, } from "@gnu-taler/taler-util"; import { WalletApiOperation } from "@gnu-taler/taler-wallet-core"; import { useState } from "preact/hooks"; @@ -33,6 +36,7 @@ import { RecursiveState } from "../../utils/index.js"; import { PropsFromParams, PropsFromURI, State } from "./index.js"; export function useComponentStateFromParams({ + talerExchangeWithdrawUri: maybeTalerUri, amount, cancel, onSuccess, @@ -44,7 +48,29 @@ export function useComponentStateFromParams({ WalletApiOperation.ListExchanges, {}, ); - return { amount: Amounts.parseOrThrow(amount), exchanges }; + const uri = parseWithdrawExchangeUri(maybeTalerUri); + const exchangeByTalerUri = uri?.exchangeBaseUrl; + let ex: ExchangeFullDetails | undefined; + if (exchangeByTalerUri && uri.exchangePub) { + await api.wallet.call(WalletApiOperation.AddExchange, { + exchangeBaseUrl: exchangeByTalerUri, + masterPub: uri.exchangePub, + }); + const info = await api.wallet.call( + WalletApiOperation.GetExchangeDetailedInfo, + { + exchangeBaseUrl: exchangeByTalerUri, + }, + ); + + ex = info.exchange; + } + const chosenAmount = uri + ? uri.amount + ? Amounts.parseOrThrow(uri.amount) + : Amounts.parseOrThrow(`${ex ? ex.currency : "KUDOS"}:66`) + : Amounts.parseOrThrow(amount); + return { amount: chosenAmount, exchanges, exchange: ex }; }); if (!uriInfoHook) return { status: "loading", error: undefined }; @@ -60,6 +86,7 @@ export function useComponentStateFromParams({ } const chosenAmount = uriInfoHook.response.amount; + const exchangeByTalerUri = uriInfoHook.response.exchange?.exchangeBaseUrl; const exchangeList = uriInfoHook.response.exchanges.exchanges; async function doManualWithdraw( @@ -92,7 +119,7 @@ export function useComponentStateFromParams({ undefined, chosenAmount, exchangeList, - undefined, + exchangeByTalerUri, ); } diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx index 50bf99a0c..57d6238b2 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx @@ -142,3 +142,12 @@ function WithdrawWithMobile({ ); } + +export function SelectAmountView({ currency }: State.SelectAmount): VNode { + const { i18n } = useTranslationContext(); + return ( + +

select the amount for ${currency}

+
+ ); +} diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts index 34057a310..65670fb69 100644 --- a/packages/taler-wallet-webextension/src/platform/chrome.ts +++ b/packages/taler-wallet-webextension/src/platform/chrome.ts @@ -259,6 +259,7 @@ function openWalletURIFromPopup(uri: TalerUri): void { encodeURIComponent; let url: string | undefined = undefined; switch (uri.type) { + case TalerUriAction.WithdrawExchange: case TalerUriAction.Withdraw: url = chrome.runtime.getURL( `static/wallet.html#/cta/withdraw?talerUri=${encodeURIComponent( diff --git a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx index af966a5ae..6a0585907 100644 --- a/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx +++ b/packages/taler-wallet-webextension/src/popup/TalerActionFound.tsx @@ -40,6 +40,7 @@ function ContentByUriType({ }) { const { i18n } = useTranslationContext(); switch (uri.type) { + case TalerUriAction.WithdrawExchange: case TalerUriAction.Withdraw: return (
diff --git a/packages/taler-wallet-webextension/src/wallet/Application.tsx b/packages/taler-wallet-webextension/src/wallet/Application.tsx index 13afccb6c..7d4dafb56 100644 --- a/packages/taler-wallet-webextension/src/wallet/Application.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Application.tsx @@ -391,9 +391,16 @@ export function Application(): VNode { /> ( + component={({ + amount, + talerUri, + }: { + amount: string; + talerUri: string; + }) => ( redirectTo(Pages.balance)} onSuccess={(tid: string) => diff --git a/packages/taler-wallet-webextension/src/wallet/Settings.tsx b/packages/taler-wallet-webextension/src/wallet/Settings.tsx index 6ca443d10..10bcee314 100644 --- a/packages/taler-wallet-webextension/src/wallet/Settings.tsx +++ b/packages/taler-wallet-webextension/src/wallet/Settings.tsx @@ -250,13 +250,6 @@ export function SettingsView({ - Display @@ -340,6 +333,10 @@ function AdvanceSettings(): VNode { label: i18n.str`Allow batch withdrawals`, description: i18n.str`Using the batch withdrawal API allows faster withdrawals (wallet restart required)`, }, + langSelector: { + label: i18n.str`Lang selector`, + description: i18n.str`Allows to manually change the language of the UI. Otherwise it will be automatically selected by your browser configuration.`, + }, }; return ( -- cgit v1.2.3