"use client"; import { useEffect, useMemo, useState } from "react"; import { Button } from "@/components/ui/button"; import { Badge } from "@/components/ui/badge"; import { Package, Calendar, HardDrive, ShieldCheck, History, Monitor, Apple, Terminal, Loader2, AlertCircle, ArrowUpRight, GitBranch, FileText, Inbox, } from "lucide-react"; import { cn } from "@/lib/utils"; import { ReleaseNotes } from "@/components/release-notes"; import { PlatformDownloadGrid } from "@/components/platform-download-grid"; import { DOWNLOAD_SOURCES, resolveDownloadUrl, type DownloadSourceKey, } from "@/lib/download-sources"; interface ChannelPlatform { name: string; url: string; size?: number; sha512?: string; } interface ChannelData { version: string; tag?: string; channel?: "stable" | "preview"; releaseDate?: string; releaseNotes?: string; htmlUrl?: string; windows?: ChannelPlatform | null; macos?: ChannelPlatform | null; linux?: ChannelPlatform | null; } interface DownloadData { source?: "github" | "legacy"; stable: ChannelData | null; preview: ChannelData | null; versions: ChannelData[]; } const CHANNEL_META = [ { key: "stable" as const, label: "正式版", desc: "稳定渠道,与自动更新的慢走模式一致" }, { key: "preview" as const, label: "预览版", desc: "抢先体验新功能,可能存在不稳定因素" }, ]; type Selection = | { kind: "latest"; channel: "stable" | "preview" } | { kind: "version"; version: string }; export default function DownloadPage() { const [data, setData] = useState(null); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); const [selection, setSelection] = useState(null); const [downloadSource, setDownloadSource] = useState("github"); const [copied, setCopied] = useState(false); useEffect(() => { fetch("/api/download-version") .then((res) => { if (!res.ok) throw new Error(`HTTP ${res.status}`); return res.json(); }) .then((json: DownloadData) => { setData(json); setLoading(false); }) .catch((err) => { setError(err.message); setLoading(false); }); }, []); // 汇总全部版本(最新渠道条目带 yml 数据,覆盖历史同名条目) const allVersions = useMemo(() => { if (!data) return []; const map = new Map(); for (const v of data.versions || []) map.set(v.version, v); if (data.stable) map.set(data.stable.version, data.stable); if (data.preview) map.set(data.preview.version, data.preview); return [...map.values()]; }, [data]); // 默认选中:正式版(无则预览版) const defaultLatestChannel: "stable" | "preview" = data?.stable ? "stable" : "preview"; const effectiveSelection: Selection = selection ?? { kind: "latest", channel: defaultLatestChannel }; const active = useMemo(() => { if (!data) return null; if (effectiveSelection.kind === "version") { return ( allVersions.find((v) => v.version === effectiveSelection.version) || null ); } return data[effectiveSelection.channel]; }, [data, effectiveSelection, allVersions]); const isGithub = data?.source === "github"; const win = active?.windows || null; const hasAnyDownload = !!( active && (active.windows?.url || active.macos?.url || active.linux?.url) ); const formatSize = (bytes?: number) => bytes ? `${(bytes / 1024 / 1024).toFixed(1)} MB` : "未知"; const formatDate = (d?: string) => d ? new Date(d).toLocaleDateString("zh-CN") : "未知"; const copySha = async () => { if (!win?.sha512) return; try { await navigator.clipboard.writeText(win.sha512); setCopied(true); setTimeout(() => setCopied(false), 1500); } catch { // 剪贴板不可用时忽略 } }; const handlePlatformDownload = (url?: string | null) => { if (!url) return; window.open(resolveDownloadUrl(downloadSource, url), "_blank"); }; if (loading) { return (

正在获取版本信息...

); } if (error || !data) { return (

获取版本信息失败

); } if (!active) { return (

暂无可用版本

暂时没有可用的发布版本,请稍后再来看看

); } const activeChannelLabel = active.channel === "preview" ? CHANNEL_META[1].label : CHANNEL_META[0].label; const activeIsLatest = effectiveSelection.kind === "latest"; const activeDesc = activeIsLatest ? CHANNEL_META.find((c) => c.key === effectiveSelection.channel)?.desc : "历史版本,安装包与更新内容保留展示"; return (
{/* Header */}
下载中心

Koring Launcher

基于 Electron 的 Minecraft 启动器,版本信息与自动更新机制同源( latest.yml),下载安装包即可开始使用

{isGithub && ( 版本信息由 GitHub Releases 自动识别 )}
{/* 渠道切换 + 历史版本 */}
{CHANNEL_META.map((c) => { const d = c.key === "stable" ? data.stable : data.preview; const isActive = effectiveSelection.kind === "latest" && effectiveSelection.channel === c.key; return ( ); })}
{allVersions.length > 0 && ( )}
{/* 版本信息卡 */}

{active.version}

{activeChannelLabel}

{activeDesc}

{active.htmlUrl && ( 在 GitHub 查看发布页 )}
{/* 元信息 */}

发布时间

{formatDate(active.releaseDate)}

安装包大小

{formatSize(win?.size)}

{/* 下载源切换 */} {isGithub && hasAnyDownload && (
下载源 {DOWNLOAD_SOURCES.map((s) => ( ))}
)} {/* 平台下载(按钮常驻,无版本则禁用) */}
handlePlatformDownload(p.download?.url)} />
{/* 此版本的变更 */} {active.releaseNotes && (

此版本的变更

)}
); }