diff options
Diffstat (limited to 'packages/taler-wallet-webextension')
10 files changed, 127 insertions, 43 deletions
diff --git a/packages/taler-wallet-webextension/src/context/iocContext.ts b/packages/taler-wallet-webextension/src/context/iocContext.ts index b1a9aa128..c7fee0bc0 100644 --- a/packages/taler-wallet-webextension/src/context/iocContext.ts +++ b/packages/taler-wallet-webextension/src/context/iocContext.ts @@ -25,9 +25,11 @@ import { platform } from "../platform/api.js"; interface Type { findTalerUriInActiveTab: () => Promise<string | undefined>; + findTalerUriInClipboard: () => Promise<string | undefined>; } const Context = createContext<Type>({ findTalerUriInActiveTab: async () => undefined, + findTalerUriInClipboard: async () => undefined, }); /** @@ -56,7 +58,10 @@ export const IoCProviderForRuntime = ({ children: any; }): VNode => { return h(Context.Provider, { - value: { findTalerUriInActiveTab: platform.findTalerUriInActiveTab }, + value: { + findTalerUriInActiveTab: platform.findTalerUriInActiveTab, + findTalerUriInClipboard: platform.findTalerUriInClipboard, + }, children, }); }; diff --git a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx index d3d2c68e4..18e593283 100644 --- a/packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx @@ -122,13 +122,13 @@ export function ReadyView({ }} > <i18n.Translate>Exchange</i18n.Translate> - <Link> + {/* <Link> <SvgIcon title="Edit" dangerouslySetInnerHTML={{ __html: editIcon }} color="black" /> - </Link> + </Link> */} </div> } text={<ExchangeDetails exchange={exchangeUrl} />} diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts index 7425dbd29..7bd667268 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/index.ts @@ -85,6 +85,7 @@ export namespace State { ageRestriction?: SelectFieldHandler; + talerWithdrawUri?: string; cancel: () => Promise<void>; }; } diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts index 015c9aaca..0d2e150e7 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/state.ts @@ -410,6 +410,7 @@ export function useComponentStateFromURI( toBeReceived, withdrawalFee, chosenAmount, + talerWithdrawUri, ageRestriction, doWithdrawal: { onClick: diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx index 850bd6e8f..440586343 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx @@ -23,6 +23,7 @@ import { SelectList } from "../../components/SelectList.js"; import { Input, Link, + LinkSuccess, SubTitle, SuccessBox, SvgIcon, @@ -35,6 +36,8 @@ import { TermsOfServiceSection } from "../TermsOfServiceSection.js"; import { State } from "./index.js"; import editIcon from "../../svg/edit_24px.svg"; import { Amount } from "../../components/Amount.js"; +import { QR } from "../../components/QR.js"; +import { useState } from "preact/hooks"; export function LoadingUriView({ error }: State.LoadingUriError): VNode { const { i18n } = useTranslationContext(); @@ -126,13 +129,13 @@ export function SuccessView(state: State.Success): VNode { }} > <i18n.Translate>Exchange</i18n.Translate> - <Link> + {/* <Link> <SvgIcon title="Edit" dangerouslySetInnerHTML={{ __html: editIcon }} color="black" /> - </Link> + </Link> */} </div> } text={<ExchangeDetails exchange={state.exchangeUrl} />} @@ -164,31 +167,36 @@ export function SuccessView(state: State.Success): VNode { </section> {state.tosProps && <TermsOfServiceSection {...state.tosProps} />} {state.tosProps ? ( - <section> - {(state.tosProps.terms.status === "accepted" || - (state.mustAcceptFirst && state.tosProps.reviewed)) && ( - <Button - variant="contained" - color="success" - disabled={!state.doWithdrawal.onClick} - onClick={state.doWithdrawal.onClick} - > - <i18n.Translate> - Withdraw <Amount value={state.toBeReceived} /> - </i18n.Translate> - </Button> - )} - {state.tosProps.terms.status === "notfound" && ( - <Button - variant="contained" - color="warning" - disabled={!state.doWithdrawal.onClick} - onClick={state.doWithdrawal.onClick} - > - <i18n.Translate>Withdraw anyway</i18n.Translate> - </Button> - )} - </section> + <Fragment> + <section> + {(state.tosProps.terms.status === "accepted" || + (state.mustAcceptFirst && state.tosProps.reviewed)) && ( + <Button + variant="contained" + color="success" + disabled={!state.doWithdrawal.onClick} + onClick={state.doWithdrawal.onClick} + > + <i18n.Translate> + Withdraw <Amount value={state.toBeReceived} /> + </i18n.Translate> + </Button> + )} + {state.tosProps.terms.status === "notfound" && ( + <Button + variant="contained" + color="warning" + disabled={!state.doWithdrawal.onClick} + onClick={state.doWithdrawal.onClick} + > + <i18n.Translate>Withdraw anyway</i18n.Translate> + </Button> + )} + </section> + {state.talerWithdrawUri ? ( + <WithdrawWithMobile talerWithdrawUri={state.talerWithdrawUri} /> + ) : undefined} + </Fragment> ) : ( <section> <i18n.Translate>Loading terms of service...</i18n.Translate> @@ -202,3 +210,35 @@ export function SuccessView(state: State.Success): VNode { </WalletAction> ); } + +function WithdrawWithMobile({ + talerWithdrawUri, +}: { + talerWithdrawUri: string; +}): VNode { + const { i18n } = useTranslationContext(); + const [showQR, setShowQR] = useState<boolean>(false); + + return ( + <section> + <LinkSuccess upperCased onClick={() => setShowQR((qr) => !qr)}> + {!showQR ? ( + <i18n.Translate>Withdraw to a mobile phone</i18n.Translate> + ) : ( + <i18n.Translate>Hide QR</i18n.Translate> + )} + </LinkSuccess> + {showQR && ( + <div> + <QR text={talerWithdrawUri} /> + <i18n.Translate> + Scan the QR code or + <a href={talerWithdrawUri}> + <i18n.Translate>click here</i18n.Translate> + </a> + </i18n.Translate> + </div> + )} + </section> + ); +} diff --git a/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts b/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts index 449cb698f..74d7cbbd9 100644 --- a/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts +++ b/packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts @@ -17,20 +17,39 @@ import { useEffect, useState } from "preact/hooks"; import { useIocContext } from "../context/iocContext.js"; +export interface UriLocation { + uri: string; + location: "clipboard" | "activeTab" +} + export function useTalerActionURL(): [ - string | undefined, + UriLocation | undefined, (s: boolean) => void, ] { - const [talerActionUrl, setTalerActionUrl] = useState<string | undefined>( + const [talerActionUrl, setTalerActionUrl] = useState<UriLocation | undefined>( undefined, ); const [dismissed, setDismissed] = useState(false); - const { findTalerUriInActiveTab } = useIocContext(); + const { findTalerUriInActiveTab, findTalerUriInClipboard } = useIocContext(); useEffect(() => { async function check(): Promise<void> { - const talerUri = await findTalerUriInActiveTab(); - setTalerActionUrl(talerUri); + const clipUri = await findTalerUriInClipboard(); + if (clipUri) { + setTalerActionUrl({ + location: "clipboard", + uri: clipUri + }); + return; + } + const tabUri = await findTalerUriInActiveTab(); + if (tabUri) { + setTalerActionUrl({ + location: "activeTab", + uri: tabUri + }); + return; + } } check(); }); diff --git a/packages/taler-wallet-webextension/src/platform/api.ts b/packages/taler-wallet-webextension/src/platform/api.ts index 37f52192f..23fd80ed7 100644 --- a/packages/taler-wallet-webextension/src/platform/api.ts +++ b/packages/taler-wallet-webextension/src/platform/api.ts @@ -163,13 +163,22 @@ export interface PlatformAPI { findTalerUriInActiveTab(): Promise<string | undefined>; /** - * Used from the frontend to send commands to the wallet + * Popup API * - * @param operation - * @param payload + * Read the current tab html and try to find any Taler URI or QR code present. * - * @return response from the backend + * @return Taler URI if found */ + findTalerUriInClipboard(): Promise<string | undefined>; + + /** + * Used from the frontend to send commands to the wallet + * + * @param operation + * @param payload + * + * @return response from the backend + */ sendMessageToWalletBackground( operation: string, payload: any, diff --git a/packages/taler-wallet-webextension/src/platform/chrome.ts b/packages/taler-wallet-webextension/src/platform/chrome.ts index 4ce995bd7..7311354c9 100644 --- a/packages/taler-wallet-webextension/src/platform/chrome.ts +++ b/packages/taler-wallet-webextension/src/platform/chrome.ts @@ -30,6 +30,7 @@ import { const api: PlatformAPI = { isFirefox, findTalerUriInActiveTab, + findTalerUriInClipboard, getPermissionsApi, getWalletWebExVersion, listenToWalletBackground, @@ -689,6 +690,11 @@ async function findTalerUriInTab(tabId: number): Promise<string | undefined> { } } +async function findTalerUriInClipboard(): Promise<string | undefined> { + const textInClipboard = await window.navigator.clipboard.readText(); + return textInClipboard.startsWith("taler://") || textInClipboard.startsWith("taler+http://") ? textInClipboard : undefined +} + async function findTalerUriInActiveTab(): Promise<string | undefined> { const tab = await getCurrentTab(); if (!tab || tab.id === undefined) return; diff --git a/packages/taler-wallet-webextension/src/platform/dev.ts b/packages/taler-wallet-webextension/src/platform/dev.ts index e5db0c8ec..bb7e181c4 100644 --- a/packages/taler-wallet-webextension/src/platform/dev.ts +++ b/packages/taler-wallet-webextension/src/platform/dev.ts @@ -23,6 +23,7 @@ const api: PlatformAPI = { isFirefox: () => false, keepAlive: (cb: VoidFunction) => cb(), findTalerUriInActiveTab: async () => undefined, + findTalerUriInClipboard: async () => undefined, containsTalerHeaderListener: () => { return true; }, diff --git a/packages/taler-wallet-webextension/src/popup/Application.tsx b/packages/taler-wallet-webextension/src/popup/Application.tsx index 2bf09d07e..457f26cfd 100644 --- a/packages/taler-wallet-webextension/src/popup/Application.tsx +++ b/packages/taler-wallet-webextension/src/popup/Application.tsx @@ -42,13 +42,15 @@ import { BalancePage } from "./BalancePage.js"; import { TalerActionFound } from "./TalerActionFound.js"; function CheckTalerActionComponent(): VNode { - const [talerActionUrl] = useTalerActionURL(); + const [action] = useTalerActionURL(); + + const actionUri = action?.uri; useEffect(() => { - if (talerActionUrl) { - route(Pages.cta({ action: encodeURIComponent(talerActionUrl) })); + if (actionUri) { + route(Pages.cta({ action: encodeURIComponent(actionUri) })); } - }, [talerActionUrl]); + }, [actionUri]); return <Fragment />; } |