aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-webextension')
-rw-r--r--packages/taler-wallet-webextension/src/context/iocContext.ts7
-rw-r--r--packages/taler-wallet-webextension/src/cta/InvoiceCreate/views.tsx4
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw/index.ts1
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw/state.ts1
-rw-r--r--packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx94
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useTalerActionURL.ts29
-rw-r--r--packages/taler-wallet-webextension/src/platform/api.ts17
-rw-r--r--packages/taler-wallet-webextension/src/platform/chrome.ts6
-rw-r--r--packages/taler-wallet-webextension/src/platform/dev.ts1
-rw-r--r--packages/taler-wallet-webextension/src/popup/Application.tsx10
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 &nbsp; <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 &nbsp; <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 &nbsp;
+ <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 />;
}