snort/packages/app/src/Element/LinkPreview.tsx

62 lines
1.6 KiB
TypeScript
Raw Normal View History

2023-03-28 09:52:44 +00:00
import { useEffect, useState } from "react";
2023-04-04 12:50:18 +00:00
import { ApiHost } from "Const";
import Spinner from "Icons/Spinner";
import { ProxyImg } from "Element/ProxyImg";
interface LinkPreviewData {
title?: string;
description?: string;
image?: string;
}
2023-03-28 09:52:44 +00:00
async function fetchUrlPreviewInfo(url: string) {
2023-04-04 12:55:29 +00:00
try {
const res = await fetch(`${ApiHost}/api/v1/preview?url=${encodeURIComponent(url)}`);
if (res.ok) {
return (await res.json()) as LinkPreviewData;
}
} catch (e) {
console.warn(`Failed to load link preview`, url);
2023-03-28 09:52:44 +00:00
}
}
const LinkPreview = ({ url }: { url: string }) => {
2023-04-04 12:55:29 +00:00
const [preview, setPreview] = useState<LinkPreviewData | null>();
2023-04-04 12:50:18 +00:00
2023-03-28 09:52:44 +00:00
useEffect(() => {
2023-04-04 12:50:18 +00:00
(async () => {
const data = await fetchUrlPreviewInfo(url);
2023-04-04 15:33:00 +00:00
if (data && data.title) {
2023-04-04 12:50:18 +00:00
setPreview(data);
2023-04-04 12:55:29 +00:00
} else {
setPreview(null);
2023-04-04 12:50:18 +00:00
}
2023-04-04 12:55:29 +00:00
})();
2023-03-28 09:52:44 +00:00
}, [url]);
2023-04-04 12:50:18 +00:00
2023-04-04 12:55:29 +00:00
if (preview === null) return null;
2023-03-28 09:52:44 +00:00
return (
<div className="link-preview-container">
2023-04-04 12:50:18 +00:00
{preview && (
<a href={url} onClick={e => e.stopPropagation()} target="_blank" rel="noreferrer" className="ext">
{preview?.image && <ProxyImg src={preview?.image} className="link-preview-image" />}
<p className="link-preview-title">
{preview?.title}
{preview?.description && (
<>
<br />
<small>{preview?.description}</small>
</>
)}
</p>
</a>
)}
{!preview && <Spinner className="f-center" />}
</div>
2023-03-28 09:52:44 +00:00
);
};
export default LinkPreview;