refactor: og and msg history mark
This commit is contained in:
@@ -1,68 +1,72 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import { useLazyGetOGInfoQuery } from "../../../app/services/message";
|
||||
import { useAppSelector } from "../../../app/store";
|
||||
|
||||
|
||||
export default function URLPreview({ url = "" }) {
|
||||
const [favicon, setFavicon] = useState("");
|
||||
const [getInfo] = useLazyGetOGInfoQuery();
|
||||
const [getInfo, { isLoading }] = useLazyGetOGInfoQuery();
|
||||
const ogData = useAppSelector(store => store.footprint.og[url]);
|
||||
const [data, setData] = useState<{ title: string; description: string; ogImage: string } | null>(
|
||||
null
|
||||
);
|
||||
useEffect(() => {
|
||||
const getMetaData = async (url: string) => {
|
||||
if (ogData) {
|
||||
let defaultFavIcon = "";
|
||||
try {
|
||||
defaultFavIcon = `${new URL(url).origin}/favicon.ico`;
|
||||
} catch {
|
||||
defaultFavIcon = `${location.origin}/favicon.ico`;
|
||||
}
|
||||
// todo
|
||||
const { data } = await getInfo(url);
|
||||
const title = data?.title || data?.site_name || "";
|
||||
const description = data?.description || "";
|
||||
const ogImage = data?.images.find((i) => !!i.url)?.url || "";
|
||||
const favicon = data?.favicon_url || defaultFavIcon;
|
||||
const title = ogData?.title || ogData?.site_name || "";
|
||||
const description = ogData?.description || "";
|
||||
const ogImage = ogData?.images.find((i) => !!i.url)?.url || "";
|
||||
const favicon = ogData?.favicon_url || defaultFavIcon;
|
||||
setFavicon(favicon);
|
||||
setData({ title, description, ogImage });
|
||||
// console.log("wtf url", data);
|
||||
};
|
||||
getMetaData(url);
|
||||
}, [url]);
|
||||
const handleFavError = () => {
|
||||
setFavicon("");
|
||||
};
|
||||
const handleOGImageError = () => {
|
||||
setData(prev => {
|
||||
if (!prev) return prev;
|
||||
return { ...prev, ogImage: "" };
|
||||
});
|
||||
};
|
||||
} else if (url) {
|
||||
// fetch first
|
||||
getInfo(url);
|
||||
}
|
||||
}, [url, ogData]);
|
||||
// const handleFavError = () => {
|
||||
// setFavicon("");
|
||||
// };
|
||||
// const handleOGImageError = () => {
|
||||
// setData(prev => {
|
||||
// if (!prev) return prev;
|
||||
// return { ...prev, ogImage: "" };
|
||||
// });
|
||||
// };
|
||||
if (isLoading) return <div className="h-28"></div>;
|
||||
if (!url || !data || !data.title) return null;
|
||||
const { title, description, ogImage } = data;
|
||||
|
||||
const containerClass = `flex items-center border border-solid border-gray-300 dark:border-gray-600 box-border rounded-md w-[80%] md:w-[380px]`;
|
||||
const dotsClass = `truncate`;
|
||||
|
||||
return ogImage ? (
|
||||
// 简版
|
||||
<a className={`${containerClass} flex-col !items-start p-3`} href={url} target="_blank" rel="noreferrer">
|
||||
<h3 className={`text-primary-500 w-full ${dotsClass}`}>{title}</h3>
|
||||
<p className={`text-xs text-gray-400 mb-2 w-full ${dotsClass}`}>{description}</p>
|
||||
<h3 className={`text-primary-500 w-full truncate`}>{title}</h3>
|
||||
<p className={`text-xs text-gray-400 mb-2 w-full truncate`}>{description}</p>
|
||||
<div className="w-full h-[180px]">
|
||||
<img className="w-full h-full object-cover" onError={handleOGImageError} src={ogImage} alt="og image" />
|
||||
<img className="w-full h-full object-cover" src={ogImage} alt="og image" />
|
||||
</div>
|
||||
</a>
|
||||
) : (
|
||||
// 带图详情
|
||||
<a
|
||||
className={`${containerClass} gap-2 px-2 py-3`}
|
||||
href={url} target="_blank" rel="noreferrer">
|
||||
{favicon && (
|
||||
<div className="flex rounded">
|
||||
<img onError={handleFavError} className="object-contain w-12 h-12" src={favicon} alt="favicon" />
|
||||
<img className="object-contain w-12 h-12" src={favicon} alt="favicon" />
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col">
|
||||
<h3 className="text-sm text-gray-900 dark:text-gray-100">{title}</h3>
|
||||
<p className={`hidden md:block text-xs text-gray-500 dark:text-gray-400 w-[288px] ${dotsClass}`}>{description}</p>
|
||||
<span className={`text-[10px] text-gray-500 w-[288px] ${dotsClass}`}>{url}</span>
|
||||
<p className={`hidden md:block text-xs text-gray-500 dark:text-gray-400 w-[288px] truncate`}>{description}</p>
|
||||
<span className={`text-[10px] text-gray-500 w-[288px] truncate`}>{url}</span>
|
||||
</div>
|
||||
</a>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user