Skip to content

Commit

Permalink
frontend/lightning: enable paste LN invoice
Browse files Browse the repository at this point in the history
Paste invoice feature was disabled because of clipboard compatibility
issues. This introduces a workaround that fixes the issue exposing an
empty text input were the user can manually paste the invoice. It is not
pretty, but for now it'll be fine.
  • Loading branch information
Beerosagos committed Oct 8, 2024
1 parent 044ced8 commit b7615eb
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 21 deletions.
6 changes: 3 additions & 3 deletions frontends/web/src/locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -1327,12 +1327,12 @@
"memo": "Memo",
"title": "Confirm transaction details"
},
"invoice": {
"input": "Or paste your invoice here"
},
"qrCode": {
"label": "Scan lightning invoice"
},
"rawInput": {
"label": "Paste invoice from clipboard"
},
"sending": {
"connecting": "Connecting to node",
"message": "Sending payment"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@
height: 100vh;
max-height: 100%;
}
}
}
16 changes: 14 additions & 2 deletions frontends/web/src/routes/lightning/send/send.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,26 @@
color: var(--color-secondary);
}

.error {
height: 70px;
}

.successMessage strong {
color: var(--color-default);
}

.camera video {
margin-bottom: var(--space-default);
}

@media (max-width: 768px) {
.camera,
.camera video {
max-height: 330px;
min-height:200px;
position: relative;
}
}

.error {
height: 90px;
}
}
49 changes: 34 additions & 15 deletions frontends/web/src/routes/lightning/send/send.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import { useCallback, useEffect, useState } from 'react';
import { ChangeEvent, useCallback, useEffect, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import * as accountApi from '../../../api/account';
import { Column, Grid, GuideWrapper, GuidedContent, Header, Main } from '../../../components/layout';
Expand Down Expand Up @@ -98,44 +98,63 @@ const PaymentInput = ({ input }: PaymentInputProps) => {

type SendWorkflowProps = {
onBack: () => void;
onCameraInput: (input: string) => void;
onInvoiceInput: (input: string) => void;
onCustomAmount: (input: number) => void;
onSend: () => void;
parsedInput?: InputType;
rawInputError?: string;
inputError?: string;
customAmount?: number;
step: TStep;
};

const SendWorkflow = ({
onBack,
onCameraInput,
onInvoiceInput,
onCustomAmount,
onSend,
parsedInput,
rawInputError,
inputError,
customAmount,
step,
}: SendWorkflowProps) => {
const { t } = useTranslation();
const [lnInvoice, setLnInvoice] = useState('');

// Memoize the ScanQRVideo component to prevent unnecessary re-renders due to state updates.
const memoizedScanQRVideo = useMemo(() => (
<ScanQRVideo onResult={onInvoiceInput} />
), [onInvoiceInput]);

switch (step) {
case 'select-invoice':
return (
<View textCenter width="660px">
<View textCenter width="660px" >
<ViewHeader title="Scan lightning invoice" />
<ViewContent textAlign="center">
<Grid col="1">
<Column className={styles.camera}>
{rawInputError && <Status type="warning">{rawInputError}</Status>}
<ScanQRVideo onResult={onCameraInput} />
{/* temporary disabled paste button, reason: reading from HTML5 clipboard api is surpressed in Qt/Android WebView */}
{/* <Button transparent onClick={() => console.log('TODO: implement paste')}>
{t('lightning.send.rawInput.label')}
</Button> */}
{ /* we need a cointainer for the error with a fixed height to avoid layout shifts,
that would cause the yellow target on the video component to become misaligned due
to the fact that it is memoized and so it doesn't re-render when inputError changes.*/ }
<div className={styles.error}>
{inputError && <Status type="warning">{inputError}</Status>}
</div>
{memoizedScanQRVideo}
<Input
placeholder={t('lightning.send.invoice.input')}
onInput={(e: ChangeEvent<HTMLInputElement>) => setLnInvoice(e.target.value)}
value={lnInvoice}
autoFocus/>
</Column>
</Grid>
</ViewContent>
<ViewButtons reverseRow>
<ViewButtons>
<Button disabled={!lnInvoice} primary onClick={() => {
onInvoiceInput(lnInvoice);
setLnInvoice('');
}}>
{t('button.send')}
</Button>
<Button secondary onClick={onBack}>
{t('button.back')}
</Button>
Expand Down Expand Up @@ -310,11 +329,11 @@ export const Send = () => {
<Header title={<h2>{t('lightning.send.title')}</h2>} />
<SendWorkflow
onBack={back}
onCameraInput={parseInput}
onInvoiceInput={parseInput}
onCustomAmount={setCustomAmount}
onSend={sendPayment}
parsedInput={paymentDetails}
rawInputError={rawInputError}
inputError={rawInputError}
customAmount={customAmount}
step={step}
/>
Expand Down

0 comments on commit b7615eb

Please sign in to comment.