Skip to content

Commit 39e4e01

Browse files
committed
Docs: Show pre-release if available
1 parent 4c54464 commit 39e4e01

2 files changed

Lines changed: 148 additions & 0 deletions

File tree

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
import { useEffect, useState } from "react";
2+
import Link from "@docusaurus/Link";
3+
import pageStyles from "../../pages/styles.module.css";
4+
5+
const API_URL =
6+
"https://api.github.com/repos/BornToBeRoot/NETworkManager/releases?per_page=30";
7+
const CACHE_KEY = "ntm-latest-prerelease";
8+
const CACHE_TTL_MS = 10 * 60 * 1000;
9+
10+
const DOWNLOAD_VARIANTS = [
11+
{ field: "setupUrl", label: "Setup", color: "primary" },
12+
{ field: "portableUrl", label: "Portable", color: "info" },
13+
{ field: "archiveUrl", label: "Archive", color: "info" },
14+
];
15+
16+
function readCache() {
17+
try {
18+
const raw = localStorage.getItem(CACHE_KEY);
19+
if (!raw) return null;
20+
const { timestamp, data } = JSON.parse(raw);
21+
if (Date.now() - timestamp > CACHE_TTL_MS) return null;
22+
return data;
23+
} catch {
24+
return null;
25+
}
26+
}
27+
28+
function writeCache(data) {
29+
try {
30+
localStorage.setItem(
31+
CACHE_KEY,
32+
JSON.stringify({ timestamp: Date.now(), data }),
33+
);
34+
} catch {
35+
// ignore quota / unavailable storage
36+
}
37+
}
38+
39+
function findAssetUrl(assets, suffix) {
40+
return assets.find((a) => a.name.endsWith(suffix))?.browser_download_url;
41+
}
42+
43+
function formatReleaseDate(iso) {
44+
const d = new Date(iso);
45+
const dd = String(d.getDate()).padStart(2, "0");
46+
const mm = String(d.getMonth() + 1).padStart(2, "0");
47+
return `${dd}.${mm}.${d.getFullYear()}`;
48+
}
49+
50+
export default function LatestPrerelease() {
51+
const [state, setState] = useState({ status: "loading" });
52+
53+
useEffect(() => {
54+
const cached = readCache();
55+
if (cached !== null) {
56+
setState(
57+
cached.release
58+
? { status: "ready", release: cached.release }
59+
: { status: "none" },
60+
);
61+
return;
62+
}
63+
64+
const controller = new AbortController();
65+
const { signal } = controller;
66+
67+
fetch(API_URL, { signal })
68+
.then((res) => {
69+
if (!res.ok) throw new Error(`GitHub API ${res.status}`);
70+
return res.json();
71+
})
72+
.then((releases) => {
73+
if (signal.aborted) return;
74+
const latest = releases.find((r) => !r.draft);
75+
const pre = latest && latest.prerelease ? latest : null;
76+
if (!pre) {
77+
writeCache({ release: null });
78+
setState({ status: "none" });
79+
return;
80+
}
81+
const release = {
82+
tagName: pre.tag_name,
83+
publishedAt: pre.published_at,
84+
htmlUrl: pre.html_url,
85+
setupUrl: findAssetUrl(pre.assets, "_Setup.msi"),
86+
portableUrl: findAssetUrl(pre.assets, "_Portable.zip"),
87+
archiveUrl: findAssetUrl(pre.assets, "_Archive.zip"),
88+
};
89+
writeCache({ release });
90+
setState({ status: "ready", release });
91+
})
92+
.catch((err) => {
93+
if (err.name === "AbortError" || signal.aborted) return;
94+
setState({ status: "error" });
95+
});
96+
97+
return () => controller.abort();
98+
}, []);
99+
100+
if (state.status === "none") {
101+
return (
102+
<p>
103+
<em>Currently no pre-release version available.</em>
104+
</p>
105+
);
106+
}
107+
108+
if (state.status !== "ready") {
109+
return null;
110+
}
111+
112+
const { release } = state;
113+
const downloads = DOWNLOAD_VARIANTS.filter((v) => release[v.field]);
114+
115+
return (
116+
<>
117+
<div style={{ display: "flex", justifyContent: "space-between" }}>
118+
<h3>{release.tagName}</h3>
119+
<div>Release Date: {formatReleaseDate(release.publishedAt)}</div>
120+
</div>
121+
122+
<div className={`${pageStyles.centerButtonContainer} margin-bottom--lg`}>
123+
{downloads.map((v) => (
124+
<Link
125+
key={v.field}
126+
className={`button button--${v.color} button--outline ${pageStyles.downloadButton}`}
127+
to={release[v.field]}
128+
>
129+
{v.label}
130+
</Link>
131+
))}
132+
</div>
133+
134+
<div className={pageStyles.centerButtonContainer}>
135+
<Link
136+
className={`button button--secondary button--outline ${pageStyles.additionalButton}`}
137+
to={release.htmlUrl}
138+
target="_blank"
139+
>
140+
📃 Release notes
141+
</Link>
142+
</div>
143+
</>
144+
);
145+
}

Website/src/pages/download.mdx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ keywords: [NETworkManager download, network manager download, free network tool,
66

77
import Link from "@docusaurus/Link";
88
import styles from "./styles.module.css";
9+
import LatestPrerelease from "@site/src/components/LatestPrerelease";
910

1011
# Download
1112

@@ -180,6 +181,8 @@ Pre-release versions with the latest features and bug fixes are (sometimes) avai
180181

181182
You can help to improve the software by testing pre-release versions and reporting bugs via [GitHub Issues](https://github.com/BornToBeRoot/NETworkManager/issues/new/choose).
182183

184+
<LatestPrerelease />
185+
183186
:::warning
184187

185188
Please note that pre-release versions are not as stable as regular versions and may contain more bugs.

0 commit comments

Comments
 (0)