Downloads

This commit is contained in:
Scald 2023-05-17 09:17:31 +05:30
parent 25cddb3036
commit 7c72de36bf
No known key found for this signature in database
GPG Key ID: 39E71519BFF23499
7 changed files with 344 additions and 3 deletions

BIN
public/java.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
public/windows.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 B

162
src/css/pages/Downloads.css Normal file
View File

@ -0,0 +1,162 @@
.Downloads {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
}
.Downloads_Container {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100%;
max-width: 1200px;
margin-top: 70px;
}
.Downloads_Container h3 {
font-size: 18px;
font-weight: 400;
color: #c5c5c5;
text-align: center;
}
.Downloads_Cards {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
flex-wrap: wrap;
gap: 40px;
margin: 40px;
}
.DownloadCard {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
color: #000000;
padding: 20px;
width: 300px;
border-radius: 10px;
background-color: #fafafa;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.75);
transition: all 0.2s ease-in-out;
text-align: center;
cursor: pointer;
}
.DownloadCard:hover {
transform: scale(1.05);
box-shadow: 0 0 20px 0 rgba(0, 0, 0, 0.75);
}
.DownloadCard_Version {
font-size: 16px;
font-weight: 400;
color: #7a7a7a;
}
.DownloadCard_Icon {
height: 64px;
width: 64px;
margin: 20px;
}
.DownloadCard_Info {
margin: 20px;
}
.DownloadCard_Info h4 {
font-size: 20px;
font-weight: 500;
margin: 0;
}
.DownloadCard_Info p {
font-size: 16px;
font-weight: 400;
margin: 5px;
color: #7a7a7a;
}
.DownloadCard_Download {
color: #1969c9;
}
.Downloads_More {
color: #ffffff;
display: flex;
width: 100%;
max-width: 500px;
flex-direction: column;
align-items: center;
justify-content: center;
margin: 40px;
gap: 20px;
}
.Downloads_More h4 {
font-size: 35px;
font-weight: 700;
margin-top: 0;
}
.Downloads_More_Grasscutter {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: 100%;
gap: 20px;
background-color: #fafafa;
border-radius: 10px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.75);
transition: all 0.2s ease-in-out;
text-align: center;
padding: 40px;
}
.Downloads_More_Grasscutter h5 {
font-size: 20px;
font-weight: 500;
margin: 0;
color: #000;
}
.Downloads_More_Cultivation {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
width: 100%;
gap: 20px;
background-color: #fafafa;
border-radius: 10px;
box-shadow: 0 0 10px 0 rgba(0, 0, 0, 0.75);
transition: all 0.2s ease-in-out;
text-align: center;
padding: 40px;
}
.Downloads_More_Cultivation h5 {
font-size: 20px;
font-weight: 500;
margin: 0;
color: #000;
}
@media screen and (max-width: 600px) {
.Downloads_More_Grasscutter {
flex-direction: column;
width: 300px;
}
.Downloads_More_Cultivation {
flex-direction: column;
width: 300px;
}
}

View File

@ -4,6 +4,7 @@ import { Routes, Route } from "react-router-dom";
import Header from "@components/Header"; import Header from "@components/Header";
import Home from "@pages/Home"; import Home from "@pages/Home";
import Downloads from "@pages/Downloads";
import "@css/App.css"; import "@css/App.css";
@ -14,7 +15,7 @@ class App extends React.Component {
<Header /> <Header />
<Routes> <Routes>
<Route path={"/"} element={<Home />} /> <Route path={"/"} element={<Home />} />
<Route path={"/downloads"} element={<p>Downloads</p>} /> <Route path={"/downloads"} element={<Downloads />} />
<Route path={"/wiki"} element={<p>Wiki</p>} /> <Route path={"/wiki"} element={<p>Wiki</p>} />
<Route path={"/features"} element={<p>Features</p>} /> <Route path={"/features"} element={<p>Features</p>} />
<Route path={"/config"} element={<p>Config Generator</p>} /> <Route path={"/config"} element={<p>Config Generator</p>} />

View File

@ -0,0 +1,33 @@
import React from "react";
interface IProps {
title: string;
description: string;
downloadLink: string;
downloadVersion: string;
icon: string;
}
class DownloadCard extends React.Component<IProps, never> {
constructor(props: IProps) {
super(props);
}
render() {
return (
<div className={"DownloadCard"} onClick={() => window.open(this.props.downloadLink)}>
<p className={"DownloadCard_Version"}>{this.props.downloadVersion}</p>
<img className={"DownloadCard_Icon"} src={this.props.icon} alt={"Icon"} />
<div className={"DownloadCard_Info"}>
<h4>{this.props.title}</h4>
<p>{this.props.description}</p>
</div>
<div className={"DownloadCard_Download"}>
<p>Download</p>
</div>
</div>
);
}
}
export default DownloadCard;

109
src/ui/pages/Downloads.tsx Normal file
View File

@ -0,0 +1,109 @@
import React from "react";
import StyledHeading from "@components/common/StyledHeading";
import DownloadCard from "@components/downloads/DownloadCard";
import BasicButton from "@components/common/BasicButton";
import { getLatestReleaseAsync } from "@app/utils";
import "@css/pages/Downloads.css";
interface IState {
grasscutterVersion: string;
grasscutterDownloadLink: string;
cultivationVersion: string;
cultivationDownloadLink: string;
}
class Downloads extends React.Component<{}, IState> {
constructor(props: {}) {
super(props);
this.state = {
grasscutterVersion: "",
grasscutterDownloadLink: "",
cultivationVersion: "",
cultivationDownloadLink: ""
};
}
setDownloads = async () => {
const data = await getLatestReleaseAsync();
this.setState({
grasscutterVersion: data.grasscutter.version,
grasscutterDownloadLink: data.grasscutter.url,
cultivationVersion: data.cultivation.version,
cultivationDownloadLink: data.cultivation.url
});
}
async componentDidMount() {
await this.setDownloads();
}
render() {
return (
<div className={"Downloads"}>
<div className={"Downloads_Container"}>
<StyledHeading text={"Latest Downloads"} />
<h3>We recommend using Cultivation to launch your server<br /> if you do not know what a JAR file is.</h3>
<div className={"Downloads_Cards"}>
<DownloadCard
title={"Grasscutter"}
description={"Server JAR File"}
icon={"java.png"}
downloadLink={this.state.grasscutterDownloadLink}
downloadVersion={this.state.grasscutterVersion}
/>
<DownloadCard
title={"Cultivation"}
description={"For Windows"}
icon={"windows.png"}
downloadLink={this.state.cultivationDownloadLink}
downloadVersion={this.state.cultivationVersion}
/>
</div>
<div className={"Downloads_More"}>
<h4>Looking for more builds?</h4>
<div className={"Downloads_More_Grasscutter"}>
<h5>Grasscutter: </h5>
<BasicButton
text={"Latest Unstable"}
color={"#0095ff"}
onClick={() => window.open("https://nightly.link/Grasscutters/Grasscutter/workflows/build/unstable/Grasscutter.zip")}
/>
<BasicButton
text={"Older Builds"}
color={"#121928"}
onClick={() => window.open("https://github.com/Grasscutters/Grasscutter/releases")}
/>
</div>
<div className={"Downloads_More_Cultivation"}>
<h5>Cultivation: </h5>
<BasicButton
text={"Latest Commit"}
color={"#0095ff"}
onClick={() => window.open("https://nightly.link/Grasscutters/Cultivation/workflows/build/main/CultivationWin.zip")}
/>
<BasicButton
text={"Older Builds"}
color={"#121928"}
onClick={() => window.open("https://github.com/Grasscutters/Cultivation/releases")}
/>
</div>
</div>
</div>
</div>
);
}
}
export default Downloads;

View File

@ -1,10 +1,11 @@
const repo: string = "grasscutters/grasscutter"; const grasscutter: string = "grasscutters/grasscutter";
const cultivation: string = "grasscutters/cultivation";
/** /**
* Get the number of stars, forks and watchers of the repo * Get the number of stars, forks and watchers of the repo
*/ */
export async function getStatsAsync() { export async function getStatsAsync() {
const res = await fetch(`https://api.github.com/repos/${repo}`, { const res = await fetch(`https://api.github.com/repos/${grasscutter}`, {
headers: { Accept: "application/vnd.github.v3+json" } headers: { Accept: "application/vnd.github.v3+json" }
}); });
@ -16,3 +17,38 @@ export async function getStatsAsync() {
watchers: data.subscribers_count watchers: data.subscribers_count
} }
} }
/**
* Fetch the latest release of the repos
*/
export async function getLatestReleaseAsync() {
const resGC = await fetch(`https://api.github.com/repos/${grasscutter}/releases/latest`, {
headers: { Accept: "application/vnd.github.v3+json" }
});
const dataGC = await resGC.json();
const resC = await fetch(`https://api.github.com/repos/${cultivation}/releases/latest`, {
headers: { Accept: "application/vnd.github.v3+json" }
});
const dataC = await resC.json();
for (const asset of dataC.assets) {
if (asset.browser_download_url.endsWith(".msi")) {
dataC.assets[0] = asset;
break;
}
}
return {
grasscutter: {
version: dataGC.tag_name,
url: dataGC.assets[0].browser_download_url
},
cultivation: {
version: dataC.tag_name,
url: dataC.assets[0].browser_download_url
}
}
}