mui button impl

This commit is contained in:
Sebastian 2022-06-01 15:47:47 -03:00
parent 2aade8e7ae
commit af7b107f45
No known key found for this signature in database
GPG Key ID: BE4FF68352439FC1
37 changed files with 476 additions and 367 deletions

View File

@ -77,8 +77,8 @@ export const BasicExample = (): VNode => (
]}
confirm={{
label: "turn on wifi",
action: () => {
return null;
action: async () => {
return;
},
}}
/>

View File

@ -15,7 +15,7 @@ interface Props extends JSX.HTMLAttributes<HTMLDivElement> {
}[];
confirm?: {
label: string;
action: () => void;
action: () => Promise<void>;
};
}

View File

@ -18,7 +18,7 @@ import { h, VNode } from "preact";
interface Props {
enabled?: boolean;
onToggle?: () => void;
onToggle?: () => Promise<void>;
label: VNode;
name: string;
description?: VNode;

View File

@ -19,7 +19,7 @@ import { h, VNode } from "preact";
interface Props {
enabled: boolean;
onToggle: () => void;
onToggle: () => Promise<void>;
label: VNode;
name: string;
}

View File

@ -1,16 +1,14 @@
import { getUnpackedSettings } from "http2";
import { h, VNode } from "preact";
import arrowDown from "../svg/chevron-down.svg";
import {
ButtonBoxPrimary,
ButtonPrimary,
ParagraphClickable,
} from "./styled/index.js";
import { useState } from "preact/hooks";
import { Button } from "../mui/Button.js";
import arrowDown from "../svg/chevron-down.svg";
import { ParagraphClickable } from "./styled/index.js";
export interface Props {
label: (s: string) => VNode;
actions: string[];
onClick: (s: string) => void;
onClick: (s: string) => Promise<void>;
}
/**
@ -43,9 +41,9 @@ export function MultiActionButton({
if (!canChange) {
return (
<ButtonPrimary onClick={() => doClick(selected)}>
<Button variant="contained" onClick={() => doClick(selected)}>
{label(selected)}
</ButtonPrimary>
</Button>
);
}
@ -73,40 +71,44 @@ export function MultiActionButton({
))}
</div>
)}
<ButtonBoxPrimary
<Button
variant="contained"
onClick={() => doClick(selected)}
style={{
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
marginRight: 0,
maxWidth: 170,
// maxWidth: 170,
overflowX: "hidden",
textOverflow: "ellipsis",
}}
>
{label(selected)}
</ButtonBoxPrimary>
</Button>
<ButtonPrimary
onClick={() => setOpened((s) => !s)}
<Button
variant="outlined"
onClick={async () => setOpened((s) => !s)}
style={{
marginLeft: 0,
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
width: 36,
padding: 4,
height: 36,
fill: "white",
paddingLeft: 4,
paddingRight: 4,
minWidth: "unset",
}}
>
<div
style={{
height: 24,
width: 24,
marginLeft: 4,
marginRight: 4,
// fill: "white",
}}
dangerouslySetInnerHTML={{ __html: arrowDown }}
/>
</ButtonPrimary>
</Button>
</div>
);
}

View File

@ -25,11 +25,11 @@ import { useLocalStorage } from "../hooks/useLocalStorage.js";
interface Type {
devMode: boolean;
toggleDevMode: () => void;
toggleDevMode: () => Promise<void>;
}
const Context = createContext<Type>({
devMode: false,
toggleDevMode: () => null,
toggleDevMode: async () => { return; },
});
export const useDevContext = (): Type => useContext(Context);
@ -44,8 +44,8 @@ export const DevContextProviderForTesting = ({
return h(Context.Provider, {
value: {
devMode: value,
toggleDevMode: () => {
null;
toggleDevMode: async () => {
return;
},
},
children,
@ -55,7 +55,7 @@ export const DevContextProviderForTesting = ({
export const DevContextProvider = ({ children }: { children: any }): VNode => {
const [value, setter] = useLocalStorage("devMode");
const devMode = value === "true";
const toggleDevMode = (): void => setter((v) => (!v ? "true" : undefined));
const toggleDevMode = async (): Promise<void> => setter((v) => (!v ? "true" : undefined));
children =
children.length === 1 && typeof children === "function"
? children({ devMode })

View File

@ -44,13 +44,14 @@ import {
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { ButtonHandler } from "../mui/handlers.js";
import * as wxApi from "../wxApi.js";
interface Props {
talerDepositUri?: string;
amount: AmountString;
goBack: () => void;
goBack: () => Promise<void>;
}
type State = Loading | Ready | Completed;
@ -206,11 +207,15 @@ export function View({ state }: ViewProps): VNode {
/>
</section>
<section>
<ButtonSuccess upperCased onClick={state.confirm.onClick}>
<Button
variant="contained"
color="success"
onClick={state.confirm.onClick}
>
<i18n.Translate>
Deposit {<Amount value={state.effective} />}
</i18n.Translate>
</ButtonSuccess>
</Button>
</section>
</WalletAction>
);

View File

@ -33,6 +33,10 @@ export default {
argTypes: {},
};
const noop = async (): Promise<void> => {
return;
};
export const NoBalance = createExample(TestedComponent, {
state: {
status: "ready",
@ -61,8 +65,8 @@ export const NoBalance = createExample(TestedComponent, {
amountRaw: "USD:10",
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});
export const NoEnoughBalance = createExample(TestedComponent, {
@ -97,8 +101,8 @@ export const NoEnoughBalance = createExample(TestedComponent, {
amountRaw: "USD:10",
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});
export const EnoughBalanceButRestricted = createExample(TestedComponent, {
@ -133,8 +137,8 @@ export const EnoughBalanceButRestricted = createExample(TestedComponent, {
amountRaw: "USD:10",
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});
export const PaymentPossible = createExample(TestedComponent, {
@ -172,8 +176,8 @@ export const PaymentPossible = createExample(TestedComponent, {
proposalId: "proposal1234",
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});
export const PaymentPossibleWithFee = createExample(TestedComponent, {
@ -211,8 +215,8 @@ export const PaymentPossibleWithFee = createExample(TestedComponent, {
proposalId: "proposal1234",
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});
import beer from "../../static-dev/beer.png";
@ -271,8 +275,8 @@ export const TicketWithAProductList = createExample(TestedComponent, {
proposalId: "proposal1234",
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});
export const AlreadyConfirmedByOther = createExample(TestedComponent, {
@ -309,8 +313,8 @@ export const AlreadyConfirmedByOther = createExample(TestedComponent, {
paid: false,
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});
export const AlreadyPaidWithoutFulfillment = createExample(TestedComponent, {
@ -347,8 +351,8 @@ export const AlreadyPaidWithoutFulfillment = createExample(TestedComponent, {
paid: true,
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});
export const AlreadyPaidWithFulfillment = createExample(TestedComponent, {
@ -387,6 +391,6 @@ export const AlreadyPaidWithFulfillment = createExample(TestedComponent, {
paid: true,
},
},
goBack: () => null,
goToWalletManualWithdraw: () => null,
goBack: noop,
goToWalletManualWithdraw: noop,
});

View File

@ -60,13 +60,14 @@ import {
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { ButtonHandler } from "../mui/handlers.js";
import * as wxApi from "../wxApi.js";
interface Props {
talerPayUri?: string;
goToWalletManualWithdraw: (currency?: string) => void;
goBack: () => void;
goToWalletManualWithdraw: (currency?: string) => Promise<void>;
goBack: () => Promise<void>;
}
type State = Loading | Ready | Confirmed;
@ -265,8 +266,8 @@ export function View({
goToWalletManualWithdraw,
}: {
state: Ready | Confirmed;
goToWalletManualWithdraw: (currency?: string) => void;
goBack: () => void;
goToWalletManualWithdraw: (currency?: string) => Promise<void>;
goBack: () => Promise<void>;
}): VNode {
const { i18n } = useTranslationContext();
const contractTerms: ContractTerms = state.payStatus.contractTerms;
@ -522,7 +523,7 @@ function ButtonsSection({
goToWalletManualWithdraw,
}: {
state: Ready | Confirmed;
goToWalletManualWithdraw: (currency: string) => void;
goToWalletManualWithdraw: (currency: string) => Promise<void>;
}): VNode {
const { i18n } = useTranslationContext();
if (state.status === "ready") {
@ -531,11 +532,15 @@ function ButtonsSection({
return (
<Fragment>
<section>
<ButtonSuccess upperCased onClick={state.payHandler.onClick}>
<Button
variant="contained"
color="success"
onClick={state.payHandler.onClick}
>
<i18n.Translate>
Pay {<Amount value={payStatus.amountEffective} />}
</i18n.Translate>
</ButtonSuccess>
</Button>
</section>
<PayWithMobile state={state} />
</Fragment>
@ -560,12 +565,13 @@ function ButtonsSection({
<WarningBox>{BalanceMessage}</WarningBox>
</section>
<section>
<ButtonSuccess
upperCased
<Button
variant="contained"
color="success"
onClick={() => goToWalletManualWithdraw(state.amount.currency)}
>
<i18n.Translate>Withdraw digital cash</i18n.Translate>
</ButtonSuccess>
</Button>
</section>
<PayWithMobile state={state} />
</Fragment>

View File

@ -40,6 +40,7 @@ import {
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { ButtonHandler } from "../mui/handlers.js";
import * as wxApi from "../wxApi.js";
import { ProductList } from "./Pay.js";
@ -188,9 +189,9 @@ export function View({ state }: ViewProps): VNode {
</section>
) : undefined}
<section>
<ButtonSuccess onClick={state.accept.onClick}>
<Button variant="contained" onClick={state.accept.onClick}>
<i18n.Translate>Confirm refund</i18n.Translate>
</ButtonSuccess>
</Button>
</section>
</WalletAction>
);

View File

@ -2,14 +2,13 @@ import { Fragment, h, VNode } from "preact";
import { CheckboxOutlined } from "../components/CheckboxOutlined.js";
import { ExchangeXmlTos } from "../components/ExchangeToS.js";
import {
ButtonSuccess,
ButtonWarning,
LinkSuccess,
TermsOfService,
WarningBox,
WarningText,
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
import { TermsState } from "../utils/index.js";
export interface Props {
@ -58,20 +57,28 @@ export function TermsOfServiceSection({
)}
{terms.status === "new" && (
<section>
<ButtonSuccess upperCased onClick={() => onReview(true)}>
<Button
variant="contained"
color="success"
onClick={async () => onReview(true)}
>
<i18n.Translate>
Review exchange terms of service
</i18n.Translate>
</ButtonSuccess>
</Button>
</section>
)}
{terms.status === "changed" && (
<section>
<ButtonWarning upperCased onClick={() => onReview(true)}>
<Button
variant="contained"
color="success"
onClick={async () => onReview(true)}
>
<i18n.Translate>
Review new version of terms of service
</i18n.Translate>
</ButtonWarning>
</Button>
</section>
)}
</Fragment>
@ -95,7 +102,7 @@ export function TermsOfServiceSection({
I accept the exchange terms of service
</i18n.Translate>
}
onToggle={() => {
onToggle={async () => {
onAccept(!reviewed);
if (ableToReviewTermsOfService) onReview(false);
}}
@ -154,7 +161,7 @@ export function TermsOfServiceSection({
I accept the exchange terms of service
</i18n.Translate>
}
onToggle={() => {
onToggle={async () => {
onAccept(!reviewed);
if (ableToReviewTermsOfService) onReview(false);
}}

View File

@ -210,9 +210,13 @@ export function View({ state }: { state: State }): VNode {
/>
</section>
<section>
<ButtonSuccess onClick={state.accept.onClick}>
<Button
variant="contained"
color="success"
onClick={state.accept.onClick}
>
<i18n.Translate>Accept tip</i18n.Translate>
</ButtonSuccess>
</Button>
<Button onClick={state.ignore.onClick}>
<i18n.Translate>Ignore</i18n.Translate>
</Button>

View File

@ -33,8 +33,6 @@ import { LogoHeader } from "../components/LogoHeader.js";
import { Part } from "../components/Part.js";
import { SelectList } from "../components/SelectList.js";
import {
ButtonSuccess,
ButtonWarning,
Input,
LinkSuccess,
SubTitle,
@ -43,19 +41,14 @@ import {
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { ButtonHandler, SelectFieldHandler } from "../mui/handlers.js";
import { buildTermsOfServiceState } from "../utils/index.js";
import {
ButtonHandler,
SelectFieldHandler,
ToggleHandler,
} from "../mui/handlers.js";
import * as wxApi from "../wxApi.js";
import {
Props as TermsOfServiceSectionProps,
TermsOfServiceSection,
} from "./TermsOfServiceSection.js";
import { startOfWeekYear } from "date-fns/esm";
import { Checkbox } from "../components/Checkbox.js";
interface Props {
talerWithdrawUri?: string;
@ -527,22 +520,24 @@ export function View({ state }: { state: State }): VNode {
<section>
{(state.tosProps.terms.status === "accepted" ||
(state.mustAcceptFirst && state.tosProps.reviewed)) && (
<ButtonSuccess
upperCased
<Button
variant="contained"
color="success"
disabled={!state.doWithdrawal.onClick}
onClick={state.doWithdrawal.onClick}
>
<i18n.Translate>Confirm withdrawal</i18n.Translate>
</ButtonSuccess>
</Button>
)}
{state.tosProps.terms.status === "notfound" && (
<ButtonWarning
upperCased
<Button
variant="contained"
color="warning"
disabled={!state.doWithdrawal.onClick}
onClick={state.doWithdrawal.onClick}
>
<i18n.Translate>Withdraw anyway</i18n.Translate>
</ButtonWarning>
</Button>
)}
</section>
) : (

View File

@ -68,18 +68,22 @@ export const WithTitle = (): VNode => (
</Wrapper>
);
const showSomething = async function (): Promise<void> {
alert("closed");
};
export const WithAction = (): VNode => (
<Wrapper>
<Alert title="Warning" severity="warning" onClose={() => alert("closed")}>
<Alert title="Warning" severity="warning" onClose={showSomething}>
this is an warning
</Alert>
<Alert title="Error" severity="error" onClose={() => alert("closed")}>
<Alert title="Error" severity="error" onClose={showSomething}>
this is an error
</Alert>
<Alert title="Success" severity="success" onClose={() => alert("closed")}>
<Alert title="Success" severity="success" onClose={showSomething}>
this is an success
</Alert>
<Alert title="Info" severity="info" onClose={() => alert("closed")}>
<Alert title="Info" severity="info" onClose={showSomething}>
this is an info
</Alert>
</Wrapper>

View File

@ -49,7 +49,7 @@ interface Props {
title?: string;
variant?: "filled" | "outlined" | "standard";
role?: string;
onClose?: () => void;
onClose?: () => Promise<void>;
// icon: VNode;
severity?: "info" | "warning" | "success" | "error";
children: ComponentChildren;

View File

@ -1,7 +1,7 @@
import { ComponentChildren, h, VNode, JSX } from "preact";
import { css } from "@linaria/core";
// eslint-disable-next-line import/extensions
import { theme, ripple, Colors } from "./style";
import { theme, ripple, Colors, rippleOutlined } from "./style";
// eslint-disable-next-line import/extensions
import { alpha } from "./colors/manipulation";
@ -31,12 +31,13 @@ interface Props {
disableFocusRipple?: boolean;
endIcon?: string | VNode;
fullWidth?: boolean;
style?: h.JSX.CSSProperties;
href?: string;
size?: "small" | "medium" | "large";
startIcon?: VNode | string;
variant?: "contained" | "outlined" | "text";
color?: Colors;
onClick?: () => void;
onClick?: () => Promise<void>;
}
const button = css`
@ -199,6 +200,7 @@ export function Button({
fullWidth,
variant = "text",
size = "medium",
style: parentStyle,
color = "primary",
onClick,
}: Props): VNode {
@ -267,12 +269,15 @@ export function Button({
colorVariant[variant],
sizeVariant[variant][size],
].join(" ")}
containedRipple={variant === "contained"}
onClick={onClick}
style={{
...parentStyle,
"--color-main": theme.palette[color].main,
"--color-contrastText": theme.palette[color].contrastText,
"--color-main-alpha-half": alpha(theme.palette[color].main, 0.5),
"--color-dark": theme.palette[color].dark,
"--color-light": theme.palette[color].light,
"--color-main-alpha-opacity": alpha(
theme.palette[color].main,
theme.palette.action.hoverOpacity,
@ -295,13 +300,15 @@ export function Button({
interface BaseProps extends JSX.HTMLAttributes<HTMLButtonElement> {
class: string;
onClick?: () => void;
onClick?: () => Promise<void>;
containedRipple?: boolean;
children?: ComponentChildren;
}
function ButtonBase({
class: _class,
children,
containedRipple,
onClick,
dangerouslySetInnerHTML,
...rest
@ -309,7 +316,11 @@ function ButtonBase({
function doClick(): void {
if (onClick) onClick();
}
const classNames = [buttonBaseStyle, _class, ripple].join(" ");
const classNames = [
buttonBaseStyle,
_class,
containedRipple ? ripple : rippleOutlined,
].join(" ");
if (dangerouslySetInnerHTML) {
return (
<button
@ -332,7 +343,7 @@ export function IconButton({
onClick,
}: {
svg: any;
onClick?: () => void;
onClick?: () => Promise<void>;
}): VNode {
return (
<ButtonBase

View File

@ -46,13 +46,33 @@ export const theme = createTheme();
export const ripple = css`
background-position: center;
transition: background 0.5s;
&:hover {
background: #eeeeee radial-gradient(circle, transparent 1%, #eeeeee 1%)
transition: background 0.2s;
&:hover:enabled {
background: var(--color-main)
radial-gradient(circle, transparent 1%, var(--color-dark) 1%)
center/15000%;
}
&:active {
background-color: currentColor;
&:active:enabled {
background-color: var(--color-main);
background-size: 100%;
transition: background 0s;
}
`;
export const rippleOutlined = css`
background-position: center;
transition: background 0.2s;
&:hover:enabled {
background: var(--color-contrastText)
radial-gradient(circle, transparent 1%, var(--color-light) 1%)
center/15000%;
}
&:active:enabled {
background-color: var(--color-contrastText);
background-size: 100%;
transition: background 0s;
}
@ -680,15 +700,15 @@ function createTheme() {
function getDefaultSecondary(mode = "light") {
if (mode === "dark") {
return {
main: purple[200],
light: purple[50],
dark: purple[400],
main: grey[200],
light: grey[50],
dark: grey[400],
};
}
return {
main: purple[500],
light: purple[300],
dark: purple[700],
main: grey[300],
light: grey[100],
dark: grey[600],
};
}

View File

@ -61,7 +61,7 @@ export function Application(): VNode {
<IoCProviderForRuntime>
<PendingTransactions
goToTransaction={(txId: string) =>
route(Pages.balance_transaction.replace(":tid", txId))
redirectTo(Pages.balance_transaction.replace(":tid", txId))
}
/>
<Match>
@ -74,15 +74,19 @@ export function Application(): VNode {
path={Pages.balance}
component={BalancePage}
goToWalletManualWithdraw={() =>
route(
redirectTo(
Pages.balance_manual_withdraw.replace(":currency?", ""),
)
}
goToWalletDeposit={(currency: string) =>
route(Pages.balance_deposit.replace(":currency", currency))
redirectTo(
Pages.balance_deposit.replace(":currency", currency),
)
}
goToWalletHistory={(currency: string) =>
route(Pages.balance_history.replace(":currency?", currency))
redirectTo(
Pages.balance_history.replace(":currency?", currency),
)
}
/>
@ -96,7 +100,7 @@ export function Application(): VNode {
url={decodeURIComponent(action)}
onDismiss={() => {
setDismissed(true);
route(Pages.balance);
return redirectTo(Pages.balance);
}}
/>
);
@ -106,16 +110,12 @@ export function Application(): VNode {
<Route
path={Pages.backup}
component={BackupPage}
onAddProvider={() => {
route(Pages.backup_provider_add);
}}
onAddProvider={() => redirectTo(Pages.backup_provider_add)}
/>
<Route
path={Pages.backup_provider_detail}
component={ProviderDetailPage}
onBack={() => {
route(Pages.backup);
}}
onBack={() => redirectTo(Pages.backup)}
/>
<Route
@ -175,6 +175,10 @@ function RedirectToWalletPage(): VNode {
);
}
async function redirectTo(location: string): Promise<void> {
route(location);
}
function Redirect({ to }: { to: string }): null {
useEffect(() => {
route(to, true);

View File

@ -22,17 +22,17 @@ import { JustInDevMode } from "../components/JustInDevMode.js";
import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import { MultiActionButton } from "../components/MultiActionButton.js";
import { ButtonBoxPrimary, ButtonPrimary } from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { AddNewActionView } from "../wallet/AddNewActionView.js";
import * as wxApi from "../wxApi.js";
import { NoBalanceHelp } from "./NoBalanceHelp.js";
export interface Props {
goToWalletDeposit: (currency: string) => void;
goToWalletHistory: (currency: string) => void;
goToWalletManualWithdraw: () => void;
goToWalletDeposit: (currency: string) => Promise<void>;
goToWalletHistory: (currency: string) => Promise<void>;
goToWalletManualWithdraw: () => Promise<void>;
}
export function BalancePage({
goToWalletManualWithdraw,
@ -65,7 +65,7 @@ export function BalancePage({
}
if (addingAction) {
return <AddNewActionView onCancel={() => setAddingAction(false)} />;
return <AddNewActionView onCancel={async () => setAddingAction(false)} />;
}
return (
@ -74,16 +74,16 @@ export function BalancePage({
goToWalletManualWithdraw={goToWalletManualWithdraw}
goToWalletDeposit={goToWalletDeposit}
goToWalletHistory={goToWalletHistory}
goToAddAction={() => setAddingAction(true)}
goToAddAction={async () => setAddingAction(true)}
/>
);
}
export interface BalanceViewProps {
balances: Balance[];
goToWalletManualWithdraw: () => void;
goToAddAction: () => void;
goToWalletDeposit: (currency: string) => void;
goToWalletHistory: (currency: string) => void;
goToWalletManualWithdraw: () => Promise<void>;
goToAddAction: () => Promise<void>;
goToWalletDeposit: (currency: string) => Promise<void>;
goToWalletHistory: (currency: string) => Promise<void>;
}
export function BalanceView({
@ -113,22 +113,20 @@ export function BalanceView({
/>
</section>
<footer style={{ justifyContent: "space-between" }}>
<ButtonPrimary onClick={goToWalletManualWithdraw}>
<Button variant="contained" onClick={goToWalletManualWithdraw}>
<i18n.Translate>Withdraw</i18n.Translate>
</ButtonPrimary>
</Button>
{currencyWithNonZeroAmount.length > 0 && (
<MultiActionButton
label={(s) => (
<i18n.Translate>Deposit {<span>{s}</span>}</i18n.Translate>
)}
label={(s) => <i18n.Translate>Deposit {s}</i18n.Translate>}
actions={currencyWithNonZeroAmount}
onClick={(c) => goToWalletDeposit(c)}
/>
)}
<JustInDevMode>
<ButtonBoxPrimary onClick={goToAddAction}>
<Button onClick={goToAddAction}>
<i18n.Translate>Enter URI</i18n.Translate>
</ButtonBoxPrimary>
</Button>
</JustInDevMode>
</footer>
</Fragment>

View File

@ -8,7 +8,7 @@ import { Typography } from "../mui/Typography.js";
export function NoBalanceHelp({
goToWalletManualWithdraw,
}: {
goToWalletManualWithdraw: () => void;
goToWalletManualWithdraw: () => Promise<void>;
}): VNode {
return (
<Paper

View File

@ -28,16 +28,17 @@ import {
Title,
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
export interface Props {
url: string;
onDismiss: () => void;
onDismiss: () => Promise<void>;
}
export function TalerActionFound({ url, onDismiss }: Props): VNode {
const uriType = classifyTalerUri(url);
const { i18n } = useTranslationContext();
function redirectToWallet(): void {
async function redirectToWallet(): Promise<void> {
platform.openWalletURIFromPopup(url);
}
return (
@ -51,9 +52,13 @@ export function TalerActionFound({ url, onDismiss }: Props): VNode {
<p>
<i18n.Translate>This page has pay action.</i18n.Translate>
</p>
<ButtonSuccess onClick={redirectToWallet}>
<Button
variant="contained"
color="success"
onClick={redirectToWallet}
>
<i18n.Translate>Open pay page</i18n.Translate>
</ButtonSuccess>
</Button>
</div>
)}
{uriType === TalerUriType.TalerWithdraw && (
@ -63,9 +68,13 @@ export function TalerActionFound({ url, onDismiss }: Props): VNode {
This page has a withdrawal action.
</i18n.Translate>
</p>
<ButtonSuccess onClick={redirectToWallet}>
<Button
variant="contained"
color="success"
onClick={redirectToWallet}
>
<i18n.Translate>Open withdraw page</i18n.Translate>
</ButtonSuccess>
</Button>
</div>
)}
{uriType === TalerUriType.TalerTip && (
@ -73,9 +82,13 @@ export function TalerActionFound({ url, onDismiss }: Props): VNode {
<p>
<i18n.Translate>This page has a tip action.</i18n.Translate>
</p>
<ButtonSuccess onClick={redirectToWallet}>
<Button
variant="contained"
color="success"
onClick={redirectToWallet}
>
<i18n.Translate>Open tip page</i18n.Translate>
</ButtonSuccess>
</Button>
</div>
)}
{uriType === TalerUriType.TalerNotifyReserve && (
@ -85,9 +98,13 @@ export function TalerActionFound({ url, onDismiss }: Props): VNode {
This page has a notify reserve action.
</i18n.Translate>
</p>
<ButtonSuccess onClick={redirectToWallet}>
<Button
variant="contained"
color="success"
onClick={redirectToWallet}
>
<i18n.Translate>Notify</i18n.Translate>
</ButtonSuccess>
</Button>
</div>
)}
{uriType === TalerUriType.TalerRefund && (
@ -95,9 +112,13 @@ export function TalerActionFound({ url, onDismiss }: Props): VNode {
<p>
<i18n.Translate>This page has a refund action.</i18n.Translate>
</p>
<ButtonSuccess onClick={redirectToWallet}>
<Button
variant="contained"
color="success"
onClick={redirectToWallet}
>
<i18n.Translate>Open refund page</i18n.Translate>
</ButtonSuccess>
</Button>
</div>
)}
{uriType === TalerUriType.Unknown && (
@ -113,10 +134,9 @@ export function TalerActionFound({ url, onDismiss }: Props): VNode {
</section>
<footer>
<div />
<ButtonPrimary onClick={() => onDismiss()}>
{" "}
<i18n.Translate>Dismiss</i18n.Translate>{" "}
</ButtonPrimary>
<Button variant="contained" onClick={onDismiss}>
<i18n.Translate>Dismiss</i18n.Translate>
</Button>
</footer>
</Fragment>
);

View File

@ -2,15 +2,12 @@ import { classifyTalerUri, TalerUriType } from "@gnu-taler/taler-util";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { platform } from "../platform/api.js";
import {
Button,
ButtonSuccess,
InputWithLabel,
} from "../components/styled/index.js";
import { InputWithLabel } from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
export interface Props {
onCancel: () => void;
onCancel: () => Promise<void>;
}
export function AddNewActionView({ onCancel }: Props): VNode {
@ -18,7 +15,7 @@ export function AddNewActionView({ onCancel }: Props): VNode {
const uriType = classifyTalerUri(url);
const { i18n } = useTranslationContext();
function redirectToWallet(): void {
async function redirectToWallet(): Promise<void> {
platform.openWalletURIFromPopup(url);
}
@ -41,11 +38,15 @@ export function AddNewActionView({ onCancel }: Props): VNode {
</InputWithLabel>
</section>
<footer>
<Button onClick={onCancel}>
<Button variant="contained" color="secondary" onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
{uriType !== TalerUriType.Unknown && (
<ButtonSuccess onClick={redirectToWallet}>
<Button
variant="contained"
color="success"
onClick={redirectToWallet}
>
{(() => {
switch (uriType) {
case TalerUriType.TalerNotifyReserve:
@ -61,7 +62,7 @@ export function AddNewActionView({ onCancel }: Props): VNode {
}
return <Fragment />;
})()}
</ButtonSuccess>
</Button>
)}
</footer>
</Fragment>

View File

@ -94,7 +94,9 @@ export function Application(): VNode {
>
<PendingTransactions
goToTransaction={(txId: string) =>
route(Pages.balance_transaction.replace(":tid", txId))
redirectTo(
Pages.balance_transaction.replace(":tid", txId),
)
}
/>
</div>
@ -123,10 +125,12 @@ export function Application(): VNode {
path={Pages.balance_history}
component={HistoryPage}
goToWalletDeposit={(currency: string) =>
route(Pages.balance_deposit.replace(":currency", currency))
redirectTo(
Pages.balance_deposit.replace(":currency", currency),
)
}
goToWalletManualWithdraw={(currency?: string) =>
route(
redirectTo(
Pages.balance_manual_withdraw.replace(
":currency?",
currency || "",
@ -137,29 +141,31 @@ export function Application(): VNode {
<Route
path={Pages.balance_transaction}
component={TransactionPage}
goToWalletHistory={(currency?: string) => {
route(
goToWalletHistory={(currency?: string) =>
redirectTo(
Pages.balance_history.replace(":currency?", currency || ""),
);
}}
)
}
/>
<Route
path={Pages.balance_manual_withdraw}
component={ManualWithdrawPage}
onCancel={() => {
route(Pages.balance);
}}
onCancel={() => redirectTo(Pages.balance)}
/>
<Route
path={Pages.balance_deposit}
component={DepositPage}
onCancel={(currency: string) => {
route(Pages.balance_history.replace(":currency?", currency));
redirectTo(
Pages.balance_history.replace(":currency?", currency),
);
}}
onSuccess={(currency: string) => {
route(Pages.balance_history.replace(":currency?", currency));
redirectTo(
Pages.balance_history.replace(":currency?", currency),
);
setGlobalNotification(
<i18n.Translate>
All done, your transaction is in progress
@ -178,23 +184,17 @@ export function Application(): VNode {
<Route
path={Pages.backup}
component={BackupPage}
onAddProvider={() => {
route(Pages.backup_provider_add);
}}
onAddProvider={() => redirectTo(Pages.backup_provider_add)}
/>
<Route
path={Pages.backup_provider_detail}
component={ProviderDetailPage}
onBack={() => {
route(Pages.backup);
}}
onBack={() => redirectTo(Pages.backup)}
/>
<Route
path={Pages.backup_provider_add}
component={ProviderAddPage}
onBack={() => {
route(Pages.backup);
}}
onBack={() => redirectTo(Pages.backup)}
/>
{/**
@ -203,9 +203,7 @@ export function Application(): VNode {
<Route
path={Pages.settings_exchange_add}
component={ExchangeAddPage}
onBack={() => {
route(Pages.balance);
}}
onBack={() => redirectTo(Pages.balance)}
/>
{/**
@ -221,14 +219,14 @@ export function Application(): VNode {
path={Pages.cta_pay}
component={PayPage}
goToWalletManualWithdraw={(currency?: string) =>
route(
redirectTo(
Pages.balance_manual_withdraw.replace(
":currency?",
currency || "",
),
)
}
goBack={() => route(Pages.balance)}
goBack={() => redirectTo(Pages.balance)}
/>
<Route path={Pages.cta_refund} component={RefundPage} />
<Route path={Pages.cta_tips} component={TipPage} />
@ -258,9 +256,12 @@ export function Application(): VNode {
);
}
async function redirectTo(location: string): Promise<void> {
route(location);
}
function Redirect({ to }: { to: string }): null {
useEffect(() => {
console.log("got some wrong route", to);
route(to, true);
});
return null;

View File

@ -31,8 +31,6 @@ import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import {
BoldLight,
ButtonPrimary,
ButtonSuccess,
Centered,
CenteredBoldText,
CenteredText,
@ -42,11 +40,12 @@ import {
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { Pages } from "../NavigationBar.js";
import * as wxApi from "../wxApi.js";
interface Props {
onAddProvider: () => void;
onAddProvider: () => Promise<void>;
}
export function BackupPage({ onAddProvider }: Props): VNode {
@ -87,7 +86,7 @@ export function BackupPage({ onAddProvider }: Props): VNode {
export interface ViewProps {
providers: ProviderInfo[];
onAddProvider: () => void;
onAddProvider: () => Promise<void>;
onSyncAll: () => Promise<void>;
}
@ -121,9 +120,9 @@ export function BackupView({
<BoldLight>
<i18n.Translate>No backup providers configured</i18n.Translate>
</BoldLight>
<ButtonSuccess onClick={onAddProvider}>
<Button variant="contained" color="success" onClick={onAddProvider}>
<i18n.Translate>Add provider</i18n.Translate>
</ButtonSuccess>
</Button>
</Centered>
)}
</section>
@ -131,16 +130,16 @@ export function BackupView({
<footer>
<div />
<div>
<ButtonPrimary onClick={onSyncAll}>
<Button variant="contained" onClick={onSyncAll}>
{providers.length > 1 ? (
<i18n.Translate>Sync all backups</i18n.Translate>
) : (
<i18n.Translate>Sync now</i18n.Translate>
)}
</ButtonPrimary>
<ButtonSuccess onClick={onAddProvider}>
</Button>
<Button variant="contained" color="success" onClick={onAddProvider}>
<i18n.Translate>Add provider</i18n.Translate>
</ButtonSuccess>
</Button>
</div>
</footer>
)}

View File

@ -21,14 +21,12 @@
*/
import { AmountJson, Amounts } from "@gnu-taler/taler-util";
import { TalerError } from "@gnu-taler/taler-wallet-core";
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import { ErrorMessage } from "../components/ErrorMessage.js";
import { SelectList } from "../components/SelectList.js";
import {
BoldLight,
ButtonPrimary,
Centered,
Input,
InputWithLabel,
@ -37,6 +35,7 @@ import {
SubTitle,
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
import { SelectFieldHandler, TextFieldHandler } from "../mui/handlers.js";
import { Pages } from "../NavigationBar.js";
@ -270,12 +269,13 @@ export function CreateManualWithdraw({
</section>
<footer>
<div />
<ButtonPrimary
<Button
variant="contained"
disabled={!state.parsedAmount || !state.exchange.value}
onClick={() => onCreate(state.exchange.value, state.parsedAmount!)}
>
<i18n.Translate>Start withdrawal</i18n.Translate>
</ButtonPrimary>
</Button>
</footer>
</Fragment>
);

View File

@ -23,8 +23,6 @@ import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import { SelectList } from "../components/SelectList.js";
import {
Button,
ButtonPrimary,
ErrorText,
Input,
InputWithLabel,
@ -33,6 +31,7 @@ import {
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { HookError, useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import {
ButtonHandler,
SelectFieldHandler,
@ -275,7 +274,11 @@ export function View({ state }: ViewProps): VNode {
</p>
</WarningBox>
<footer>
<Button onClick={state.cancelHandler.onClick}>
<Button
variant="contained"
color="secondary"
onClick={state.cancelHandler.onClick}
>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
</footer>
@ -345,20 +348,24 @@ export function View({ state }: ViewProps): VNode {
}
</section>
<footer>
<Button onClick={state.cancelHandler.onClick}>
<Button
variant="contained"
color="secondary"
onClick={state.cancelHandler.onClick}
>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
{!state.depositHandler.onClick ? (
<ButtonPrimary disabled>
<Button variant="contained" disabled>
<i18n.Translate>Deposit</i18n.Translate>
</ButtonPrimary>
</Button>
) : (
<ButtonPrimary onClick={state.depositHandler.onClick}>
<Button variant="contained" onClick={state.depositHandler.onClick}>
<i18n.Translate>
Deposit {Amounts.stringifyValue(state.totalToDeposit)}{" "}
{state.currency}
</i18n.Translate>
</ButtonPrimary>
</Button>
)}
</footer>
</Fragment>

View File

@ -30,6 +30,9 @@ import { Time } from "../components/Time.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { useDiagnostics } from "../hooks/useDiagnostics.js";
import { Button } from "../mui/Button.js";
import { Grid } from "../mui/Grid.js";
import { Paper } from "../mui/Paper.js";
import * as wxApi from "../wxApi.js";
export function DeveloperPage(): VNode {
@ -133,7 +136,6 @@ export function View({
const money_by_exchange = coins.reduce(
(prev, cur) => {
const denom = Amounts.parseOrThrow(cur.denom_value);
console.log(cur);
if (!prev[cur.exchange_base_url]) {
prev[cur.exchange_base_url] = [];
currencies[cur.exchange_base_url] = denom.currency;
@ -154,57 +156,72 @@ export function View({
[exchange_name: string]: CalculatedCoinfInfo[];
},
);
function Item({ children }: any) {
return <div>{children}</div>;
}
return (
<div>
<p>
<i18n.Translate>Debug tools</i18n.Translate>:
</p>
<button
onClick={() =>
confirmReset(
i18n.str`Do you want to IRREVOCABLY DESTROY everything inside your wallet and LOSE ALL YOUR COINS?`,
wxApi.resetDb,
)
}
>
<i18n.Translate>reset</i18n.Translate>
</button>
<button
onClick={() =>
confirmReset(
i18n.str`TESTING: This may delete all your coin, proceed with caution`,
wxApi.runGarbageCollector,
)
}
>
<i18n.Translate>run gc</i18n.Translate>
</button>
<br />
<button onClick={() => fileRef?.current?.click()}>
<i18n.Translate>import database</i18n.Translate>
</button>
<input
ref={fileRef}
style={{ display: "none" }}
type="file"
onChange={async (e) => {
const f: FileList | null = e.currentTarget.files;
if (!f || f.length != 1) {
return Promise.reject();
}
const buf = await f[0].arrayBuffer();
const str = new Uint8Array(buf).reduce(
(data, byte) => data + String.fromCharCode(byte),
"",
);
return onImportDatabase(str);
}}
/>
<br />
<button onClick={onExportDatabase}>
<i18n.Translate>export database</i18n.Translate>
</button>
<Grid container justifyContent="space-between" spacing={1}>
<Grid item>
<Button
variant="contained"
onClick={() =>
confirmReset(
i18n.str`Do you want to IRREVOCABLY DESTROY everything inside your wallet and LOSE ALL YOUR COINS?`,
wxApi.resetDb,
)
}
>
<i18n.Translate>reset</i18n.Translate>
</Button>
</Grid>
<Grid item>
<Button
variant="contained"
onClick={() =>
confirmReset(
i18n.str`TESTING: This may delete all your coin, proceed with caution`,
wxApi.runGarbageCollector,
)
}
>
<i18n.Translate>run gc</i18n.Translate>
</Button>
</Grid>
<Grid item>
<Button
variant="contained"
onClick={async () => fileRef?.current?.click()}
>
<i18n.Translate>import database</i18n.Translate>
</Button>
</Grid>
<Grid item>
<input
ref={fileRef}
style={{ display: "none" }}
type="file"
onChange={async (e) => {
const f: FileList | null = e.currentTarget.files;
if (!f || f.length != 1) {
return Promise.reject();
}
const buf = await f[0].arrayBuffer();
const str = new Uint8Array(buf).reduce(
(data, byte) => data + String.fromCharCode(byte),
"",
);
return onImportDatabase(str);
}}
/>
<Button variant="contained" onClick={onExportDatabase}>
<i18n.Translate>export database</i18n.Translate>
</Button>
</Grid>
</Grid>
{downloadedDatabase && (
<div>
<i18n.Translate>

View File

@ -1,21 +1,17 @@
import { Fragment, h, VNode } from "preact";
import { useState } from "preact/hooks";
import {
Button,
ButtonSuccess,
ButtonWarning,
Title,
} from "../components/styled/index.js";
import { Title } from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { TermsOfServiceSection } from "../cta/TermsOfServiceSection.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { buildTermsOfServiceState, TermsState } from "../utils/index.js";
import * as wxApi from "../wxApi.js";
export interface Props {
url: string;
onCancel: () => void;
onConfirm: () => void;
onCancel: () => Promise<void>;
onConfirm: () => Promise<void>;
}
export function ExchangeAddConfirmPage({
@ -71,8 +67,8 @@ export interface ViewProps {
url: string;
terms: TermsState | undefined;
onAccept: (b: boolean) => Promise<void>;
onCancel: () => void;
onConfirm: () => void;
onCancel: () => Promise<void>;
onConfirm: () => Promise<void>;
}
export function View({
@ -114,30 +110,35 @@ export function View({
)}
<footer>
<Button onClick={onCancel}>
<Button variant="contained" color="secondary" onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
{!terms && (
<Button disabled>
<Button variant="contained" disabled>
<i18n.Translate>Loading terms..</i18n.Translate>
</Button>
)}
{terms && (
<Fragment>
{needsReview && !reviewed && (
<ButtonSuccess disabled upperCased onClick={onConfirm}>
<Button
variant="contained"
color="success"
disabled
onClick={onConfirm}
>
<i18n.Translate>Add exchange</i18n.Translate>
</ButtonSuccess>
</Button>
)}
{(terms.status === "accepted" || (needsReview && reviewed)) && (
<ButtonSuccess upperCased onClick={onConfirm}>
<Button variant="contained" color="success" onClick={onConfirm}>
<i18n.Translate>Add exchange</i18n.Translate>
</ButtonSuccess>
</Button>
)}
{terms.status === "notfound" && (
<ButtonWarning upperCased onClick={onConfirm}>
<Button variant="contained" color="warning" onClick={onConfirm}>
<i18n.Translate>Add exchange anyway</i18n.Translate>
</ButtonWarning>
</Button>
)}
</Fragment>
)}

View File

@ -28,7 +28,7 @@ import { ExchangeSetUrlPage } from "./ExchangeSetUrl.js";
interface Props {
currency?: string;
onBack: () => void;
onBack: () => Promise<void>;
}
export function ExchangeAddPage({ currency, onBack }: Props): VNode {

View File

@ -6,8 +6,6 @@ import { Fragment, h, VNode } from "preact";
import { useEffect, useState } from "preact/hooks";
import { ErrorMessage } from "../components/ErrorMessage.js";
import {
Button,
ButtonPrimary,
Input,
LightText,
SubTitle,
@ -15,11 +13,12 @@ import {
WarningBox,
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
export interface Props {
initialValue?: string;
expectedCurrency?: string;
onCancel: () => void;
onCancel: () => Promise<void>;
onVerify: (s: string) => Promise<TalerConfigResponse | undefined>;
onConfirm: (url: string) => Promise<string | undefined>;
withError?: string;
@ -64,7 +63,7 @@ function useEndpointStatus<T>(
}
}, 500);
setHandler(h);
}, [value, setHandler, handler, onVerify]);
}, [value, setHandler, onVerify]);
return {
error: dirty ? error : undefined,
@ -172,10 +171,11 @@ export function ExchangeSetUrlPage({
</p>
</section>
<footer>
<Button onClick={onCancel}>
<Button variant="contained" color="secondary" onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
<ButtonPrimary
<Button
variant="contained"
disabled={
!result ||
!!error ||
@ -189,7 +189,7 @@ export function ExchangeSetUrlPage({
}}
>
<i18n.Translate>Next</i18n.Translate>
</ButtonPrimary>
</Button>
</footer>
</Fragment>
);

View File

@ -26,7 +26,6 @@ import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import {
ButtonBoxPrimary,
ButtonPrimary,
CenteredBoldText,
CenteredText,
DateSeparator,
@ -36,13 +35,14 @@ import { Time } from "../components/Time.js";
import { TransactionItem } from "../components/TransactionItem.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { NoBalanceHelp } from "../popup/NoBalanceHelp.js";
import * as wxApi from "../wxApi.js";
interface Props {
currency?: string;
goToWalletDeposit: (currency: string) => void;
goToWalletManualWithdraw: (currency?: string) => void;
goToWalletDeposit: (currency: string) => Promise<void>;
goToWalletManualWithdraw: (currency?: string) => Promise<void>;
}
export function HistoryPage({
currency,
@ -101,8 +101,8 @@ export function HistoryView({
goToWalletManualWithdraw,
goToWalletDeposit,
}: {
goToWalletDeposit: (currency: string) => void;
goToWalletManualWithdraw: (currency?: string) => void;
goToWalletDeposit: (currency: string) => Promise<void>;
goToWalletManualWithdraw: (currency?: string) => Promise<void>;
defaultCurrency?: string;
transactions: Transaction[];
balances: Balance[];
@ -198,19 +198,22 @@ export function HistoryView({
)}
</div>
<div>
<ButtonPrimary
style={{ marginLeft: 0, marginTop: 8 }}
<Button
variant="contained"
// style={{ marginLeft: 0, marginTop: 8 }}
onClick={() => goToWalletManualWithdraw(selectedCurrency)}
>
<i18n.Translate>Withdraw</i18n.Translate>
</ButtonPrimary>
</Button>
{currencyAmount && Amounts.isNonZero(currencyAmount) && (
<ButtonBoxPrimary
style={{ marginLeft: 0, marginTop: 8 }}
<Button
variant="outlined"
color="primary"
// style={{ marginLeft: 0, marginTop: 8 }}
onClick={() => goToWalletDeposit(selectedCurrency)}
>
<i18n.Translate>Deposit</i18n.Translate>
</ButtonBoxPrimary>
</Button>
)}
</div>
</div>

View File

@ -34,7 +34,7 @@ import { ReserveCreated } from "./ReserveCreated.js";
interface Props {
currency?: string;
onCancel: () => void;
onCancel: () => Promise<void>;
}
export function ManualWithdrawPage({ currency, onCancel }: Props): VNode {

View File

@ -25,8 +25,6 @@ import { useEffect, useState } from "preact/hooks";
import { Checkbox } from "../components/Checkbox.js";
import { ErrorMessage } from "../components/ErrorMessage.js";
import {
Button,
ButtonPrimary,
Input,
LightText,
SmallLightText,
@ -34,12 +32,13 @@ import {
Title,
} from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
import { queryToSlashConfig } from "../utils/index.js";
import * as wxApi from "../wxApi.js";
interface Props {
currency: string;
onBack: () => void;
onBack: () => Promise<void>;
}
export function ProviderAddPage({ onBack }: Props): VNode {
@ -67,11 +66,13 @@ export function ProviderAddPage({ onBack }: Props): VNode {
<ConfirmProviderView
provider={verifying.provider}
url={verifying.url}
onCancel={() => {
onCancel={async () => {
setVerifying(undefined);
}}
onConfirm={() => {
wxApi.addBackupProvider(verifying.url, verifying.name).then(onBack);
return wxApi
.addBackupProvider(verifying.url, verifying.name)
.then(onBack);
}}
/>
);
@ -79,7 +80,7 @@ export function ProviderAddPage({ onBack }: Props): VNode {
export interface SetUrlViewProps {
initialValue?: string;
onCancel: () => void;
onCancel: () => Promise<void>;
onVerify: (s: string) => Promise<BackupBackupProviderTerms | undefined>;
onConfirm: (url: string, name: string) => Promise<string | undefined>;
withError?: string;
@ -161,10 +162,11 @@ export function SetUrlView({
</p>
</section>
<footer>
<Button onClick={onCancel}>
<Button variant="contained" color="secondary" onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
<ButtonPrimary
<Button
variant="contained"
disabled={!value && !urlError}
onClick={() => {
const url = canonicalizeBaseUrl(value);
@ -174,7 +176,7 @@ export function SetUrlView({
}}
>
<i18n.Translate>Next</i18n.Translate>
</ButtonPrimary>
</Button>
</footer>
</Fragment>
);
@ -183,8 +185,8 @@ export function SetUrlView({
export interface ConfirmProviderViewProps {
provider: BackupBackupProviderTerms;
url: string;
onCancel: () => void;
onConfirm: () => void;
onCancel: () => Promise<void>;
onConfirm: () => Promise<void>;
}
export function ConfirmProviderView({
url,
@ -236,17 +238,17 @@ export function ConfirmProviderView({
<Checkbox
label={<i18n.Translate>Accept terms of service</i18n.Translate>}
name="terms"
onToggle={() => setAccepted((old) => !old)}
onToggle={async () => setAccepted((old) => !old)}
enabled={accepted}
/>
</section>
<footer>
<Button onClick={onCancel}>
<Button variant="contained" color="secondary" onClick={onCancel}>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
<ButtonPrimary disabled={!accepted} onClick={onConfirm}>
<Button variant="contained" disabled={!accepted} onClick={onConfirm}>
<i18n.Translate>Add provider</i18n.Translate>
</ButtonPrimary>
</Button>
</footer>
</Fragment>
);

View File

@ -25,21 +25,16 @@ import { Fragment, h, VNode } from "preact";
import { ErrorMessage } from "../components/ErrorMessage.js";
import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import {
Button,
ButtonDestructive,
ButtonPrimary,
PaymentStatus,
SmallLightText,
} from "../components/styled/index.js";
import { PaymentStatus, SmallLightText } from "../components/styled/index.js";
import { Time } from "../components/Time.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import * as wxApi from "../wxApi.js";
interface Props {
pid: string;
onBack: () => void;
onBack: () => Promise<void>;
}
export function ProviderDetailPage({ pid: providerURL, onBack }: Props): VNode {
@ -77,10 +72,10 @@ export function ProviderDetailPage({ pid: providerURL, onBack }: Props): VNode {
<ProviderView
url={providerURL}
info={state.response}
onSync={async () => wxApi.syncOneProvider(providerURL)}
onDelete={async () => wxApi.removeProvider(providerURL).then(onBack)}
onSync={() => wxApi.syncOneProvider(providerURL)}
onDelete={() => wxApi.removeProvider(providerURL).then(onBack)}
onBack={onBack}
onExtend={() => {
onExtend={async () => {
null;
}}
/>
@ -90,10 +85,10 @@ export function ProviderDetailPage({ pid: providerURL, onBack }: Props): VNode {
export interface ViewProps {
url: string;
info: ProviderInfo | null;
onDelete: () => void;
onSync: () => void;
onBack: () => void;
onExtend: () => void;
onDelete: () => Promise<void>;
onSync: () => Promise<void>;
onBack: () => Promise<void>;
onExtend: () => Promise<void>;
}
export function ProviderView({
@ -116,7 +111,7 @@ export function ProviderView({
</p>
</section>
<footer>
<Button onClick={onBack}>
<Button variant="contained" color="secondary" onClick={onBack}>
<i18n.Translate>See providers</i18n.Translate>
</Button>
<div />
@ -149,9 +144,9 @@ export function ProviderView({
</b>{" "}
<Time timestamp={lb} format="dd MMMM yyyy" />
</p>
<ButtonPrimary onClick={onSync}>
<Button variant="contained" onClick={onSync}>
<i18n.Translate>Back up</i18n.Translate>
</ButtonPrimary>
</Button>
{info.terms && (
<Fragment>
<p>
@ -164,9 +159,9 @@ export function ProviderView({
</Fragment>
)}
<p>{descriptionByStatus(info.paymentStatus, i18n)}</p>
<ButtonPrimary disabled onClick={onExtend}>
<Button variant="contained" disabled onClick={onExtend}>
<i18n.Translate>Extend</i18n.Translate>
</ButtonPrimary>
</Button>
{info.paymentStatus.type === ProviderPaymentType.TermsChanged && (
<div>
@ -212,13 +207,13 @@ export function ProviderView({
)}
</section>
<footer>
<Button onClick={onBack}>
<Button variant="contained" color="secondary" onClick={onBack}>
<i18n.Translate>See providers</i18n.Translate>
</Button>
<div>
<ButtonDestructive onClick={onDelete}>
<Button variant="contained" color="error" onClick={onDelete}>
<i18n.Translate>Remove provider</i18n.Translate>
</ButtonDestructive>
</Button>
</div>
</footer>
</Fragment>

View File

@ -4,18 +4,15 @@ import { Amount } from "../components/Amount.js";
import { BankDetailsByPaytoType } from "../components/BankDetailsByPaytoType.js";
import { ErrorMessage } from "../components/ErrorMessage.js";
import { QR } from "../components/QR.js";
import {
ButtonDestructive,
Title,
WarningBox,
} from "../components/styled/index.js";
import { Title, WarningBox } from "../components/styled/index.js";
import { useTranslationContext } from "../context/translation.js";
import { Button } from "../mui/Button.js";
export interface Props {
reservePub: string;
paytoURI: PaytoUri | undefined;
exchangeBaseUrl: string;
amount: AmountJson;
onCancel: () => void;
onCancel: () => Promise<void>;
}
export function ReserveCreated({
@ -82,9 +79,9 @@ export function ReserveCreated({
</section>
<footer>
<div />
<ButtonDestructive onClick={onCancel}>
<Button variant="contained" color="error" onClick={onCancel}>
<i18n.Translate>Cancel withdrawal</i18n.Translate>
</ButtonDestructive>
</Button>
</footer>
</Fragment>
);

View File

@ -66,7 +66,7 @@ export interface ViewProps {
setDeviceName: (s: string) => Promise<void>;
permissionToggle: ToggleHandler;
developerMode: boolean;
toggleDeveloperMode: () => void;
toggleDeveloperMode: () => Promise<void>;
knownExchanges: Array<ExchangeListItem>;
}

View File

@ -21,7 +21,6 @@ import {
Location,
NotificationType,
parsePaytoUri,
parsePayUri,
PaytoUri,
stringifyPaytoUri,
TalerProtocolTimestamp,
@ -47,17 +46,11 @@ import { Loading } from "../components/Loading.js";
import { LoadingError } from "../components/LoadingError.js";
import { Kind, Part, PartCollapsible, PartPayto } from "../components/Part.js";
import {
Button,
ButtonBox,
ButtonDestructive,
ButtonPrimary,
CenteredDialog,
HistoryRow,
InfoBox,
ListOfProducts,
Overlay,
Row,
RowBorderGray,
SmallLightText,
SubTitle,
WarningBox,
@ -65,12 +58,13 @@ import {
import { Time } from "../components/Time.js";
import { useTranslationContext } from "../context/translation.js";
import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js";
import { Button } from "../mui/Button.js";
import { Pages } from "../NavigationBar.js";
import * as wxApi from "../wxApi.js";
interface Props {
tid: string;
goToWalletHistory: (currency?: string) => void;
goToWalletHistory: (currency?: string) => Promise<void>;
}
async function getTransaction(tid: string): Promise<Transaction> {
@ -122,7 +116,7 @@ export function TransactionPage({ tid, goToWalletHistory }: Props): VNode {
onRetry={() =>
wxApi.retryTransaction(tid).then(() => goToWalletHistory(currency))
}
onRefund={(id) => wxApi.applyRefundFromPurchaseId(id)}
onRefund={(id) => wxApi.applyRefundFromPurchaseId(id).then()}
onBack={() => goToWalletHistory(currency)}
/>
);
@ -130,10 +124,10 @@ export function TransactionPage({ tid, goToWalletHistory }: Props): VNode {
export interface WalletTransactionProps {
transaction: Transaction;
onDelete: () => void;
onRetry: () => void;
onRefund: (id: string) => void;
onBack: () => void;
onDelete: () => Promise<void>;
onRetry: () => Promise<void>;
onRefund: (id: string) => Promise<void>;
onBack: () => Promise<void>;
}
const PurchaseDetailsTable = styled.table`
@ -152,7 +146,7 @@ export function TransactionView({
}: WalletTransactionProps): VNode {
const [confirmBeforeForget, setConfirmBeforeForget] = useState(false);
function doCheckBeforeForget(): void {
async function doCheckBeforeForget(): Promise<void> {
if (
transaction.pending &&
transaction.type === TransactionType.Withdrawal
@ -198,13 +192,17 @@ export function TransactionView({
<div />
<div>
{showRetry ? (
<ButtonPrimary onClick={onRetry}>
<Button variant="contained" onClick={onRetry}>
<i18n.Translate>Retry</i18n.Translate>
</ButtonPrimary>
</Button>
) : null}
<ButtonDestructive onClick={doCheckBeforeForget}>
<Button
variant="contained"
color="error"
onClick={doCheckBeforeForget}
>
<i18n.Translate>Forget</i18n.Translate>
</ButtonDestructive>
</Button>
</div>
</footer>
</Fragment>
@ -229,13 +227,17 @@ export function TransactionView({
</i18n.Translate>
</section>
<footer>
<Button onClick={() => setConfirmBeforeForget(false)}>
<Button
variant="contained"
color="secondary"
onClick={async () => setConfirmBeforeForget(false)}
>
<i18n.Translate>Cancel</i18n.Translate>
</Button>
<ButtonDestructive onClick={onDelete}>
<Button variant="contained" color="error" onClick={onDelete}>
<i18n.Translate>Confirm</i18n.Translate>
</ButtonDestructive>
</Button>
</footer>
</CenteredDialog>
</Overlay>
@ -387,9 +389,12 @@ export function TransactionView({
<div>
<div />
<div>
<ButtonPrimary onClick={() => onRefund(transaction.proposalId)}>
<Button
variant="contained"
onClick={() => onRefund(transaction.proposalId)}
>
<i18n.Translate>Accept</i18n.Translate>
</ButtonPrimary>
</Button>
</div>
</div>
</InfoBox>