4e1f208a9f
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
36 lines
1.3 KiB
JavaScript
36 lines
1.3 KiB
JavaScript
// Clipboard write that works on plain-HTTP self-hosted deployments.
|
|
//
|
|
// navigator.clipboard is gated by the browser's Secure Context restriction
|
|
// (HTTPS or localhost only). FabledCurator runs over plain HTTP per the
|
|
// homelab posture, so the modern API is undefined in production. We fall
|
|
// back to the legacy execCommand('copy') path via a temporary off-screen
|
|
// textarea — wide browser support, no HTTPS requirement.
|
|
|
|
export async function copyText (text) {
|
|
const str = text == null ? '' : String(text)
|
|
if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {
|
|
try {
|
|
await navigator.clipboard.writeText(str)
|
|
return
|
|
} catch {
|
|
// Fall through to the legacy path. Some browsers throw even when
|
|
// the API exists (permission denied, focus loss, etc.).
|
|
}
|
|
}
|
|
const ta = document.createElement('textarea')
|
|
ta.value = str
|
|
ta.setAttribute('readonly', '')
|
|
ta.style.position = 'fixed'
|
|
ta.style.top = '0'
|
|
ta.style.left = '0'
|
|
ta.style.opacity = '0'
|
|
ta.style.pointerEvents = 'none'
|
|
document.body.appendChild(ta)
|
|
ta.select()
|
|
ta.setSelectionRange(0, str.length)
|
|
let ok = false
|
|
try { ok = document.execCommand('copy') } catch { ok = false }
|
|
document.body.removeChild(ta)
|
|
if (!ok) throw new Error('clipboard copy not supported')
|
|
}
|