implement the simplest recovery function
This commit is contained in:
parent
8390c60031
commit
414b1b84e8
@ -110,6 +110,7 @@ export const Pages = {
|
|||||||
|
|
||||||
cta: pageDefinition<{ action: string }>("/cta/:action"),
|
cta: pageDefinition<{ action: string }>("/cta/:action"),
|
||||||
ctaPay: "/cta/pay",
|
ctaPay: "/cta/pay",
|
||||||
|
ctaRecovery: "/cta/recovery",
|
||||||
ctaRefund: "/cta/refund",
|
ctaRefund: "/cta/refund",
|
||||||
ctaTips: "/cta/tip",
|
ctaTips: "/cta/tip",
|
||||||
ctaWithdraw: "/cta/withdraw",
|
ctaWithdraw: "/cta/withdraw",
|
||||||
|
66
packages/taler-wallet-webextension/src/cta/Recovery/index.ts
Normal file
66
packages/taler-wallet-webextension/src/cta/Recovery/index.ts
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2022 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
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/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { AmountJson } from "@gnu-taler/taler-util";
|
||||||
|
import { Loading } from "../../components/Loading.js";
|
||||||
|
import { HookError } from "../../hooks/useAsyncAsHook.js";
|
||||||
|
import { ButtonHandler } from "../../mui/handlers.js";
|
||||||
|
import { compose, StateViewMap } from "../../utils/index.js";
|
||||||
|
import * as wxApi from "../../wxApi.js";
|
||||||
|
import { useComponentState } from "./state.js";
|
||||||
|
import { LoadingUriView, ReadyView } from "./views.js";
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
talerRecoveryUri?: string;
|
||||||
|
onCancel: () => Promise<void>;
|
||||||
|
onSuccess: () => Promise<void>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type State = State.Loading | State.LoadingUriError | State.Ready;
|
||||||
|
|
||||||
|
export namespace State {
|
||||||
|
export interface Loading {
|
||||||
|
status: "loading";
|
||||||
|
error: undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LoadingUriError {
|
||||||
|
status: "loading-uri";
|
||||||
|
error: HookError;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BaseInfo {
|
||||||
|
error: undefined;
|
||||||
|
cancel: ButtonHandler;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Ready extends BaseInfo {
|
||||||
|
status: "ready";
|
||||||
|
accept: ButtonHandler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const viewMapping: StateViewMap<State> = {
|
||||||
|
loading: Loading,
|
||||||
|
"loading-uri": LoadingUriView,
|
||||||
|
ready: ReadyView,
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RecoveryPage = compose(
|
||||||
|
"Recovery",
|
||||||
|
(p: Props) => useComponentState(p, wxApi),
|
||||||
|
viewMapping,
|
||||||
|
);
|
67
packages/taler-wallet-webextension/src/cta/Recovery/state.ts
Normal file
67
packages/taler-wallet-webextension/src/cta/Recovery/state.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2022 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
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/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { parseRecoveryUri } from "@gnu-taler/taler-util";
|
||||||
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
|
import * as wxApi from "../../wxApi.js";
|
||||||
|
import { wxClient } from "../../wxApi.js";
|
||||||
|
import { Props, State } from "./index.js";
|
||||||
|
|
||||||
|
export function useComponentState(
|
||||||
|
{ talerRecoveryUri, onCancel, onSuccess }: Props,
|
||||||
|
api: typeof wxApi,
|
||||||
|
): State {
|
||||||
|
if (!talerRecoveryUri) {
|
||||||
|
return {
|
||||||
|
status: "loading-uri",
|
||||||
|
error: {
|
||||||
|
operational: false,
|
||||||
|
hasError: true,
|
||||||
|
message: "Missing URI",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const info = parseRecoveryUri(talerRecoveryUri);
|
||||||
|
|
||||||
|
if (!info) {
|
||||||
|
return {
|
||||||
|
status: "loading-uri",
|
||||||
|
error: {
|
||||||
|
operational: false,
|
||||||
|
hasError: true,
|
||||||
|
message: "Could not be read",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
const recovery = info;
|
||||||
|
|
||||||
|
async function recoverBackup(): Promise<void> {
|
||||||
|
await wxClient.call(WalletApiOperation.ImportBackupRecovery, { recovery });
|
||||||
|
onSuccess();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
status: "ready",
|
||||||
|
|
||||||
|
accept: {
|
||||||
|
onClick: recoverBackup,
|
||||||
|
},
|
||||||
|
cancel: {
|
||||||
|
onClick: onCancel,
|
||||||
|
},
|
||||||
|
error: undefined,
|
||||||
|
};
|
||||||
|
}
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2022 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
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/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Sebastian Javier Marchano (sebasjm)
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Amounts } from "@gnu-taler/taler-util";
|
||||||
|
import { createExample } from "../../test-utils.js";
|
||||||
|
import { ReadyView } from "./views.js";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "cta/recovery",
|
||||||
|
};
|
21
packages/taler-wallet-webextension/src/cta/Recovery/test.ts
Normal file
21
packages/taler-wallet-webextension/src/cta/Recovery/test.ts
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2022 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
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/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
describe("Backup import CTA states", () => {
|
||||||
|
it.skip("should test something", async () => {
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
This file is part of GNU Taler
|
||||||
|
(C) 2022 Taler Systems S.A.
|
||||||
|
|
||||||
|
GNU Taler is free software; you can redistribute it and/or modify it under the
|
||||||
|
terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 3, or (at your option) any later version.
|
||||||
|
|
||||||
|
GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||||
|
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
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/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Fragment, h, VNode } from "preact";
|
||||||
|
import { LoadingError } from "../../components/LoadingError.js";
|
||||||
|
import { LogoHeader } from "../../components/LogoHeader.js";
|
||||||
|
import { SubTitle, WalletAction } from "../../components/styled/index.js";
|
||||||
|
import { useTranslationContext } from "../../context/translation.js";
|
||||||
|
import { Button } from "../../mui/Button.js";
|
||||||
|
import { State } from "./index.js";
|
||||||
|
|
||||||
|
export function LoadingUriView({ error }: State.LoadingUriError): VNode {
|
||||||
|
const { i18n } = useTranslationContext();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LoadingError
|
||||||
|
title={
|
||||||
|
<i18n.Translate>
|
||||||
|
Could not load backup recovery information
|
||||||
|
</i18n.Translate>
|
||||||
|
}
|
||||||
|
error={error}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ReadyView({ accept, cancel }: State.Ready): VNode {
|
||||||
|
const { i18n } = useTranslationContext();
|
||||||
|
return (
|
||||||
|
<WalletAction>
|
||||||
|
<LogoHeader />
|
||||||
|
|
||||||
|
<SubTitle>
|
||||||
|
<i18n.Translate>Digital wallet recovery</i18n.Translate>
|
||||||
|
</SubTitle>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<p>
|
||||||
|
<i18n.Translate>Import backup, show info</i18n.Translate>
|
||||||
|
</p>
|
||||||
|
<Button variant="contained" onClick={accept.onClick}>
|
||||||
|
Import
|
||||||
|
</Button>
|
||||||
|
<Button variant="contained" onClick={cancel.onClick}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
</section>
|
||||||
|
</WalletAction>
|
||||||
|
);
|
||||||
|
}
|
@ -236,6 +236,11 @@ function openWalletURIFromPopup(talerUri: string): void {
|
|||||||
`static/wallet.html#/cta/withdraw?talerWithdrawUri=${talerUri}`,
|
`static/wallet.html#/cta/withdraw?talerWithdrawUri=${talerUri}`,
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
case TalerUriType.TalerRecovery:
|
||||||
|
url = chrome.runtime.getURL(
|
||||||
|
`static/wallet.html#/cta/recovery?talerRecoveryUri=${talerUri}`,
|
||||||
|
);
|
||||||
|
break;
|
||||||
case TalerUriType.TalerPay:
|
case TalerUriType.TalerPay:
|
||||||
url = chrome.runtime.getURL(
|
url = chrome.runtime.getURL(
|
||||||
`static/wallet.html#/cta/pay?talerPayUri=${talerUri}`,
|
`static/wallet.html#/cta/pay?talerPayUri=${talerUri}`,
|
||||||
|
@ -64,6 +64,7 @@ import { TransferCreatePage } from "../cta/TransferCreate/index.js";
|
|||||||
import { InvoiceCreatePage } from "../cta/InvoiceCreate/index.js";
|
import { InvoiceCreatePage } from "../cta/InvoiceCreate/index.js";
|
||||||
import { TransferPickupPage } from "../cta/TransferPickup/index.js";
|
import { TransferPickupPage } from "../cta/TransferPickup/index.js";
|
||||||
import { InvoicePayPage } from "../cta/InvoicePay/index.js";
|
import { InvoicePayPage } from "../cta/InvoicePay/index.js";
|
||||||
|
import { RecoveryPage } from "../cta/Recovery/index.js";
|
||||||
|
|
||||||
export function Application(): VNode {
|
export function Application(): VNode {
|
||||||
const [globalNotification, setGlobalNotification] = useState<
|
const [globalNotification, setGlobalNotification] = useState<
|
||||||
@ -328,6 +329,12 @@ export function Application(): VNode {
|
|||||||
redirectTo(Pages.balanceTransaction({ tid }))
|
redirectTo(Pages.balanceTransaction({ tid }))
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
|
<Route
|
||||||
|
path={Pages.ctaRecovery}
|
||||||
|
component={RecoveryPage}
|
||||||
|
onCancel={() => redirectTo(Pages.balance)}
|
||||||
|
onSuccess={() => redirectTo(Pages.backup)}
|
||||||
|
/>
|
||||||
|
|
||||||
{/**
|
{/**
|
||||||
* NOT FOUND
|
* NOT FOUND
|
||||||
|
@ -21,7 +21,10 @@
|
|||||||
|
|
||||||
import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
|
import { ProviderPaymentType } from "@gnu-taler/taler-wallet-core";
|
||||||
import { addDays } from "date-fns";
|
import { addDays } from "date-fns";
|
||||||
import { BackupView as TestedComponent } from "./BackupPage.js";
|
import {
|
||||||
|
BackupView as TestedComponent,
|
||||||
|
ShowRecoveryInfo,
|
||||||
|
} from "./BackupPage.js";
|
||||||
import { createExample } from "../test-utils.js";
|
import { createExample } from "../test-utils.js";
|
||||||
import { TalerProtocolTimestamp } from "@gnu-taler/taler-util";
|
import { TalerProtocolTimestamp } from "@gnu-taler/taler-util";
|
||||||
|
|
||||||
@ -194,3 +197,7 @@ export const OneProvider = createExample(TestedComponent, {
|
|||||||
export const Empty = createExample(TestedComponent, {
|
export const Empty = createExample(TestedComponent, {
|
||||||
providers: [],
|
providers: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const Recovery = createExample(ShowRecoveryInfo, {
|
||||||
|
info: "taler://recovery/ASLDKJASLKDJASD",
|
||||||
|
});
|
||||||
|
@ -14,12 +14,17 @@
|
|||||||
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 { AbsoluteTime } from "@gnu-taler/taler-util";
|
import {
|
||||||
|
AbsoluteTime,
|
||||||
|
BackupRecovery,
|
||||||
|
constructRecoveryUri,
|
||||||
|
} from "@gnu-taler/taler-util";
|
||||||
import {
|
import {
|
||||||
ProviderInfo,
|
ProviderInfo,
|
||||||
ProviderPaymentPaid,
|
ProviderPaymentPaid,
|
||||||
ProviderPaymentStatus,
|
ProviderPaymentStatus,
|
||||||
ProviderPaymentType,
|
ProviderPaymentType,
|
||||||
|
WalletApiOperation,
|
||||||
} from "@gnu-taler/taler-wallet-core";
|
} from "@gnu-taler/taler-wallet-core";
|
||||||
import {
|
import {
|
||||||
differenceInMonths,
|
differenceInMonths,
|
||||||
@ -37,20 +42,78 @@ import {
|
|||||||
RowBorderGray,
|
RowBorderGray,
|
||||||
SmallLightText,
|
SmallLightText,
|
||||||
SmallText,
|
SmallText,
|
||||||
|
WarningBox,
|
||||||
} from "../components/styled/index.js";
|
} from "../components/styled/index.js";
|
||||||
import { useTranslationContext } from "../context/translation.js";
|
import { useTranslationContext } from "../context/translation.js";
|
||||||
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
|
||||||
import { Button } from "../mui/Button.js";
|
import { Button } from "../mui/Button.js";
|
||||||
import { Pages } from "../NavigationBar.js";
|
import { Pages } from "../NavigationBar.js";
|
||||||
import * as wxApi from "../wxApi.js";
|
import * as wxApi from "../wxApi.js";
|
||||||
|
import { wxClient } from "../wxApi.js";
|
||||||
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
import { QR } from "../components/QR.js";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
onAddProvider: () => Promise<void>;
|
onAddProvider: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function ShowRecoveryInfo({
|
||||||
|
info,
|
||||||
|
onClose,
|
||||||
|
}: {
|
||||||
|
info: string;
|
||||||
|
onClose: () => Promise<void>;
|
||||||
|
}): VNode {
|
||||||
|
const [display, setDisplay] = useState(false);
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
async function copyText(): Promise<void> {
|
||||||
|
navigator.clipboard.writeText(info);
|
||||||
|
setCopied(true);
|
||||||
|
}
|
||||||
|
useEffect(() => {
|
||||||
|
if (copied) {
|
||||||
|
setTimeout(() => {
|
||||||
|
setCopied(false);
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
}, [copied]);
|
||||||
|
return (
|
||||||
|
<Fragment>
|
||||||
|
<h2>Wallet Recovery</h2>
|
||||||
|
<WarningBox>Do not share this QR or URI with anyone</WarningBox>
|
||||||
|
<section>
|
||||||
|
<p>
|
||||||
|
The qr code can be scanned by another wallet to keep synchronized with
|
||||||
|
this wallet.
|
||||||
|
</p>
|
||||||
|
<Button variant="contained" onClick={async () => setDisplay((d) => !d)}>
|
||||||
|
{display ? "Hide" : "Show"} QR code
|
||||||
|
</Button>
|
||||||
|
{display && <QR text={JSON.stringify(info)} />}
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<p>You can also use the string version</p>
|
||||||
|
<Button variant="contained" disabled={copied} onClick={copyText}>
|
||||||
|
Copy recovery URI
|
||||||
|
</Button>
|
||||||
|
</section>
|
||||||
|
<footer>
|
||||||
|
<div></div>
|
||||||
|
<div>
|
||||||
|
<Button variant="contained" onClick={onClose}>
|
||||||
|
Close
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</Fragment>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function BackupPage({ onAddProvider }: Props): VNode {
|
export function BackupPage({ onAddProvider }: Props): VNode {
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
const status = useAsyncAsHook(wxApi.getBackupInfo);
|
const status = useAsyncAsHook(wxApi.getBackupInfo);
|
||||||
|
const [recoveryInfo, setRecoveryInfo] = useState<string>("");
|
||||||
if (!status) {
|
if (!status) {
|
||||||
return <Loading />;
|
return <Loading />;
|
||||||
}
|
}
|
||||||
@ -63,6 +126,12 @@ export function BackupPage({ onAddProvider }: Props): VNode {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function getRecoveryInfo(): Promise<void> {
|
||||||
|
const r = await wxClient.call(WalletApiOperation.ExportBackupRecovery, {});
|
||||||
|
const str = constructRecoveryUri(r);
|
||||||
|
setRecoveryInfo(str);
|
||||||
|
}
|
||||||
|
|
||||||
const providers = status.response.providers.sort((a, b) => {
|
const providers = status.response.providers.sort((a, b) => {
|
||||||
if (
|
if (
|
||||||
a.paymentStatus.type === ProviderPaymentType.Paid &&
|
a.paymentStatus.type === ProviderPaymentType.Paid &&
|
||||||
@ -75,11 +144,21 @@ export function BackupPage({ onAddProvider }: Props): VNode {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (recoveryInfo) {
|
||||||
|
return (
|
||||||
|
<ShowRecoveryInfo
|
||||||
|
info={recoveryInfo}
|
||||||
|
onClose={async () => setRecoveryInfo("")}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<BackupView
|
<BackupView
|
||||||
providers={providers}
|
providers={providers}
|
||||||
onAddProvider={onAddProvider}
|
onAddProvider={onAddProvider}
|
||||||
onSyncAll={wxApi.syncAllProviders}
|
onSyncAll={wxApi.syncAllProviders}
|
||||||
|
onShowInfo={getRecoveryInfo}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -88,12 +167,14 @@ export interface ViewProps {
|
|||||||
providers: ProviderInfo[];
|
providers: ProviderInfo[];
|
||||||
onAddProvider: () => Promise<void>;
|
onAddProvider: () => Promise<void>;
|
||||||
onSyncAll: () => Promise<void>;
|
onSyncAll: () => Promise<void>;
|
||||||
|
onShowInfo: () => Promise<void>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BackupView({
|
export function BackupView({
|
||||||
providers,
|
providers,
|
||||||
onAddProvider,
|
onAddProvider,
|
||||||
onSyncAll,
|
onSyncAll,
|
||||||
|
onShowInfo,
|
||||||
}: ViewProps): VNode {
|
}: ViewProps): VNode {
|
||||||
const { i18n } = useTranslationContext();
|
const { i18n } = useTranslationContext();
|
||||||
return (
|
return (
|
||||||
@ -128,7 +209,11 @@ export function BackupView({
|
|||||||
</section>
|
</section>
|
||||||
{!!providers.length && (
|
{!!providers.length && (
|
||||||
<footer>
|
<footer>
|
||||||
<div />
|
<div>
|
||||||
|
<Button variant="contained" onClick={onShowInfo}>
|
||||||
|
Show recovery
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<Button variant="contained" onClick={onSyncAll}>
|
<Button variant="contained" onClick={onSyncAll}>
|
||||||
{providers.length > 1 ? (
|
{providers.length > 1 ? (
|
||||||
|
@ -19,6 +19,7 @@ import {
|
|||||||
BackupBackupProviderTerms,
|
BackupBackupProviderTerms,
|
||||||
canonicalizeBaseUrl,
|
canonicalizeBaseUrl,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
|
||||||
import { Fragment, h, VNode } from "preact";
|
import { Fragment, h, VNode } from "preact";
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { Checkbox } from "../components/Checkbox.js";
|
import { Checkbox } from "../components/Checkbox.js";
|
||||||
@ -34,6 +35,7 @@ import { useTranslationContext } from "../context/translation.js";
|
|||||||
import { Button } from "../mui/Button.js";
|
import { Button } from "../mui/Button.js";
|
||||||
import { queryToSlashConfig } from "../utils/index.js";
|
import { queryToSlashConfig } from "../utils/index.js";
|
||||||
import * as wxApi from "../wxApi.js";
|
import * as wxApi from "../wxApi.js";
|
||||||
|
import { wxClient } from "../wxApi.js";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
currency: string;
|
currency: string;
|
||||||
@ -69,8 +71,12 @@ export function ProviderAddPage({ onBack }: Props): VNode {
|
|||||||
setVerifying(undefined);
|
setVerifying(undefined);
|
||||||
}}
|
}}
|
||||||
onConfirm={() => {
|
onConfirm={() => {
|
||||||
return wxApi
|
return wxClient
|
||||||
.addBackupProvider(verifying.url, verifying.name)
|
.call(WalletApiOperation.AddBackupProvider, {
|
||||||
|
backupProviderBaseUrl: verifying.url,
|
||||||
|
name: verifying.name,
|
||||||
|
activate: true,
|
||||||
|
})
|
||||||
.then(onBack);
|
.then(onBack);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -167,7 +167,7 @@ export class WxWalletCoreApiClient implements WalletCoreApiClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const wxClient = new WxWalletCoreApiClient();
|
export const wxClient = new WxWalletCoreApiClient();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pay for a proposal.
|
* Pay for a proposal.
|
||||||
|
@ -290,6 +290,11 @@ function parseTalerUriAndRedirect(tabId: number, talerUri: string): void {
|
|||||||
tabId,
|
tabId,
|
||||||
`/cta/transfer/pickup?talerPayPushUri=${talerUri}`,
|
`/cta/transfer/pickup?talerPayPushUri=${talerUri}`,
|
||||||
);
|
);
|
||||||
|
case TalerUriType.TalerRecovery:
|
||||||
|
return platform.redirectTabToWalletPage(
|
||||||
|
tabId,
|
||||||
|
`/cta/transfer/recovery?talerBackupUri=${talerUri}`,
|
||||||
|
);
|
||||||
case TalerUriType.TalerNotifyReserve:
|
case TalerUriType.TalerNotifyReserve:
|
||||||
// FIXME: Is this still useful?
|
// FIXME: Is this still useful?
|
||||||
// handleNotifyReserve(w);
|
// handleNotifyReserve(w);
|
||||||
|
Loading…
Reference in New Issue
Block a user