aboutsummaryrefslogtreecommitdiff
path: root/packages/taler-wallet-webextension/src/components
diff options
context:
space:
mode:
Diffstat (limited to 'packages/taler-wallet-webextension/src/components')
-rw-r--r--packages/taler-wallet-webextension/src/components/BalanceTable.tsx6
-rw-r--r--packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx418
-rw-r--r--packages/taler-wallet-webextension/src/components/Modal.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/components/MultiActionButton.tsx18
-rw-r--r--packages/taler-wallet-webextension/src/components/SelectList.tsx2
-rw-r--r--packages/taler-wallet-webextension/src/components/ShowBanksForPaytoPopup.tsx61
-rw-r--r--packages/taler-wallet-webextension/src/components/ShowQRsForPaytoPopup.tsx94
-rw-r--r--packages/taler-wallet-webextension/src/components/TermsOfService/views.tsx26
-rw-r--r--packages/taler-wallet-webextension/src/components/WalletActivity.tsx33
-rw-r--r--packages/taler-wallet-webextension/src/components/styled/index.tsx32
10 files changed, 507 insertions, 185 deletions
diff --git a/packages/taler-wallet-webextension/src/components/BalanceTable.tsx b/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
index 6dd577b88..a6ccc10ca 100644
--- a/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
+++ b/packages/taler-wallet-webextension/src/components/BalanceTable.tsx
@@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-import { Amounts, ScopeType, WalletBalance } from "@gnu-taler/taler-util";
+import { Amounts, ScopeInfo, ScopeType, WalletBalance } from "@gnu-taler/taler-util";
import { Fragment, VNode, h } from "preact";
import {
TableWithRoundRows as TableWithRoundedRows
@@ -25,7 +25,7 @@ export function BalanceTable({
goToWalletHistory,
}: {
balances: WalletBalance[];
- goToWalletHistory: (currency: string) => void;
+ goToWalletHistory: (currency: ScopeInfo) => void;
}): VNode {
return (
<Fragment>
@@ -36,7 +36,7 @@ export function BalanceTable({
return (
<tr
key={idx}
- onClick={() => goToWalletHistory(av.currency)}
+ onClick={() => goToWalletHistory(entry.scopeInfo)}
style={{ cursor: "pointer" }}
>
<td>{av.currency}</td>
diff --git a/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx b/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
index 8b6377fc5..65368fd81 100644
--- a/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
+++ b/packages/taler-wallet-webextension/src/components/BankDetailsByPaytoType.tsx
@@ -17,19 +17,34 @@
import {
AmountJson,
Amounts,
+ AmountString,
parsePaytoUri,
+ PaytoUriIBAN,
+ PaytoUriTalerBank,
+ PaytoUriUnknown,
segwitMinAmount,
stringifyPaytoUri,
TranslatedString,
WithdrawalExchangeAccountDetails,
} from "@gnu-taler/taler-util";
-import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import {
+ encodeCrockForURI,
+ useTranslationContext,
+} from "@gnu-taler/web-util/browser";
import { ComponentChildren, Fragment, h, VNode } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
+import { Button } from "../mui/Button.js";
import { CopiedIcon, CopyIcon } from "../svg/index.js";
import { Amount } from "./Amount.js";
import { ButtonBox, TooltipLeft, WarningBox } from "./styled/index.js";
-import { Button } from "../mui/Button.js";
+import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
+import { WalletApiOperation } from "@gnu-taler/taler-wallet-core";
+import { useBackendContext } from "../context/backend.js";
+import { QR } from "./QR.js";
+import { Pages } from "../NavigationBar.js";
+import { ShowQRsForPaytoPopup } from "./ShowQRsForPaytoPopup.js";
+import { SafeHandler } from "../mui/handlers.js";
+import { ShowBanksForPaytoPopup } from "./ShowBanksForPaytoPopup.js";
export interface BankDetailsProps {
subject: string;
@@ -59,71 +74,12 @@ export function BankDetailsByPaytoType({
const payto = parsePaytoUri(selectedAccount.paytoUri);
if (!payto) return <Fragment />;
+ // make sure the payto has the right params
payto.params["amount"] = altCurrency
? selectedAccount.transferAmount!
: Amounts.stringify(amount);
payto.params["message"] = subject;
- function Frame({
- title,
- children,
- }: {
- title: TranslatedString;
- children: ComponentChildren;
- }): VNode {
- return (
- <section
- style={{
- textAlign: "left",
- border: "solid 1px black",
- padding: 8,
- borderRadius: 4,
- }}
- >
- <div
- style={{
- display: "flex",
- width: "100%",
- justifyContent: "space-between",
- }}
- >
- <p style={{ marginTop: 0 }}>{title}</p>
- <div></div>
- </div>
-
- {children}
-
- {accounts.length > 1 ? (
- <Fragment>
- {accounts.map((ac, acIdx) => {
- const accountLabel = ac.bankLabel ?? `Account #${acIdx + 1}`;
- return (
- <Button
- key={acIdx}
- variant={acIdx === index ? "contained" : "outlined"}
- onClick={async () => {
- setIndex(acIdx);
- }}
- >
- {accountLabel} (
- {ac.currencySpecification?.name ?? amount.currency})
- </Button>
- );
- })}
-
- {/* <Button variant={currency === altCurrency ? "contained" : "outlined"}
- onClick={async () => {
- setCurrency(altCurrency)
- }}
- >
- <i18n.Translate>{altCurrency}</i18n.Translate>
- </Button> */}
- </Fragment>
- ) : undefined}
- </section>
- );
- }
-
if (payto.isKnown && payto.targetType === "bitcoin") {
const min = segwitMinAmount(amount.currency);
const addrs = payto.segwitAddrs.map(
@@ -132,7 +88,13 @@ export function BankDetailsByPaytoType({
addrs.unshift(`${payto.targetPath} ${Amounts.stringifyValue(amount)}`);
const copyContent = addrs.join("\n");
return (
- <Frame title={i18n.str`Bitcoin transfer details`}>
+ <Frame
+ title={i18n.str`Bitcoin transfer details`}
+ accounts={accounts}
+ updateIndex={setIndex}
+ currentIndex={index}
+ defaultCurrency={amount.currency}
+ >
<p>
<i18n.Translate>
The exchange need a transaction with 3 output, one output is the
@@ -176,6 +138,47 @@ export function BankDetailsByPaytoType({
);
}
+ return (
+ <Frame
+ title={i18n.str`Bank transfer details`}
+ accounts={accounts}
+ updateIndex={setIndex}
+ currentIndex={index}
+ defaultCurrency={amount.currency}
+ >
+ <IBANAccountInfoTable payto={payto} subject={subject} />
+ </Frame>
+ );
+}
+
+function IBANAccountInfoTable({
+ payto,
+ subject,
+}: {
+ subject: string;
+ payto: PaytoUriUnknown | PaytoUriIBAN | PaytoUriTalerBank;
+}) {
+ const { i18n } = useTranslationContext();
+ const api = useBackendContext();
+ const [showBanks, setShowBanks] = useState(false);
+ const [showQrs, setShowQrs] = useState(false);
+
+ const hook = useAsyncAsHook(async () => {
+ const qrs = await api.wallet.call(WalletApiOperation.GetQrCodesForPayto, {
+ paytoUri: stringifyPaytoUri(payto),
+ });
+ const banks = await api.wallet.call(
+ WalletApiOperation.GetBankingChoicesForPayto,
+ {
+ paytoUri: stringifyPaytoUri(payto),
+ },
+ );
+ return { qrs, banks };
+ }, []);
+
+ const qrCodes = !hook || hook.hasError ? [] : hook.response.qrs.codes;
+ const banksSites = !hook || hook.hasError ? [] : hook.response.banks.choices;
+
const accountPart = !payto.isKnown ? (
<Fragment>
<Row name={i18n.str`Account`} value={payto.targetPath} />
@@ -196,96 +199,147 @@ export function BankDetailsByPaytoType({
const receiver =
payto.params["receiver-name"] || payto.params["receiver"] || undefined;
+
return (
- <Frame title={i18n.str`Bank transfer details`}>
- <table>
- <tbody>
- <tr>
- <td colSpan={3}>
- <i18n.Translate>Step 1:</i18n.Translate>
- &nbsp;
- <i18n.Translate>
- Copy this code and paste it into the subject/purpose field in
- your banking app or bank website
- </i18n.Translate>
- </td>
- </tr>
- <Row name={i18n.str`Subject`} value={subject} literal />
+ <table>
+ <tbody>
+ <tr>
+ <td colSpan={3}>
+ <i18n.Translate>Step 1:</i18n.Translate>
+ &nbsp;
+ <i18n.Translate>
+ Copy this code and paste it into the subject/purpose field in your
+ banking app or bank website
+ </i18n.Translate>
+ </td>
+ </tr>
+ <Row name={i18n.str`Subject`} value={subject} literal />
- <tr>
- <td colSpan={3}>
- <i18n.Translate>Step 2:</i18n.Translate>
- &nbsp;
- <i18n.Translate>
- If you don't already have it in your banking favourites list,
- then copy and paste this IBAN and the name into the receiver
- fields in your banking app or website
- </i18n.Translate>
- </td>
- </tr>
- {accountPart}
- {receiver ? (
- <Row name={i18n.str`Receiver name`} value={receiver} />
- ) : undefined}
+ <tr>
+ <td colSpan={3}>
+ <i18n.Translate>Step 2:</i18n.Translate>
+ &nbsp;
+ <i18n.Translate>
+ If you don't already have it in your banking favourites list, then
+ copy and paste this IBAN and the name into the receiver fields in
+ your banking app or website
+ </i18n.Translate>
+ </td>
+ </tr>
+ {accountPart}
+ {receiver ? (
+ <Row name={i18n.str`Receiver name`} value={receiver} />
+ ) : undefined}
- <tr>
- <td colSpan={3}>
- <i18n.Translate>Step 3:</i18n.Translate>
- &nbsp;
- <i18n.Translate>
- Finish the wire transfer setting the amount in your banking app
- or website, then this withdrawal will proceed automatically.
- </i18n.Translate>
- </td>
- </tr>
- <Row
- name={i18n.str`Amount`}
- value={
- <Amount
- value={altCurrency ? selectedAccount.transferAmount! : amount}
- hideCurrency
- />
- }
- />
+ <tr>
+ <td colSpan={3}>
+ <i18n.Translate>Step 3:</i18n.Translate>
+ &nbsp;
+ <i18n.Translate>
+ Finish the wire transfer setting the amount in your banking app or
+ website, then this withdrawal will proceed automatically.
+ </i18n.Translate>
+ </td>
+ </tr>
+ <Row
+ name={i18n.str`Amount`}
+ value={
+ <Amount
+ value={payto.params["amount"] as AmountString}
+ hideCurrency
+ />
+ }
+ />
- <tr>
- <td colSpan={3}>
- <WarningBox style={{ margin: 0 }}>
- <span>
- <i18n.Translate>
- Make sure ALL data is correct, including the subject;
- otherwise, the money will not arrive in this wallet. You can
- use the copy buttons (<CopyIcon />) to prevent typing errors
- or the "payto://" URI below to copy just one value.
- </i18n.Translate>
- </span>
- </WarningBox>
- </td>
- </tr>
+ <tr>
+ <td colSpan={3}>
+ <WarningBox style={{ margin: 0 }}>
+ <span>
+ <i18n.Translate>
+ Make sure ALL data is correct, including the subject;
+ otherwise, the money will not arrive in this wallet. You can
+ use the copy buttons (<CopyIcon />) to prevent typing errors
+ or the "payto://" URI below to copy just one value.
+ </i18n.Translate>
+ </span>
+ </WarningBox>
+ </td>
+ </tr>
- <tr>
- <td colSpan={2} width="100%" style={{ wordBreak: "break-all" }}>
- <i18n.Translate>
- Alternative if your bank already supports PayTo URI, you can use
- this{" "}
- <a
- target="_bank"
- rel="noreferrer"
- title="RFC 8905 for designating targets for payments"
- href="https://tools.ietf.org/html/rfc8905"
- >
- PayTo URI
- </a>{" "}
- link instead
- </i18n.Translate>
- </td>
- <td>
- <CopyButton getContent={() => stringifyPaytoUri(payto)} />
- </td>
- </tr>
- </tbody>
- </table>
- </Frame>
+ <tr>
+ <td colSpan={3} width="100%" style={{ wordBreak: "break-all" }}>
+ <i18n.Translate>
+ Alternative if your bank already supports PayTo URI, you can use
+ this{" "}
+ <a
+ target="_bank"
+ rel="noreferrer"
+ title="RFC 8905 for designating targets for payments"
+ href="https://tools.ietf.org/html/rfc8905"
+ >
+ PayTo URI
+ </a>{" "}
+ link instead
+ </i18n.Translate>
+ </td>
+ <td>
+ <CopyButton getContent={() => stringifyPaytoUri(payto)} />
+ </td>
+ </tr>
+
+ {banksSites.length < 1 ? undefined : (
+ <Fragment>
+ <div>
+ <a
+ href="#"
+ onClick={(e) => {
+ setShowBanks(true);
+ e.preventDefault();
+ }}
+ >
+ <i18n.Translate>
+ Continue with banking app or website
+ </i18n.Translate>
+ </a>
+ </div>
+
+ {showBanks ? (
+ <ShowBanksForPaytoPopup
+ banks={banksSites}
+ onClose={{
+ onClick: (async () =>
+ setShowBanks(false)) as SafeHandler<void>,
+ }}
+ />
+ ) : undefined}
+ </Fragment>
+ )}
+
+ {qrCodes.length < 1 ? undefined : (
+ <Fragment>
+ <div>
+ <a
+ href="#"
+ onClick={(e) => {
+ setShowQrs(true);
+ e.preventDefault();
+ }}
+ >
+ <i18n.Translate>Show QR code</i18n.Translate>
+ </a>
+ </div>
+ {showQrs ? (
+ <ShowQRsForPaytoPopup
+ qrs={qrCodes}
+ onClose={{
+ onClick: (async () => setShowQrs(false)) as SafeHandler<void>,
+ }}
+ />
+ ) : undefined}
+ </Fragment>
+ )}
+ </tbody>
+ </table>
);
}
@@ -358,3 +412,71 @@ function Row({
</tr>
);
}
+
+function Frame({
+ title,
+ children,
+ accounts,
+ defaultCurrency,
+ currentIndex,
+ updateIndex,
+}: {
+ title: TranslatedString;
+ children: ComponentChildren;
+ currentIndex: number;
+ updateIndex: (idx: number) => void;
+ defaultCurrency: string;
+ accounts: WithdrawalExchangeAccountDetails[];
+}): VNode {
+ return (
+ <section
+ style={{
+ textAlign: "left",
+ border: "solid 1px black",
+ padding: 8,
+ borderRadius: 4,
+ }}
+ >
+ <div
+ style={{
+ display: "flex",
+ width: "100%",
+ justifyContent: "space-between",
+ }}
+ >
+ <p style={{ marginTop: 0 }}>{title}</p>
+ <div></div>
+ </div>
+
+ {children}
+
+ {accounts.length > 1 ? (
+ <Fragment>
+ {accounts.map((ac, acIdx) => {
+ const accountLabel = ac.bankLabel ?? `Account #${acIdx + 1}`;
+ return (
+ <Button
+ key={acIdx}
+ variant={acIdx === currentIndex ? "contained" : "outlined"}
+ onClick={async () => {
+ updateIndex(acIdx);
+ }}
+ >
+ {accountLabel} (
+ {ac.currencySpecification?.name ?? defaultCurrency})
+ </Button>
+ );
+ })}
+
+ {/* <Button variant={currency === altCurrency ? "contained" : "outlined"}
+ onClick={async () => {
+ setCurrency(altCurrency)
+ }}
+ >
+ <i18n.Translate>{altCurrency}</i18n.Translate>
+ </Button> */}
+ </Fragment>
+ ) : undefined}
+ </section>
+ );
+}
diff --git a/packages/taler-wallet-webextension/src/components/Modal.tsx b/packages/taler-wallet-webextension/src/components/Modal.tsx
index c5f716c76..9023761bf 100644
--- a/packages/taler-wallet-webextension/src/components/Modal.tsx
+++ b/packages/taler-wallet-webextension/src/components/Modal.tsx
@@ -52,7 +52,7 @@ const Body = styled.div`
export function Modal({ title, children, onClose }: Props): VNode {
return (
- <div style={{ top: 0, position: "fixed", width: "100%", height: "100%" }}>
+ <div style={{ top: 0, left: 0, position: "fixed", width: "100%", height: "100%" }}>
<FullSize onClick={onClose?.onClick}>
<div
onClick={(e) => e.stopPropagation()}
diff --git a/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx b/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx
index 7d3cf3f57..3f22e4849 100644
--- a/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx
+++ b/packages/taler-wallet-webextension/src/components/MultiActionButton.tsx
@@ -20,10 +20,10 @@ import { Button } from "../mui/Button.js";
import arrowDown from "../svg/chevron-down.inline.svg";
import { ParagraphClickable } from "./styled/index.js";
-export interface Props {
- label: (s: string) => TranslatedString;
- actions: string[];
- onClick: (s: string) => Promise<void>;
+export interface Props<T> {
+ label: (s: T) => TranslatedString;
+ actions: T[];
+ onClick: (s: T) => Promise<void>;
}
/**
@@ -37,19 +37,19 @@ export interface Props {
*
* @returns
*/
-export function MultiActionButton({
+export function MultiActionButton<T>({
label,
actions,
onClick: doClick,
-}: Props): VNode {
- const defaultAction = actions.length > 0 ? actions[0] : "";
+}: Props<T>): VNode {
+ const defaultAction = actions.length > 0 ? actions[0] : "" as T;
const [opened, setOpened] = useState(false);
- const [selected, setSelected] = useState<string>(defaultAction);
+ const [selected, setSelected] = useState<T>(defaultAction);
const canChange = actions.length > 1;
const options = canChange ? actions.filter((a) => a !== selected) : [];
- function select(m: string): void {
+ function select(m: T): void {
setSelected(m);
setOpened(false);
}
diff --git a/packages/taler-wallet-webextension/src/components/SelectList.tsx b/packages/taler-wallet-webextension/src/components/SelectList.tsx
index 6eb72a266..a879da840 100644
--- a/packages/taler-wallet-webextension/src/components/SelectList.tsx
+++ b/packages/taler-wallet-webextension/src/components/SelectList.tsx
@@ -47,7 +47,7 @@ export function SelectList({
<Fragment>
<label
htmlFor={`text-${name}`}
- style={{ marginLeft: "0.5em", fontWeight: "bold" }}
+ style={{ marginLeft: "0.2rem", fontWeight: "bold" }}
>
{" "}
{label}
diff --git a/packages/taler-wallet-webextension/src/components/ShowBanksForPaytoPopup.tsx b/packages/taler-wallet-webextension/src/components/ShowBanksForPaytoPopup.tsx
new file mode 100644
index 000000000..268dcc1b3
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/ShowBanksForPaytoPopup.tsx
@@ -0,0 +1,61 @@
+/*
+ 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 {
+ BankingChoiceSpec
+} from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { styled } from "@linaria/react";
+import { Fragment, h, VNode } from "preact";
+import { ButtonHandler } from "../mui/handlers.js";
+import { Modal } from "./Modal.js";
+
+const BanksTable = styled.table`
+ width: 100%;
+ border-spacing: 0px;
+ & > tr > td {
+ padding: 5px;
+ }
+ & > tr > td:nth-child(2n) {
+ text-align: right;
+ overflow-wrap: anywhere;
+ }
+ & > tr:nth-child(2n) {
+ background: #ebebeb;
+ }
+`;
+
+interface Props { banks: BankingChoiceSpec[], onClose: ButtonHandler };
+
+export function ShowBanksForPaytoPopup({ banks, onClose }: Props): VNode {
+ const { i18n } = useTranslationContext();
+
+ return (
+ <Modal title="Supported banks" onClose={onClose}>
+ <div style={{ overflowY: "auto", height: "95%", padding: 5 }}>
+ <BanksTable>
+ {banks.map((b, idx) => {
+
+ return <tr key={idx}>
+ <td>
+ <a href={b.uri}>{b.label}</a>
+ </td>
+ </tr>
+ })}
+ </BanksTable>
+ </div>
+ </Modal>
+ );
+}
diff --git a/packages/taler-wallet-webextension/src/components/ShowQRsForPaytoPopup.tsx b/packages/taler-wallet-webextension/src/components/ShowQRsForPaytoPopup.tsx
new file mode 100644
index 000000000..a1d1d0269
--- /dev/null
+++ b/packages/taler-wallet-webextension/src/components/ShowQRsForPaytoPopup.tsx
@@ -0,0 +1,94 @@
+/*
+ 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 {
+ QrCodeSpec
+} from "@gnu-taler/taler-util";
+import { useTranslationContext } from "@gnu-taler/web-util/browser";
+import { styled } from "@linaria/react";
+import { Fragment, h, VNode } from "preact";
+import { ButtonHandler } from "../mui/handlers.js";
+import { Modal } from "./Modal.js";
+import { QR } from "./QR.js";
+import { useState } from "preact/hooks";
+
+const QRsTable = styled.table`
+ width: 100%;
+ & > tr > td {
+ padding: 5px;
+ }
+ & > tr > td {
+ border-spacing: 0px;
+ border-radius: 4px;
+ border: 1px black solid;
+ }
+ & > tr > td:nth-child(2n) {
+ text-align: right;
+ overflow-wrap: anywhere;
+ }
+`;
+
+const AccordionCss = styled.div`
+& > .accordion {
+ color: #444;
+ cursor: pointer;
+ padding: 8px;
+ font-size: large;
+ width: 100%;
+ text-align: left;
+ border: none;
+ outline: none;
+ transition: 0.4s;
+}
+
+& > .panel {
+ padding: 0 18px;
+ background-color: white;
+ display: none;
+ overflow: hidden;
+}`
+
+interface Props { qrs: QrCodeSpec[], onClose: ButtonHandler };
+
+function Accordion({ section, content }: { section: string, content: string }): VNode {
+ const [opened, setOpened] = useState(false)
+ return <AccordionCss>
+ <button class={opened ? "accordion active" : "accordion"} onClick={() => { setOpened(!opened) }}>{section}</button>
+ <div class="panel" style={{ display: opened ? "block" : "none" }}>
+ <QR text={content} />
+ </div>
+ </AccordionCss>
+}
+
+export function ShowQRsForPaytoPopup({ qrs, onClose }: Props): VNode {
+ const { i18n } = useTranslationContext();
+
+ return (
+ <Modal title="Qrs" onClose={onClose}>
+ <div style={{ overflowY: "auto", height: "95%", padding: 5 }}>
+ <QRsTable>
+ {qrs.map((q, idx) => {
+
+ return <tr key={idx}>
+ <td>
+ <Accordion section={q.type} content={q.qrContent} />
+ </td>
+ </tr>
+ })}
+ </QRsTable>
+ </div>
+ </Modal>
+ );
+}
diff --git a/packages/taler-wallet-webextension/src/components/TermsOfService/views.tsx b/packages/taler-wallet-webextension/src/components/TermsOfService/views.tsx
index f3172a741..8d9d3a499 100644
--- a/packages/taler-wallet-webextension/src/components/TermsOfService/views.tsx
+++ b/packages/taler-wallet-webextension/src/components/TermsOfService/views.tsx
@@ -159,7 +159,18 @@ export function ShowTosContentView({
</section>
)}
{terms.content && (
- <section style={{ justifyContent: "space-around", display: "flex" }}>
+ <section
+ style={{
+ justifyContent: "space-around",
+ display: "flex",
+ position: "relative",
+ resize: "vertical",
+ overflow: "hidden",
+ marginTop: "4px",
+ minHeight: "120px",
+ height: "240px",
+ }}
+ >
{terms.content.type === "xml" &&
(!terms.content.document ? (
<WarningBox>
@@ -186,7 +197,18 @@ export function ShowTosContentView({
</div>
))}
{terms.content.type === "html" && (
- <iframe style={{ width: "100%" }} srcDoc={terms.content.html} />
+ <iframe
+ style={{
+ width: "100%",
+ height: "100%",
+ border: "2px solid #0003",
+ borderRadius: "4px",
+ boxSizing: "border-box",
+ }}
+ src={`data:text/html;utf-8,${encodeURIComponent(
+ terms.content.html,
+ )}`}
+ />
)}
{terms.content.type === "pdf" && (
<a href={terms.content.location.toString()} download="tos.pdf">
diff --git a/packages/taler-wallet-webextension/src/components/WalletActivity.tsx b/packages/taler-wallet-webextension/src/components/WalletActivity.tsx
index c0bc5532b..ab3668ca0 100644
--- a/packages/taler-wallet-webextension/src/components/WalletActivity.tsx
+++ b/packages/taler-wallet-webextension/src/components/WalletActivity.tsx
@@ -180,7 +180,7 @@ function ShowBalanceChange({ events }: MoreInfoPRops): VNode {
<dd>
<a
title={not.hintTransactionId}
- href={Pages.balanceTransaction({ tid: not.hintTransactionId })}
+ href={`#${Pages.balanceTransaction({ tid: not.hintTransactionId })}`}
>
{not.hintTransactionId.substring(0, 10)}
</a>
@@ -257,7 +257,7 @@ function ShowTransactionStateTransition({
<dd>
<a
title={not.transactionId}
- href={Pages.balanceTransaction({ tid: not.transactionId })}
+ href={`#${Pages.balanceTransaction({ tid: not.transactionId })}`}
>
{not.transactionId.substring(0, 10)}
</a>
@@ -312,34 +312,34 @@ function ShowExchangeStateTransition({ events }: MoreInfoPRops): VNode {
<dt>Exchange</dt>
<dd>{not.exchangeBaseUrl}</dd>
{not.oldExchangeState &&
- not.newExchangeState.exchangeEntryStatus !==
+ not.newExchangeState?.exchangeEntryStatus !==
not.oldExchangeState?.exchangeEntryStatus && (
<Fragment>
<dt>Entry status</dt>
<dd>
from {not.oldExchangeState.exchangeEntryStatus} to{" "}
- {not.newExchangeState.exchangeEntryStatus}
+ {not.newExchangeState?.exchangeEntryStatus}
</dd>
</Fragment>
)}
{not.oldExchangeState &&
- not.newExchangeState.exchangeUpdateStatus !==
+ not.newExchangeState?.exchangeUpdateStatus !==
not.oldExchangeState?.exchangeUpdateStatus && (
<Fragment>
<dt>Update status</dt>
<dd>
from {not.oldExchangeState.exchangeUpdateStatus} to{" "}
- {not.newExchangeState.exchangeUpdateStatus}
+ {not.newExchangeState?.exchangeUpdateStatus}
</dd>
</Fragment>
)}
{not.oldExchangeState &&
- not.newExchangeState.tosStatus !== not.oldExchangeState?.tosStatus && (
+ not.newExchangeState?.tosStatus !== not.oldExchangeState?.tosStatus && (
<Fragment>
<dt>Tos status</dt>
<dd>
from {not.oldExchangeState.tosStatus} to{" "}
- {not.newExchangeState.tosStatus}
+ {not.newExchangeState?.tosStatus}
</dd>
</Fragment>
)}
@@ -722,10 +722,15 @@ function refresh(
let currentTab: chrome.tabs.Tab | undefined;
// Allow running outside the extension for testing
// tslint:disable-next-line:no-string-literal
-if (typeof chrome !== "undefined") {
- chrome.tabs.getCurrent().then((d) => {
- currentTab = d;
- });
+if (typeof chrome !== "undefined" && typeof chrome.tabs !== "undefined") {
+ const p = chrome.tabs.getCurrent();
+ // this may be called outside the render phase (in the background)
+ // when this happen currentTab is not needed but also undefined
+ if (p) {
+ p.then((d) => {
+ currentTab = d;
+ });
+ }
}
export function ObservabilityEventsTable(): VNode {
@@ -1064,7 +1069,9 @@ export function ActiveTasksTable(): VNode {
{task.transaction ? (
<a
title={task.transaction}
- href={Pages.balanceTransaction({ tid: task.transaction })}
+ href={`#${Pages.balanceTransaction({
+ tid: task.transaction,
+ })}`}
>
{task.transaction.substring(0, 10)}
</a>
diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx
index 739b71064..329d1b6e4 100644
--- a/packages/taler-wallet-webextension/src/components/styled/index.tsx
+++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx
@@ -273,8 +273,15 @@ const Tooltip = styled.div<{ content: string }>`
position: absolute;
z-index: 1000001;
padding: 0.5em 0.75em;
- font: normal normal 11px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI",
- Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
+ font:
+ normal normal 11px/1.5 -apple-system,
+ BlinkMacSystemFont,
+ "Segoe UI",
+ Helvetica,
+ Arial,
+ sans-serif,
+ "Apple Color Emoji",
+ "Segoe UI Emoji";
-webkit-font-smoothing: subpixel-antialiased;
color: white;
text-align: center;
@@ -539,7 +546,7 @@ export const LinkPrimary = styled(Link)`
color: black;
`;
-export const ButtonPrimary = styled(ButtonVariant) <{ small?: boolean }>`
+export const ButtonPrimary = styled(ButtonVariant)<{ small?: boolean }>`
font-size: ${({ small }: any) => (small ? "small" : "inherit")};
background-color: #0042b2;
border-color: #0042b2;
@@ -690,13 +697,13 @@ export const SmallBoldText = styled.div`
font-weight: bold;
`;
-export const AgeSign = styled.div<{size:number}>`
+export const AgeSign = styled.div<{ size: number }>`
display: inline-block;
border: red solid 1px;
border-radius: 100%;
- width: ${({ size }: {size:number}) => (`${size}px`)};
- height: ${({ size }: {size:number}) => (`${size}px`)};
- line-height: ${({ size }: {size:number}) => (`${size}px`)};
+ width: ${({ size }: { size: number }) => `${size}px`};
+ height: ${({ size }: { size: number }) => `${size}px`};
+ line-height: ${({ size }: { size: number }) => `${size}px`};
padding: 3px;
`;
@@ -920,11 +927,18 @@ export const NiceSelect = styled.div`
background-color: white;
+ border: 2px solid #0003;
border-radius: 0.25rem;
font-size: 1em;
padding: 8px 32px 8px 8px;
/* 0.5em 3em 0.5em 1em; */
cursor: pointer;
+
+ &:hover,
+ &:focus,
+ &:active {
+ background-color: #0000000a;
+ }
}
position: relative;
@@ -1074,7 +1088,9 @@ export const StyledCheckboxLabel = styled.div`
color: #959495;
}
input:focus + div + label {
- box-shadow: 0 0 0 0.05em #fff, 0 0 0.15em 0.1em currentColor;
+ box-shadow:
+ 0 0 0 0.05em #fff,
+ 0 0 0.15em 0.1em currentColor;
}
`;