From 6ea3fa49fce189635875a34473048f0cec71ea0a Mon Sep 17 00:00:00 2001 From: b1rdmania <102524336+b1rdmania@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:20:20 +0000 Subject: [PATCH] Improve iOS copy link with execCommand fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Try modern Clipboard API first - Fall back to execCommand('copy') with textarea trick - Uses setSelectionRange for iOS compatibility - Only show manual text box if both methods fail 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- src/main.ts | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/src/main.ts b/src/main.ts index 1805dea..2d15c5c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -696,15 +696,38 @@ class MotifApp { } } - // Try to copy to clipboard first (works on desktop) + // Try to copy to clipboard let copied = false; + + // Method 1: Modern Clipboard API try { if (navigator.clipboard?.writeText) { await navigator.clipboard.writeText(shareUrl); copied = true; } } catch { - // Clipboard failed, fall through to text box + // Clipboard API failed, try fallback + } + + // Method 2: execCommand fallback (works better on iOS Safari) + if (!copied) { + try { + const textarea = document.createElement('textarea'); + textarea.value = shareUrl; + textarea.style.position = 'fixed'; + textarea.style.left = '-9999px'; + textarea.style.top = '0'; + textarea.setAttribute('readonly', ''); // Prevent zoom on iOS + document.body.appendChild(textarea); + textarea.focus(); + textarea.select(); + // iOS needs setSelectionRange + textarea.setSelectionRange(0, shareUrl.length); + copied = document.execCommand('copy'); + document.body.removeChild(textarea); + } catch { + // execCommand failed too + } } if (copied) { @@ -714,10 +737,13 @@ class MotifApp { setTimeout(() => { this.copyLinkBtn.textContent = originalText; }, 1500); + // Hide the text box if it was showing from a previous attempt + this.shareLinkBox.style.display = 'none'; } else { - // Fallback: show text box for manual copy (iOS) + // Last resort: show text box for manual copy this.shareLinkInput.value = shareUrl; this.shareLinkBox.style.display = 'block'; + this.shareLinkInput.focus(); this.shareLinkInput.select(); } }