Load download links from live API
This commit is contained in:
@@ -159,11 +159,13 @@ only screen and (-o-min-device-pixel-ratio: 2/1) {
|
||||
|
||||
.masthead-download .subtext span {
|
||||
margin-right: 4px;
|
||||
color: rgba(255, 255, 255, .5);
|
||||
}
|
||||
|
||||
|
||||
.masthead-platforms {
|
||||
display: inline;
|
||||
color: #fff !important;
|
||||
}
|
||||
|
||||
/* Home page
|
||||
|
||||
81
src/components/DownloadButton.astro
Normal file
81
src/components/DownloadButton.astro
Normal file
@@ -0,0 +1,81 @@
|
||||
---
|
||||
import { getLatestDownloads } from "../lib/downloads";
|
||||
|
||||
const latestDownloads = await getLatestDownloads();
|
||||
const downloads = latestDownloads.success ? latestDownloads.data : [];
|
||||
|
||||
const defaultDownload = downloads[0];
|
||||
---
|
||||
|
||||
<div class="masthead-download" data-downloads={JSON.stringify(downloads)}>
|
||||
{
|
||||
defaultDownload ? (
|
||||
<a
|
||||
href={defaultDownload.href}
|
||||
class="btn btn-primary btn-large"
|
||||
data-download-button
|
||||
aria-label={`Download TenWholeYears for ${defaultDownload.label}`}
|
||||
>
|
||||
Download for {defaultDownload.label}
|
||||
</a>
|
||||
) : (
|
||||
<a href="/downloads/" class="btn btn-primary btn-large">
|
||||
View Downloads
|
||||
</a>
|
||||
)
|
||||
}
|
||||
<div class="subtext">
|
||||
<span>or</span>
|
||||
<a href="/downloads/" class="masthead-platforms">Other Platforms</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script is:inline>
|
||||
$(() => {
|
||||
const $downloadRoot = $("[data-downloads]");
|
||||
if (!$downloadRoot.length) return;
|
||||
|
||||
const $downloadButton = $downloadRoot.find("[data-download-button]");
|
||||
if (!$downloadButton.length) return;
|
||||
|
||||
let downloads = [];
|
||||
try {
|
||||
downloads = JSON.parse(
|
||||
$downloadRoot.attr("data-downloads") || "[]",
|
||||
);
|
||||
} catch {
|
||||
return;
|
||||
}
|
||||
|
||||
const findDownload = (platform) =>
|
||||
$.grep(downloads, (download) => download.platform === platform)[0];
|
||||
|
||||
const getDetectedPlatform = () => {
|
||||
const userAgentDataPlatform =
|
||||
navigator.userAgentData?.platform?.toLowerCase() || "";
|
||||
const userAgent = navigator.userAgent.toLowerCase();
|
||||
const platform = navigator.platform.toLowerCase();
|
||||
const browserPlatform = `${userAgentDataPlatform} ${userAgent} ${platform}`;
|
||||
|
||||
if (
|
||||
browserPlatform.includes("android") ||
|
||||
browserPlatform.includes("oculus") ||
|
||||
browserPlatform.includes("quest")
|
||||
) {
|
||||
return "meta";
|
||||
}
|
||||
if (browserPlatform.includes("linux")) return "linux";
|
||||
if (browserPlatform.includes("win")) return "windows";
|
||||
|
||||
return "windows";
|
||||
};
|
||||
|
||||
const download = findDownload(getDetectedPlatform()) || downloads[0];
|
||||
if (!download) return;
|
||||
|
||||
$downloadButton
|
||||
.attr("href", download.href)
|
||||
.attr("aria-label", `Download TenWholeYears for ${download.label}`)
|
||||
.text(`Download for ${download.label}`);
|
||||
});
|
||||
</script>
|
||||
@@ -17,9 +17,9 @@ import Footer from "../components/Footer.astro";
|
||||
<link rel="icon" type="image/x-icon" href="/favicon.ico">
|
||||
</head>
|
||||
<body>
|
||||
<script src="/js/jquery-4.0.0.min.js" is:inline></script>
|
||||
<slot />
|
||||
<Footer />
|
||||
<script src="/js/jquery-4.0.0.min.js" is:inline></script>
|
||||
<script src="/js/bootstrap.min.js" is:inline></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -9,6 +9,7 @@ export const api = {
|
||||
builds: {
|
||||
v1: {
|
||||
async getLatestVersions(): Promise<ApiResult<LatestBuildsResponse>> {
|
||||
try {
|
||||
const response = await fetch(`${TWY_API_URL}/${BUILDS_V1}/latest`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -27,8 +28,15 @@ export const api = {
|
||||
var obj = (await response.json()) as LatestBuildsResponse;
|
||||
|
||||
return ApiResult.success(obj);
|
||||
} catch (error: unknown) {
|
||||
if (error instanceof Error)
|
||||
return ApiResult.failure<LatestBuildsResponse>(error.message);
|
||||
|
||||
return ApiResult.failure<LatestBuildsResponse>("An unexpected error occured.");
|
||||
}
|
||||
},
|
||||
async getPatchNotes(): Promise<ApiResult<PatchNote[]>> {
|
||||
async getPatchNotes(): Promise<PatchNote[]> {
|
||||
try {
|
||||
const response = await fetch(`${TWY_API_URL}/${BUILDS_V1}/patchNotes`, {
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
@@ -41,12 +49,14 @@ export const api = {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
});
|
||||
return ApiResult.failure<PatchNote[]>("Failed to load latest versions.");
|
||||
return [];
|
||||
}
|
||||
|
||||
var obj = (await response.json()) as PatchNote[];
|
||||
return (await response.json()) as PatchNote[];
|
||||
|
||||
return ApiResult.success(obj);
|
||||
} catch (error) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
66
src/lib/downloads.ts
Normal file
66
src/lib/downloads.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import { TWY_CDN_URL } from "astro:env/server";
|
||||
|
||||
import { api } from "./api";
|
||||
import { ApiResult } from "./types/api";
|
||||
import type { LatestBuildsResponse } from "./types/api/builds";
|
||||
|
||||
export type DownloadPlatform = "windows" | "linux" | "meta";
|
||||
|
||||
export type DownloadOption = {
|
||||
platform: DownloadPlatform;
|
||||
label: string;
|
||||
version: string;
|
||||
href: string;
|
||||
icon: string;
|
||||
};
|
||||
|
||||
type DownloadPlatformConfig = {
|
||||
platform: DownloadPlatform;
|
||||
label: string;
|
||||
icon: string;
|
||||
versionKey: keyof LatestBuildsResponse;
|
||||
};
|
||||
|
||||
export const downloadPlatforms: DownloadPlatformConfig[] = [
|
||||
{
|
||||
platform: "windows",
|
||||
label: "Windows",
|
||||
icon: "/img/platforms/platform-windows.png",
|
||||
versionKey: "latestWindowsVersion",
|
||||
},
|
||||
{
|
||||
platform: "linux",
|
||||
label: "Linux",
|
||||
icon: "/img/platforms/platform-linux.png",
|
||||
versionKey: "latestLinuxVersion",
|
||||
},
|
||||
{
|
||||
platform: "meta",
|
||||
label: "Meta Quest",
|
||||
icon: "/img/platforms/platform-oculus.png",
|
||||
versionKey: "latestMetaVersion",
|
||||
},
|
||||
];
|
||||
|
||||
export const buildDownloadOptions = (
|
||||
latestVersions: LatestBuildsResponse,
|
||||
): DownloadOption[] =>
|
||||
downloadPlatforms.map(({ platform, label, icon, versionKey }) => {
|
||||
const version = latestVersions[versionKey];
|
||||
|
||||
return {
|
||||
platform,
|
||||
label,
|
||||
version,
|
||||
href: `${TWY_CDN_URL}/builds/${encodeURIComponent(version)}/${platform}.zip`,
|
||||
icon,
|
||||
};
|
||||
});
|
||||
|
||||
export const getLatestDownloads = async (): Promise<ApiResult<DownloadOption[]>> => {
|
||||
const latestVersions = await api.builds.v1.getLatestVersions();
|
||||
if (!latestVersions.success)
|
||||
return ApiResult.failure<DownloadOption[]>(latestVersions.error);
|
||||
|
||||
return ApiResult.success(buildDownloadOptions(latestVersions.data));
|
||||
};
|
||||
@@ -1,40 +1,12 @@
|
||||
---
|
||||
import { api } from "../lib/api";
|
||||
import { getLatestDownloads } from "../lib/downloads";
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
|
||||
const downloads = [
|
||||
{
|
||||
platform: "Windows",
|
||||
version: "v1.0.3",
|
||||
href: "#",
|
||||
icon: "/img/platforms/platform-windows.png",
|
||||
checksum: "checksum: REPLACE_ME",
|
||||
},
|
||||
{
|
||||
platform: "Linux",
|
||||
version: "v1.0.3",
|
||||
href: "#",
|
||||
icon: "/img/platforms/platform-linux.png",
|
||||
checksum: "checksum: REPLACE_ME",
|
||||
},
|
||||
{
|
||||
platform: "Oculus Quest",
|
||||
version: "v1.0.3",
|
||||
href: "#",
|
||||
icon: "/img/platforms/platform-oculus.png",
|
||||
checksum: "checksum: REPLACE_ME",
|
||||
},
|
||||
];
|
||||
const latestDownloads = await getLatestDownloads();
|
||||
const downloads = latestDownloads.success ? latestDownloads.data : [];
|
||||
|
||||
const patchNotes = [
|
||||
{
|
||||
version: "v1.0.3",
|
||||
date: "6/26/2026",
|
||||
changes: [
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
|
||||
"Nunc at augue eu nulla aliquet consectetur et in magna.",
|
||||
],
|
||||
}
|
||||
];
|
||||
const patchNotes = await api.builds.v1.getPatchNotes();
|
||||
---
|
||||
|
||||
<Layout>
|
||||
@@ -47,6 +19,8 @@ const patchNotes = [
|
||||
Choose the build for your platform.
|
||||
</p>
|
||||
|
||||
{
|
||||
downloads.length > 0 ? (
|
||||
<div class="row">
|
||||
{downloads.map((download) => (
|
||||
<div class="span4">
|
||||
@@ -59,16 +33,13 @@ const patchNotes = [
|
||||
height="72"
|
||||
/>
|
||||
</p>
|
||||
<h3>{download.platform}</h3>
|
||||
<h3>{download.label}</h3>
|
||||
<p>{download.version}</p>
|
||||
{/* <p class="muted">
|
||||
<code>{download.checksum}</code>
|
||||
</p> */}
|
||||
<p>
|
||||
<a
|
||||
href={download.href}
|
||||
class="btn btn-primary"
|
||||
aria-label={`Download for ${download.platform}`}
|
||||
aria-label={`Download for ${download.label}`}
|
||||
>
|
||||
Download
|
||||
</a>
|
||||
@@ -77,12 +48,20 @@ const patchNotes = [
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div class="alert alert-warning">
|
||||
Downloads are unavailable right now.
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
<section class="download-patch-notes">
|
||||
<div class="page-header">
|
||||
<h2>Patch Notes</h2>
|
||||
</div>
|
||||
{patchNotes.map((patchNote) => (
|
||||
{
|
||||
patchNotes.length > 0 ? (
|
||||
patchNotes.map((patchNote) => (
|
||||
<div class="well patch-note">
|
||||
<h3>{patchNote.version}</h3>
|
||||
<p class="muted">{patchNote.date}</p>
|
||||
@@ -92,7 +71,13 @@ const patchNotes = [
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
))}
|
||||
))
|
||||
) : (
|
||||
<div class="well patch-note">
|
||||
<p>No patch notes yet.</p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
</section>
|
||||
</div>
|
||||
</Layout>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
import DownloadButton from "../components/DownloadButton.astro";
|
||||
import Layout from "../layouts/Layout.astro";
|
||||
|
||||
const credits = [
|
||||
@@ -105,17 +106,7 @@ const credits = [
|
||||
/>
|
||||
<h1 class="masthead-title">TenWholeYears</h1>
|
||||
<p>A love letter to Rec Room on its true 10th anniversary</p>
|
||||
<div class="masthead-download">
|
||||
<a href="/downloads/" class="btn btn-primary btn-large">
|
||||
Download for Windows x64
|
||||
</a>
|
||||
<div class="subtext">
|
||||
<span>or</span>
|
||||
<a href="/downloads/" class="masthead-platforms"
|
||||
>Other Platforms</a
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
<DownloadButton />
|
||||
</div>
|
||||
</div>
|
||||
<div class="container">
|
||||
|
||||
Reference in New Issue
Block a user