/** * Copy text to the clipboard, with a fallback for non-secure contexts. * * Bambuddy is usually reached over plain HTTP on a LAN / tailnet IP, where * `navigator.clipboard` is unavailable — so the hidden-textarea + execCommand * fallback is required, not optional. Returns true if the copy succeeded. */ export async function copyTextToClipboard(text: string): Promise { if (navigator.clipboard && window.isSecureContext) { try { await navigator.clipboard.writeText(text); return true; } catch { // Fall through to the legacy path. } } const ta = document.createElement('textarea'); ta.value = text; ta.style.position = 'fixed'; ta.style.opacity = '0'; document.body.appendChild(ta); try { ta.select(); return document.execCommand('copy'); } catch { return false; } finally { if (ta.parentNode) ta.parentNode.removeChild(ta); } } /** Trigger a browser download of `text` as a file named `filename`. */ export function downloadTextFile(text: string, filename: string, mimeType = 'text/plain'): void { const blob = new Blob([text], { type: mimeType }); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = filename; document.body.appendChild(a); a.click(); a.remove(); URL.revokeObjectURL(url); }