/* 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 */ /** * Main entry point for extension pages. * * @author sebasjm */ import { Amounts, TalerUri, TalerUriAction, TranslatedString, parseTalerUri, stringifyTalerUri, } from "@gnu-taler/taler-util"; import { TranslationProvider, useTranslationContext, } from "@gnu-taler/web-util/browser"; import { createHashHistory } from "history"; import { ComponentChildren, Fragment, VNode, h } from "preact"; import { Route, Router, route } from "preact-router"; import { useEffect } from "preact/hooks"; import { Pages, WalletNavBar, WalletNavBarOptions, getPathnameForTalerURI, } from "../NavigationBar.js"; import { AlertView, CurrentAlerts } from "../components/CurrentAlerts.js"; import { LogoHeader } from "../components/LogoHeader.js"; import PendingTransactions from "../components/PendingTransactions.js"; import { LinkPrimary, RedBanner, SubTitle, WalletAction, WalletBox, } from "../components/styled/index.js"; import { AlertProvider } from "../context/alert.js"; import { IoCProviderForRuntime } from "../context/iocContext.js"; import { DepositPage as DepositPageCTA } from "../cta/Deposit/index.js"; import { InvoiceCreatePage } from "../cta/InvoiceCreate/index.js"; import { InvoicePayPage } from "../cta/InvoicePay/index.js"; import { PaymentPage } from "../cta/Payment/index.js"; import { PaymentTemplatePage } from "../cta/PaymentTemplate/index.js"; import { RecoveryPage } from "../cta/Recovery/index.js"; import { RefundPage } from "../cta/Refund/index.js"; import { TransferCreatePage } from "../cta/TransferCreate/index.js"; import { TransferPickupPage } from "../cta/TransferPickup/index.js"; import { WithdrawPageFromParams, WithdrawPageFromURI, } from "../cta/Withdraw/index.js"; import { useIsOnline } from "../hooks/useIsOnline.js"; import { strings } from "../i18n/strings.js"; import CloseIcon from "../svg/close_24px.inline.svg"; import { AddBackupProviderPage } from "./AddBackupProvider/index.js"; import { AddExchange } from "./AddExchange/index.js"; import { BackupPage } from "./BackupPage.js"; import { DepositPage } from "./DepositPage/index.js"; import { DestinationSelectionPage } from "./DestinationSelection/index.js"; import { DeveloperPage } from "./DeveloperPage.js"; import { HistoryPage } from "./History.js"; import { NotificationsPage } from "./Notifications/index.js"; import { ProviderDetailPage } from "./ProviderDetailPage.js"; import { QrReaderPage } from "./QrReader.js"; import { SettingsPage } from "./Settings.js"; import { TransactionPage } from "./Transaction.js"; import { WelcomePage } from "./Welcome.js"; import { WalletActivity } from "../components/WalletActivity.js"; import { EnabledBySettings } from "../components/EnabledBySettings.js"; import { DevExperimentPage } from "../cta/DevExperiment/index.js"; import { ConfirmAddExchangeView } from "./AddExchange/views.js"; export function Application(): VNode { const { i18n } = useTranslationContext(); const hash_history = createHashHistory(); async function redirectToTxInfo(tid: string): Promise { redirectTo(Pages.balanceTransaction({ tid })); } function redirectToURL(str: string): void { window.location.href = new URL(str).href } return ( ( )} /> ( { redirectTo( Pages.defaultCta({ uri: stringifyTalerUri(talerActionUrl), }), ); }} /> )} /> ( )} /> ( )} /> {/** * SETTINGS */} ( redirectTo(Pages.balance)} /> )} /> ( redirectTo(Pages.sendCash({ amount: `${currency}:0` })) } goToWalletManualWithdraw={(currency?: string) => redirectTo( Pages.receiveCash({ amount: !currency ? undefined : `${currency}:0`, }), ) } /> )} /> ( redirectTo(Pages.sendCash({ amount: `${currency}:0` })) } goToWalletManualWithdraw={(currency?: string) => redirectTo( Pages.receiveCash({ amount: !currency ? undefined : `${currency}:0`, }), ) } /> )} /> ( redirectTo(Pages.balanceDeposit({ amount })) } goToWalletWalletSend={(amount: string) => redirectTo(Pages.ctaTransferCreate({ amount })) } /> )} /> ( redirectTo(Pages.ctaWithdrawManual({ amount })) } goToWalletWalletInvoice={(amount?: string) => redirectTo(Pages.ctaInvoiceCreate({ amount })) } /> )} /> ( redirectTo(Pages.balanceHistory({ currency })) } /> )} /> ( { redirectTo(Pages.balanceHistory({ currency })); }} onSuccess={(currency: string) => { redirectTo(Pages.balanceHistory({ currency })); }} /> )} /> ( redirectTo(Pages.backupProviderAdd)} /> )} /> ( redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`) } onWithdraw={(amount: string) => redirectTo(Pages.receiveCash({ amount })) } onBack={() => redirectTo(Pages.backup)} /> )} /> ( redirectTo(`${Pages.ctaPay}?talerPayUri=${uri}`) } onComplete={(pid: string) => redirectTo(Pages.backupProviderDetail({ pid })) } onBack={() => redirectTo(Pages.backup)} /> )} /> {/** * DEV */} ( )} /> {/** * CALL TO ACTION */} { const path = getPathnameForTalerURI(uri); if (!path) { return ( ); } return ; }} /> ( redirectTo(Pages.receiveCash({ amount })) } cancel={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.receiveCash({ amount })) } cancel={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( { const page = `${Pages.ctaWithdrawManual({ amount: newamount })}?talerUri=${encodeURIComponent(talerUri)}`; redirectTo(page); }} talerExchangeWithdrawUri={talerUri} amount={amount} cancel={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.receiveCash({ amount })) } onClose={() => redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.balance)} onSuccess={(tid: string) => redirectTo(Pages.balanceTransaction({ tid })) } /> )} /> ( redirectTo(Pages.balance)} onSuccess={() => redirectTo(Pages.backup)} /> )} /> ( redirectTo(Pages.balanceHistory({}))} onSuccess={() => redirectTo(Pages.balanceHistory({}))} /> )} /> { const tUri = parseTalerUri(decodeURIComponent(talerUri)) const baseUrl = tUri?.type === TalerUriAction.AddExchange ? tUri.exchangeBaseUrl : undefined if (!baseUrl) { redirectTo(Pages.balanceHistory({})) return invalid url {talerUri} } return redirectTo(Pages.balanceHistory({}))} onConfirm={() => redirectTo(Pages.balanceHistory({}))} /> }} /> {/** * NOT FOUND * all redirects should be at the end */} } /> } /> ); } async function redirectTo(location: string): Promise { route(location); } function Redirect({ to }: { to: string }): null { useEffect(() => { route(to, true); }); return null; } // function matchesRoute(url: string, route: string): boolean { // type MatcherFunc = ( // url: string, // route: string, // opts: any, // ) => Record | false; // const internalPreactMatcher: MatcherFunc = (Router as any).exec; // const result = internalPreactMatcher(url, route, {}); // return !result ? false : true; // } function CallToActionTemplate({ title, children, }: { title: TranslatedString; children: ComponentChildren; }): VNode { const { i18n } = useTranslationContext(); return ( {title} {children} Return to wallet ); } function WalletTemplate({ path, children, goToTransaction, goToURL, }: { path?: WalletNavBarOptions; children: ComponentChildren; goToTransaction?: (id: string) => Promise; goToURL: (url: string) => void; }): VNode { const online = useIsOnline(); const { i18n } = useTranslationContext(); return ( {!online && ( {i18n.str`Network is offline`} )} {children} ); }