This commit is contained in:
Sebastian 2023-05-02 09:56:44 -03:00
parent 23fca6d867
commit a957e61a9c
No known key found for this signature in database
GPG Key ID: 173909D1A5F66069
7 changed files with 73 additions and 75 deletions

View File

@ -14,7 +14,11 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/ */
import { CoreApiResponse, NotificationType } from "@gnu-taler/taler-util"; import {
CoreApiResponse,
NotificationType,
TalerUri,
} from "@gnu-taler/taler-util";
import { import {
WalletConfig, WalletConfig,
WalletConfigParameter, WalletConfigParameter,
@ -229,7 +233,7 @@ export interface ForegroundPlatformAPI {
* *
* @param talerUri * @param talerUri
*/ */
openWalletURIFromPopup(talerUri: string): void; openWalletURIFromPopup(talerUri: TalerUri): void;
/** /**
* Popup API * Popup API

View File

@ -20,6 +20,8 @@ import {
TalerUriAction, TalerUriAction,
TalerError, TalerError,
parseTalerUri, parseTalerUri,
TalerUri,
stringifyTalerUri,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { WalletOperations } from "@gnu-taler/taler-wallet-core"; import { WalletOperations } from "@gnu-taler/taler-wallet-core";
import { BackgroundOperations } from "../wxApi.js"; import { BackgroundOperations } from "../wxApi.js";
@ -247,17 +249,8 @@ function notifyWhenAppIsReady(): Promise<void> {
}); });
} }
function openWalletURIFromPopup(maybeTalerUri: string): void { function openWalletURIFromPopup(uri: TalerUri): void {
const talerUri = maybeTalerUri.startsWith("ext+") const talerUri = stringifyTalerUri(uri);
? maybeTalerUri.substring(4)
: maybeTalerUri;
const uri = parseTalerUri(talerUri);
if (!uri) {
logger.warn(
`Response with HTTP 402 the Taler header but could not classify ${talerUri}`,
);
return;
}
//FIXME: this should redirect to just one place //FIXME: this should redirect to just one place
// the target pathname should handle what happens if the endpoint is not there // the target pathname should handle what happens if the endpoint is not there
// like "trying to open from popup but this uri is not handled" // like "trying to open from popup but this uri is not handled"
@ -335,7 +328,7 @@ function openWalletURIFromPopup(maybeTalerUri: string): void {
} }
} }
chrome.tabs.create({ active: true, url }, () => { chrome.tabs.update({ active: true, url }, () => {
window.close(); window.close();
}); });
} }

View File

@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/ */
import { CoreApiResponse } from "@gnu-taler/taler-util"; import { CoreApiResponse, TalerUri } from "@gnu-taler/taler-util";
import { WalletOperations } from "@gnu-taler/taler-wallet-core"; import { WalletOperations } from "@gnu-taler/taler-wallet-core";
import { BackgroundOperations } from "../wxApi.js"; import { BackgroundOperations } from "../wxApi.js";
import { import {
@ -73,7 +73,7 @@ const api: BackgroundPlatformAPI & ForegroundPlatformAPI = {
window.parent.frames["wallet" as any].location = `/wallet.html#${page}`; window.parent.frames["wallet" as any].location = `/wallet.html#${page}`;
window.location.href = "about:blank"; window.location.href = "about:blank";
}, },
openWalletURIFromPopup: (page: string) => { openWalletURIFromPopup: (page: TalerUri) => {
alert("openWalletURIFromPopup not implemented yet"); alert("openWalletURIFromPopup not implemented yet");
}, },
redirectTabToWalletPage: (tabId: number, page: string) => { redirectTabToWalletPage: (tabId: number, page: string) => {

View File

@ -19,10 +19,10 @@
* @author Sebastian Javier Marchano (sebasjm) * @author Sebastian Javier Marchano (sebasjm)
*/ */
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util"; import { parseTalerUri, TalerUri, TalerUriAction } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact"; import { Fragment, h, VNode } from "preact";
import { Title } from "../components/styled/index.js"; import { Title } from "../components/styled/index.js";
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Button } from "../mui/Button.js"; import { Button } from "../mui/Button.js";
import { platform } from "../platform/foreground.js"; import { platform } from "../platform/foreground.js";
@ -32,15 +32,15 @@ export interface Props {
} }
function ContentByUriType({ function ContentByUriType({
type, uri,
onConfirm, onConfirm,
}: { }: {
type: TalerUriType; uri: TalerUri;
onConfirm: () => Promise<void>; onConfirm: () => Promise<void>;
}) { }) {
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
switch (type) { switch (uri.type) {
case TalerUriType.TalerWithdraw: case TalerUriAction.Withdraw:
return ( return (
<div> <div>
<p> <p>
@ -52,8 +52,8 @@ function ContentByUriType({
</div> </div>
); );
case TalerUriType.TalerPayTemplate: case TalerUriAction.PayTemplate:
case TalerUriType.TalerPay: case TalerUriAction.Pay:
return ( return (
<div> <div>
<p> <p>
@ -64,7 +64,7 @@ function ContentByUriType({
</Button> </Button>
</div> </div>
); );
case TalerUriType.TalerTip: case TalerUriAction.Tip:
return ( return (
<div> <div>
<p> <p>
@ -76,7 +76,7 @@ function ContentByUriType({
</div> </div>
); );
case TalerUriType.TalerRefund: case TalerUriAction.Refund:
return ( return (
<div> <div>
<p> <p>
@ -88,34 +88,25 @@ function ContentByUriType({
</div> </div>
); );
case TalerUriType.TalerDevExperiment: case TalerUriAction.DevExperiment:
case TalerUriType.TalerTemplate: case TalerUriAction.PayPull:
case TalerUriType.TalerPayPull: case TalerUriAction.PayPush:
case TalerUriType.TalerPayPush: case TalerUriAction.Restore:
case TalerUriType.TalerRecovery: case TalerUriAction.Auditor:
case TalerUriType.Unknown: case TalerUriAction.Exchange:
return ( return null;
<div>
<p>
<i18n.Translate>
This page has a malformed taler uri.
</i18n.Translate>
</p>
</div>
);
default: { default: {
const error: never = type; const error: never = uri;
return null; return null;
} }
} }
} }
export function TalerActionFound({ url, onDismiss }: Props): VNode { export function TalerActionFound({ url, onDismiss }: Props): VNode {
const uriType = classifyTalerUri(url); const talerUri = parseTalerUri(url);
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
async function redirectToWallet(): Promise<void> { async function redirectToWallet(): Promise<void> {
platform.openWalletURIFromPopup(url); platform.openWalletURIFromPopup(talerUri!);
} }
return ( return (
<Fragment> <Fragment>
@ -123,7 +114,17 @@ export function TalerActionFound({ url, onDismiss }: Props): VNode {
<Title> <Title>
<i18n.Translate>Taler Action</i18n.Translate> <i18n.Translate>Taler Action</i18n.Translate>
</Title> </Title>
<ContentByUriType type={uriType} onConfirm={redirectToWallet} /> {!talerUri ? (
<div>
<p>
<i18n.Translate>
This page has a malformed taler uri.
</i18n.Translate>
</p>
</div>
) : (
<ContentByUriType uri={talerUri} onConfirm={redirectToWallet} />
)}
</section> </section>
<footer> <footer>
<div /> <div />

View File

@ -13,13 +13,13 @@
You should have received a copy of the GNU General Public License along with You should have received a copy of the GNU General Public License along with
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/ */
import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util"; import { parseTalerUri, TalerUriAction } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Fragment, h, VNode } from "preact"; import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks"; import { useState } from "preact/hooks";
import { platform } from "../platform/foreground.js";
import { InputWithLabel } from "../components/styled/index.js"; import { InputWithLabel } from "../components/styled/index.js";
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { Button } from "../mui/Button.js"; import { Button } from "../mui/Button.js";
import { platform } from "../platform/foreground.js";
export interface Props { export interface Props {
onCancel: () => Promise<void>; onCancel: () => Promise<void>;
@ -27,19 +27,17 @@ export interface Props {
export function AddNewActionView({ onCancel }: Props): VNode { export function AddNewActionView({ onCancel }: Props): VNode {
const [url, setUrl] = useState(""); const [url, setUrl] = useState("");
const uriType = classifyTalerUri(url); const uri = parseTalerUri(url);
const { i18n } = useTranslationContext(); const { i18n } = useTranslationContext();
async function redirectToWallet(): Promise<void> { async function redirectToWallet(): Promise<void> {
platform.openWalletURIFromPopup(url); platform.openWalletURIFromPopup(uri!);
} }
return ( return (
<Fragment> <Fragment>
<section> <section>
<InputWithLabel <InputWithLabel invalid={url !== "" && !uri}>
invalid={url !== "" && uriType === TalerUriType.Unknown}
>
<label>GNU Taler URI</label> <label>GNU Taler URI</label>
<div> <div>
<input <input
@ -56,21 +54,21 @@ export function AddNewActionView({ onCancel }: Props): VNode {
<Button variant="contained" color="secondary" onClick={onCancel}> <Button variant="contained" color="secondary" onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate> <i18n.Translate>Cancel</i18n.Translate>
</Button> </Button>
{uriType !== TalerUriType.Unknown && ( {uri && (
<Button <Button
variant="contained" variant="contained"
color="success" color="success"
onClick={redirectToWallet} onClick={redirectToWallet}
> >
{(() => { {(() => {
switch (uriType) { switch (uri.type) {
case TalerUriType.TalerPay: case TalerUriAction.Pay:
return <i18n.Translate>Open pay page</i18n.Translate>; return <i18n.Translate>Open pay page</i18n.Translate>;
case TalerUriType.TalerRefund: case TalerUriAction.Refund:
return <i18n.Translate>Open refund page</i18n.Translate>; return <i18n.Translate>Open refund page</i18n.Translate>;
case TalerUriType.TalerTip: case TalerUriAction.Tip:
return <i18n.Translate>Open tip page</i18n.Translate>; return <i18n.Translate>Open tip page</i18n.Translate>;
case TalerUriType.TalerWithdraw: case TalerUriAction.Withdraw:
return <i18n.Translate>Open withdraw page</i18n.Translate>; return <i18n.Translate>Open withdraw page</i18n.Translate>;
} }
return <Fragment />; return <Fragment />;

View File

@ -20,7 +20,7 @@
* @author sebasjm * @author sebasjm
*/ */
import { TranslatedString } from "@gnu-taler/taler-util"; import { TalerUri, TranslatedString } from "@gnu-taler/taler-util";
import { import {
TranslationProvider, TranslationProvider,
useTranslationContext, useTranslationContext,
@ -102,7 +102,7 @@ export function Application(): VNode {
component={() => ( component={() => (
<WalletTemplate goToTransaction={redirectToTxInfo}> <WalletTemplate goToTransaction={redirectToTxInfo}>
<QrReaderPage <QrReaderPage
onDetected={(talerActionUrl: string) => { onDetected={(talerActionUrl: TalerUri) => {
platform.openWalletURIFromPopup(talerActionUrl); platform.openWalletURIFromPopup(talerActionUrl);
}} }}
/> />

View File

@ -15,22 +15,21 @@
*/ */
import { import {
classifyTalerUri, parseTalerUri,
TalerUriType, TalerUri,
TranslatedString, TranslatedString,
} from "@gnu-taler/taler-util"; } from "@gnu-taler/taler-util";
import { styled } from "@linaria/react";
import { css } from "@linaria/core";
import { Fragment, h, VNode } from "preact";
import { Ref, useEffect, useMemo, useRef, useState } from "preact/hooks";
import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser"; import { useTranslationContext } from "@gnu-taler/web-util/lib/index.browser";
import { css } from "@linaria/core";
import { styled } from "@linaria/react";
import jsQR, * as pr from "jsqr";
import { Fragment, h, VNode } from "preact";
import { useRef, useState } from "preact/hooks";
import { Alert } from "../mui/Alert.js"; import { Alert } from "../mui/Alert.js";
import { Button } from "../mui/Button.js"; import { Button } from "../mui/Button.js";
import { TextField } from "../mui/TextField.js";
import jsQR, * as pr from "jsqr";
import { InputFile } from "../mui/InputFile.js";
import { Grid } from "../mui/Grid.js"; import { Grid } from "../mui/Grid.js";
import { notDeepEqual } from "assert"; import { InputFile } from "../mui/InputFile.js";
import { TextField } from "../mui/TextField.js";
const QrCanvas = css` const QrCanvas = css`
width: 80%; width: 80%;
@ -51,7 +50,7 @@ const Container = styled.div`
`; `;
export interface Props { export interface Props {
onDetected: (url: string) => void; onDetected: (url: TalerUri) => void;
} }
type XY = { x: number; y: number }; type XY = { x: number; y: number };
@ -214,7 +213,7 @@ export function QrReaderPage({ onDetected }: Props): VNode {
function onChange(str: string) { function onChange(str: string) {
if (!!str) { if (!!str) {
if (classifyTalerUri(str) === TalerUriType.Unknown) { if (!parseTalerUri(str)) {
setError( setError(
i18n.str`URI is not valid. Taler URI should start with "taler://"`, i18n.str`URI is not valid. Taler URI should start with "taler://"`,
); );
@ -318,7 +317,10 @@ export function QrReaderPage({ onDetected }: Props): VNode {
disabled={!!error} disabled={!!error}
variant="contained" variant="contained"
color="success" color="success"
onClick={async () => onDetected(value)} onClick={async () => {
const uri = parseTalerUri(value);
if (uri) onDetected(uri);
}}
> >
<i18n.Translate>Open</i18n.Translate> <i18n.Translate>Open</i18n.Translate>
</Button> </Button>