clipboard.ts 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243
  1. /**
  2. * Copy text to the clipboard, with a fallback for non-secure contexts.
  3. *
  4. * Bambuddy is usually reached over plain HTTP on a LAN / tailnet IP, where
  5. * `navigator.clipboard` is unavailable — so the hidden-textarea + execCommand
  6. * fallback is required, not optional. Returns true if the copy succeeded.
  7. */
  8. export async function copyTextToClipboard(text: string): Promise<boolean> {
  9. if (navigator.clipboard && window.isSecureContext) {
  10. try {
  11. await navigator.clipboard.writeText(text);
  12. return true;
  13. } catch {
  14. // Fall through to the legacy path.
  15. }
  16. }
  17. const ta = document.createElement('textarea');
  18. ta.value = text;
  19. ta.style.position = 'fixed';
  20. ta.style.opacity = '0';
  21. document.body.appendChild(ta);
  22. try {
  23. ta.select();
  24. return document.execCommand('copy');
  25. } catch {
  26. return false;
  27. } finally {
  28. if (ta.parentNode) ta.parentNode.removeChild(ta);
  29. }
  30. }
  31. /** Trigger a browser download of `text` as a file named `filename`. */
  32. export function downloadTextFile(text: string, filename: string, mimeType = 'text/plain'): void {
  33. const blob = new Blob([text], { type: mimeType });
  34. const url = URL.createObjectURL(blob);
  35. const a = document.createElement('a');
  36. a.href = url;
  37. a.download = filename;
  38. document.body.appendChild(a);
  39. a.click();
  40. a.remove();
  41. URL.revokeObjectURL(url);
  42. }