fix(landing): resolve download URLs from GitHub Releases API so Windo… #4779
2 changed files+52−5
Modifiedlanding/src/App.tsx+50−3View fileUnifiedSplit
@@ -759,11 +759,39 @@ function FAQ() {
759759 );
760760}
761761
762const GH_RELEASES = "https://github.com/ccantynz-alt/voxlen/releases/latest/download";
762const GH_OWNER = "ccantynz-alt";
763const GH_REPO = "voxlen";
764const GH_RELEASES = `https://github.com/${GH_OWNER}/${GH_REPO}/releases/latest/download`;
765const GH_API_LATEST = `https://api.github.com/repos/${GH_OWNER}/${GH_REPO}/releases/latest`;
763766const APP_VERSION = "1.0.8";
764767
765768type Platform = "mac-arm" | "mac-intel" | "windows" | "linux" | "unknown";
766769
770type ReleaseAsset = { name: string; browser_download_url: string };
771
772function pickAssetFor(platform: Exclude<Platform, "unknown">, assets: ReleaseAsset[]): ReleaseAsset | null {
773 const lowered = assets.map((a) => ({ ...a, lower: a.name.toLowerCase() }));
774 const find = (pred: (a: { name: string; lower: string; browser_download_url: string }) => boolean) =>
775 lowered.find(pred) ?? null;
776 switch (platform) {
777 case "mac-arm":
778 return find((a) => a.lower.endsWith(".dmg") && (a.lower.includes("aarch64") || a.lower.includes("arm64")))
779 ?? find((a) => a.lower.endsWith(".dmg"));
780 case "mac-intel":
781 return find((a) => a.lower.endsWith(".dmg") && (a.lower.includes("x64") || a.lower.includes("x86_64") || a.lower.includes("intel")))
782 ?? find((a) => a.lower.endsWith(".dmg"));
783 case "windows":
784 return find((a) => a.lower.endsWith(".msi") && (a.lower.includes("x64") || a.lower.includes("x86_64")))
785 ?? find((a) => a.lower.endsWith(".msi"))
786 ?? find((a) => a.lower.endsWith(".exe") && a.lower.includes("setup"))
787 ?? find((a) => a.lower.endsWith(".exe"));
788 case "linux":
789 return find((a) => a.lower.endsWith(".appimage") && (a.lower.includes("amd64") || a.lower.includes("x86_64")))
790 ?? find((a) => a.lower.endsWith(".appimage"))
791 ?? find((a) => a.lower.endsWith(".deb"));
792 }
793}
794
767795function detectPlatform(): Platform {
768796 if (typeof window === "undefined") return "unknown";
769797 const ua = window.navigator.userAgent;
@@ -816,11 +844,30 @@ const DOWNLOADS: Record<
816844
817845function CTA() {
818846 const [platform, setPlatform] = useState<Platform>("unknown");
847 const [liveAssets, setLiveAssets] = useState<ReleaseAsset[] | null>(null);
819848
820849 useEffect(() => {
821850 setPlatform(detectPlatform());
851 const ac = new AbortController();
852 fetch(GH_API_LATEST, { signal: ac.signal, headers: { Accept: "application/vnd.github+json" } })
853 .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`GitHub API ${r.status}`))))
854 .then((json: { assets?: ReleaseAsset[] }) => {
855 if (Array.isArray(json.assets)) setLiveAssets(json.assets);
856 })
857 .catch(() => {
858 // Network blocked or rate-limited: fall back to hardcoded filenames below.
859 });
860 return () => ac.abort();
822861 }, []);
823862
863 const hrefFor = (key: Exclude<Platform, "unknown">): string => {
864 if (liveAssets) {
865 const picked = pickAssetFor(key, liveAssets);
866 if (picked) return picked.browser_download_url;
867 }
868 return `${GH_RELEASES}/${encodeURIComponent(DOWNLOADS[key].file)}`;
869 };
870
824871 const primary = platform !== "unknown" ? DOWNLOADS[platform] : null;
825872 const PrimaryIcon = primary?.icon === "apple" ? Apple : Monitor;
826873
@@ -849,7 +896,7 @@ function CTA() {
849896 {primary && (
850897 <motion.div variants={fadeUp} className="flex justify-center mb-4">
851898 <a
852 href={`${GH_RELEASES}/${encodeURIComponent(primary.file)}`}
899 href={hrefFor(platform as Exclude<Platform, "unknown">)}
853900 className="group h-16 px-10 rounded-2xl bg-marcoreid-600 text-white font-bold flex items-center gap-4 hover:bg-marcoreid-700 transition-all shadow-xl shadow-marcoreid-600/30 hover:shadow-marcoreid-600/50 hover:scale-[1.02]"
854901 >
855902 <PrimaryIcon className="h-7 w-7" />
@@ -885,7 +932,7 @@ function CTA() {
885932 <motion.a
886933 key={key}
887934 variants={fadeUp}
888 href={`${GH_RELEASES}/${encodeURIComponent(d.file)}`}
935 href={hrefFor(key)}
889936 className={`group relative p-5 rounded-xl border transition-all ${
890937 isDetected
891938 ? "bg-marcoreid-600/5 border-marcoreid-600/40 hover:border-marcoreid-600/60"
Modifiedpackage-lock.json+2−2View fileUnifiedSplit
@@ -1,12 +1,12 @@
11{
22 "name": "marco-reid-voice",
3 "version": "1.0.7",
3 "version": "1.0.8",
44 "lockfileVersion": 3,
55 "requires": true,
66 "packages": {
77 "": {
88 "name": "marco-reid-voice",
9 "version": "1.0.7",
9 "version": "1.0.8",
1010 "dependencies": {
1111 "@radix-ui/react-dialog": "^1.1.4",
1212 "@radix-ui/react-dropdown-menu": "^2.1.4",
1313
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts