From c580eeaabff8e0bd49e7261d25a9deef724cf89a Mon Sep 17 00:00:00 2001 From: ryder777777 Date: Tue, 20 Oct 2026 15:05:34 +0000 Subject: [PATCH] fix(frontend): add execCommand fallback and manual-copy alert when clipboard API fails (#1481) --- frontend/src/ReferralLinkGenerator.jsx | 37 ++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/frontend/src/ReferralLinkGenerator.jsx b/frontend/src/ReferralLinkGenerator.jsx index 9884ec59..9ccbb769 100644 --- a/frontend/src/ReferralLinkGenerator.jsx +++ b/frontend/src/ReferralLinkGenerator.jsx @@ -68,13 +68,40 @@ export default function ReferralLinkGenerator({ }, [id, walletAddress]); const handleCopy = async () => { + const link = buildInviteLink(); try { - await navigator.clipboard.writeText(buildInviteLink()); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } catch (err) { - console.error('Failed to copy:', err); + if (navigator.clipboard && typeof navigator.clipboard.writeText === 'function') { + await navigator.clipboard.writeText(link); + setCopied(true); + setError(''); + setTimeout(() => setCopied(false), 2000); + return; + } + } catch { + // Fall through to execCommand fallback below (#1481) } + + try { + const textarea = document.createElement('textarea'); + textarea.value = link; + textarea.setAttribute('readonly', ''); + textarea.style.position = 'fixed'; + textarea.style.opacity = '0'; + document.body.appendChild(textarea); + textarea.select(); + const succeeded = typeof document.execCommand === 'function' && document.execCommand('copy'); + document.body.removeChild(textarea); + if (succeeded) { + setCopied(true); + setError(''); + setTimeout(() => setCopied(false), 2000); + return; + } + } catch { + // Ignore and show manual copy prompt + } + + setError('Clipboard unavailable — please select and copy the referral link manually.'); }; const buildShareText = () => {