From 28477aafc6d3ff0015ccd2ee4795a629f1d45735 Mon Sep 17 00:00:00 2001 From: kyy Date: Tue, 10 Feb 2026 12:35:15 +0900 Subject: [PATCH] =?UTF-8?q?Http=20=ED=99=98=EA=B2=BD=20CopyButton=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- devfront/src/components/ui/copy-button.tsx | 23 +++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/devfront/src/components/ui/copy-button.tsx b/devfront/src/components/ui/copy-button.tsx index 83996231..ad59eea3 100644 --- a/devfront/src/components/ui/copy-button.tsx +++ b/devfront/src/components/ui/copy-button.tsx @@ -27,7 +27,28 @@ export function CopyButton({ const copyToClipboard = async () => { try { - await navigator.clipboard.writeText(value); + if (navigator.clipboard && window.isSecureContext) { + await navigator.clipboard.writeText(value); + } else { + // Fallback for non-secure contexts (HTTP) or missing navigator.clipboard + const textArea = document.createElement("textarea"); + textArea.value = value; + textArea.style.position = "fixed"; + textArea.style.left = "-9999px"; + textArea.style.top = "0"; + document.body.appendChild(textArea); + textArea.focus(); + textArea.select(); + try { + const successful = document.execCommand('copy'); + if (!successful) throw new Error('execCommand copy failed'); + } catch (err) { + console.error('Fallback: Oops, unable to copy', err); + throw err; + } finally { + document.body.removeChild(textArea); + } + } setHasCopied(true); if (onCopy) onCopy(); } catch (err) {