From af5f069b2806acb0f17884f7f748e09a56351539 Mon Sep 17 00:00:00 2001 From: turizspace Date: Tue, 22 Oct 2024 23:45:50 +0300 Subject: [PATCH] QR Code & Copy to Clipboard when WebLN not available Possible to now scan a qr code when WebLN is not available. one can also copy invoice to clipboard to paste on a lightning enabled wallet --- src/lib/components/UserLud16.svelte | 401 ++++++++++++++++------------ 1 file changed, 237 insertions(+), 164 deletions(-) diff --git a/src/lib/components/UserLud16.svelte b/src/lib/components/UserLud16.svelte index 7bacda7..c8e0b53 100644 --- a/src/lib/components/UserLud16.svelte +++ b/src/lib/components/UserLud16.svelte @@ -6,7 +6,8 @@ import { nip19 } from 'nostr-tools'; import { onDestroy, onMount } from 'svelte'; import { writable } from 'svelte/store'; - import { getZapEndpoint, makeZapRequest } from '@/zapUtils'; + import { getZapEndpoint } from '@/zapUtils'; + import QRCode from 'qrcode'; export let pubkey: string; @@ -15,10 +16,12 @@ const customZapAmountSats = writable(0); const customZapComment = writable(''); const showModal = writable(false); - + const qrModal = writable(false); + let invoiceToCopy = ''; + let qrCodeDataUrl = ''; onMount(() => { - if (pubkey && pubkey.length == 64) { + if (pubkey && pubkey.length === 64) { if (!$kind0.get(pubkey)) { const rb = new RequestBuilder(pubkey); rb.withFilter().authors([pubkey]).kinds([0]); @@ -40,18 +43,15 @@ } } - showModal.set(true); }); - // Cleanup on destroy onDestroy(() => { if (q) { q.cancel(); } }); - $: { const content = $kind0.get(pubkey)?.content; let lud16 = ''; @@ -68,198 +68,271 @@ profileLud16.set(lud16); } - const closeModal = () => showModal.set(false); - - async function handleZap() { - const lud16 = $profileLud16; - const comment = $customZapComment; - - const metadata = { - content: JSON.stringify({ lud16, comment }) - }; - - try { - const callback = await getZapEndpoint(metadata); - - if (callback) { - const amountToSend = $customZapAmountSats * 1000; - - if (!amountToSend) { - console.error('No zap amount entered.'); - alert('Please enter a valid zap amount.'); - return; + const handleClipboardCopy = () => { + if (navigator.clipboard) { + navigator.clipboard.writeText(invoiceToCopy).then(() => { + alert('Invoice copied to clipboard!'); + }).catch(err => { + alert('Failed to copy invoice to clipboard. Please try again.'); + console.error('Failed to copy:', err); + }); + } else { + // Fallback method for older browsers + const tempTextArea = document.createElement('textarea'); + tempTextArea.value = invoiceToCopy; + document.body.appendChild(tempTextArea); + tempTextArea.select(); + try { + document.execCommand('copy'); + alert('Invoice copied to clipboard!'); + } catch (err) { + console.error('Failed to copy with fallback:', err); + alert('Manual copy failed. Please copy manually.'); } + document.body.removeChild(tempTextArea); + } + }; - // Fetch the invoice using the callback URL - const response = await fetch(`${callback}?amount=${amountToSend}`); - if (!response.ok) { - console.error('Failed to fetch invoice:', response.statusText); - alert('Error fetching invoice. Please try again later.'); - return; - } - const { pr: invoice } = await response.json(); - console.log('Invoice received:', invoice); + const generateQRCode = async (invoice) => { + let attempts = 0; + const maxAttempts = 3; + while (attempts < maxAttempts) { try { - if (window.webln) { - await window.webln.enable(); - await window.webln.sendPayment(invoice); - console.log('Payment sent successfully via WebLN!'); - alert('Payment sent successfully!'); + qrCodeDataUrl = await QRCode.toDataURL(invoice); + qrModal.set(true); // Show the QR modal when QR code is generated + return; // Exit the function if successful + } catch (err) { + attempts++; + console.error('Error generating QR code:', err); + + // If max attempts reached, show a fallback message + if (attempts === maxAttempts) { + qrCodeDataUrl = null; + alert('Failed to generate QR code after multiple attempts. Please try again later or copy the invoice directly.'); } else { - console.error('WebLN not available.'); - alert('WebLN is not available. Please use a WebLN-compatible browser.'); + alert(`Attempt ${attempts} failed. Retrying...`); } - } catch (err) { - console.error('WebLN payment error:', err); - alert(`Failed to send payment via WebLN. Error: ${err.message}`); } - } else { - console.error('Failed to retrieve zap endpoint.'); - alert('Unable to retrieve zap endpoint. Please try again later.'); } - } catch (err) { - console.error('Error in zap process:', err); - alert(`An error occurred while processing the zap. Error: ${err.message}`); - } + }; - closeModal(); -} - + async function handleZap() { + const lud16 = $profileLud16; + const comment = $customZapComment; + + const metadata = { + content: JSON.stringify({ lud16, comment }) + }; + try { + // Fetch the zap endpoint + const callback = await getZapEndpoint(metadata); + if (callback) { + const amountToSend = $customZapAmountSats * 1000; - {#if $showModal} -