import { formatDistanceToNow, formatRelative } from "date-fns"; import ReleaseBody from "~/modules/downloads/older/release-body"; import RootLayout from "~/layouts/RootLayout.astro"; import { Octokit, type RestEndpointMethodTypes } from "@octokit/rest"; import { FaAndroid, FaApple, FaGit, FaGooglePlay, FaLinux, FaWindows, } from "react-icons/fa6"; import type { IconType } from "react-icons"; import { useEffect, useState } from "react"; function getIcon(assetUrl: string) { assetUrl = assetUrl.toLowerCase(); if (assetUrl.includes("linux")) return FaLinux; if (assetUrl.includes("windows")) return FaWindows; if (assetUrl.includes("mac")) return FaApple; if (assetUrl.includes("android")) return FaAndroid; if (assetUrl.includes("playstore")) return FaGooglePlay; if (assetUrl.includes("ios")) return FaApple; return FaGit; } function formatName(assetName: string) { // format the assetName to be // {OS} ({package extension}) const lowerCasedAssetName = assetName.toLowerCase(); const extension = assetName.split(".").at(-1); if (lowerCasedAssetName.includes("linux")) { if (lowerCasedAssetName.includes("aarch64")) { return [`Linux`, extension, `ARM64`] } return [`Linux`, extension, `x64`] }; if (lowerCasedAssetName.includes("windows")) return [`Windows`, extension]; if (lowerCasedAssetName.includes("mac")) return [`macOS`, extension]; if ( lowerCasedAssetName.includes("android") || lowerCasedAssetName.includes("playstore") ) return [`Android`, extension]; if (lowerCasedAssetName.includes("ios")) return [`iOS`, extension]; return [assetName.replace(`.${extension}`, ""), extension]; } type OctokitAsset = RestEndpointMethodTypes["repos"]["listReleases"]["response"]["data"][0]["assets"][0]; function groupByOS(downloads: OctokitAsset[]) { return downloads.reduce( (acc, val) => { const lowName = val.name.toLowerCase(); if (lowName.includes("android") || lowName.includes("playstore")) acc["android"] = [...(acc.android ?? []), val]; if (lowName.includes("linux")) acc["linux"] = [...(acc["linux"] ?? []), val]; if (lowName.includes("windows")) acc["windows"] = [...(acc["windows"] ?? []), val]; if (lowName.includes("ios")) acc["ios"] = [...(acc["ios"] ?? []), val]; if (lowName.includes("mac")) acc["mac"] = [...(acc["mac"] ?? []), val]; return acc; }, {} as Record< "android" | "ios" | "mac" | "linux" | "windows", OctokitAsset[] > ); } const icons: Record = { android: [FaAndroid, "#3DDC84"], mac: [FaApple, ""], ios: [FaApple, ""], linux: [FaLinux, "#000000"], windows: [FaWindows, "#0078D7"], }; export default function ReleasesSection() { const github = new Octokit(); const [releases, setReleases] = useState([]); useEffect(() => { github.repos.listReleases({ owner: "KRTirtho", repo: "spotube", }).then((res) => { setReleases(res.data); }) }, []) return <> { releases.map((release) => { return (

{release.tag_name} ( {formatDistanceToNow(release.published_at ?? new Date(), { addSuffix: true, })} )

{Object.entries(groupByOS(release.assets)).map( ([osName, assets]) => { const Icon = icons[osName][0]; return (
{osName}
{assets.map((asset) => { const Icon = getIcon(asset.browser_download_url); const formattedName = formatName(asset.name); return ( ); })}
); } )}

); }) } }