diff --git a/packages/taler-wallet-webextension/src/NavigationBar.tsx b/packages/taler-wallet-webextension/src/NavigationBar.tsx index 10b901162..70fb7bdcb 100644 --- a/packages/taler-wallet-webextension/src/NavigationBar.tsx +++ b/packages/taler-wallet-webextension/src/NavigationBar.tsx @@ -85,8 +85,8 @@ export const Pages = { balanceHistory: pageDefinition<{ currency?: string }>( "/balance/history/:currency?", ), - balanceManualWithdraw: pageDefinition<{ currency?: string }>( - "/balance/manual-withdraw/:currency?", + balanceManualWithdraw: pageDefinition<{ amount?: string }>( + "/balance/manual-withdraw/:amount?", ), balanceDeposit: pageDefinition<{ currency: string }>( "/balance/deposit/:currency", @@ -94,12 +94,8 @@ export const Pages = { balanceTransaction: pageDefinition<{ tid: string }>( "/balance/transaction/:tid", ), - sendCash: pageDefinition<{ currency?: string }>( - "/destination/send/:currency?", - ), - receiveCash: pageDefinition<{ currency?: string }>( - "/destination/get/:currency?", - ), + sendCash: pageDefinition<{ amount?: string }>("/destination/send/:amount"), + receiveCash: pageDefinition<{ amount?: string }>("/destination/get/:amount?"), dev: "/dev", backup: "/backup", diff --git a/packages/taler-wallet-webextension/src/components/styled/index.tsx b/packages/taler-wallet-webextension/src/components/styled/index.tsx index 70f996743..605860300 100644 --- a/packages/taler-wallet-webextension/src/components/styled/index.tsx +++ b/packages/taler-wallet-webextension/src/components/styled/index.tsx @@ -842,10 +842,12 @@ interface SvgIconProps { title: string; color: string; onClick?: any; + transform?: string; } export const SvgIcon = styled.div` & > svg { fill: ${({ color }) => color}; + transform: ${({ transform }) => (transform ? transform : "")}; } width: 24px; height: 24px; diff --git a/packages/taler-wallet-webextension/src/cta/Payment/index.ts b/packages/taler-wallet-webextension/src/cta/Payment/index.ts index 2eb41eb17..889e532c2 100644 --- a/packages/taler-wallet-webextension/src/cta/Payment/index.ts +++ b/packages/taler-wallet-webextension/src/cta/Payment/index.ts @@ -27,7 +27,7 @@ import { LoadingUriView, BaseView } from "./views.js"; export interface Props { talerPayUri?: string; - goToWalletManualWithdraw: (currency?: string) => Promise; + goToWalletManualWithdraw: (amount?: string) => Promise; cancel: () => Promise; } @@ -55,7 +55,7 @@ export namespace State { amount: AmountJson; uri: string; error: undefined; - goToWalletManualWithdraw: (currency?: string) => Promise; + goToWalletManualWithdraw: (amount?: string) => Promise; cancel: () => Promise; } export interface NoBalanceForCurrency extends BaseInfo { diff --git a/packages/taler-wallet-webextension/src/cta/Payment/views.tsx b/packages/taler-wallet-webextension/src/cta/Payment/views.tsx index bf5f4209b..c43745909 100644 --- a/packages/taler-wallet-webextension/src/cta/Payment/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/Payment/views.tsx @@ -393,7 +393,9 @@ function ButtonsSection({ diff --git a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx index 380a5903f..5949076e0 100644 --- a/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx +++ b/packages/taler-wallet-webextension/src/cta/Withdraw/views.tsx @@ -129,7 +129,6 @@ export function SuccessView(state: State.Success): VNode { title="Edit" dangerouslySetInnerHTML={{ __html: editIcon }} color="black" - onClick={() => console.log("ok")} /> } diff --git a/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts b/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts index 0538a55aa..a61fe7965 100644 --- a/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts +++ b/packages/taler-wallet-webextension/src/hooks/useDiagnostics.ts @@ -34,11 +34,9 @@ export function useDiagnostics(): [WalletDiagnostics | undefined, boolean] { }, 1000); const doFetch = async (): Promise => { const d = await wxApi.getDiagnostics(); - console.log("got diagnostics", d); gotDiagnostics = true; setDiagnostics(d); }; - console.log("fetching diagnostics"); doFetch(); }, []); return [diagnostics, timedOut]; diff --git a/packages/taler-wallet-webextension/src/mui/Button.stories.tsx b/packages/taler-wallet-webextension/src/mui/Button.stories.tsx index f953b4a36..8f6b47afb 100644 --- a/packages/taler-wallet-webextension/src/mui/Button.stories.tsx +++ b/packages/taler-wallet-webextension/src/mui/Button.stories.tsx @@ -33,6 +33,10 @@ export default { const Stack = styled.div` display: flex; flex-direction: column; + & > button { + margin: 14px; + } + background-color: white; `; export const BasicExample = (): VNode => ( diff --git a/packages/taler-wallet-webextension/src/mui/TextField.tsx b/packages/taler-wallet-webextension/src/mui/TextField.tsx index 82fc155ef..c59bb28b6 100644 --- a/packages/taler-wallet-webextension/src/mui/TextField.tsx +++ b/packages/taler-wallet-webextension/src/mui/TextField.tsx @@ -43,6 +43,9 @@ export interface Props { placeholder?: string; required?: boolean; + startAdornment?: VNode; + endAdornment?: VNode; + //FIXME: change to "grabFocus" // focused?: boolean; rows?: number; @@ -75,7 +78,6 @@ export function TextField({ }: Props): VNode { // htmlFor={id} id={inputLabelId} const Input = select ? selectVariant[variant] : inputVariant[variant]; - // console.log("variant", Input); return ( {label && {label}} diff --git a/packages/taler-wallet-webextension/src/mui/input/InputBase.tsx b/packages/taler-wallet-webextension/src/mui/input/InputBase.tsx index fc16b7ce4..fce82f9d2 100644 --- a/packages/taler-wallet-webextension/src/mui/input/InputBase.tsx +++ b/packages/taler-wallet-webextension/src/mui/input/InputBase.tsx @@ -53,6 +53,8 @@ export function InputBaseRoot({ multiline, focused, fullWidth, + startAdornment, + endAdornment, children, }: any): VNode { const fcs = useFormControl({}); @@ -61,6 +63,8 @@ export function InputBaseRoot({ data-disabled={disabled} data-focused={focused} data-multiline={multiline} + data-hasStart={!!startAdornment} + data-hasEnd={!!endAdornment} data-error={error} class={[ _class, @@ -156,22 +160,28 @@ export function InputBaseComponent({ multiline, type, class: _class, + startAdornment, + endAdornment, ...props }: any): VNode { return ( - + + {startAdornment} + + {endAdornment} + ); } @@ -388,7 +398,6 @@ export function TextareaAutoSize({ getStyleValue(computedStyle, "border-bottom-width") + getStyleValue(computedStyle, "border-top-width"); - // console.log(boxSizing, padding, border); // The height of the inner content const innerHeight = inputShallow.scrollHeight; @@ -412,7 +421,6 @@ export function TextareaAutoSize({ outerHeight + (boxSizing === "border-box" ? padding + border : 0); const overflow = Math.abs(outerHeight - innerHeight) <= 1; - console.log("height", outerHeight, minRows, maxRows); setState((prevState) => { // Need a large enough difference to update the height. // This prevents infinite rendering loop. diff --git a/packages/taler-wallet-webextension/src/mui/input/InputFilled.tsx b/packages/taler-wallet-webextension/src/mui/input/InputFilled.tsx index 53c6da295..fa5144ca3 100644 --- a/packages/taler-wallet-webextension/src/mui/input/InputFilled.tsx +++ b/packages/taler-wallet-webextension/src/mui/input/InputFilled.tsx @@ -27,7 +27,6 @@ export interface Props { defaultValue?: string; disabled?: boolean; disableUnderline?: boolean; - endAdornment?: VNode; error?: boolean; fullWidth?: boolean; id?: string; @@ -42,6 +41,7 @@ export interface Props { required?: boolean; rows?: number; startAdornment?: VNode; + endAdornment?: VNode; type?: string; value?: string; } @@ -108,6 +108,9 @@ const filledRootStyle = css` &[data-multiline] { padding: 25px 12px 8px; } + /* &[data-hasStart] { + padding-left: 25px; + } */ `; const underlineStyle = css` diff --git a/packages/taler-wallet-webextension/src/platform/dev.ts b/packages/taler-wallet-webextension/src/platform/dev.ts index 5074071e6..fce5722c0 100644 --- a/packages/taler-wallet-webextension/src/platform/dev.ts +++ b/packages/taler-wallet-webextension/src/platform/dev.ts @@ -40,7 +40,6 @@ const api: PlatformAPI = { function waitAndNotify(): void { total--; if (total < 1) { - console.log("done"); fn(); } } diff --git a/packages/taler-wallet-webextension/src/platform/firefox.ts b/packages/taler-wallet-webextension/src/platform/firefox.ts index 611cbf8d3..a56e21f24 100644 --- a/packages/taler-wallet-webextension/src/platform/firefox.ts +++ b/packages/taler-wallet-webextension/src/platform/firefox.ts @@ -63,7 +63,6 @@ function notifyWhenAppIsReady(callback: () => void): void { function redirectTabToWalletPage(tabId: number, page: string): void { const url = chrome.runtime.getURL(`/static/wallet.html#${page}`); - console.log("redirecting tabId: ", tabId, " to: ", url); chrome.tabs.update(tabId, { url, loadReplace: true } as any); } diff --git a/packages/taler-wallet-webextension/src/popup/Application.tsx b/packages/taler-wallet-webextension/src/popup/Application.tsx index be3c8a2f8..9ad979c93 100644 --- a/packages/taler-wallet-webextension/src/popup/Application.tsx +++ b/packages/taler-wallet-webextension/src/popup/Application.tsx @@ -75,7 +75,7 @@ export function Application(): VNode { path={Pages.balance} component={BalancePage} goToWalletManualWithdraw={() => - redirectTo(Pages.balanceManualWithdraw({})) + redirectTo(Pages.receiveCash({})) } goToWalletDeposit={(currency: string) => redirectTo(Pages.balanceDeposit({ currency })) @@ -133,6 +133,10 @@ export function Application(): VNode { path={Pages.backupProviderAdd} component={RedirectToWalletPage} /> + - Get + Add {currencyWithNonZeroAmount.length > 0 && ( - redirectTo(Pages.sendCash({ currency })) + redirectTo(Pages.sendCash({ amount: `${currency}:0` })) } goToWalletManualWithdraw={(currency?: string) => - redirectTo(Pages.receiveCash({ currency })) + redirectTo( + Pages.receiveCash({ + amount: !currency ? undefined : `${currency}:0`, + }), + ) } /> + redirectTo(Pages.balanceManualWithdraw({ amount })) + } /> - redirectTo(Pages.balanceManualWithdraw({ currency })) + goToWalletManualWithdraw={(amount?: string) => + redirectTo(Pages.balanceManualWithdraw({ amount })) } cancel={() => redirectTo(Pages.balance)} /> diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.stories.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.stories.tsx index 876f683f6..ec997dfb3 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.stories.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.stories.tsx @@ -30,8 +30,8 @@ export default { }; export const GetCash = createExample(DestinationSelectionGetCash, { - currency: "usd", + amount: "usd:0", }); export const SendCash = createExample(DestinationSelectionSendCash, { - currency: "eur", + amount: "eur:1", }); diff --git a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx index 187a2412f..5f9c5065c 100644 --- a/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx +++ b/packages/taler-wallet-webextension/src/wallet/DestinationSelection.tsx @@ -14,17 +14,22 @@ GNU Taler; see the file COPYING. If not, see */ +import { Amounts } from "@gnu-taler/taler-util"; import { styled } from "@linaria/react"; import { Fragment, h, VNode } from "preact"; +import { useState } from "preact/hooks"; +import { + InputWithLabel, + LightText, + SvgIcon, +} from "../components/styled/index.js"; +import { useTranslationContext } from "../context/translation.js"; +import { Button } from "../mui/Button.js"; +import { Grid } from "../mui/Grid.js"; import { Paper } from "../mui/Paper.js"; - -const QrVideo = styled.video` - width: 80%; - margin-left: auto; - margin-right: auto; - padding: 8px; - background-color: black; -`; +import { TextField } from "../mui/TextField.js"; +import arrowIcon from "../svg/chevron-down.svg"; +import bankIcon from "../svg/ri-bank-line.svg"; const Container = styled.div` display: flex; @@ -36,25 +41,379 @@ const Container = styled.div` interface Props { action: "send" | "get"; - currency?: string; + amount?: string; + goToWalletManualWithdraw: (amount: string) => void; } -export function DestinationSelectionGetCash({ currency }: Props): VNode { +type Contact = { + icon: string; + name: string; + description: string; +}; + +const ContactTable = styled.table` + width: 100%; + & > tr > td { + padding: 8px; + & > div:not([data-disabled]):hover { + background-color: lightblue; + } + color: black; + div[data-disabled] > * { + color: gray; + } + } + + & > tr:nth-child(2n) { + background: #ebebeb; + } +`; + +const MediaExample = styled.div` + text-size-adjust: 100%; + color: inherit; + font-family: inherit; + font-size: inherit; + line-height: inherit; + text-transform: none; + text-align: left; + box-sizing: border-box; + align-items: center; + display: flex; + padding: 8px 8px; + + &[data-disabled]:hover { + cursor: inherit; + } + cursor: pointer; +`; + +const MediaLeft = styled.div` + text-size-adjust: 100%; + + color: inherit; + font-family: inherit; + font-size: inherit; + line-height: inherit; + text-transform: none; + text-align: left; + box-sizing: border-box; + padding-right: 8px; + display: block; +`; + +const MediaBody = styled.div` + text-size-adjust: 100%; + + font-family: inherit; + text-transform: none; + text-align: left; + box-sizing: border-box; + flex: 1 1; + font-size: 14px; + font-weight: 500; + line-height: 1.42857; +`; +const MediaRight = styled.div` + text-size-adjust: 100%; + + color: inherit; + font-family: inherit; + font-size: inherit; + line-height: inherit; + text-transform: none; + text-align: left; + box-sizing: border-box; + padding-left: 8px; +`; + +const CircleDiv = styled.div` + box-sizing: border-box; + align-items: center; + background-position: 50%; + background-repeat: no-repeat; + background-size: cover; + border-radius: 50%; + display: flex; + justify-content: center; + margin-left: auto; + margin-right: auto; + overflow: hidden; + text-align: center; + text-decoration: none; + text-transform: uppercase; + transition: background-color 0.15s ease, border-color 0.15s ease, + color 0.15s ease; + font-size: 16px; + background-color: #86a7bd1a; + height: 40px; + line-height: 40px; + width: 40px; + border: none; +`; + +function RowExample({ + info, + disabled, +}: { + info: Contact; + disabled?: boolean; +}): VNode { + return ( + + + + + + + + {info.name} + {info.description} + + + + + + ); +} + +export function DestinationSelectionGetCash({ + amount: initialAmount, + goToWalletManualWithdraw, +}: Props): VNode { + const parsedInitialAmount = !initialAmount + ? undefined + : Amounts.parse(initialAmount); + const parsedInitialAmountValue = !parsedInitialAmount + ? "" + : Amounts.stringifyValue(parsedInitialAmount); + const currency = parsedInitialAmount?.currency; + + const [amount, setAmount] = useState(parsedInitialAmountValue); + const { i18n } = useTranslationContext(); + const previous1: Contact[] = []; + const previous2: Contact[] = [ + { + name: "International Bank", + icon: bankIcon, + description: "account ending with 3454", + }, + { + name: "Max", + icon: bankIcon, + description: "account ending with 3454", + }, + { + name: "Alex", + icon: bankIcon, + description: "account ending with 3454", + }, + ]; + + if (!currency) { + return
currency not provided
; + } + const currencyAndAmount = `${currency}:${amount}`; + const parsedAmount = Amounts.parse(currencyAndAmount); + // const dirty = parsedInitialAmountValue !== amount; + const invalid = !parsedAmount || Amounts.isZero(parsedAmount); return ( -

Request {currency} from:

- Bank account - Another person +

+ Specify the amount and the origin +

+ {currency} + } + value={amount} + onChange={(e) => { + setAmount(e); + }} + /> + + + {previous2.length > 0 ? ( + +

Previous origins:

+ + + + {previous2.map((info, i) => ( + + + + + + ))} + + + +
+ ) : undefined} + +

Create new origin for the money

+
+ + + +

From my bank account

+ +
+
+ + +

From someone else

+ +
+
+ + +

From a business or charity

+ +
+
+
+ + +

From a exchange reserve or purse

+ +
+
+
); } -export function DestinationSelectionSendCash({ currency }: Props): VNode { +export function DestinationSelectionSendCash({ + amount: initialAmount, +}: Props): VNode { + const parsedInitialAmount = !initialAmount + ? undefined + : Amounts.parse(initialAmount); + const parsedInitialAmountValue = !parsedInitialAmount + ? "" + : Amounts.stringifyValue(parsedInitialAmount); + const currency = parsedInitialAmount?.currency; + + const [amount, setAmount] = useState(parsedInitialAmountValue); + const { i18n } = useTranslationContext(); + const previous1: Contact[] = []; + const previous2: Contact[] = [ + { + name: "International Bank", + icon: bankIcon, + description: "account ending with 3454", + }, + { + name: "Max", + icon: bankIcon, + description: "account ending with 3454", + }, + { + name: "Alex", + icon: bankIcon, + description: "account ending with 3454", + }, + ]; + + if (!currency) { + return
currency not provided
; + } + const currencyAndAmount = `${currency}:${amount}`; + const parsedAmount = Amounts.parse(currencyAndAmount); + const invalid = !parsedAmount || Amounts.isZero(parsedAmount); return ( -

Sending {currency} to:

- Bank account - Another person +

+ Specify the amount and the destination +

+ + {currency} + } + value={amount} + onChange={(e) => { + setAmount(e); + }} + /> + + + {previous2.length > 0 ? ( + +

Previous destinations:

+ + + + {previous2.map((info, i) => ( + + + + + + ))} + + + +
+ ) : undefined} + +

Create a destination for the money

+
+ + + +

To my bank account

+ +
+
+ + +

To someone else

+ +
+
+ + +

To a business or charity

+ +
+
+
+ + +

To an exchange reserve or purse

+ +
+
+
); } diff --git a/packages/taler-wallet-webextension/src/wallet/History.tsx b/packages/taler-wallet-webextension/src/wallet/History.tsx index f331cc457..f02e43391 100644 --- a/packages/taler-wallet-webextension/src/wallet/History.tsx +++ b/packages/taler-wallet-webextension/src/wallet/History.tsx @@ -210,7 +210,7 @@ export function HistoryView({ // style={{ marginLeft: 0, marginTop: 8 }} onClick={() => goToWalletManualWithdraw(selectedCurrency)} > - Get + Add {currencyAmount && Amounts.isNonZero(currencyAmount) && (