diff options
author | Sebastian <sebasjm@gmail.com> | 2022-08-15 23:01:05 -0300 |
---|---|---|
committer | Sebastian <sebasjm@gmail.com> | 2022-08-15 23:01:05 -0300 |
commit | fb8372dfbf27b7b4e8b2fe4f81aa2ba18bfcf638 (patch) | |
tree | 604fca93fdb0ff3ac21803941a49e073011da56c | |
parent | 0798aa5cedad2a599829f2b13d4573c64a081c29 (diff) |
default exchange and select currency
5 files changed, 207 insertions, 65 deletions
diff --git a/packages/taler-wallet-webextension/src/mui/Modal.tsx b/packages/taler-wallet-webextension/src/mui/Modal.tsx index 5a30bcf26..b24a45d61 100644 --- a/packages/taler-wallet-webextension/src/mui/Modal.tsx +++ b/packages/taler-wallet-webextension/src/mui/Modal.tsx @@ -1,9 +1,25 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + import { css } from "@linaria/core"; import { h, JSX, VNode, ComponentChildren } from "preact"; import { useCallback, useEffect, useRef, useState } from "preact/hooks"; // eslint-disable-next-line import/extensions import { alpha } from "./colors/manipulation"; -import { ModalManager } from "./ModalManager"; +import { ModalManager } from "./ModalManager.js"; import { Portal } from "./Portal.js"; // eslint-disable-next-line import/extensions import { theme } from "./style"; @@ -22,12 +38,16 @@ interface Props { children: ComponentChildren; open?: boolean; exited?: boolean; - container?: HTMLElement; + container?: VNode; } const defaultManager = new ModalManager(); const manager = defaultManager; +function getModal(): any { + return null; //TODO: fix +} + export function Modal({ open, // exited, @@ -52,18 +72,18 @@ export function Modal({ return; } - if (open && isTopModal()) { - handleMounted(); - } else { - ariaHidden(modalRef.current, true); - } + // if (open && isTopModal()) { + // handleMounted(); + // } else { + // ariaHidden(modalRef.current, true); + // } }); return ( <Portal ref={handlePortalRef} container={container} - disablePortal={disablePortal} + // disablePortal={disablePortal} > <div class={[_class, baseStyle].join(" ")} @@ -105,7 +125,7 @@ function getOffsetLeft(rect: any, horizontal: any): number { return offset; } -function getTransformOriginValue(transformOrigin): string { +function getTransformOriginValue(transformOrigin: any): string { return [transformOrigin.horizontal, transformOrigin.vertical] .map((n) => (typeof n === "number" ? `${n}px` : n)) .join(" "); diff --git a/packages/taler-wallet-webextension/src/mui/ModalManager.ts b/packages/taler-wallet-webextension/src/mui/ModalManager.ts index 2894ffa7a..b4a3ee597 100644 --- a/packages/taler-wallet-webextension/src/mui/ModalManager.ts +++ b/packages/taler-wallet-webextension/src/mui/ModalManager.ts @@ -1,3 +1,19 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + //////////////////// function ownerDocument(node: Node | null | undefined): Document { return (node && node.ownerDocument) || document; diff --git a/packages/taler-wallet-webextension/src/mui/Popover.tsx b/packages/taler-wallet-webextension/src/mui/Popover.tsx index 408f87987..69e0ab10a 100644 --- a/packages/taler-wallet-webextension/src/mui/Popover.tsx +++ b/packages/taler-wallet-webextension/src/mui/Popover.tsx @@ -1,3 +1,19 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + import { css } from "@linaria/core"; import { h, JSX, VNode, ComponentChildren } from "preact"; // eslint-disable-next-line import/extensions @@ -48,7 +64,7 @@ function getOffsetLeft(rect: any, horizontal: any): number { return offset; } -function getTransformOriginValue(transformOrigin): string { +function getTransformOriginValue(transformOrigin: any): string { return [transformOrigin.horizontal, transformOrigin.vertical] .map((n) => (typeof n === "number" ? `${n}px` : n)) .join(" "); diff --git a/packages/taler-wallet-webextension/src/mui/Portal.tsx b/packages/taler-wallet-webextension/src/mui/Portal.tsx index 828a574fd..f9be021f0 100644 --- a/packages/taler-wallet-webextension/src/mui/Portal.tsx +++ b/packages/taler-wallet-webextension/src/mui/Portal.tsx @@ -1,3 +1,19 @@ +/* + This file is part of GNU Taler + (C) 2022 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/> + */ + import { css } from "@linaria/core"; import { createPortal, forwardRef } from "preact/compat"; import { @@ -26,7 +42,7 @@ const baseStyle = css` `; interface Props { - class: string; + // class: string; children: ComponentChildren; disablePortal?: boolean; container?: VNode; @@ -39,10 +55,11 @@ export const Portal = forwardRef(function Portal( const [mountNode, setMountNode] = useState<HTMLElement | undefined>( undefined, ); - const handleRef = useForkRef( - isValidElement(children) ? children.ref : null, - ref, - ); + const handleRef = null; + // useForkRef( + // isValidElement(children) ? children.ref : null, + // ref, + // ); useEffect(() => { if (!disablePortal) { @@ -81,25 +98,25 @@ function getContainer(container: any): any { return typeof container === "function" ? container() : container; } -function useForkRef<Instance>( - refA: React.Ref<Instance> | null | undefined, - refB: React.Ref<Instance> | null | undefined, -): React.Ref<Instance> | null { - /** - * This will create a new function if the ref props change and are defined. - * This means react will call the old forkRef with `null` and the new forkRef - * with the ref. Cleanup naturally emerges from this behavior. - */ - return useMemo(() => { - if (refA == null && refB == null) { - return null; - } - return (refValue) => { - setRef(refA, refValue); - setRef(refB, refValue); - }; - }, [refA, refB]); -} +// function useForkRef<Instance>( +// refA: React.Ref<Instance> | null | undefined, +// refB: React.Ref<Instance> | null | undefined, +// ): React.Ref<Instance> | null { +// /** +// * This will create a new function if the ref props change and are defined. +// * This means react will call the old forkRef with `null` and the new forkRef +// * with the ref. Cleanup naturally emerges from this behavior. +// */ +// return useMemo(() => { +// if (refA == null && refB == null) { +// return null; +// } +// return (refValue) => { +// setRef(refA, refValue); +// setRef(refB, refValue); +// }; +// }, [refA, refB]); +// } function setRef<T>( ref: RefObject<T | null> | ((instance: T | null) => void) | null | undefined, diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx index 5f9c5065c..ba5dcf1da 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx @@ -18,18 +18,29 @@ import { Amounts } from "@gnu-taler/taler-util"; import { styled } from "@linaria/react"; import { Fragment, h, VNode } from "preact"; import { useState } from "preact/hooks"; +import { ErrorMessage } from "../components/ErrorMessage.js"; +import { Loading } from "../components/Loading.js"; +import { LoadingError } from "../components/LoadingError.js"; +import { SelectList } from "../components/SelectList.js"; import { + Input, InputWithLabel, LightText, + LinkPrimary, + SubTitle, SvgIcon, } from "../components/styled/index.js"; import { useTranslationContext } from "../context/translation.js"; +import { useAsyncAsHook } from "../hooks/useAsyncAsHook.js"; +import { Alert } from "../mui/Alert.js"; import { Button } from "../mui/Button.js"; import { Grid } from "../mui/Grid.js"; import { Paper } from "../mui/Paper.js"; import { TextField } from "../mui/TextField.js"; +import { Pages } from "../NavigationBar.js"; import arrowIcon from "../svg/chevron-down.svg"; import bankIcon from "../svg/ri-bank-line.svg"; +import * as wxApi from "../wxApi.js"; const Container = styled.div` display: flex; @@ -152,6 +163,57 @@ const CircleDiv = styled.div` border: none; `; +export function SelectCurrency({ + onChange, +}: { + onChange: (s: string) => void; +}): VNode { + const { i18n } = useTranslationContext(); + + const hook = useAsyncAsHook(wxApi.listExchanges); + + if (!hook) { + return <Loading />; + } + if (hook.hasError) { + return ( + <LoadingError + error={hook} + title={<i18n.Translate>Could not load list of exchange</i18n.Translate>} + /> + ); + } + const list: Record<string, string> = {}; + hook.response.exchanges.forEach((e) => (list[e.currency] = e.currency)); + list[""] = "Select a currency"; + return ( + <Fragment> + <h1> + <i18n.Translate>Specify the amount and the origin</i18n.Translate> + </h1> + + <Alert severity="warning"> + Choose a currency to proceed or add more exchanges in the settings tab + </Alert> + <Input> + <SelectList + label={<i18n.Translate>Known currencies</i18n.Translate>} + list={list} + name="lang" + value={""} + onChange={(v) => onChange(v)} + /> + </Input> + <div style={{ display: "flex", justifyContent: "space-between" }}> + <div /> + <LinkPrimary href={Pages.settingsExchangeAdd({})}> + <i18n.Translate>Add an exchange</i18n.Translate> + </LinkPrimary> + </div> + </Fragment> + ); +} + function RowExample({ info, disabled, @@ -194,9 +256,9 @@ export function DestinationSelectionGetCash({ ? undefined : Amounts.parse(initialAmount); const parsedInitialAmountValue = !parsedInitialAmount - ? "" + ? "0" : Amounts.stringifyValue(parsedInitialAmount); - const currency = parsedInitialAmount?.currency; + const [currency, setCurrency] = useState(parsedInitialAmount?.currency); const [amount, setAmount] = useState(parsedInitialAmountValue); const { i18n } = useTranslationContext(); @@ -220,7 +282,11 @@ export function DestinationSelectionGetCash({ ]; if (!currency) { - return <div>currency not provided</div>; + return ( + <div> + <SelectCurrency onChange={(c) => setCurrency(c)} /> + </div> + ); } const currencyAndAmount = `${currency}:${amount}`; const parsedAmount = Amounts.parse(currencyAndAmount); @@ -231,20 +297,25 @@ export function DestinationSelectionGetCash({ <h1> <i18n.Translate>Specify the amount and the origin</i18n.Translate> </h1> - <TextField - label="Amount" - type="number" - variant="filled" - error={invalid} - required - startAdornment={ - <div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div> - } - value={amount} - onChange={(e) => { - setAmount(e); - }} - /> + <Grid container columns={2} justifyContent="space-between"> + <TextField + label="Amount" + type="number" + variant="filled" + error={invalid} + required + startAdornment={ + <div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div> + } + value={amount} + onChange={(e) => { + setAmount(e); + }} + /> + <Button onClick={async () => setCurrency(undefined)}> + Change currency + </Button> + </Grid> <Grid container spacing={1} columns={1}> {previous2.length > 0 ? ( @@ -350,20 +421,22 @@ export function DestinationSelectionSendCash({ <i18n.Translate>Specify the amount and the destination</i18n.Translate> </h1> - <TextField - label="Amount" - type="number" - variant="filled" - required - error={invalid} - startAdornment={ - <div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div> - } - value={amount} - onChange={(e) => { - setAmount(e); - }} - /> + <div> + <TextField + label="Amount" + type="number" + variant="filled" + required + error={invalid} + startAdornment={ + <div style={{ padding: "25px 12px 8px 12px" }}>{currency}</div> + } + value={amount} + onChange={(e) => { + setAmount(e); + }} + /> + </div> <Grid container spacing={1} columns={1}> {previous2.length > 0 ? ( |