aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian <sebasjm@gmail.com>2021-07-14 15:21:40 -0300
committerSebastian <sebasjm@gmail.com>2021-07-14 15:21:40 -0300
commit18c5371d659222155b27883b2531576af0f86d54 (patch)
tree457f2ae32f5146256dd0b912cf054ead57694e29
parentc34c7d37cb0327ff7d8b5c3d25e2928f3023d30c (diff)
balance refactor
-rw-r--r--packages/taler-wallet-webextension/src/components/styled/index.tsx1
-rw-r--r--packages/taler-wallet-webextension/src/hooks/useBalances.tsx52
-rw-r--r--packages/taler-wallet-webextension/src/popup/BackupPage.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/popup/Balance.stories.tsx114
-rw-r--r--packages/taler-wallet-webextension/src/popup/Balance.tsx173
-rw-r--r--packages/taler-wallet-webextension/src/popup/BalancePage.tsx118
-rw-r--r--packages/taler-wallet-webextension/src/popupEntryPoint.tsx2
7 files changed, 287 insertions, 175 deletions
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index 7d8118392..ebca5893e 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -238,3 +238,4 @@ export const ErrorBox = styled.div`
}
}
`
+
diff --git a/packages/taler-wallet-webextension/src/hooks/useBalances.tsx b/packages/taler-wallet-webextension/src/hooks/useBalances.tsx
new file mode 100644
index 000000000..f12fca21c
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/hooks/useBalances.tsx
@@ -0,0 +1,52 @@
+/*
+ This file is part of TALER
+ (C) 2016 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import { BalancesResponse } from "@gnu-taler/taler-util";
+import { useEffect, useState } from "preact/hooks";
+import * as wxApi from "../wxApi";
+
+
+interface BalancesHookOk {
+ error: false;
+ response: BalancesResponse;
+}
+
+interface BalancesHookError {
+ error: true;
+}
+
+export type BalancesHook = BalancesHookOk | BalancesHookError | undefined;
+
+export function useBalances(): BalancesHook {
+ const [balance, setBalance] = useState<BalancesHook>(undefined);
+ console.log('render balance')
+ useEffect(() => {
+ async function checkBalance() {
+ try {
+ const response = await wxApi.getBalance();
+ console.log("got balance", balance);
+ setBalance({ error: false, response });
+ } catch (e) {
+ console.error("could not retrieve balances", e);
+ setBalance({ error: true });
+ }
+ }
+ checkBalance()
+ return wxApi.onUpdateNotification(checkBalance);
+ }, []);
+
+ return balance;
+}
diff --git a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
index 9428922d5..768a64a14 100644
--- a/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
+++ b/packages/taler-wallet-webextension/src/popup/BackupPage.tsx
@@ -18,7 +18,7 @@
import { i18n, Timestamp } from "@gnu-taler/taler-util";
import { ProviderInfo, ProviderPaymentStatus } from "@gnu-taler/taler-wallet-core";
import { differenceInMonths, formatDuration, intervalToDuration } from "date-fns";
-import { FunctionalComponent, Fragment, JSX, VNode, AnyComponent } from "preact";
+import { Fragment, JSX, VNode } from "preact";
import {
BoldLight, ButtonPrimary, ButtonSuccess, Centered,
CenteredText, CenteredTextBold, PopupBox, RowBorderGray,
diff --git a/packages/taler-wallet-webextension/src/popup/Balance.stories.tsx b/packages/taler-wallet-webextension/src/popup/Balance.stories.tsx
new file mode 100644
index 000000000..b661ac679
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/popup/Balance.stories.tsx
@@ -0,0 +1,114 @@
+/*
+ This file is part of GNU Taler
+ (C) 2021 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 { ProviderPaymentType } from '@gnu-taler/taler-wallet-core';
+import { addDays } from 'date-fns';
+import { ComponentChild, ComponentChildren, FunctionalComponent, h } from 'preact';
+import { BalanceView as TestedComponent } from './BalancePage';
+
+export default {
+ title: 'popup/balance/detail',
+ component: TestedComponent,
+ argTypes: {
+ }
+};
+
+
+function createExample<Props>(Component: FunctionalComponent<Props>, props: Partial<Props>) {
+ const r = (args: any) => <Component {...args} />
+ r.args = props
+ return r
+}
+
+export const NotYetLoaded = createExample(TestedComponent, {
+});
+
+const NullLink = ({ children }: { children?: ComponentChildren }) => h('a', { children, href: 'javascript:void(0);' })
+export const GotError = createExample(TestedComponent, {
+ balance: {
+ error: true
+ },
+ Linker: NullLink,
+});
+
+export const EmptyBalance = createExample(TestedComponent, {
+ balance: {
+ error: false,
+ response: {
+ balances: []
+ },
+ },
+ Linker: NullLink,
+});
+
+export const SomeCoins = createExample(TestedComponent, {
+ balance: {
+ error: false,
+ response: {
+ balances: [{
+ available: 'USD:10.5',
+ hasPendingTransactions: false,
+ pendingIncoming: 'USD:0',
+ pendingOutgoing: 'USD:0',
+ requiresUserInput: false
+ }]
+ },
+ },
+ Linker: NullLink,
+});
+
+export const SomeCoinsAndIncomingMoney = createExample(TestedComponent, {
+ balance: {
+ error: false,
+ response: {
+ balances: [{
+ available: 'USD:2.23',
+ hasPendingTransactions: false,
+ pendingIncoming: 'USD:5.11',
+ pendingOutgoing: 'USD:0',
+ requiresUserInput: false
+ }]
+ },
+ },
+ Linker: NullLink,
+});
+
+export const SomeCoinsInTwoCurrencies = createExample(TestedComponent, {
+ balance: {
+ error: false,
+ response: {
+ balances: [{
+ available: 'USD:2',
+ hasPendingTransactions: false,
+ pendingIncoming: 'USD:5',
+ pendingOutgoing: 'USD:0',
+ requiresUserInput: false
+ },{
+ available: 'EUR:4',
+ hasPendingTransactions: false,
+ pendingIncoming: 'EUR:5',
+ pendingOutgoing: 'EUR:0',
+ requiresUserInput: false
+ }]
+ },
+ },
+ Linker: NullLink,
+});
diff --git a/packages/taler-wallet-webextension/src/popup/Balance.tsx b/packages/taler-wallet-webextension/src/popup/Balance.tsx
deleted file mode 100644
index ae0eb07ff..000000000
--- a/packages/taler-wallet-webextension/src/popup/Balance.tsx
+++ /dev/null
@@ -1,173 +0,0 @@
-/*
- This file is part of TALER
- (C) 2016 GNUnet e.V.
-
- 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.
-
- 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
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
- */
-
-import {
- Amounts,
- BalancesResponse,
- Balance, i18n, AmountJson, amountFractionalBase
-} from "@gnu-taler/taler-util";
-import { Component, JSX } from "preact";
-import { PageLink, renderAmount } from "../renderHtml";
-import * as wxApi from "../wxApi";
-
-
-/**
- * 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 (
- <span>
- <span style={{ fontSize: "5em", display: "block" }}>{v}</span>{" "}
- <span>{amount.currency}</span>
- </span>
- );
-}
-
-function EmptyBalanceView(): JSX.Element {
- return (
- <p><i18n.Translate>
- You have no balance to show. Need some{" "}
- <PageLink pageName="/welcome">help</PageLink> getting started?
- </i18n.Translate></p>
- );
-}
-
-
-export class BalancePage extends Component<any, any> {
- 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<void> {
- 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 = (
- <span><i18n.Translate>
- <span style={{ color: "darkgreen" }}>
- {"+"}
- {renderAmount(entry.pendingIncoming)}
- </span>{" "}
- incoming
- </i18n.Translate></span>
- );
- }
-
- const l = [incoming, payment].filter((x) => x !== undefined);
- if (l.length === 0) {
- return <span />;
- }
-
- if (l.length === 1) {
- return <span>({l})</span>;
- }
- return (
- <span>
- ({l[0]}, {l[1]})
- </span>
- );
- }
-
- render(): JSX.Element {
- const wallet = this.balance;
- if (this.gotError) {
- return (
- <div class="balance">
- <p>{i18n.str`Error: could not retrieve balance information.`}</p>
- <p>
- Click <PageLink pageName="welcome.html">here</PageLink> for help and
- diagnostics.
- </p>
- </div>
- );
- }
- if (!wallet) {
- return <span></span>;
- }
-
- const listing = wallet.balances.map((entry) => {
- const av = Amounts.parseOrThrow(entry.available);
- return (
- <p key={av.currency}>
- {bigAmount(av)} {this.formatPending(entry)}
- </p>
- );
- });
- return listing.length > 0 ? (
- <div class="balance">{listing}</div>
- ) : (
- <EmptyBalanceView />
- );
- }
-}
diff --git a/packages/taler-wallet-webextension/src/popup/BalancePage.tsx b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
new file mode 100644
index 000000000..24744d3f2
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/popup/BalancePage.tsx
@@ -0,0 +1,118 @@
+/*
+ This file is part of TALER
+ (C) 2016 GNUnet e.V.
+
+ 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.
+
+ 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
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import {
+ amountFractionalBase, Amounts,
+
+ Balance, BalancesResponse,
+ i18n
+} from "@gnu-taler/taler-util";
+import { JSX } from "preact";
+import { PopupBox, Centered } from "../components/styled/index";
+import { BalancesHook, useBalances } from "../hooks/useBalances";
+import { PageLink, renderAmount } from "../renderHtml";
+
+
+export function BalancePage() {
+ const balance = useBalances()
+ return <BalanceView balance={balance} Linker={PageLink} />
+}
+export interface BalanceViewProps {
+ balance: BalancesHook,
+ Linker: typeof PageLink,
+}
+export function BalanceView({ balance, Linker }: BalanceViewProps) {
+ if (!balance) {
+ return <span />
+ }
+
+ if (balance.error) {
+ return (
+ <div class="balance">
+ <p>{i18n.str`Error: could not retrieve balance information.`}</p>
+ <p>
+ Click <Linker pageName="welcome.html">here</Linker> for help and
+ diagnostics.
+ </p>
+ </div>
+ )
+ }
+ if (balance.response.balances.length === 0) {
+ return (
+ <p><i18n.Translate>
+ You have no balance to show. Need some{" "}
+ <Linker pageName="/welcome">help</Linker> getting started?
+ </i18n.Translate></p>
+ )
+ }
+ return <ShowBalances wallet={balance.response} />
+}
+
+function 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);
+
+ if (!Amounts.isZero(pendingIncoming)) {
+ incoming = (
+ <span><i18n.Translate>
+ <span style={{ color: "darkgreen" }}>
+ {"+"}
+ {renderAmount(entry.pendingIncoming)}
+ </span>{" "}
+ incoming
+ </i18n.Translate></span>
+ );
+ }
+
+ const l = [incoming, payment].filter((x) => x !== undefined);
+ if (l.length === 0) {
+ return <span />;
+ }
+
+ if (l.length === 1) {
+ return <span>({l})</span>;
+ }
+ return (
+ <span>
+ ({l[0]}, {l[1]})
+ </span>
+ );
+}
+
+
+function ShowBalances({ wallet }: { wallet: BalancesResponse }) {
+ return <PopupBox>
+ <section>
+ <Centered>{wallet.balances.map((entry) => {
+ const av = Amounts.parseOrThrow(entry.available);
+ const v = av.value + av.fraction / amountFractionalBase;
+ return (
+ <p key={av.currency}>
+ <span>
+ <span style={{ fontSize: "5em", display: "block" }}>{v}</span>{" "}
+ <span>{av.currency}</span>
+ </span>
+ {formatPending(entry)}
+ </p>
+ );
+ })}</Centered>
+ </section>
+ </PopupBox>
+}
diff --git a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
index 42e9ab90e..613218b80 100644
--- a/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
+++ b/packages/taler-wallet-webextension/src/popupEntryPoint.tsx
@@ -29,7 +29,7 @@ import { DevContextProvider } from "./context/useDevContext";
import { useTalerActionURL } from "./hooks/useTalerActionURL";
import { strings } from "./i18n/strings";
import { BackupPage } from "./popup/BackupPage";
-import { BalancePage } from "./popup/Balance";
+import { BalancePage } from "./popup/BalancePage";
import { DeveloperPage as DeveloperPage } from "./popup/Debug";
import { HistoryPage } from "./popup/History";
import {