"use client"; import { useEffect, useState } from "react"; import Link from "next/link"; type SourceDocument = { name: string; subtitle?: string; description?: string; iconURL?: string; tintColor?: string; apps: Array<{ name: string; bundleIdentifier: string; developerName: string; subtitle?: string; localizedDescription: string; iconURL?: string; category: string; versions: Array<{ version: string; buildVersion: string; date: string; downloadURL: string; size: number }> }>; }; // Single-user deployment: hard-code the public API origin. const API_BASE = "https://api.altdock.app.amania.jp"; function formatBytes(value: number) { if (!value) return "0 B"; const units = ["B", "KB", "MB", "GB"]; const index = Math.min(Math.floor(Math.log(value) / Math.log(1024)), units.length - 1); return `${(value / 1024 ** index).toFixed(index === 0 ? 0 : 1)} ${units[index]}`; } export default function PublicSourceView({ slug }: { slug: string }) { const [document, setDocument] = useState(null); const [error, setError] = useState(false); useEffect(() => { fetch(`${API_BASE}/sources/${slug}/source.json`) .then((response) => response.ok ? response.json() : Promise.reject(new Error("not found"))) .then(setDocument) .catch(() => setError(true)); }, [slug]); if (error) return
A

Source not found

This Source is still a draft or the URL is incorrect.

Open AltDock
; if (!document) return
A

Loading Source…

; return
AAltDockALTSTORE PAL SOURCE
{document.iconURL ? : document.name.slice(0, 1)}
SOURCE / {slug}

{document.name}

{document.subtitle}

{document.description &&

{document.description}

}
{document.apps.length ? document.apps.map((app) => { const release = app.versions[0]; return
{app.iconURL ? : app.name.slice(0, 1)}{app.category}

{app.name}

{app.developerName} · {app.bundleIdentifier}

{app.localizedDescription || app.subtitle || "A PAL-ready iOS app."}

{release ?
Latest releasev{release.version} build {release.buildVersion}{formatBytes(release.size)}
:
No published release yet
}
; }) :
No published apps yet.

Come back when the developer ships their first release.

}
; }