40 lines
1.5 KiB
TypeScript
40 lines
1.5 KiB
TypeScript
import { DownloadIcon } from "lucide-react";
|
|
import { buttonVariants } from "@/components/ui/button";
|
|
import { CopyButton } from "@/components/copy-button";
|
|
import { type Release, formatDate, formatSize, releasesPage } from "@/lib/releases";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
/** The download button for a release (children beside it), with its version and checksum below. */
|
|
export function Download({ release, children }: { release: Release | null; children?: React.ReactNode }) {
|
|
const button = (
|
|
<div className="flex flex-wrap gap-3">
|
|
<a href={release?.setup?.url ?? releasesPage} className={buttonVariants({ size: "lg", className: "px-4" })}>
|
|
<DownloadIcon />
|
|
Download for Windows
|
|
</a>
|
|
{children}
|
|
</div>
|
|
);
|
|
if (!release?.setup) return button;
|
|
return (
|
|
<div className="space-y-3">
|
|
{button}
|
|
<p className="text-sm text-muted-foreground">
|
|
Version {release.version} · {formatDate(release.date)} · {formatSize(release.setup.size)}
|
|
{release.imvu && <> · for IMVU Classic {release.imvu}</>}
|
|
</p>
|
|
{release.sha256 && <Checksum sha256={release.sha256} />}
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export function Checksum({ sha256, className }: { sha256: string; className?: string }) {
|
|
return (
|
|
<div className={cn("flex max-w-full items-center gap-2", className)}>
|
|
<span className="shrink-0 text-xs text-muted-foreground">SHA-256</span>
|
|
<code className="min-w-0 truncate rounded bg-muted px-1.5 py-0.5 font-mono text-xs">{sha256}</code>
|
|
<CopyButton text={sha256} />
|
|
</div>
|
|
);
|
|
}
|