import React, { useEffect, useState } from 'react'; import { Globe, X } from 'lucide-react'; import { LinkPreview, loadLinkPreview } from '../../lib/linkPreview'; import { loadAuthorized } from '../../lib/media'; import { safeHref } from '../../lib/safeUrl'; interface LinkPreviewCardProps { url: string; canEdit: boolean; onHide: (title: string) => void; } function usePicture(preview: LinkPreview | null, kind: 'image' | 'icon'): string | null { const [src, setSrc] = useState(null); const has = preview ? (kind === 'image' ? preview.hasImage : preview.hasIcon) : false; const key = preview?.key; useEffect(() => { if (!has || !key) return; let alive = true; loadAuthorized(`/api/v1/link-preview/${key}/${kind}`) .then((p) => alive && setSrc(p.url)) .catch(() => {}); return () => { alive = false; }; }, [has, key, kind]); return src; } // Compact card above a bullet with a web address: icon and site, title, one line of description and a // small picture. Nothing is shown when the page offers nothing usable. export const LinkPreviewCard: React.FC = ({ url, canEdit, onHide }) => { const [preview, setPreview] = useState(null); const image = usePicture(preview, 'image'); const icon = usePicture(preview, 'icon'); const href = safeHref(url); useEffect(() => { let alive = true; setPreview(null); void loadLinkPreview(url).then((p) => alive && setPreview(p)); return () => { alive = false; }; }, [url]); if (!preview || !href) return null; return (
{icon ? ( ) : ( )} {preview.siteName}
{preview.title &&
{preview.title}
} {preview.description &&
{preview.description}
}
{image && }
{canEdit && ( )}
); };