/** * Save image — on mobile use navigator.share (same as recipe card), * on desktop trigger download. */ const isMobile = () => /iPhone|iPad|iPod|Android/i.test(navigator.userAgent) /** * Save from a data URL. * Mobile: navigator.share({files}) → system share sheet (save to photos / AirDrop etc) * Desktop: download link. */ export async function saveImageFromUrl(dataUrl, filename) { // Try navigator.share with files (works on iOS Safari, Chrome mobile) if (navigator.share && navigator.canShare) { try { const res = await fetch(dataUrl) const blob = await res.blob() const file = new File([blob], filename + '.png', { type: 'image/png' }) if (navigator.canShare({ files: [file] })) { await navigator.share({ files: [file] }) return 'shared' } } catch (e) { // User cancelled share or share failed, fall through to download if (e.name === 'AbortError') return 'cancelled' } } // Fallback: direct download const a = document.createElement('a') a.href = dataUrl a.download = filename + '.png' document.body.appendChild(a) a.click() setTimeout(() => a.remove(), 100) return 'downloaded' }