preact routing on the wallet
This commit is contained in:
parent
30f86f8748
commit
4ed4535bc0
@ -10,7 +10,8 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
|
"clean": "rimraf dist lib tsconfig.tsbuildinfo",
|
||||||
"test": "jest ./tests",
|
"test": "jest ./tests",
|
||||||
"compile": "tsc && rollup -c"
|
"compile": "tsc && rollup -c",
|
||||||
|
"watch": "tsc --watch & rollup -w -c"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@gnu-taler/taler-util": "workspace:*",
|
"@gnu-taler/taler-util": "workspace:*",
|
||||||
@ -29,12 +30,14 @@
|
|||||||
"@rollup/plugin-replace": "^2.3.4",
|
"@rollup/plugin-replace": "^2.3.4",
|
||||||
"@testing-library/preact": "^2.0.1",
|
"@testing-library/preact": "^2.0.1",
|
||||||
"@types/chrome": "^0.0.128",
|
"@types/chrome": "^0.0.128",
|
||||||
|
"@types/history": "^4.7.8",
|
||||||
"@types/jest": "^26.0.23",
|
"@types/jest": "^26.0.23",
|
||||||
"@types/node": "^14.14.22",
|
"@types/node": "^14.14.22",
|
||||||
"ava": "3.15.0",
|
"ava": "3.15.0",
|
||||||
"babel-plugin-transform-react-jsx": "^6.24.1",
|
"babel-plugin-transform-react-jsx": "^6.24.1",
|
||||||
"enzyme": "^3.11.0",
|
"enzyme": "^3.11.0",
|
||||||
"enzyme-adapter-preact-pure": "^3.1.0",
|
"enzyme-adapter-preact-pure": "^3.1.0",
|
||||||
|
"history": "4.10.1",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"jest-preset-preact": "^4.0.3",
|
"jest-preset-preact": "^4.0.3",
|
||||||
"preact-cli": "^3.0.5",
|
"preact-cli": "^3.0.5",
|
||||||
|
99
packages/taler-wallet-webextension/src/Application.tsx
Normal file
99
packages/taler-wallet-webextension/src/Application.tsx
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
import Router, { route, Route } from "preact-router";
|
||||||
|
import { createHashHistory } from 'history';
|
||||||
|
import { useEffect } from "preact/hooks";
|
||||||
|
|
||||||
|
import { WalletPopup } from "./pages/popup";
|
||||||
|
import { WithdrawalDialog } from "./pages/withdraw";
|
||||||
|
import { Welcome } from "./pages/welcome";
|
||||||
|
import { TalerPayDialog } from "./pages/pay";
|
||||||
|
import { RefundStatusView } from "./pages/refund";
|
||||||
|
import { TalerTipDialog } from './pages/tip';
|
||||||
|
|
||||||
|
|
||||||
|
export enum Pages {
|
||||||
|
welcome = '/welcome',
|
||||||
|
pay = '/pay',
|
||||||
|
payback = '/payback',
|
||||||
|
refund = '/refund',
|
||||||
|
reset_required = '/reset-required',
|
||||||
|
return_coins = '/return-coins',
|
||||||
|
tips = '/tips',
|
||||||
|
withdraw = '/withdraw',
|
||||||
|
popup = '/popup/:rest',
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Application() {
|
||||||
|
const sp = new URL(document.location.href).searchParams
|
||||||
|
const queryParams: any = {}
|
||||||
|
sp.forEach((v, k) => { queryParams[k] = v; });
|
||||||
|
|
||||||
|
return <Router history={createHashHistory()} >
|
||||||
|
<Route path={Pages.popup} component={WalletPopup} />
|
||||||
|
|
||||||
|
<Route path={Pages.welcome} component={() => {
|
||||||
|
return <section id="main">
|
||||||
|
<div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;">
|
||||||
|
<h1 style="font-family: monospace; font-size: 250%;">
|
||||||
|
<span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<h1>Browser Extension Installed!</h1>
|
||||||
|
<div>
|
||||||
|
<Welcome />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
}} />
|
||||||
|
|
||||||
|
<Route path={Pages.pay} component={() => {
|
||||||
|
return <section id="main">
|
||||||
|
<h1>GNU Taler Wallet</h1>
|
||||||
|
<article class="fade">
|
||||||
|
<TalerPayDialog talerPayUri={queryParams.talerPayUri} />
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
}} />
|
||||||
|
|
||||||
|
<Route path={Pages.refund} component={() => {
|
||||||
|
return <section id="main">
|
||||||
|
<h1>GNU Taler Wallet</h1>
|
||||||
|
<article class="fade">
|
||||||
|
<RefundStatusView talerRefundUri={queryParams.talerRefundUri} />
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
}} />
|
||||||
|
|
||||||
|
<Route path={Pages.tips} component={() => {
|
||||||
|
return <section id="main">
|
||||||
|
<h1>GNU Taler Wallet</h1>
|
||||||
|
<div>
|
||||||
|
<TalerTipDialog talerTipUri={queryParams.talerTipUri} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
}} />
|
||||||
|
<Route path={Pages.withdraw} component={() => {
|
||||||
|
return <section id="main">
|
||||||
|
<div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;">
|
||||||
|
<h1 style="font-family: monospace; font-size: 250%;">
|
||||||
|
<span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div class="fade">
|
||||||
|
<WithdrawalDialog talerWithdrawUri={queryParams.talerWithdrawUri} />
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
}} />
|
||||||
|
|
||||||
|
<Route path={Pages.reset_required} component={() => <div>no yet implemented</div>} />
|
||||||
|
<Route path={Pages.payback} component={() => <div>no yet implemented</div>} />
|
||||||
|
<Route path={Pages.return_coins} component={() => <div>no yet implemented</div>} />
|
||||||
|
|
||||||
|
<Route default component={Redirect} to='/popup/balance' />
|
||||||
|
</Router>
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Redirect({ to }: { to: string }): null {
|
||||||
|
useEffect(() => {
|
||||||
|
route(to, true)
|
||||||
|
})
|
||||||
|
return null
|
||||||
|
}
|
@ -20,50 +20,17 @@
|
|||||||
* @author Florian Dold <dold@taler.net>
|
* @author Florian Dold <dold@taler.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {render} from "preact";
|
import { render } from "preact";
|
||||||
import { createPopup } from "./pages/popup";
|
|
||||||
import { createWithdrawPage } from "./pages/withdraw";
|
|
||||||
import { createWelcomePage } from "./pages/welcome";
|
|
||||||
import { createPayPage } from "./pages/pay";
|
|
||||||
import { createRefundPage } from "./pages/refund";
|
|
||||||
import { setupI18n } from "@gnu-taler/taler-wallet-core";
|
import { setupI18n } from "@gnu-taler/taler-wallet-core";
|
||||||
import { createTipPage } from './pages/tip';
|
import { Application } from './Application';
|
||||||
|
|
||||||
function main(): void {
|
function main(): void {
|
||||||
try {
|
try {
|
||||||
let mainElement;
|
|
||||||
const m = location.pathname.match(/([^/]+)$/);
|
|
||||||
if (!m) {
|
|
||||||
throw Error("can't parse page URL");
|
|
||||||
}
|
|
||||||
const page = m[1];
|
|
||||||
switch (page) {
|
|
||||||
case "popup.html":
|
|
||||||
mainElement = createPopup();
|
|
||||||
break;
|
|
||||||
case "withdraw.html":
|
|
||||||
mainElement = createWithdrawPage();
|
|
||||||
break;
|
|
||||||
case "welcome.html":
|
|
||||||
mainElement = createWelcomePage();
|
|
||||||
break;
|
|
||||||
case "pay.html":
|
|
||||||
mainElement = createPayPage();
|
|
||||||
break;
|
|
||||||
case "refund.html":
|
|
||||||
mainElement = createRefundPage();
|
|
||||||
break;
|
|
||||||
case "tip.html":
|
|
||||||
mainElement = createTipPage();
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw Error(`page '${page}' not implemented`);
|
|
||||||
}
|
|
||||||
const container = document.getElementById("container");
|
const container = document.getElementById("container");
|
||||||
if (!container) {
|
if (!container) {
|
||||||
throw Error("container not found, can't mount page contents");
|
throw Error("container not found, can't mount page contents");
|
||||||
}
|
}
|
||||||
render(mainElement, container);
|
render(Application(), container);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error("got error", e);
|
console.error("got error", e);
|
||||||
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
|
document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`;
|
||||||
|
@ -41,7 +41,11 @@ import {
|
|||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
import { JSX, VNode } from "preact";
|
import { JSX, VNode } from "preact";
|
||||||
|
|
||||||
function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
interface Props {
|
||||||
|
talerPayUri?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TalerPayDialog({ talerPayUri }: Props): JSX.Element {
|
||||||
const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>(undefined);
|
const [payStatus, setPayStatus] = useState<PreparePayResult | undefined>(undefined);
|
||||||
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined);
|
const [payResult, setPayResult] = useState<ConfirmPayResult | undefined>(undefined);
|
||||||
const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
|
const [payErrMsg, setPayErrMsg] = useState<string | undefined>("");
|
||||||
@ -50,6 +54,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
let totalFees: AmountJson | undefined = undefined;
|
let totalFees: AmountJson | undefined = undefined;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!talerPayUri) return;
|
||||||
const doFetch = async (): Promise<void> => {
|
const doFetch = async (): Promise<void> => {
|
||||||
const p = await wxApi.preparePay(talerPayUri);
|
const p = await wxApi.preparePay(talerPayUri);
|
||||||
setPayStatus(p);
|
setPayStatus(p);
|
||||||
@ -57,6 +62,10 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
doFetch();
|
doFetch();
|
||||||
}, [numTries, talerPayUri]);
|
}, [numTries, talerPayUri]);
|
||||||
|
|
||||||
|
if (!talerPayUri) {
|
||||||
|
return <span>missing pay uri</span>
|
||||||
|
}
|
||||||
|
|
||||||
if (!payStatus) {
|
if (!payStatus) {
|
||||||
return <span>Loading payment information ...</span>;
|
return <span>Loading payment information ...</span>;
|
||||||
}
|
}
|
||||||
@ -83,7 +92,7 @@ function TalerPayDialog({ talerPayUri }: { talerPayUri: string }): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
<span>
|
<span>
|
||||||
You have already paid for this article. Click{" "}
|
You have already paid for this article. Click{" "}
|
||||||
<a href={fulfillmentUrl}>here</a> to view it again.
|
<a href={fulfillmentUrl} target="_bank" rel="external">here</a> to view it again.
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
@ -24,9 +24,7 @@
|
|||||||
/**
|
/**
|
||||||
* Imports.
|
* Imports.
|
||||||
*/
|
*/
|
||||||
import * as i18n from "../i18n";
|
import {
|
||||||
|
|
||||||
import {
|
|
||||||
AmountJson,
|
AmountJson,
|
||||||
Amounts,
|
Amounts,
|
||||||
BalancesResponse,
|
BalancesResponse,
|
||||||
@ -40,121 +38,43 @@ import {
|
|||||||
Timestamp,
|
Timestamp,
|
||||||
amountFractionalBase,
|
amountFractionalBase,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
|
import { Component, ComponentChildren, JSX } from "preact";
|
||||||
import { renderAmount, PageLink } from "../renderHtml";
|
import { route, Route, Router } from 'preact-router';
|
||||||
|
import { Match } from 'preact-router/match';
|
||||||
|
import { useEffect, useState } from "preact/hooks";
|
||||||
|
import * as i18n from "../i18n";
|
||||||
|
import { PageLink, renderAmount } from "../renderHtml";
|
||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
|
|
||||||
import { useState, useEffect } from "preact/hooks";
|
|
||||||
|
|
||||||
import { PermissionsCheckbox } from "./welcome";
|
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
|
|
||||||
|
|
||||||
class Router extends Component<any, any> {
|
|
||||||
static setRoute(s: string): void {
|
|
||||||
window.location.hash = s;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getRoute(): string {
|
|
||||||
// Omit the '#' at the beginning
|
|
||||||
return window.location.hash.substring(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static onRoute(f: any): () => void {
|
|
||||||
Router.routeHandlers.push(f);
|
|
||||||
return () => {
|
|
||||||
const i = Router.routeHandlers.indexOf(f);
|
|
||||||
this.routeHandlers = this.routeHandlers.splice(i, 1);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static routeHandlers: any[] = [];
|
|
||||||
|
|
||||||
componentWillMount(): void {
|
|
||||||
console.log("router mounted");
|
|
||||||
window.onhashchange = () => {
|
|
||||||
this.setState({});
|
|
||||||
for (const f of Router.routeHandlers) {
|
|
||||||
f();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): JSX.Element {
|
|
||||||
const route = window.location.hash.substring(1);
|
|
||||||
console.log("rendering route", route);
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (childProps.route === route) {
|
|
||||||
foundChild = child;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
const c: ComponentChild | null = foundChild || defaultChild;
|
|
||||||
if (!c) {
|
|
||||||
throw Error("unknown route");
|
|
||||||
}
|
|
||||||
Router.setRoute((c as any).props.route);
|
|
||||||
return <div>{c}</div>;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TabProps {
|
interface TabProps {
|
||||||
target: string;
|
target: string;
|
||||||
|
current?: string;
|
||||||
children?: ComponentChildren;
|
children?: ComponentChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
function Tab(props: TabProps): JSX.Element {
|
function Tab(props: TabProps): JSX.Element {
|
||||||
let cssClass = "";
|
let cssClass = "";
|
||||||
if (props.target === Router.getRoute()) {
|
if (props.current === props.target) {
|
||||||
cssClass = "active";
|
cssClass = "active";
|
||||||
}
|
}
|
||||||
const onClick = (e: JSXInternal.TargetedMouseEvent<HTMLAnchorElement>): void => {
|
|
||||||
Router.setRoute(props.target);
|
|
||||||
e.preventDefault();
|
|
||||||
};
|
|
||||||
return (
|
return (
|
||||||
<a onClick={onClick} href={props.target} className={cssClass}>
|
<a href={props.target} className={cssClass}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</a>
|
</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class WalletNavBar extends Component<any, any> {
|
function WalletNavBar({ current }: { current?: string }) {
|
||||||
private cancelSubscription: any;
|
|
||||||
|
|
||||||
componentWillMount(): void {
|
|
||||||
this.cancelSubscription = Router.onRoute(() => {
|
|
||||||
this.setState({});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
componentWillUnmount(): void {
|
|
||||||
if (this.cancelSubscription) {
|
|
||||||
this.cancelSubscription();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render(): JSX.Element {
|
|
||||||
console.log("rendering nav bar");
|
|
||||||
return (
|
return (
|
||||||
<div className="nav" id="header">
|
<div className="nav" id="header">
|
||||||
<Tab target="/balance">{i18n.str`Balance`}</Tab>
|
<Tab target="/popup/balance" current={current}>{i18n.str`Balance`}</Tab>
|
||||||
<Tab target="/history">{i18n.str`History`}</Tab>
|
<Tab target="/popup/history" current={current}>{i18n.str`History`}</Tab>
|
||||||
<Tab target="/settings">{i18n.str`Settings`}</Tab>
|
<Tab target="/popup/settings" current={current}>{i18n.str`Settings`}</Tab>
|
||||||
<Tab target="/debug">{i18n.str`Debug`}</Tab>
|
<Tab target="/popup/debug" current={current}>{i18n.str`Debug`}</Tab>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -174,7 +94,7 @@ function EmptyBalanceView(): JSX.Element {
|
|||||||
return (
|
return (
|
||||||
<i18n.Translate wrap="p">
|
<i18n.Translate wrap="p">
|
||||||
You have no balance to show. Need some{" "}
|
You have no balance to show. Need some{" "}
|
||||||
<PageLink pageName="welcome.html">help</PageLink> getting started?
|
<PageLink pageName="/welcome">help</PageLink> getting started?
|
||||||
</i18n.Translate>
|
</i18n.Translate>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -494,7 +414,7 @@ function WalletHistory(props: any): JSX.Element {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{txs.map((tx,i) => (
|
{txs.map((tx, i) => (
|
||||||
<TransactionItem key={i} tx={tx} />
|
<TransactionItem key={i} tx={tx} />
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
@ -634,7 +554,7 @@ async function findTalerUriInActiveTab(): Promise<string | undefined> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function WalletPopup(): JSX.Element {
|
export function WalletPopup(): JSX.Element {
|
||||||
const [talerActionUrl, setTalerActionUrl] = useState<string | undefined>(
|
const [talerActionUrl, setTalerActionUrl] = useState<string | undefined>(
|
||||||
undefined,
|
undefined,
|
||||||
);
|
);
|
||||||
@ -671,19 +591,29 @@ function WalletPopup(): JSX.Element {
|
|||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<WalletNavBar />
|
<Match>{({ path }: any) => <WalletNavBar current={path} />}</Match>
|
||||||
<div style={{ margin: "1em" }}>
|
<div style={{ margin: "1em" }}>
|
||||||
<Router>
|
<Router>
|
||||||
<WalletBalanceView route="/balance" default />
|
<Route path={Pages.balance} component={WalletBalanceView} />
|
||||||
<WalletSettings route="/settings" />
|
<Route path={Pages.settings} component={WalletSettings} />
|
||||||
<WalletDebug route="/debug" />
|
<Route path={Pages.debug} component={WalletDebug} />
|
||||||
<WalletHistory route="/history" />
|
<Route path={Pages.history} component={WalletHistory} />
|
||||||
</Router>
|
</Router>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createPopup(): JSX.Element {
|
enum Pages {
|
||||||
return <WalletPopup />;
|
balance = '/popup/balance',
|
||||||
|
settings = '/popup/settings',
|
||||||
|
debug = '/popup/debug',
|
||||||
|
history = '/popup/history',
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Redirect({ to }: { to: string }): null {
|
||||||
|
useEffect(() => {
|
||||||
|
route(to, true)
|
||||||
|
})
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
@ -26,18 +26,22 @@ import {
|
|||||||
ApplyRefundResponse,
|
ApplyRefundResponse,
|
||||||
Amounts,
|
Amounts,
|
||||||
} from "@gnu-taler/taler-util";
|
} from "@gnu-taler/taler-util";
|
||||||
// import { h } from 'preact';
|
|
||||||
import { useEffect, useState } from "preact/hooks";
|
import { useEffect, useState } from "preact/hooks";
|
||||||
import { JSX } from "preact/jsx-runtime";
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
function RefundStatusView(props: { talerRefundUri: string }): JSX.Element {
|
interface Props {
|
||||||
const [applyResult, setApplyResult] = useState<ApplyRefundResponse|undefined>(undefined);
|
talerRefundUri?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function RefundStatusView({ talerRefundUri }: Props): JSX.Element {
|
||||||
|
const [applyResult, setApplyResult] = useState<ApplyRefundResponse | undefined>(undefined);
|
||||||
const [errMsg, setErrMsg] = useState<string | undefined>(undefined);
|
const [errMsg, setErrMsg] = useState<string | undefined>(undefined);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!talerRefundUri) return;
|
||||||
const doFetch = async (): Promise<void> => {
|
const doFetch = async (): Promise<void> => {
|
||||||
try {
|
try {
|
||||||
const result = await wxApi.applyRefund(props.talerRefundUri);
|
const result = await wxApi.applyRefund(talerRefundUri);
|
||||||
setApplyResult(result);
|
setApplyResult(result);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
@ -46,10 +50,14 @@ function RefundStatusView(props: { talerRefundUri: string }): JSX.Element {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
doFetch();
|
doFetch();
|
||||||
}, [props.talerRefundUri]);
|
}, [talerRefundUri]);
|
||||||
|
|
||||||
console.log("rendering");
|
console.log("rendering");
|
||||||
|
|
||||||
|
if (!talerRefundUri) {
|
||||||
|
return <span>missing taler refund uri</span>;
|
||||||
|
}
|
||||||
|
|
||||||
if (errMsg) {
|
if (errMsg) {
|
||||||
return <span>Error: {errMsg}</span>;
|
return <span>Error: {errMsg}</span>;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,11 @@ import { AmountView } from "../renderHtml";
|
|||||||
import * as wxApi from "../wxApi";
|
import * as wxApi from "../wxApi";
|
||||||
import { JSX } from "preact/jsx-runtime";
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
function TalerTipDialog({ talerTipUri }: { talerTipUri: string }): JSX.Element {
|
interface Props {
|
||||||
|
talerTipUri?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TalerTipDialog({ talerTipUri }: Props): JSX.Element {
|
||||||
const [updateCounter, setUpdateCounter] = useState<number>(0);
|
const [updateCounter, setUpdateCounter] = useState<number>(0);
|
||||||
const [prepareTipResult, setPrepareTipResult] = useState<
|
const [prepareTipResult, setPrepareTipResult] = useState<
|
||||||
PrepareTipResult | undefined
|
PrepareTipResult | undefined
|
||||||
@ -35,6 +39,7 @@ function TalerTipDialog({ talerTipUri }: { talerTipUri: string }): JSX.Element {
|
|||||||
const [tipIgnored, setTipIgnored] = useState(false);
|
const [tipIgnored, setTipIgnored] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!talerTipUri) return;
|
||||||
const doFetch = async (): Promise<void> => {
|
const doFetch = async (): Promise<void> => {
|
||||||
const p = await wxApi.prepareTip({ talerTipUri });
|
const p = await wxApi.prepareTip({ talerTipUri });
|
||||||
setPrepareTipResult(p);
|
setPrepareTipResult(p);
|
||||||
@ -54,6 +59,10 @@ function TalerTipDialog({ talerTipUri }: { talerTipUri: string }): JSX.Element {
|
|||||||
setTipIgnored(true);
|
setTipIgnored(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (!talerTipUri) {
|
||||||
|
return <span>missing tip uri</span>;
|
||||||
|
}
|
||||||
|
|
||||||
if (tipIgnored) {
|
if (tipIgnored) {
|
||||||
return <span>You've ignored the tip.</span>;
|
return <span>You've ignored the tip.</span>;
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ function Diagnostics(): JSX.Element | null {
|
|||||||
<p>
|
<p>
|
||||||
Your wallet database is outdated. Currently automatic migration is
|
Your wallet database is outdated. Currently automatic migration is
|
||||||
not supported. Please go{" "}
|
not supported. Please go{" "}
|
||||||
<PageLink pageName="reset-required.html">here</PageLink> to reset
|
<PageLink pageName="/reset-required">here</PageLink> to reset
|
||||||
the wallet database.
|
the wallet database.
|
||||||
</p>
|
</p>
|
||||||
) : null}
|
) : null}
|
||||||
@ -99,13 +99,11 @@ function Diagnostics(): JSX.Element | null {
|
|||||||
return <p>Running diagnostics ...</p>;
|
return <p>Running diagnostics ...</p>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PermissionsCheckbox(): JSX.Element {
|
|
||||||
const [extendedPermissionsEnabled, setExtendedPermissionsEnabled] = useState(
|
async function handleExtendedPerm(isEnabled: boolean, setEnable: (v:boolean) => void): Promise<void> {
|
||||||
false,
|
|
||||||
);
|
|
||||||
async function handleExtendedPerm(): Promise<void> {
|
|
||||||
let nextVal: boolean | undefined;
|
let nextVal: boolean | undefined;
|
||||||
if (extendedPermissionsEnabled) {
|
|
||||||
|
if (!isEnabled) {
|
||||||
const granted = await new Promise<boolean>((resolve, reject) => {
|
const granted = await new Promise<boolean>((resolve, reject) => {
|
||||||
// We set permissions here, since apparently FF wants this to be done
|
// We set permissions here, since apparently FF wants this to be done
|
||||||
// as the result of an input event ...
|
// as the result of an input event ...
|
||||||
@ -121,16 +119,18 @@ export function PermissionsCheckbox(): JSX.Element {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
const res = await wxApi.setExtendedPermissions(granted);
|
const res = await wxApi.setExtendedPermissions(granted);
|
||||||
console.log(res);
|
|
||||||
nextVal = res.newValue;
|
nextVal = res.newValue;
|
||||||
} else {
|
} else {
|
||||||
const res = await wxApi.setExtendedPermissions(false);
|
const res = await wxApi.setExtendedPermissions(false);
|
||||||
console.log(res);
|
|
||||||
nextVal = res.newValue;
|
nextVal = res.newValue;
|
||||||
}
|
}
|
||||||
console.log("new permissions applied:", nextVal);
|
console.log("new permissions applied:", nextVal);
|
||||||
setExtendedPermissionsEnabled(nextVal ?? false);
|
setEnable(nextVal ?? false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function PermissionsCheckbox(): JSX.Element {
|
||||||
|
const [extendedPermissionsEnabled, setExtendedPermissionsEnabled] = useState(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
async function getExtendedPermValue(): Promise<void> {
|
async function getExtendedPermValue(): Promise<void> {
|
||||||
const res = await wxApi.getExtendedPermissions();
|
const res = await wxApi.getExtendedPermissions();
|
||||||
@ -138,11 +138,12 @@ export function PermissionsCheckbox(): JSX.Element {
|
|||||||
}
|
}
|
||||||
getExtendedPermValue();
|
getExtendedPermValue();
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<input
|
<input
|
||||||
checked={extendedPermissionsEnabled}
|
checked={extendedPermissionsEnabled}
|
||||||
onChange={() => handleExtendedPerm()}
|
onChange={() => handleExtendedPerm(extendedPermissionsEnabled, setExtendedPermissionsEnabled) }
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
id="checkbox-perm"
|
id="checkbox-perm"
|
||||||
style={{ width: "1.5em", height: "1.5em", verticalAlign: "middle" }}
|
style={{ width: "1.5em", height: "1.5em", verticalAlign: "middle" }}
|
||||||
@ -168,7 +169,7 @@ export function PermissionsCheckbox(): JSX.Element {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function Welcome(): JSX.Element {
|
export function Welcome(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<p>Thank you for installing the wallet.</p>
|
<p>Thank you for installing the wallet.</p>
|
||||||
|
@ -34,12 +34,14 @@ import {
|
|||||||
import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
|
import { WithdrawUriInfoResponse } from "@gnu-taler/taler-util";
|
||||||
import { JSX } from "preact/jsx-runtime";
|
import { JSX } from "preact/jsx-runtime";
|
||||||
|
|
||||||
function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
|
interface Props {
|
||||||
|
talerWithdrawUri?: string;
|
||||||
|
}
|
||||||
|
export function WithdrawalDialog({ talerWithdrawUri }: Props): JSX.Element {
|
||||||
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
|
const [details, setDetails] = useState<WithdrawUriInfoResponse | undefined>(undefined);
|
||||||
const [selectedExchange, setSelectedExchange] = useState<
|
const [selectedExchange, setSelectedExchange] = useState<
|
||||||
string | undefined
|
string | undefined
|
||||||
>(undefined);
|
>(undefined);
|
||||||
const talerWithdrawUri = props.talerWithdrawUri;
|
|
||||||
const [cancelled, setCancelled] = useState(false);
|
const [cancelled, setCancelled] = useState(false);
|
||||||
const [selecting, setSelecting] = useState(false);
|
const [selecting, setSelecting] = useState(false);
|
||||||
const [errMsg, setErrMsg] = useState<string | undefined>("");
|
const [errMsg, setErrMsg] = useState<string | undefined>("");
|
||||||
@ -52,10 +54,9 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
|
|||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!talerWithdrawUri) return
|
||||||
const fetchData = async (): Promise<void> => {
|
const fetchData = async (): Promise<void> => {
|
||||||
const res = await getWithdrawalDetailsForUri({
|
const res = await getWithdrawalDetailsForUri({ talerWithdrawUri });
|
||||||
talerWithdrawUri: props.talerWithdrawUri,
|
|
||||||
});
|
|
||||||
setDetails(res);
|
setDetails(res);
|
||||||
if (res.defaultExchangeBaseUrl) {
|
if (res.defaultExchangeBaseUrl) {
|
||||||
setSelectedExchange(res.defaultExchangeBaseUrl);
|
setSelectedExchange(res.defaultExchangeBaseUrl);
|
||||||
@ -64,6 +65,10 @@ function WithdrawalDialog(props: { talerWithdrawUri: string }): JSX.Element {
|
|||||||
fetchData();
|
fetchData();
|
||||||
}, [selectedExchange, errMsg, selecting, talerWithdrawUri, updateCounter]);
|
}, [selectedExchange, errMsg, selecting, talerWithdrawUri, updateCounter]);
|
||||||
|
|
||||||
|
if (!talerWithdrawUri) {
|
||||||
|
return <span>missing withdraw uri</span>;
|
||||||
|
}
|
||||||
|
|
||||||
if (!details) {
|
if (!details) {
|
||||||
return <span>Loading...</span>;
|
return <span>Loading...</span>;
|
||||||
}
|
}
|
||||||
|
@ -167,7 +167,7 @@ export function ProgressButton({isLoading, ...rest}: LoadingButtonProps): JSX.El
|
|||||||
export function PageLink(
|
export function PageLink(
|
||||||
props: { pageName: string, children?: ComponentChildren },
|
props: { pageName: string, children?: ComponentChildren },
|
||||||
): JSX.Element {
|
): JSX.Element {
|
||||||
const url = chrome.extension.getURL(`/${props.pageName}`);
|
const url = chrome.extension.getURL(`/static/popup.html#/${props.pageName}`);
|
||||||
return (
|
return (
|
||||||
<a
|
<a
|
||||||
className="actionLink"
|
className="actionLink"
|
||||||
|
@ -276,7 +276,7 @@ try {
|
|||||||
chrome.runtime.onInstalled.addListener((details) => {
|
chrome.runtime.onInstalled.addListener((details) => {
|
||||||
console.log("onInstalled with reason", details.reason);
|
console.log("onInstalled with reason", details.reason);
|
||||||
if (details.reason === "install") {
|
if (details.reason === "install") {
|
||||||
const url = chrome.extension.getURL("/static/welcome.html");
|
const url = chrome.extension.getURL("/static/popup.html#/welcome");
|
||||||
chrome.tabs.create({ active: true, url: url });
|
chrome.tabs.create({ active: true, url: url });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -311,7 +311,7 @@ function headerListener(
|
|||||||
switch (uriType) {
|
switch (uriType) {
|
||||||
case TalerUriType.TalerWithdraw:
|
case TalerUriType.TalerWithdraw:
|
||||||
return makeSyncWalletRedirect(
|
return makeSyncWalletRedirect(
|
||||||
"/static/withdraw.html",
|
"/static/popup.html#/withdraw",
|
||||||
details.tabId,
|
details.tabId,
|
||||||
details.url,
|
details.url,
|
||||||
{
|
{
|
||||||
@ -320,7 +320,7 @@ function headerListener(
|
|||||||
);
|
);
|
||||||
case TalerUriType.TalerPay:
|
case TalerUriType.TalerPay:
|
||||||
return makeSyncWalletRedirect(
|
return makeSyncWalletRedirect(
|
||||||
"/static/pay.html",
|
"/static/popup.html#/pay",
|
||||||
details.tabId,
|
details.tabId,
|
||||||
details.url,
|
details.url,
|
||||||
{
|
{
|
||||||
@ -329,7 +329,7 @@ function headerListener(
|
|||||||
);
|
);
|
||||||
case TalerUriType.TalerTip:
|
case TalerUriType.TalerTip:
|
||||||
return makeSyncWalletRedirect(
|
return makeSyncWalletRedirect(
|
||||||
"/static/tip.html",
|
"/static/popup.html#/tip",
|
||||||
details.tabId,
|
details.tabId,
|
||||||
details.url,
|
details.url,
|
||||||
{
|
{
|
||||||
@ -338,7 +338,7 @@ function headerListener(
|
|||||||
);
|
);
|
||||||
case TalerUriType.TalerRefund:
|
case TalerUriType.TalerRefund:
|
||||||
return makeSyncWalletRedirect(
|
return makeSyncWalletRedirect(
|
||||||
"/static/refund.html",
|
"/static/popup.html#/refund",
|
||||||
details.tabId,
|
details.tabId,
|
||||||
details.url,
|
details.url,
|
||||||
{
|
{
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
|
|
||||||
<title>Taler Wallet: Add Auditor</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/style/wallet.css" />
|
|
||||||
|
|
||||||
<link rel="icon" href="/img/icon.png" />
|
|
||||||
|
|
||||||
<script src="/pageEntryPoint.js"></script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.tree-item {
|
|
||||||
margin: 2em;
|
|
||||||
border-radius: 5px;
|
|
||||||
border: 1px solid gray;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
.button-linky {
|
|
||||||
background: none;
|
|
||||||
color: black;
|
|
||||||
text-decoration: underline;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="container"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,35 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet: Auditors</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/style/wallet.css" />
|
|
||||||
|
|
||||||
<link rel="icon" href="/img/icon.png" />
|
|
||||||
|
|
||||||
<script src="/dist/webextension/pageEntryPoint.js"></script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-size: 100%;
|
|
||||||
}
|
|
||||||
.tree-item {
|
|
||||||
margin: 2em;
|
|
||||||
border-radius: 5px;
|
|
||||||
border: 1px solid gray;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
.button-linky {
|
|
||||||
background: none;
|
|
||||||
color: black;
|
|
||||||
text-decoration: underline;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="container"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,16 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet: Benchmarks</title>
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/wallet.css" />
|
|
||||||
<link rel="icon" href="/static/img/icon.png" />
|
|
||||||
<script src="/dist/pageEntryPoint.js"></script>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<section id="main">
|
|
||||||
<h1>Benchmarks</h1>
|
|
||||||
<div id="container"></div>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,73 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet: Confirm Contract</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/pure.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/wallet.css" />
|
|
||||||
<link rel="icon" href="/static/img/icon.png" />
|
|
||||||
<script src="/dist/pageEntryPoint.js"></script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
button.accept {
|
|
||||||
background-color: #5757d2;
|
|
||||||
border: 1px solid black;
|
|
||||||
border-radius: 5px;
|
|
||||||
margin: 1em 0;
|
|
||||||
padding: 0.5em;
|
|
||||||
font-weight: bold;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
button.linky {
|
|
||||||
background: none !important;
|
|
||||||
border: none;
|
|
||||||
padding: 0 !important;
|
|
||||||
|
|
||||||
font-family: arial, sans-serif;
|
|
||||||
color: #069;
|
|
||||||
text-decoration: underline;
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
input.url {
|
|
||||||
width: 25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
button.accept:disabled {
|
|
||||||
background-color: #dedbe8;
|
|
||||||
border: 1px solid white;
|
|
||||||
border-radius: 5px;
|
|
||||||
margin: 1em 0;
|
|
||||||
padding: 0.5em;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #2c2c2c;
|
|
||||||
}
|
|
||||||
|
|
||||||
.errorbox {
|
|
||||||
border: 1px solid;
|
|
||||||
display: inline-block;
|
|
||||||
margin: 1em;
|
|
||||||
padding: 1em;
|
|
||||||
font-weight: bold;
|
|
||||||
background: #ff8a8a;
|
|
||||||
}
|
|
||||||
|
|
||||||
.okaybox {
|
|
||||||
border: 1px solid;
|
|
||||||
display: inline-block;
|
|
||||||
margin: 1em;
|
|
||||||
padding: 1em;
|
|
||||||
font-weight: bold;
|
|
||||||
background: #00fa9a;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<section id="main">
|
|
||||||
<h1>GNU Taler Wallet</h1>
|
|
||||||
<article id="container" class="fade"></article>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,34 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet: Payback</title>
|
|
||||||
|
|
||||||
<link rel="stylesheet" type="text/css" href="/style/pure.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/style/wallet.css" />
|
|
||||||
<link rel="icon" href="/img/icon.png" />
|
|
||||||
<script src="/pageEntryPoint.js"></script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-size: 100%;
|
|
||||||
}
|
|
||||||
.tree-item {
|
|
||||||
margin: 2em;
|
|
||||||
border-radius: 5px;
|
|
||||||
border: 1px solid gray;
|
|
||||||
padding: 1em;
|
|
||||||
}
|
|
||||||
.button-linky {
|
|
||||||
background: none;
|
|
||||||
color: black;
|
|
||||||
text-decoration: underline;
|
|
||||||
border: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div id="container"></div>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,19 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet: Refund Status</title>
|
|
||||||
|
|
||||||
<link rel="icon" href="/static/img/icon.png" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/pure.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/wallet.css" />
|
|
||||||
<script src="/dist/pageEntryPoint.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<section id="main">
|
|
||||||
<h1>GNU Taler Wallet</h1>
|
|
||||||
<article id="container" class="fade"></article>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,25 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet: Select Taler Provider</title>
|
|
||||||
|
|
||||||
<link rel="icon" href="/img/icon.png" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/style/pure.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/style/wallet.css" />
|
|
||||||
<script src="/pageEntryPoint.js"></script>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
body {
|
|
||||||
font-size: 100%;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<section id="main">
|
|
||||||
<div id="container"></div>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
body {
|
body {
|
||||||
min-height: 20em;
|
min-height: 20em;
|
||||||
width: 30em;
|
/* width: 30em; */
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
max-height: 800px;
|
max-height: 800px;
|
||||||
@ -183,3 +183,58 @@ input[type="radio"] {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
padding-top: 2em;
|
padding-top: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
pay html
|
||||||
|
*/
|
||||||
|
button.accept {
|
||||||
|
background-color: #5757d2;
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 1em 0;
|
||||||
|
padding: 0.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
button.linky {
|
||||||
|
background: none !important;
|
||||||
|
border: none;
|
||||||
|
padding: 0 !important;
|
||||||
|
|
||||||
|
font-family: arial, sans-serif;
|
||||||
|
color: #069;
|
||||||
|
text-decoration: underline;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.url {
|
||||||
|
width: 25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.accept:disabled {
|
||||||
|
background-color: #dedbe8;
|
||||||
|
border: 1px solid white;
|
||||||
|
border-radius: 5px;
|
||||||
|
margin: 1em 0;
|
||||||
|
padding: 0.5em;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #2c2c2c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.errorbox {
|
||||||
|
border: 1px solid;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
background: #ff8a8a;
|
||||||
|
}
|
||||||
|
|
||||||
|
.okaybox {
|
||||||
|
border: 1px solid;
|
||||||
|
display: inline-block;
|
||||||
|
margin: 1em;
|
||||||
|
padding: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
background: #00fa9a;
|
||||||
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet: Received Tip</title>
|
|
||||||
|
|
||||||
<link rel="icon" href="/static/img/icon.png" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/pure.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/wallet.css" />
|
|
||||||
<script src="/dist/pageEntryPoint.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<section id="main">
|
|
||||||
<h1>GNU Taler Wallet</h1>
|
|
||||||
<div id="container"></div>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,24 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet Installed</title>
|
|
||||||
|
|
||||||
<link rel="icon" href="/static/img/icon.png" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/pure.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/wallet.css" />
|
|
||||||
<script src="/dist/pageEntryPoint.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<section id="main">
|
|
||||||
<div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;">
|
|
||||||
<h1 style="font-family: monospace; font-size: 250%;">
|
|
||||||
<span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<h1>Browser Extension Installed!</h1>
|
|
||||||
<div id="container">Loading...</div>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -1,22 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html>
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<title>Taler Wallet: Withdraw</title>
|
|
||||||
<link rel="icon" href="/static/img/icon.png" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/pure.css" />
|
|
||||||
<link rel="stylesheet" type="text/css" href="/static/style/wallet.css" />
|
|
||||||
<script src="/dist/pageEntryPoint.js"></script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<section id="main">
|
|
||||||
<div style="border-bottom: 3px dashed #aa3939; margin-bottom: 2em;">
|
|
||||||
<h1 style="font-family: monospace; font-size: 250%;">
|
|
||||||
<span style="color: #aa3939;">❰</span>Taler Wallet<span style="color: #aa3939;">❱</span>
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
<div class="fade" id="container"></div>
|
|
||||||
</section>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
@ -216,12 +216,14 @@ importers:
|
|||||||
'@rollup/plugin-replace': ^2.3.4
|
'@rollup/plugin-replace': ^2.3.4
|
||||||
'@testing-library/preact': ^2.0.1
|
'@testing-library/preact': ^2.0.1
|
||||||
'@types/chrome': ^0.0.128
|
'@types/chrome': ^0.0.128
|
||||||
|
'@types/history': ^4.7.8
|
||||||
'@types/jest': ^26.0.23
|
'@types/jest': ^26.0.23
|
||||||
'@types/node': ^14.14.22
|
'@types/node': ^14.14.22
|
||||||
ava: 3.15.0
|
ava: 3.15.0
|
||||||
babel-plugin-transform-react-jsx: ^6.24.1
|
babel-plugin-transform-react-jsx: ^6.24.1
|
||||||
enzyme: ^3.11.0
|
enzyme: ^3.11.0
|
||||||
enzyme-adapter-preact-pure: ^3.1.0
|
enzyme-adapter-preact-pure: ^3.1.0
|
||||||
|
history: 4.10.1
|
||||||
jest: ^26.6.3
|
jest: ^26.6.3
|
||||||
jest-preset-preact: ^4.0.3
|
jest-preset-preact: ^4.0.3
|
||||||
preact: ^10.5.13
|
preact: ^10.5.13
|
||||||
@ -251,12 +253,14 @@ importers:
|
|||||||
'@rollup/plugin-replace': 2.3.4_rollup@2.37.1
|
'@rollup/plugin-replace': 2.3.4_rollup@2.37.1
|
||||||
'@testing-library/preact': 2.0.1_preact@10.5.13
|
'@testing-library/preact': 2.0.1_preact@10.5.13
|
||||||
'@types/chrome': 0.0.128
|
'@types/chrome': 0.0.128
|
||||||
|
'@types/history': 4.7.8
|
||||||
'@types/jest': 26.0.23
|
'@types/jest': 26.0.23
|
||||||
'@types/node': 14.14.22
|
'@types/node': 14.14.22
|
||||||
ava: 3.15.0
|
ava: 3.15.0
|
||||||
babel-plugin-transform-react-jsx: 6.24.1
|
babel-plugin-transform-react-jsx: 6.24.1
|
||||||
enzyme: 3.11.0
|
enzyme: 3.11.0
|
||||||
enzyme-adapter-preact-pure: 3.1.0_enzyme@3.11.0+preact@10.5.13
|
enzyme-adapter-preact-pure: 3.1.0_enzyme@3.11.0+preact@10.5.13
|
||||||
|
history: 4.10.1
|
||||||
jest: 26.6.3
|
jest: 26.6.3
|
||||||
jest-preset-preact: 4.0.3_669f037bdb6c36f0a67e918c516dafdd
|
jest-preset-preact: 4.0.3_669f037bdb6c36f0a67e918c516dafdd
|
||||||
preact-cli: 3.0.5_c069246dc1d99535ac277c76f8ef56e0
|
preact-cli: 3.0.5_c069246dc1d99535ac277c76f8ef56e0
|
||||||
@ -2178,6 +2182,10 @@ packages:
|
|||||||
resolution: {integrity: sha512-IG8AE1m2pWtPqQ7wXhFhy6Q59bwwnLwO36v5Rit2FrbXCIp8Sk8E2PfUCreyrdo17STwFSKDAkitVuVYbpEHvQ==}
|
resolution: {integrity: sha512-IG8AE1m2pWtPqQ7wXhFhy6Q59bwwnLwO36v5Rit2FrbXCIp8Sk8E2PfUCreyrdo17STwFSKDAkitVuVYbpEHvQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/history/4.7.8:
|
||||||
|
resolution: {integrity: sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/istanbul-lib-coverage/2.0.3:
|
/@types/istanbul-lib-coverage/2.0.3:
|
||||||
resolution: {integrity: sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==}
|
resolution: {integrity: sha512-sz7iLqvVUg1gIedBOvlkxPlc8/uVzyS5OwGz1cKjXzkl3FpL3al0crU8YGU1WoHkxn0Wxbw5tyi6hvzJKNzFsw==}
|
||||||
dev: true
|
dev: true
|
||||||
@ -6569,6 +6577,17 @@ packages:
|
|||||||
resolution: {integrity: sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==}
|
resolution: {integrity: sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/history/4.10.1:
|
||||||
|
resolution: {integrity: sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==}
|
||||||
|
dependencies:
|
||||||
|
'@babel/runtime': 7.14.0
|
||||||
|
loose-envify: 1.4.0
|
||||||
|
resolve-pathname: 3.0.0
|
||||||
|
tiny-invariant: 1.1.0
|
||||||
|
tiny-warning: 1.0.3
|
||||||
|
value-equal: 1.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/hmac-drbg/1.0.1:
|
/hmac-drbg/1.0.1:
|
||||||
resolution: {integrity: sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=}
|
resolution: {integrity: sha1-0nRXAQJabHdabFRXk+1QL8DGSaE=}
|
||||||
dependencies:
|
dependencies:
|
||||||
@ -10818,6 +10837,10 @@ packages:
|
|||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/resolve-pathname/3.0.0:
|
||||||
|
resolution: {integrity: sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/resolve-url/0.2.1:
|
/resolve-url/0.2.1:
|
||||||
resolution: {integrity: sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=}
|
resolution: {integrity: sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=}
|
||||||
deprecated: https://github.com/lydell/resolve-url#deprecated
|
deprecated: https://github.com/lydell/resolve-url#deprecated
|
||||||
@ -12097,6 +12120,14 @@ packages:
|
|||||||
resolution: {integrity: sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=}
|
resolution: {integrity: sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/tiny-invariant/1.1.0:
|
||||||
|
resolution: {integrity: sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/tiny-warning/1.0.3:
|
||||||
|
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/tmpl/1.0.4:
|
/tmpl/1.0.4:
|
||||||
resolution: {integrity: sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=}
|
resolution: {integrity: sha1-I2QN17QtAEM5ERQIIOXPRA5SHdE=}
|
||||||
dev: true
|
dev: true
|
||||||
@ -12674,6 +12705,10 @@ packages:
|
|||||||
engines: {node: '>= 0.10'}
|
engines: {node: '>= 0.10'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/value-equal/1.0.1:
|
||||||
|
resolution: {integrity: sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/vary/1.1.2:
|
/vary/1.1.2:
|
||||||
resolution: {integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=}
|
resolution: {integrity: sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=}
|
||||||
engines: {node: '>= 0.8'}
|
engines: {node: '>= 0.8'}
|
||||||
|
Loading…
Reference in New Issue
Block a user