diff --git a/frontend/src/routes/downloads.tsx b/frontend/src/routes/downloads.tsx index 90e14e19..32e78a6c 100644 --- a/frontend/src/routes/downloads.tsx +++ b/frontend/src/routes/downloads.tsx @@ -5,14 +5,56 @@ import { MarketingHeader } from "@/components/MarketingHeader"; import { Monitor, Terminal, Globe, Smartphone } from "lucide-react"; import { Apple } from "@/components/icons/Apple"; import { Android } from "@/components/icons/Android"; +import { useState, useEffect } from "react"; +import { getLatestDownloadInfo } from "@/utils/githubRelease"; import packageJson from "../../package.json"; -// Get version from package.json -const APP_VERSION = packageJson.version; -const CURRENT_VERSION = `v${APP_VERSION}`; -const BASE_DOWNLOAD_URL = `https://github.com/OpenSecretCloud/Maple/releases/download/${CURRENT_VERSION}`; +interface DownloadUrls { + macOS: string; + linuxAppImage: string; + linuxDeb: string; + linuxRpm: string; +} + +// Fallback to package.json version if GitHub API fails +const FALLBACK_VERSION = packageJson.version; +const FALLBACK_TAG = `v${FALLBACK_VERSION}`; +const FALLBACK_BASE_URL = `https://github.com/OpenSecretCloud/Maple/releases/download/${FALLBACK_TAG}`; +const FALLBACK_URLS: DownloadUrls = { + macOS: `${FALLBACK_BASE_URL}/Maple_${FALLBACK_VERSION}_universal.dmg`, + linuxAppImage: `${FALLBACK_BASE_URL}/Maple_${FALLBACK_VERSION}_amd64.AppImage`, + linuxDeb: `${FALLBACK_BASE_URL}/Maple_${FALLBACK_VERSION}_amd64.deb`, + linuxRpm: `${FALLBACK_BASE_URL}/Maple-${FALLBACK_VERSION}-1.x86_64.rpm`, +}; function DownloadPage() { + const [downloadUrls, setDownloadUrls] = useState(FALLBACK_URLS); + const [currentVersion, setCurrentVersion] = useState(FALLBACK_VERSION); + const [releaseUrl, setReleaseUrl] = useState( + `https://github.com/OpenSecretCloud/Maple/releases/tag/${FALLBACK_TAG}` + ); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + async function loadLatestRelease() { + try { + const downloadInfo = await getLatestDownloadInfo(); + if (downloadInfo) { + setDownloadUrls(downloadInfo.downloadUrls); + setCurrentVersion(downloadInfo.version); + setReleaseUrl(downloadInfo.releaseUrl); + } + } catch (error) { + console.error("Failed to load latest release info:", error); + // Keep fallback values + } finally { + setIsLoading(false); + } + } + + loadLatestRelease(); + }, []); + return ( <> @@ -51,7 +93,7 @@ function DownloadPage() {

- Current version: {APP_VERSION} •{" "} + Current version: {currentVersion} + {isLoading && (loading...)} •{" "} { + try { + const response = await fetch( + "https://api.github.com/repos/OpenSecretCloud/Maple/releases/latest" + ); + + if (!response.ok) { + console.error("Failed to fetch latest release:", response.status); + return null; + } + + const data = await response.json(); + if (!data?.tag_name || !data?.name || !data?.published_at || !data?.html_url) { + console.error("Invalid release data format from GitHub API"); + return null; + } + const release: GitHubRelease = data; + return release; + } catch (error) { + console.error("Error fetching latest release:", error); + return null; + } +} + +/** + * Gets download information for the latest release + */ +export async function getLatestDownloadInfo(): Promise { + const release = await fetchLatestRelease(); + + if (!release) { + return null; + } + + // Extract version number from tag (remove 'v' prefix if present) + const version = release.tag_name.startsWith("v") + ? release.tag_name.slice(1) + : release.tag_name; + + const baseDownloadUrl = `https://github.com/OpenSecretCloud/Maple/releases/download/${release.tag_name}`; + + return { + version, + tagName: release.tag_name, + downloadUrls: { + macOS: `${baseDownloadUrl}/Maple_${version}_universal.dmg`, + linuxAppImage: `${baseDownloadUrl}/Maple_${version}_amd64.AppImage`, + linuxDeb: `${baseDownloadUrl}/Maple_${version}_amd64.deb`, + linuxRpm: `${baseDownloadUrl}/Maple-${version}-1.x86_64.rpm`, + }, + releaseUrl: release.html_url, + }; +} \ No newline at end of file