Show compressed previews in vision lab

这个提交包含在:
cryptocommuniums-afk
2026-03-15 02:37:12 +08:00
父节点 ae93269c62
当前提交 afb013193d

查看文件

@@ -47,6 +47,67 @@ type VisionRun = {
updatedAt: Date; updatedAt: Date;
}; };
const COMMONS_SPECIAL_FILE_PATH = "/wiki/Special:FilePath/";
const COMMONS_FILE_PAGE_PATH = "/wiki/File:";
function getCompressedVisionImageUrl(imageUrl: string, width = 960) {
try {
const url = new URL(imageUrl);
if (url.hostname !== "commons.wikimedia.org") {
return imageUrl;
}
let fileName: string | null = null;
if (url.pathname.startsWith(COMMONS_SPECIAL_FILE_PATH)) {
fileName = url.pathname.slice(COMMONS_SPECIAL_FILE_PATH.length);
} else if (url.pathname.startsWith(COMMONS_FILE_PAGE_PATH)) {
fileName = url.pathname.slice(COMMONS_FILE_PAGE_PATH.length);
}
if (!fileName) {
return imageUrl;
}
const decodedFileName = decodeURIComponent(fileName);
return `https://commons.wikimedia.org/wiki/Special:Redirect/file/${encodeURIComponent(decodedFileName)}?width=${width}`;
} catch {
return imageUrl;
}
}
function VisionPreviewImage({
src,
alt,
className,
width = 960,
}: {
src: string;
alt: string;
className: string;
width?: number;
}) {
const [displaySrc, setDisplaySrc] = useState(() => getCompressedVisionImageUrl(src, width));
useEffect(() => {
setDisplaySrc(getCompressedVisionImageUrl(src, width));
}, [src, width]);
return (
<img
src={displaySrc}
alt={alt}
className={className}
loading="lazy"
referrerPolicy="no-referrer"
onError={() => {
if (displaySrc !== src) {
setDisplaySrc(src);
}
}}
/>
);
}
function statusBadge(run: VisionRun) { function statusBadge(run: VisionRun) {
if (run.status === "failed" || run.visionStatus === "failed") { if (run.status === "failed" || run.visionStatus === "failed") {
return <Badge variant="destructive"></Badge>; return <Badge variant="destructive"></Badge>;
@@ -212,12 +273,11 @@ export default function VisionLab() {
{references.map((reference) => ( {references.map((reference) => (
<Card key={reference.id} className="overflow-hidden border-0 shadow-sm"> <Card key={reference.id} className="overflow-hidden border-0 shadow-sm">
<div className="aspect-[4/3] overflow-hidden bg-muted"> <div className="aspect-[4/3] overflow-hidden bg-muted">
<img <VisionPreviewImage
src={reference.imageUrl} src={reference.imageUrl}
alt={reference.title} alt={reference.title}
className="h-full w-full object-cover" className="h-full w-full object-cover"
loading="lazy" width={960}
referrerPolicy="no-referrer"
/> />
</div> </div>
<CardHeader className="pb-3"> <CardHeader className="pb-3">
@@ -272,6 +332,24 @@ export default function VisionLab() {
{runs.map((run) => ( {runs.map((run) => (
<Card key={run.id} className="border-0 shadow-sm"> <Card key={run.id} className="border-0 shadow-sm">
<CardContent className="pt-5 space-y-3"> <CardContent className="pt-5 space-y-3">
<div className="flex flex-col gap-4 lg:flex-row">
<a
href={run.imageUrl}
target="_blank"
rel="noreferrer"
className="block overflow-hidden rounded-xl bg-muted lg:w-72 lg:flex-none"
>
<div className="aspect-[4/3]">
<VisionPreviewImage
src={run.imageUrl}
alt={run.title}
className="h-full w-full object-cover"
width={720}
/>
</div>
</a>
<div className="min-w-0 flex-1 space-y-3">
<div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between"> <div className="flex flex-col gap-3 lg:flex-row lg:items-start lg:justify-between">
<div className="space-y-1"> <div className="space-y-1">
<div className="flex flex-wrap items-center gap-2"> <div className="flex flex-wrap items-center gap-2">
@@ -325,6 +403,8 @@ export default function VisionLab() {
{run.corrections} {run.corrections}
</div> </div>
) : null} ) : null}
</div>
</div>
</CardContent> </CardContent>
</Card> </Card>
))} ))}