From 0b4976601fe2ecb0462fe72ae188b5cbba06d9cc Mon Sep 17 00:00:00 2001 From: Sebastian Date: Wed, 16 Jun 2021 18:21:03 -0300 Subject: components renaming to follow react pattern --- .../taler-wallet-webextension/src/popup/popup.tsx | 899 +-------------------- 1 file changed, 2 insertions(+), 897 deletions(-) (limited to 'packages/taler-wallet-webextension/src/popup/popup.tsx') diff --git a/packages/taler-wallet-webextension/src/popup/popup.tsx b/packages/taler-wallet-webextension/src/popup/popup.tsx index 0f76d7728..95b87fad0 100644 --- a/packages/taler-wallet-webextension/src/popup/popup.tsx +++ b/packages/taler-wallet-webextension/src/popup/popup.tsx @@ -25,29 +25,9 @@ * Imports. */ import { - AmountJson, - Amounts, - BalancesResponse, - Balance, - classifyTalerUri, - TalerUriType, - TransactionsResponse, - Transaction, - TransactionType, - AmountString, - Timestamp, - amountFractionalBase, - i18n, + classifyTalerUri, i18n, TalerUriType } from "@gnu-taler/taler-util"; -import { format } from "date-fns"; -import { Component, ComponentChildren, Fragment, JSX } from "preact"; -import { route } from 'preact-router'; -import { useEffect, useState } from "preact/hooks"; -import { Diagnostics } from "../components/Diagnostics"; -import { PermissionsCheckbox } from "../components/PermissionsCheckbox"; -import { useExtendedPermissions } from "../hooks/useExtendedPermissions"; -import { PageLink, renderAmount } from "../renderHtml"; -import * as wxApi from "../wxApi"; +import { ComponentChildren, JSX } from "preact"; export enum Pages { balance = '/balance', @@ -86,878 +66,3 @@ export function WalletNavBar({ current }: { current?: string }) { ); } -/** - * Render an amount as a large number with a small currency symbol. - */ -function bigAmount(amount: AmountJson): JSX.Element { - const v = amount.value + amount.fraction / amountFractionalBase; - return ( - - {v}{" "} - {amount.currency} - - ); -} - -function EmptyBalanceView(): JSX.Element { - return ( -

- You have no balance to show. Need some{" "} - help getting started? -

- ); -} - -export class WalletBalanceView extends Component { - private balance?: BalancesResponse; - private gotError = false; - private canceler: (() => void) | undefined = undefined; - private unmount = false; - private updateBalanceRunning = false; - - componentWillMount(): void { - this.canceler = wxApi.onUpdateNotification(() => this.updateBalance()); - this.updateBalance(); - } - - componentWillUnmount(): void { - console.log("component WalletBalanceView will unmount"); - if (this.canceler) { - this.canceler(); - } - this.unmount = true; - } - - async updateBalance(): Promise { - if (this.updateBalanceRunning) { - return; - } - this.updateBalanceRunning = true; - let balance: BalancesResponse; - try { - balance = await wxApi.getBalance(); - } catch (e) { - if (this.unmount) { - return; - } - this.gotError = true; - console.error("could not retrieve balances", e); - this.setState({}); - return; - } finally { - this.updateBalanceRunning = false; - } - if (this.unmount) { - return; - } - this.gotError = false; - console.log("got balance", balance); - this.balance = balance; - this.setState({}); - } - - formatPending(entry: Balance): JSX.Element { - let incoming: JSX.Element | undefined; - let payment: JSX.Element | undefined; - - const available = Amounts.parseOrThrow(entry.available); - const pendingIncoming = Amounts.parseOrThrow(entry.pendingIncoming); - const pendingOutgoing = Amounts.parseOrThrow(entry.pendingOutgoing); - - console.log( - "available: ", - entry.pendingIncoming ? renderAmount(entry.available) : null, - ); - console.log( - "incoming: ", - entry.pendingIncoming ? renderAmount(entry.pendingIncoming) : null, - ); - - if (!Amounts.isZero(pendingIncoming)) { - incoming = ( - - - {"+"} - {renderAmount(entry.pendingIncoming)} - {" "} - incoming - - ); - } - - const l = [incoming, payment].filter((x) => x !== undefined); - if (l.length === 0) { - return ; - } - - if (l.length === 1) { - return ({l}); - } - return ( - - ({l[0]}, {l[1]}) - - ); - } - - render(): JSX.Element { - const wallet = this.balance; - if (this.gotError) { - return ( -
-

{i18n.str`Error: could not retrieve balance information.`}

-

- Click here for help and - diagnostics. -

-
- ); - } - if (!wallet) { - return ; - } - console.log(wallet); - const listing = wallet.balances.map((entry) => { - const av = Amounts.parseOrThrow(entry.available); - return ( -

- {bigAmount(av)} {this.formatPending(entry)} -

- ); - }); - return listing.length > 0 ? ( -
{listing}
- ) : ( - - ); - } -} - -interface TransactionAmountProps { - debitCreditIndicator: "debit" | "credit" | "unknown"; - amount: AmountString | "unknown"; - pending: boolean; -} - -function TransactionAmount(props: TransactionAmountProps): JSX.Element { - const [currency, amount] = props.amount.split(":"); - let sign: string; - switch (props.debitCreditIndicator) { - case "credit": - sign = "+"; - break; - case "debit": - sign = "-"; - break; - case "unknown": - sign = ""; - } - const style: JSX.AllCSSProperties = { - marginLeft: "auto", - display: "flex", - flexDirection: "column", - alignItems: "center", - alignSelf: "center" - }; - if (props.pending) { - style.color = "gray"; - } - return ( -
-
- {sign} - {amount} -
-
{currency}
-
- ); -} - -interface TransactionLayoutProps { - debitCreditIndicator: "debit" | "credit" | "unknown"; - amount: AmountString | "unknown"; - timestamp: Timestamp; - title: string; - id: string; - subtitle: string; - iconPath: string; - pending: boolean; -} - -function TransactionLayout(props: TransactionLayoutProps): JSX.Element { - const date = new Date(props.timestamp.t_ms); - const dateStr = date.toLocaleString([], { - dateStyle: "medium", - timeStyle: "short", - } as any); - return ( -
- -
-
{dateStr}
-
- {props.title} - {props.pending ? ( - (Pending) - ) : null} -
- -
{props.subtitle}
-
- -
- ); -} - -function TransactionItem(props: { tx: Transaction }): JSX.Element { - const tx = props.tx; - switch (tx.type) { - case TransactionType.Withdrawal: - return ( - - ); - case TransactionType.Payment: - return ( - - ); - case TransactionType.Refund: - return ( - - ); - case TransactionType.Tip: - return ( - - ); - case TransactionType.Refresh: - return ( - - ); - case TransactionType.Deposit: - return ( - - ); - } -} - -export function WalletHistory(props: any): JSX.Element { - const [transactions, setTransactions] = useState< - TransactionsResponse | undefined - >(undefined); - - useEffect(() => { - const fetchData = async (): Promise => { - const res = await wxApi.getTransactions(); - setTransactions(res); - }; - fetchData(); - }, []); - - if (!transactions) { - return
Loading ...
; - } - - const txs = [...transactions.transactions].reverse(); - - return ( -
- {txs.map((tx, i) => ( - - ))} -
- ); -} - -interface WalletTransactionProps { - transaction?: Transaction, - onDelete: () => void, - onBack: () => void, -} - -export function WalletTransactionView({ transaction, onDelete, onBack }: WalletTransactionProps) { - if (!transaction) { - return
Loading ...
; - } - - function Footer() { - return
- -
- - -
- -
- } - - function Pending() { - if (!transaction?.pending) return null - return (pending...) - } - - if (transaction.type === TransactionType.Withdrawal) { - return ( -
-
-

Withdrawal

-

- From {transaction.exchangeBaseUrl} -

- - - - - - - - - - - - - - - - - -
Amount subtracted{transaction.amountRaw}
Amount received{transaction.amountEffective}
Exchange fee{Amounts.stringify( - Amounts.sub( - Amounts.parseOrThrow(transaction.amountRaw), - Amounts.parseOrThrow(transaction.amountEffective), - ).amount - )}
When{transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}
-
-
-
- ); - } - - if (transaction.type === TransactionType.Payment) { - return ( -
-
-

Payment ({transaction.proposalId.substring(0, 10)}...)

-

- To {transaction.info.merchant.name} -

- - - - - - - - - - {transaction.info.products && transaction.info.products.length > 0 && - - - - - } - - - - - - - - - - - - - - - - -
Order id{transaction.info.orderId}
Summary{transaction.info.summary}
Products
    - {transaction.info.products.map(p => -
  1. {p.description}
  2. - )}
Order amount{transaction.amountRaw}
Order amount and fees{transaction.amountEffective}
Exchange fee{Amounts.stringify( - Amounts.sub( - Amounts.parseOrThrow(transaction.amountEffective), - Amounts.parseOrThrow(transaction.amountRaw), - ).amount - )}
When{transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}
-
-
-
- ); - } - - if (transaction.type === TransactionType.Deposit) { - return ( -
-
-

Deposit ({transaction.depositGroupId})

-

- To {transaction.targetPaytoUri} -

- - - - - - - - - - - - - - - - - -
Amount deposit{transaction.amountRaw}
Amount deposit and fees{transaction.amountEffective}
Exchange fee{Amounts.stringify( - Amounts.sub( - Amounts.parseOrThrow(transaction.amountEffective), - Amounts.parseOrThrow(transaction.amountRaw), - ).amount - )}
When{transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}
-
-
-
- ); - } - - if (transaction.type === TransactionType.Refresh) { - return ( -
-
-

Refresh

-

- From {transaction.exchangeBaseUrl} -

- - - - - - - - - - - - - -
Amount refreshed{transaction.amountRaw}
Fees{transaction.amountEffective}
When{transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}
-
-
-
- ); - } - - if (transaction.type === TransactionType.Tip) { - return ( -
-
-

Tip

-

- From {transaction.merchantBaseUrl} -

- - - - - - - - - - - - - - - - - -
Amount deduce{transaction.amountRaw}
Amount received{transaction.amountEffective}
Exchange fee{Amounts.stringify( - Amounts.sub( - Amounts.parseOrThrow(transaction.amountRaw), - Amounts.parseOrThrow(transaction.amountEffective), - ).amount - )}
When{transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}
-
-
-
- ); - } - - const TRANSACTION_FROM_REFUND = /[a-z]*:([\w]{10}).*/ - if (transaction.type === TransactionType.Refund) { - return ( -
-
-

Refund ({TRANSACTION_FROM_REFUND.exec(transaction.refundedTransactionId)![1]}...)

-

- From {transaction.info.merchant.name} -

- - - - - - - - - - {transaction.info.products && transaction.info.products.length > 0 && - - - - - } - - - - - - - - - - - - - - - - -
Order id{transaction.info.orderId}
Summary{transaction.info.summary}
Products
    - {transaction.info.products.map(p => -
  1. {p.description}
  2. - )}
Amount deduce{transaction.amountRaw}
Amount received{transaction.amountEffective}
Exchange fee{Amounts.stringify( - Amounts.sub( - Amounts.parseOrThrow(transaction.amountRaw), - Amounts.parseOrThrow(transaction.amountEffective), - ).amount - )}
When{transaction.timestamp.t_ms === "never" ? "never" : format(transaction.timestamp.t_ms, 'dd/MM/yyyy HH:mm:ss')}
-
-
-
- ); - } - - - return
-} - -export function WalletTransaction({ tid }: { tid: string }): JSX.Element { - const [transaction, setTransaction] = useState< - Transaction | undefined - >(undefined); - - useEffect(() => { - const fetchData = async (): Promise => { - const res = await wxApi.getTransactions(); - const ts = res.transactions.filter(t => t.transactionId === tid) - if (ts.length === 1) { - setTransaction(ts[0]); - } else { - route(Pages.history) - } - }; - fetchData(); - }, []); - - return wxApi.deleteTransaction(tid).then(_ => history.go(-1))} - onBack={() => { history.go(-1) }} - /> -} - -export function WalletSettings() { - const [permissionsEnabled, togglePermissions] = useExtendedPermissions() - return ( -
-

Permissions

- - {/* -

Developer mode

- - */} -
- ); -} - - -export function DebugCheckbox({ enabled, onToggle }: { enabled: boolean, onToggle: () => void }): JSX.Element { - return ( -
- - - - (Enabling this option below will make using the wallet faster, but - requires more permissions from your browser.) - -
- ); -} - -function reload(): void { - try { - chrome.runtime.reload(); - window.close(); - } catch (e) { - // Functionality missing in firefox, ignore! - } -} - -async function confirmReset(): Promise { - if ( - confirm( - "Do you want to IRREVOCABLY DESTROY everything inside your" + - " wallet and LOSE ALL YOUR COINS?", - ) - ) { - await wxApi.resetDb(); - window.close(); - } -} - -export function WalletDebug(props: any): JSX.Element { - return ( -
-

Debug tools:

- -
- - - -
- ); -} - -function openExtensionPage(page: string) { - return () => { - chrome.tabs.create({ - url: chrome.extension.getURL(page), - }); - }; -} - -// function openTab(page: string) { -// return (evt: React.SyntheticEvent) => { -// evt.preventDefault(); -// chrome.tabs.create({ -// url: page, -// }); -// }; -// } - -function makeExtensionUrlWithParams( - url: string, - params?: { [name: string]: string | undefined }, -): string { - const innerUrl = new URL(chrome.extension.getURL("/" + url)); - if (params) { - for (const key in params) { - const p = params[key]; - if (p) { - innerUrl.searchParams.set(key, p); - } - } - } - return innerUrl.href; -} - -export function actionForTalerUri(talerUri: string): string | undefined { - const uriType = classifyTalerUri(talerUri); - switch (uriType) { - case TalerUriType.TalerWithdraw: - return makeExtensionUrlWithParams("static/wallet.html#/withdraw", { - talerWithdrawUri: talerUri, - }); - case TalerUriType.TalerPay: - return makeExtensionUrlWithParams("static/wallet.html#/pay", { - talerPayUri: talerUri, - }); - case TalerUriType.TalerTip: - return makeExtensionUrlWithParams("static/wallet.html#/tip", { - talerTipUri: talerUri, - }); - case TalerUriType.TalerRefund: - return makeExtensionUrlWithParams("static/wallet.html#/refund", { - talerRefundUri: talerUri, - }); - case TalerUriType.TalerNotifyReserve: - // FIXME: implement - break; - default: - console.warn( - "Response with HTTP 402 has Taler header, but header value is not a taler:// URI.", - ); - break; - } - return undefined; -} - -export async function findTalerUriInActiveTab(): Promise { - return new Promise((resolve, reject) => { - chrome.tabs.executeScript( - { - code: ` - (() => { - let x = document.querySelector("a[href^='taler://'") || document.querySelector("a[href^='taler+http://'"); - return x ? x.href.toString() : null; - })(); - `, - allFrames: false, - }, - (result) => { - if (chrome.runtime.lastError) { - console.error(chrome.runtime.lastError); - resolve(undefined); - return; - } - console.log("got result", result); - resolve(result[0]); - }, - ); - }); -} - -// export function WalletPopup(): JSX.Element { -// const [talerActionUrl, setTalerActionUrl] = useState( -// undefined, -// ); -// const [dismissed, setDismissed] = useState(false); -// useEffect(() => { -// async function check(): Promise { -// const talerUri = await findTalerUriInActiveTab(); -// if (talerUri) { -// const actionUrl = actionForTalerUri(talerUri); -// setTalerActionUrl(actionUrl); -// } -// } -// check(); -// }, []); -// if (talerActionUrl && !dismissed) { -// return ( -//
-//

Taler Action

-//

This page has a Taler action.

-//

-// -//

-//

-// -//

-//
-// ); -// } -// return ( -//
-// {({ path }: any) => } -//
-// -// -// -// -// -// -// -//
-//
-// ); -// } - -- cgit v1.2.3