import { useState, useEffect } from 'react'; interface LinkPreviewProps { url: string; } interface MicrolinkData { publisher?: string; title?: string; description?: string; image?: { url: string }; logo?: { url: string }; } export default function LinkPreview({ url }: LinkPreviewProps) { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); useEffect(() => { let isMounted = true; setLoading(true); // Check cache first to avoid rate limiting const cacheKey = `link_preview_${url}`; const cached = sessionStorage.getItem(cacheKey); if (cached) { try { const parsed = JSON.parse(cached); if (isMounted) { setData(parsed); setLoading(false); } return; } catch (e) {} } fetch(`https://api.microlink.io?url=${encodeURIComponent(url)}`) .then(res => res.json()) .then(res => { if (isMounted && res.status === 'success' && res.data) { setData(res.data); sessionStorage.setItem(cacheKey, JSON.stringify(res.data)); } if (isMounted) setLoading(false); }) .catch((err) => { console.error('Failed to fetch link preview:', err); if (isMounted) setLoading(false); }); return () => { isMounted = false; }; }, [url]); if (loading) { return (
Загрузка предпросмотра...
); } if (!data || (!data.title && !data.description && !data.image)) { return null; } // Domain for publisher fallback let domain = data.publisher; if (!domain) { try { domain = new URL(url).hostname.replace(/^www\./, ''); } catch (e) {} } return ( e.stopPropagation()} >
{data.logo?.url && } {domain}
{data.title &&
{data.title}
} {data.description &&
{data.description}
}
{data.image?.url && (
)}
); }