From 8ba2e690610d5419df33058406711006336e3b6f Mon Sep 17 00:00:00 2001 From: Jordi Montes Date: Mon, 29 Apr 2024 17:59:32 -0700 Subject: [PATCH 1/3] react bc-send-payment: refactor component render Break the component structure in multipe composable parts. --- src/components/pages/bc-send-payment.ts | 264 +++++++++++++++--------- 1 file changed, 162 insertions(+), 102 deletions(-) diff --git a/src/components/pages/bc-send-payment.ts b/src/components/pages/bc-send-payment.ts index cf496b7..11302cc 100644 --- a/src/components/pages/bc-send-payment.ts +++ b/src/components/pages/bc-send-payment.ts @@ -31,6 +31,9 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { @state() _showQR = false; + @state() + _qr = null as QRCode | null; + @property({ type: String, }) @@ -51,11 +54,143 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { } } + private renderHeading(decodedInvoice: Invoice) { + return html` +

+ ${decodedInvoice.satoshi.toLocaleString(undefined, { + useGrouping: true, + })} sats +

+ `; + } + + private renderPaidState() { + return html` +
+

Paid!

+ ${successAnimation} +
+ ` + } + + private renderPayingState() { + return html` +
+

Paying...

+ ${waitingIcon(`w-48 h-48 ${classes['text-brand-mixed']}`)} +
+ `; + } + + private renderPaymentConfirmation() { + return html` + + ${bcIcon} + Confirm Payment + + ${disconnectSection(this._connectorName)} + `; + } + + private renderWaitingForPayment() { + return html` +
+ ${waitingIcon(`w-7 h-7 ${classes['text-brand-mixed']}`)} +

+ Waiting for payment +

+
+ `; + } + + private renderConnectWalletMobile() { + let displayInvoiceBtn = null + let qrSection = null + + if (this._showQR) { + qrSection = this.renderQR(); + } else { + displayInvoiceBtn = html` + + ${qrIcon} Copy & Display Invoice + + `; + } + + return html` +
+ + + ${walletIcon} Open in a Bitcoin Wallet + + + + ${bcIcon}Connect Wallet + + ${displayInvoiceBtn} +
+ ${qrSection} + `; + } + + private renderConnectWalletDesktop() { + return html` +
+ + ${bcIcon} + Connect Wallet to Pay + +
+
${hr('or')}
+

+ Scan to Pay +

+ ${this.renderQR()} + `; + } + + private renderQR() { + if (!this._showQR || !this.invoice || !this._qr) { + return null; + } + + return html` + + + + + + ${this._hasCopiedInvoice ? copiedIcon : copyIcon} + ${this._hasCopiedInvoice ? 'Copied!' : 'Copy Invoice'} + + `; + } + override render() { if (!this.invoice) { return null; } + const errorCorrectionLevel = 'L'; + const qr = qrcode(0, errorCorrectionLevel); + qr.addData(this.invoice); + qr.make(); + + this._qr = qr; + let decodedInvoice: Invoice; try { decodedInvoice = new Invoice({pr: this.invoice}); @@ -64,111 +199,36 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { store.getState().setError((error as Error).message); return null; } - const errorCorrectionLevel = 'L'; - const qr = qrcode(0, errorCorrectionLevel); - qr.addData(this.invoice); - qr.make(); const isMobileView = window.innerWidth < 600; + if (!isMobileView) { + this._showQR = true; + } - return html`
-

- ${decodedInvoice.satoshi.toLocaleString(undefined, { - useGrouping: true, - })} sats -

- ${this._connected || this.paid - ? this.paid - ? html`
-

Paid!

- ${successAnimation} -
` - : this._isPaying - ? html`
-

Paying...

- ${waitingIcon(`w-48 h-48 ${classes['text-brand-mixed']}`)} -
` - : html` - ${bcIcon} - Confirm Payment - - ${disconnectSection(this._connectorName)} ` - : html` -
- ${waitingIcon(`w-7 h-7 ${classes['text-brand-mixed']}`)} -

- Waiting for payment -

-
- - ${!isMobileView - ? html`
- - ${bcIcon} - Connect Wallet to Pay - -
-
${hr('or')}
- -

- Scan to Pay -

-
` - : html` -
- - - ${walletIcon} Open in a Bitcoin Wallet - - - - ${bcIcon}Connect Wallet - - ${this._showQR - ? null - : html` - ${qrIcon}Copy & Display Invoice - `} -
- `} - ${!isMobileView || this._showQR - ? html` - - - - - - ${this._hasCopiedInvoice ? copiedIcon : copyIcon} - ${this._hasCopiedInvoice ? 'Copied!' : 'Copy Invoice'} - - ` - : null} - `} - `; + let paymentStateElement; + + if (this.paid) { + paymentStateElement = this.renderPaidState(); + } else if (this._isPaying) { + paymentStateElement = this.renderPayingState(); + } else if (this._connected) { + paymentStateElement = this.renderPaymentConfirmation(); + } else { + paymentStateElement = html` + ${this.renderWaitingForPayment()} + ${isMobileView ? + this.renderConnectWalletMobile() + : this.renderConnectWalletDesktop() + } + `; + } + + return html` +
+ ${this.renderHeading(decodedInvoice)} + ${paymentStateElement} +
+ `; } private _onClickConnectWallet() { From 3b9b7c58c5ba6853195b35dfef27a1bc74caf2fd Mon Sep 17 00:00:00 2001 From: Jordi Montes Date: Mon, 29 Apr 2024 22:16:59 -0700 Subject: [PATCH 2/3] react bc-send-payment: add payment-methods property The new property can have three values: all, internal or external. Internal payment methods refer to "connect" buttons. External payment methods refer to "show QR/Copy Invoice" All payment methods refer to show Internal and External options. For mobile, the "Open in a Bitcoin Wallet" is always available. --- dev/vite/index.html | 15 +++++ src/components/pages/bc-send-payment.ts | 81 ++++++++++++++++++------- 2 files changed, 75 insertions(+), 21 deletions(-) diff --git a/dev/vite/index.html b/dev/vite/index.html index 2f81ed9..2773b45 100644 --- a/dev/vite/index.html +++ b/dev/vite/index.html @@ -222,6 +222,21 @@

Request Payment Screen

+ +

Request Payment Screen Internal (no QR)

+ + +

Request Payment Screen External (no connect)

+

Start screen

diff --git a/src/components/pages/bc-send-payment.ts b/src/components/pages/bc-send-payment.ts index 11302cc..b769619 100644 --- a/src/components/pages/bc-send-payment.ts +++ b/src/components/pages/bc-send-payment.ts @@ -44,6 +44,12 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { }) paid?: boolean; + @property({ + type: String, + attribute: 'payment-methods', + }) + paymentMethods: 'all' | 'internal' | "external" = 'all'; + protected override updated(changedProperties: PropertyValues): void { super.updated(changedProperties); @@ -109,17 +115,29 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { } private renderConnectWalletMobile() { - let displayInvoiceBtn = null + let internalMethods = null + let externalMethods = null let qrSection = null - - if (this._showQR) { - qrSection = this.renderQR(); - } else { - displayInvoiceBtn = html` + + + if (this.paymentMethods === 'all' || this.paymentMethods === 'internal') { + internalMethods = html` + + ${bcIcon}Connect Wallet + + ` + } + + if (this.paymentMethods === 'all' || this.paymentMethods === 'external') { + externalMethods = html` ${qrIcon} Copy & Display Invoice `; + + if (this._showQR) { + qrSection = this.renderQR(); + } } return html` @@ -129,28 +147,49 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { ${walletIcon} Open in a Bitcoin Wallet - - ${bcIcon}Connect Wallet - - ${displayInvoiceBtn} + ${internalMethods} + ${externalMethods} ${qrSection} `; } private renderConnectWalletDesktop() { + let internalMethods = null; + if (this.paymentMethods === 'all' || this.paymentMethods === 'internal') { + internalMethods = html` +
+ + ${bcIcon} + Connect Wallet to Pay + +
+ `; + } + + let separator = null; + if (this.paymentMethods === 'all') { + separator = html` +
${hr('or')}
+ `; + } + + let externalMethods = null; + if (this.paymentMethods === 'all' || this.paymentMethods === 'external') { + externalMethods = html` +
+

+ Scan to Pay +

+ ${this.renderQR()} +
+ `; + } + return html` -
- - ${bcIcon} - Connect Wallet to Pay - -
-
${hr('or')}
-

- Scan to Pay -

- ${this.renderQR()} + ${internalMethods} + ${separator} + ${externalMethods} `; } From 19705f4709707a5db24cc2d1e37e2a6a6608ac6a Mon Sep 17 00:00:00 2001 From: Jordi Montes Date: Mon, 29 Apr 2024 22:22:12 -0700 Subject: [PATCH 3/3] script: `npm run format` --- dev/vite/index.html | 4 +- src/components/pages/bc-send-payment.ts | 62 ++++++++++++------------- 2 files changed, 31 insertions(+), 35 deletions(-) diff --git a/dev/vite/index.html b/dev/vite/index.html index 2773b45..45caedf 100644 --- a/dev/vite/index.html +++ b/dev/vite/index.html @@ -225,14 +225,14 @@

Request Payment Screen

payment-methods="all" > -

Request Payment Screen Internal (no QR)

+

Request Payment Screen Internal (no QR)

-

Request Payment Screen External (no connect)

+

Request Payment Screen External (no connect)

+

Paid!

${successAnimation}
- ` + `; } private renderPayingState() { @@ -107,25 +111,22 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { return html`
${waitingIcon(`w-7 h-7 ${classes['text-brand-mixed']}`)} -

- Waiting for payment -

+

Waiting for payment

`; } private renderConnectWalletMobile() { - let internalMethods = null - let externalMethods = null - let qrSection = null - + let internalMethods = null; + let externalMethods = null; + let qrSection = null; if (this.paymentMethods === 'all' || this.paymentMethods === 'internal') { internalMethods = html` ${bcIcon}Connect Wallet - ` + `; } if (this.paymentMethods === 'all' || this.paymentMethods === 'external') { @@ -147,8 +148,7 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { ${walletIcon} Open in a Bitcoin Wallet - ${internalMethods} - ${externalMethods} + ${internalMethods} ${externalMethods} ${qrSection} `; @@ -169,15 +169,17 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { let separator = null; if (this.paymentMethods === 'all') { - separator = html` -
${hr('or')}
- `; + separator = html`
${hr('or')}
`; } let externalMethods = null; if (this.paymentMethods === 'all' || this.paymentMethods === 'external') { externalMethods = html` -
+

Scan to Pay

@@ -186,11 +188,7 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { `; } - return html` - ${internalMethods} - ${separator} - ${externalMethods} - `; + return html` ${internalMethods} ${separator} ${externalMethods} `; } private renderQR() { @@ -209,8 +207,8 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { flex gap-1 mt-4 ${classes['text-brand-mixed']} ${ - classes.interactive - } font-semibold text-xs" + classes.interactive + } font-semibold text-xs" > ${this._hasCopiedInvoice ? copiedIcon : copyIcon} ${this._hasCopiedInvoice ? 'Copied!' : 'Copy Invoice'} @@ -253,19 +251,17 @@ export class SendPayment extends withTwind()(BitcoinConnectElement) { } else if (this._connected) { paymentStateElement = this.renderPaymentConfirmation(); } else { - paymentStateElement = html` - ${this.renderWaitingForPayment()} - ${isMobileView ? - this.renderConnectWalletMobile() - : this.renderConnectWalletDesktop() - } - `; + paymentStateElement = html` + ${this.renderWaitingForPayment()} + ${isMobileView + ? this.renderConnectWalletMobile() + : this.renderConnectWalletDesktop()} + `; } return html`
- ${this.renderHeading(decodedInvoice)} - ${paymentStateElement} + ${this.renderHeading(decodedInvoice)} ${paymentStateElement}
`; }