find taler action in clipboard and withdraw with mobile
This commit is contained in:
parent
9b2d6d766f
commit
dda90b51f6
@ -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,
|
||||
});
|
||||
};
|
||||
|
@ -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} />}
|
||||
|
@ -85,6 +85,7 @@ export namespace State {
|
||||
|
||||
ageRestriction?: SelectFieldHandler;
|
||||
|
||||
talerWithdrawUri?: string;
|
||||
cancel: () => Promise<void>;
|
||||
};
|
||||
}
|
||||
|
@ -410,6 +410,7 @@ export function useComponentStateFromURI(
|
||||
toBeReceived,
|
||||
withdrawalFee,
|
||||
chosenAmount,
|
||||
talerWithdrawUri,
|
||||
ageRestriction,
|
||||
doWithdrawal: {
|
||||
onClick:
|
||||
|
@ -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>
|
||||
);
|
||||
}
|
||||
|
@ -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();
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -23,6 +23,7 @@ const api: PlatformAPI = {
|
||||
isFirefox: () => false,
|
||||
keepAlive: (cb: VoidFunction) => cb(),
|
||||
findTalerUriInActiveTab: async () => undefined,
|
||||
findTalerUriInClipboard: async () => undefined,
|
||||
containsTalerHeaderListener: () => {
|
||||
return true;
|
||||
},
|
||||
|
@ -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 />;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user