migrate to preact
This commit is contained in:
parent
b414de8533
commit
30f86f8748
@ -6,15 +6,8 @@ module.exports = {
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:react/recommended",
|
||||
"plugin:react-hooks/recommended",
|
||||
"preact",
|
||||
],
|
||||
settings: {
|
||||
"react": {
|
||||
"version": "16.9.6",
|
||||
},
|
||||
|
||||
},
|
||||
rules: {
|
||||
"no-constant-condition": ["error", { "checkLoops": false }],
|
||||
"prefer-const": ["warn", { destructuring: "all" }],
|
||||
|
@ -9,34 +9,53 @@
|
||||
"private": false,
|
||||
"scripts": {
|
||||
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
|
||||
"test": "jest ./tests",
|
||||
"compile": "tsc && rollup -c"
|
||||
},
|
||||
"dependencies": {
|
||||
"moment": "^2.29.1",
|
||||
"@gnu-taler/taler-wallet-core": "workspace:*",
|
||||
"@gnu-taler/taler-util": "workspace:*",
|
||||
"@gnu-taler/taler-wallet-core": "workspace:*",
|
||||
"preact": "^10.5.13",
|
||||
"preact-router": "^3.2.1",
|
||||
"tslib": "^2.1.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.14.0",
|
||||
"@babel/plugin-transform-react-jsx-source": "^7.12.13",
|
||||
"@babel/preset-typescript": "^7.13.0",
|
||||
"@rollup/plugin-commonjs": "^17.0.0",
|
||||
"@rollup/plugin-json": "^4.1.0",
|
||||
"@rollup/plugin-node-resolve": "^11.1.0",
|
||||
"@rollup/plugin-replace": "^2.3.4",
|
||||
"@testing-library/preact": "^2.0.1",
|
||||
"@types/chrome": "^0.0.128",
|
||||
"@types/enzyme": "^3.10.8",
|
||||
"@types/enzyme-adapter-react-16": "^1.0.6",
|
||||
"@types/jest": "^26.0.23",
|
||||
"@types/node": "^14.14.22",
|
||||
"@types/react": "^17.0.0",
|
||||
"@types/react-dom": "^17.0.0",
|
||||
"ava": "3.15.0",
|
||||
"babel-plugin-transform-react-jsx": "^6.24.1",
|
||||
"enzyme": "^3.11.0",
|
||||
"react": "^17.0.1",
|
||||
"react-dom": "^17.0.1",
|
||||
"enzyme-adapter-preact-pure": "^3.1.0",
|
||||
"jest": "^26.6.3",
|
||||
"jest-preset-preact": "^4.0.3",
|
||||
"preact-cli": "^3.0.5",
|
||||
"preact-render-to-string": "^5.1.19",
|
||||
"rimraf": "^3.0.2",
|
||||
"rollup": "^2.37.1",
|
||||
"rollup-plugin-ignore": "^1.0.9",
|
||||
"rollup-plugin-sourcemaps": "^0.6.3",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
"typescript": "^4.1.3"
|
||||
},
|
||||
"jest": {
|
||||
"preset": "jest-preset-preact",
|
||||
"setupFiles": [
|
||||
"<rootDir>/tests/__mocks__/setupTests.ts"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"\\.(css|less)$": "identity-obj-proxy"
|
||||
},
|
||||
"transform": {
|
||||
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|po)$": "<rootDir>/tests/__mocks__/fileTransformer.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import {
|
||||
HttpRequestOptions,
|
||||
HttpResponse,
|
||||
Headers,
|
||||
bytesToString,
|
||||
} from "@gnu-taler/taler-wallet-core";
|
||||
import { TalerErrorCode } from "@gnu-taler/taler-util";
|
||||
|
||||
|
@ -21,9 +21,9 @@
|
||||
/**
|
||||
* Imports
|
||||
*/
|
||||
import React from "react";
|
||||
|
||||
import * as i18nCore from "@gnu-taler/taler-wallet-core";
|
||||
import { Component, ComponentChildren, h, JSX, toChildArray, VNode } from "preact";
|
||||
/**
|
||||
* Convert template strings to a msgid
|
||||
*/
|
||||
@ -50,7 +50,7 @@ interface TranslateSwitchProps {
|
||||
|
||||
function stringifyChildren(children: any): string {
|
||||
let n = 1;
|
||||
const ss = React.Children.map(children, (c) => {
|
||||
const ss = toChildArray(children).map((c) => {
|
||||
if (typeof c === "string") {
|
||||
return c;
|
||||
}
|
||||
@ -76,10 +76,10 @@ interface TranslateProps {
|
||||
|
||||
function getTranslatedChildren(
|
||||
translation: string,
|
||||
children: React.ReactNode,
|
||||
): React.ReactNode[] {
|
||||
children: ComponentChildren,
|
||||
): ComponentChildren {
|
||||
const tr = translation.split(/%(\d+)\$s/);
|
||||
const childArray = React.Children.toArray(children);
|
||||
const childArray = toChildArray(children);
|
||||
// Merge consecutive string children.
|
||||
const placeholderChildren = [];
|
||||
for (let i = 0; i < childArray.length; i++) {
|
||||
@ -117,15 +117,15 @@ function getTranslatedChildren(
|
||||
* </Translate>
|
||||
* ```
|
||||
*/
|
||||
export class Translate extends React.Component<TranslateProps, {}> {
|
||||
render(): JSX.Element {
|
||||
export class Translate extends Component<TranslateProps, any> {
|
||||
render() {
|
||||
const s = stringifyChildren(this.props.children);
|
||||
const translation: string = i18nCore.jed.ngettext(s, s, 1);
|
||||
const result = getTranslatedChildren(translation, this.props.children);
|
||||
if (!this.props.wrap) {
|
||||
return <div>{result}</div>;
|
||||
}
|
||||
return React.createElement(this.props.wrap, this.props.wrapProps, result);
|
||||
return h(this.props.wrap, this.props.wrapProps, result);
|
||||
}
|
||||
}
|
||||
|
||||
@ -141,16 +141,16 @@ export class Translate extends React.Component<TranslateProps, {}> {
|
||||
* </TranslateSwitch>
|
||||
* ```
|
||||
*/
|
||||
export class TranslateSwitch extends React.Component<
|
||||
export class TranslateSwitch extends Component<
|
||||
TranslateSwitchProps,
|
||||
void
|
||||
> {
|
||||
render(): JSX.Element {
|
||||
let singular: React.ReactElement<TranslationPluralProps> | undefined;
|
||||
let plural: React.ReactElement<TranslationPluralProps> | undefined;
|
||||
let singular: VNode<TranslationPluralProps> | undefined;
|
||||
let plural: VNode<TranslationPluralProps> | undefined;
|
||||
const children = this.props.children;
|
||||
if (children) {
|
||||
React.Children.forEach(children, (child: any) => {
|
||||
toChildArray(children).forEach((child: any) => {
|
||||
if (child.type === TranslatePlural) {
|
||||
plural = child;
|
||||
}
|
||||
@ -161,7 +161,7 @@ export class TranslateSwitch extends React.Component<
|
||||
}
|
||||
if (!singular || !plural) {
|
||||
console.error("translation not found");
|
||||
return React.createElement("span", {}, ["translation not found"]);
|
||||
return h("span", {}, ["translation not found"]);
|
||||
}
|
||||
singular.props.target = this.props.target;
|
||||
plural.props.target = this.props.target;
|
||||
@ -178,7 +178,7 @@ interface TranslationPluralProps {
|
||||
/**
|
||||
* See [[TranslateSwitch]].
|
||||
*/
|
||||
export class TranslatePlural extends React.Component<
|
||||
export class TranslatePlural extends Component<
|
||||
TranslationPluralProps,
|
||||
void
|
||||
> {
|
||||
@ -193,7 +193,7 @@ export class TranslatePlural extends React.Component<
|
||||
/**
|
||||
* See [[TranslateSwitch]].
|
||||
*/
|
||||
export class TranslateSingular extends React.Component<
|
||||
export class TranslateSingular extends Component<
|
||||
TranslationPluralProps,
|
||||
void
|
||||
> {
|
||||
|
@ -20,7 +20,7 @@
|
||||
* @author Florian Dold <dold@taler.net>
|
||||
*/
|
||||
|
||||
import ReactDOM from "react-dom";
|
||||
import {render} from "preact";
|
||||
import { createPopup } from "./pages/popup";
|
||||
import { createWithdrawPage } from "./pages/withdraw";
|
||||
import { createWelcomePage } from "./pages/welcome";
|
||||
@ -63,7 +63,7 @@ function main(): void {
|
||||
if (!container) {
|
||||
throw Error("container not found, can't mount page contents");
|
||||
}
|
||||
ReactDOM.render(mainElement, container);
|
||||
render(mainElement, container);
|
||||
} catch (e) {
|
||||
console.error("got error", e);
|
||||
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
|
||||
|
@ -27,7 +27,7 @@ import * as i18n from "../i18n";
|
||||
import { renderAmount, ProgressButton } from "../renderHtml";
|
||||
import * as wxApi from "../wxApi";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "preact/hooks";
|
||||
|
||||
import { getJsonI18n } from "@gnu-taler/taler-wallet-core";
|
||||
import {
|
||||
@ -39,10 +39,11 @@ import {
|
||||
ContractTerms,
|
||||
ConfirmPayResultType,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { JSX, VNode } from "preact";
|
||||
|
||||
function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
||||
const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>();
|
||||
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>();
|
||||
const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>(undefined);
|
||||
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined);
|
||||
const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
|
||||
const [numTries, setNumTries] = useState(0);
|
||||
const [loading, setLoading] = useState(false);
|
||||
@ -66,8 +67,8 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
||||
}
|
||||
|
||||
if (payStatus.status === PreparePayResultType.PaymentPossible) {
|
||||
let amountRaw = Amounts.parseOrThrow(payStatus.amountRaw);
|
||||
let amountEffective: AmountJson = Amounts.parseOrThrow(
|
||||
const amountRaw = Amounts.parseOrThrow(payStatus.amountRaw);
|
||||
const amountEffective: AmountJson = Amounts.parseOrThrow(
|
||||
payStatus.amountEffective,
|
||||
);
|
||||
totalFees = Amounts.sub(amountEffective, amountRaw).amount;
|
||||
@ -95,7 +96,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
||||
}
|
||||
}
|
||||
|
||||
let contractTerms: ContractTerms = payStatus.contractTerms;
|
||||
const contractTerms: ContractTerms = payStatus.contractTerms;
|
||||
|
||||
if (!contractTerms) {
|
||||
return (
|
||||
@ -105,7 +106,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
||||
);
|
||||
}
|
||||
|
||||
let merchantName: React.ReactElement;
|
||||
let merchantName: VNode;
|
||||
if (contractTerms.merchant && contractTerms.merchant.name) {
|
||||
merchantName = <strong>{contractTerms.merchant.name}</strong>;
|
||||
} else {
|
||||
@ -200,7 +201,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
||||
) : (
|
||||
<div>
|
||||
<ProgressButton
|
||||
loading={loading}
|
||||
isLoading={loading}
|
||||
disabled={insufficientBalance}
|
||||
onClick={() => doPayment()}
|
||||
>
|
||||
|
@ -14,6 +14,8 @@
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
|
||||
/**
|
||||
* View and edit auditors.
|
||||
*
|
||||
@ -23,7 +25,6 @@
|
||||
/**
|
||||
* Imports.
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
export function makePaybackPage(): JSX.Element {
|
||||
return <div>not implemented</div>;
|
||||
|
@ -41,18 +41,18 @@ import {
|
||||
amountFractionalBase,
|
||||
} from "@gnu-taler/taler-util";
|
||||
|
||||
import { abbrev, renderAmount, PageLink } from "../renderHtml";
|
||||
import { renderAmount, PageLink } from "../renderHtml";
|
||||
import * as wxApi from "../wxApi";
|
||||
|
||||
import React, { Fragment, useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "preact/hooks";
|
||||
|
||||
import moment from "moment";
|
||||
import { PermissionsCheckbox } from "./welcome";
|
||||
import { JSXInternal } from "preact/src/jsx";
|
||||
import { Component, ComponentChild, ComponentChildren, JSX, toChildArray, VNode } from "preact";
|
||||
|
||||
// FIXME: move to newer react functions
|
||||
/* eslint-disable react/no-deprecated */
|
||||
|
||||
class Router extends React.Component<any, any> {
|
||||
class Router extends Component<any, any> {
|
||||
static setRoute(s: string): void {
|
||||
window.location.hash = s;
|
||||
}
|
||||
@ -85,21 +85,21 @@ class Router extends React.Component<any, any> {
|
||||
render(): JSX.Element {
|
||||
const route = window.location.hash.substring(1);
|
||||
console.log("rendering route", route);
|
||||
let defaultChild: React.ReactChild | null = null;
|
||||
let foundChild: React.ReactChild | null = null;
|
||||
React.Children.forEach(this.props.children, (child) => {
|
||||
let defaultChild: ComponentChild | null = null;
|
||||
let foundChild: ComponentChild | null = null;
|
||||
toChildArray(this.props.children).forEach((child) => {
|
||||
const childProps: any = (child as any).props;
|
||||
if (!childProps) {
|
||||
return;
|
||||
}
|
||||
if (childProps.default) {
|
||||
defaultChild = child as React.ReactChild;
|
||||
defaultChild = child;
|
||||
}
|
||||
if (childProps.route === route) {
|
||||
foundChild = child as React.ReactChild;
|
||||
foundChild = child;
|
||||
}
|
||||
});
|
||||
const c: React.ReactChild | null = foundChild || defaultChild;
|
||||
const c: ComponentChild | null = foundChild || defaultChild;
|
||||
if (!c) {
|
||||
throw Error("unknown route");
|
||||
}
|
||||
@ -110,7 +110,7 @@ class Router extends React.Component<any, any> {
|
||||
|
||||
interface TabProps {
|
||||
target: string;
|
||||
children?: React.ReactNode;
|
||||
children?: ComponentChildren;
|
||||
}
|
||||
|
||||
function Tab(props: TabProps): JSX.Element {
|
||||
@ -118,7 +118,7 @@ function Tab(props: TabProps): JSX.Element {
|
||||
if (props.target === Router.getRoute()) {
|
||||
cssClass = "active";
|
||||
}
|
||||
const onClick = (e: React.MouseEvent<HTMLAnchorElement>): void => {
|
||||
const onClick = (e: JSXInternal.TargetedMouseEvent<HTMLAnchorElement>): void => {
|
||||
Router.setRoute(props.target);
|
||||
e.preventDefault();
|
||||
};
|
||||
@ -129,7 +129,7 @@ function Tab(props: TabProps): JSX.Element {
|
||||
);
|
||||
}
|
||||
|
||||
class WalletNavBar extends React.Component<any, any> {
|
||||
class WalletNavBar extends Component<any, any> {
|
||||
private cancelSubscription: any;
|
||||
|
||||
componentWillMount(): void {
|
||||
@ -179,7 +179,7 @@ function EmptyBalanceView(): JSX.Element {
|
||||
);
|
||||
}
|
||||
|
||||
class WalletBalanceView extends React.Component<any, any> {
|
||||
class WalletBalanceView extends Component<any, any> {
|
||||
private balance?: BalancesResponse;
|
||||
private gotError = false;
|
||||
private canceler: (() => void) | undefined = undefined;
|
||||
@ -323,7 +323,7 @@ function TransactionAmount(props: TransactionAmountProps): JSX.Element {
|
||||
case "unknown":
|
||||
sign = "";
|
||||
}
|
||||
const style: React.CSSProperties = {
|
||||
const style: JSX.AllCSSProperties = {
|
||||
marginLeft: "auto",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
@ -476,7 +476,7 @@ function TransactionItem(props: { tx: Transaction }): JSX.Element {
|
||||
function WalletHistory(props: any): JSX.Element {
|
||||
const [transactions, setTransactions] = useState<
|
||||
TransactionsResponse | undefined
|
||||
>();
|
||||
>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
const fetchData = async (): Promise<void> => {
|
||||
@ -484,7 +484,6 @@ function WalletHistory(props: any): JSX.Element {
|
||||
setTransactions(res);
|
||||
};
|
||||
fetchData();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
if (!transactions) {
|
||||
@ -495,14 +494,14 @@ function WalletHistory(props: any): JSX.Element {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{txs.map((tx) => (
|
||||
<TransactionItem tx={tx} />
|
||||
{txs.map((tx,i) => (
|
||||
<TransactionItem key={i} tx={tx} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
class WalletSettings extends React.Component<any, any> {
|
||||
class WalletSettings extends Component<any, any> {
|
||||
render(): JSX.Element {
|
||||
return (
|
||||
<div>
|
||||
@ -522,14 +521,14 @@ function reload(): void {
|
||||
}
|
||||
}
|
||||
|
||||
function confirmReset(): void {
|
||||
async function confirmReset(): Promise<void> {
|
||||
if (
|
||||
confirm(
|
||||
"Do you want to IRREVOCABLY DESTROY everything inside your" +
|
||||
" wallet and LOSE ALL YOUR COINS?",
|
||||
)
|
||||
) {
|
||||
wxApi.resetDb();
|
||||
await wxApi.resetDb();
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
@ -554,14 +553,14 @@ function openExtensionPage(page: string) {
|
||||
};
|
||||
}
|
||||
|
||||
function openTab(page: string) {
|
||||
return (evt: React.SyntheticEvent<any>) => {
|
||||
evt.preventDefault();
|
||||
chrome.tabs.create({
|
||||
url: page,
|
||||
});
|
||||
};
|
||||
}
|
||||
// function openTab(page: string) {
|
||||
// return (evt: React.SyntheticEvent<any>) => {
|
||||
// evt.preventDefault();
|
||||
// chrome.tabs.create({
|
||||
// url: page,
|
||||
// });
|
||||
// };
|
||||
// }
|
||||
|
||||
function makeExtensionUrlWithParams(
|
||||
url: string,
|
||||
|
@ -20,17 +20,18 @@
|
||||
* @author Florian Dold
|
||||
*/
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import * as wxApi from "../wxApi";
|
||||
import { AmountView } from "../renderHtml";
|
||||
import {
|
||||
PurchaseDetails,
|
||||
ApplyRefundResponse,
|
||||
Amounts,
|
||||
} from "@gnu-taler/taler-util";
|
||||
// import { h } from 'preact';
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
|
||||
function RefundStatusView(props: { talerRefundUri: string }): JSX.Element {
|
||||
const [applyResult, setApplyResult] = useState<ApplyRefundResponse>();
|
||||
const [applyResult, setApplyResult] = useState<ApplyRefundResponse|undefined>(undefined);
|
||||
const [errMsg, setErrMsg] = useState<string | undefined>(undefined);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -20,8 +20,7 @@
|
||||
* @author Florian Dold
|
||||
*/
|
||||
|
||||
import * as React from "react";
|
||||
|
||||
import { Component, JSX } from "preact";
|
||||
import * as wxApi from "../wxApi";
|
||||
|
||||
interface State {
|
||||
@ -36,7 +35,7 @@ interface State {
|
||||
resetRequired: boolean;
|
||||
}
|
||||
|
||||
class ResetNotification extends React.Component<any, State> {
|
||||
class ResetNotification extends Component<any, State> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = { checked: false, resetRequired: true };
|
||||
@ -50,7 +49,7 @@ class ResetNotification extends React.Component<any, State> {
|
||||
if (this.state.resetRequired) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Manual Reset Reqired</h1>
|
||||
<h1>Manual Reset Required</h1>
|
||||
<p>
|
||||
The wallet's database in your browser is incompatible with the{" "}
|
||||
currently installed wallet. Please reset manually.
|
||||
@ -63,7 +62,9 @@ class ResetNotification extends React.Component<any, State> {
|
||||
id="check"
|
||||
type="checkbox"
|
||||
checked={this.state.checked}
|
||||
onChange={(e) => this.setState({ checked: e.target.checked })}
|
||||
onChange={() => {
|
||||
this.setState(prev => ({ checked: prev.checked }))
|
||||
}}
|
||||
/>{" "}
|
||||
<label htmlFor="check">
|
||||
I understand that I will lose all my data
|
||||
|
@ -14,6 +14,8 @@
|
||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
|
||||
/**
|
||||
* Return coins to own bank account.
|
||||
*
|
||||
@ -23,8 +25,6 @@
|
||||
/**
|
||||
* Imports.
|
||||
*/
|
||||
import * as React from "react";
|
||||
|
||||
export function createReturnCoinsPage(): JSX.Element {
|
||||
return <span>Not implemented yet.</span>;
|
||||
}
|
||||
|
@ -20,17 +20,17 @@
|
||||
* @author Florian Dold <dold@taler.net>
|
||||
*/
|
||||
|
||||
import * as React from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useState } from "preact/hooks";
|
||||
import { PrepareTipResult } from "@gnu-taler/taler-util";
|
||||
import { AmountView } from "../renderHtml";
|
||||
import * as wxApi from "../wxApi";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
|
||||
function TalerTipDialog({ talerTipUri }: { talerTipUri: string }): JSX.Element {
|
||||
const [updateCounter, setUpdateCounter] = useState<number>(0);
|
||||
const [prepareTipResult, setPrepareTipResult] = useState<
|
||||
PrepareTipResult | undefined
|
||||
>();
|
||||
>(undefined);
|
||||
|
||||
const [tipIgnored, setTipIgnored] = useState(false);
|
||||
|
||||
|
@ -20,13 +20,14 @@
|
||||
* @author Florian Dold
|
||||
*/
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "preact/hooks";
|
||||
import { getDiagnostics } from "../wxApi";
|
||||
import { PageLink } from "../renderHtml";
|
||||
import * as wxApi from "../wxApi";
|
||||
import { getPermissionsApi } from "../compat";
|
||||
import { extendedPermissions } from "../permissions";
|
||||
import { WalletDiagnostics } from "@gnu-taler/taler-util";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
|
||||
function Diagnostics(): JSX.Element | null {
|
||||
const [timedOut, setTimedOut] = useState(false);
|
||||
@ -102,9 +103,9 @@ export function PermissionsCheckbox(): JSX.Element {
|
||||
const [extendedPermissionsEnabled, setExtendedPermissionsEnabled] = useState(
|
||||
false,
|
||||
);
|
||||
async function handleExtendedPerm(requestedVal: boolean): Promise<void> {
|
||||
async function handleExtendedPerm(): Promise<void> {
|
||||
let nextVal: boolean | undefined;
|
||||
if (requestedVal) {
|
||||
if (extendedPermissionsEnabled) {
|
||||
const granted = await new Promise<boolean>((resolve, reject) => {
|
||||
// We set permissions here, since apparently FF wants this to be done
|
||||
// as the result of an input event ...
|
||||
@ -141,7 +142,7 @@ export function PermissionsCheckbox(): JSX.Element {
|
||||
<div>
|
||||
<input
|
||||
checked={extendedPermissionsEnabled}
|
||||
onChange={(x) => handleExtendedPerm(x.target.checked)}
|
||||
onChange={() => handleExtendedPerm()}
|
||||
type="checkbox"
|
||||
id="checkbox-perm"
|
||||
style={{ width: "1.5em", height: "1.5em", verticalAlign: "middle" }}
|
||||
|
@ -25,19 +25,20 @@ import * as i18n from "../i18n";
|
||||
|
||||
import { renderAmount } from "../renderHtml";
|
||||
|
||||
import React, { useState, useEffect } from "react";
|
||||
import { useState, useEffect } from "preact/hooks";
|
||||
import {
|
||||
acceptWithdrawal,
|
||||
onUpdateNotification,
|
||||
getWithdrawalDetailsForUri,
|
||||
} from "../wxApi";
|
||||
import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
|
||||
import { JSX } from "preact/jsx-runtime";
|
||||
|
||||
function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
|
||||
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>();
|
||||
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
|
||||
const [selectedExchange, setSelectedExchange] = useState<
|
||||
string | undefined
|
||||
>();
|
||||
>(undefined);
|
||||
const talerWithdrawUri = props.talerWithdrawUri;
|
||||
const [cancelled, setCancelled] = useState(false);
|
||||
const [selecting, setSelecting] = useState(false);
|
||||
@ -48,7 +49,6 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
|
||||
return onUpdateNotification(() => {
|
||||
setUpdateCounter(updateCounter + 1);
|
||||
});
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -23,12 +23,13 @@
|
||||
/**
|
||||
* Imports.
|
||||
*/
|
||||
import React from "react";
|
||||
import {
|
||||
AmountJson,
|
||||
Amounts,
|
||||
amountFractionalBase,
|
||||
} from "@gnu-taler/taler-util";
|
||||
import { Component, ComponentChildren, JSX } from "preact";
|
||||
import { JSXInternal } from "preact/src/jsx";
|
||||
|
||||
/**
|
||||
* Render amount as HTML, which non-breaking space between
|
||||
@ -87,7 +88,7 @@ interface CollapsibleProps {
|
||||
* Component that shows/hides its children when clicking
|
||||
* a heading.
|
||||
*/
|
||||
export class Collapsible extends React.Component<
|
||||
export class Collapsible extends Component<
|
||||
CollapsibleProps,
|
||||
CollapsibleState
|
||||
> {
|
||||
@ -139,24 +140,18 @@ export function ExpanderText({ text }: ExpanderTextProps): JSX.Element {
|
||||
return <span>{text}</span>;
|
||||
}
|
||||
|
||||
export interface LoadingButtonProps {
|
||||
loading: boolean;
|
||||
export interface LoadingButtonProps extends JSX.HTMLAttributes<HTMLButtonElement> {
|
||||
isLoading: boolean;
|
||||
}
|
||||
|
||||
export function ProgressButton(
|
||||
props: React.PropsWithChildren<LoadingButtonProps> &
|
||||
React.DetailedHTMLProps<
|
||||
React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||
HTMLButtonElement
|
||||
>,
|
||||
): JSX.Element {
|
||||
export function ProgressButton({isLoading, ...rest}: LoadingButtonProps): JSX.Element {
|
||||
return (
|
||||
<button
|
||||
className="pure-button pure-button-primary"
|
||||
type="button"
|
||||
{...props}
|
||||
{...rest}
|
||||
>
|
||||
{props.loading ? (
|
||||
{isLoading ? (
|
||||
<span>
|
||||
<object
|
||||
className="svg-icon svg-baseline"
|
||||
@ -164,13 +159,13 @@ export function ProgressButton(
|
||||
/>
|
||||
</span>
|
||||
) : null}{" "}
|
||||
{props.children}
|
||||
{rest.children}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
export function PageLink(
|
||||
props: React.PropsWithChildren<{ pageName: string }>,
|
||||
props: { pageName: string, children?: ComponentChildren },
|
||||
): JSX.Element {
|
||||
const url = chrome.extension.getURL(`/${props.pageName}`);
|
||||
return (
|
||||
|
@ -146,7 +146,7 @@ async function dispatch(
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
default: {
|
||||
const w = currentWallet;
|
||||
if (!w) {
|
||||
r = {
|
||||
@ -163,6 +163,7 @@ async function dispatch(
|
||||
}
|
||||
r = await w.handleCoreApiRequest(req.operation, req.id, req.payload);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -0,0 +1,24 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
|
||||
// This fixed an error related to the CSS and loading gif breaking my Jest test
|
||||
// See https://facebook.github.io/jest/docs/en/webpack.html#handling-static-assets
|
||||
export default 'test-file-stub';
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
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)
|
||||
*/
|
||||
// fileTransformer.js
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
const path = require('path');
|
||||
|
||||
module.exports = {
|
||||
process(src, filename, config, options) {
|
||||
return 'module.exports = ' + JSON.stringify(path.basename(filename)) + ';';
|
||||
},
|
||||
};
|
||||
|
@ -0,0 +1,33 @@
|
||||
/*
|
||||
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 'regenerator-runtime/runtime'
|
||||
import { configure } from 'enzyme';
|
||||
import Adapter from 'enzyme-adapter-preact-pure';
|
||||
|
||||
configure({
|
||||
adapter: new Adapter()
|
||||
});
|
||||
|
||||
// Polyfill for encoding which isn't present globally in jsdom
|
||||
import { TextEncoder, TextDecoder } from 'util'
|
||||
global.TextEncoder = TextEncoder
|
||||
global.TextDecoder = TextDecoder
|
@ -14,12 +14,11 @@
|
||||
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
||||
*/
|
||||
|
||||
import test from "ava";
|
||||
import { internalSetStrings, str, Translate, strings } from "./i18n";
|
||||
import React from "react";
|
||||
import { render } from "enzyme";
|
||||
import { configure } from "enzyme";
|
||||
import Adapter from "enzyme-adapter-react-16";
|
||||
// import * as test from "ava";
|
||||
import { internalSetStrings, str, Translate } from "../src/i18n";
|
||||
import { render, configure } from "enzyme";
|
||||
import Adapter from 'enzyme-adapter-preact-pure';
|
||||
import { h } from "preact";
|
||||
|
||||
configure({ adapter: new Adapter() });
|
||||
|
||||
@ -39,30 +38,31 @@ const testStrings = {
|
||||
},
|
||||
};
|
||||
|
||||
test("str translation", (t) => {
|
||||
test("str translation", (done) => {
|
||||
|
||||
// Alias, so we nly use the function for lookups, not for string extranction.
|
||||
const strAlias = str;
|
||||
const TranslateAlias = Translate;
|
||||
internalSetStrings(testStrings);
|
||||
t.is(strAlias`str1`, "foo1");
|
||||
t.is(strAlias`str2`, "str2");
|
||||
expect(strAlias`str1`).toEqual("foo1");
|
||||
expect(strAlias`str2`).toEqual("str2");
|
||||
const a = "a";
|
||||
const b = "b";
|
||||
t.is(strAlias`str3 ${a} / ${b}`, "foo3 b ; a");
|
||||
expect(strAlias`str3 ${a} / ${b}`).toEqual("foo3 b ; a");
|
||||
const r = render(<TranslateAlias>str1</TranslateAlias>);
|
||||
t.is(r.text(), "foo1");
|
||||
expect(r.text()).toEqual("foo1");
|
||||
|
||||
const r2 = render(
|
||||
<TranslateAlias>
|
||||
str3 <span>{a}</span> / <span>{b}</span>
|
||||
</TranslateAlias>,
|
||||
);
|
||||
t.is(r2.text(), "foo3 b ; a");
|
||||
expect(r2.text()).toEqual("foo3 b ; a");
|
||||
|
||||
t.pass();
|
||||
done();
|
||||
});
|
||||
|
||||
test("existing str translation", (t) => {
|
||||
internalSetStrings(strings);
|
||||
t.pass();
|
||||
});
|
||||
// test.default("existing str translation", (t) => {
|
||||
// internalSetStrings(strings);
|
||||
// t.pass();
|
||||
// });
|
@ -2,9 +2,9 @@
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"lib": ["es6", "DOM"],
|
||||
"jsx": "react",
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "preact",
|
||||
"moduleResolution": "Node",
|
||||
"reactNamespace": "React",
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
"noImplicitAny": true,
|
||||
|
13066
pnpm-lock.yaml
13066
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user