2025-09-27 00:46:51 +03:00
|
|
|
import { useState } from "preact/hooks";
|
|
|
|
|
import Card from "../../components/Card";
|
|
|
|
|
import Section from "../../components/Section";
|
|
|
|
|
import { App, Architecture, buildDownloadUrl, downloadMatrix, DownloadMatrixEntry, getArchitecture, Platform } from "../../download-helper";
|
|
|
|
|
import "./download.css";
|
2025-09-27 13:55:04 +03:00
|
|
|
import { usePageTitle } from "../../hooks";
|
2025-09-27 15:57:01 +03:00
|
|
|
import Button, { Link } from "../../components/Button";
|
2025-09-27 16:09:16 +03:00
|
|
|
import Icon from "../../components/Icon";
|
|
|
|
|
import helpIcon from "../../assets/boxicons/bx-help-circle.svg?raw";
|
2025-09-27 00:46:51 +03:00
|
|
|
|
|
|
|
|
export default function DownloadPage() {
|
2025-09-27 01:01:06 +03:00
|
|
|
const [ currentArch, setCurrentArch ] = useState(getArchitecture());
|
2025-09-27 13:55:04 +03:00
|
|
|
usePageTitle("Download");
|
2025-09-27 00:46:51 +03:00
|
|
|
|
|
|
|
|
return (
|
|
|
|
|
<>
|
2025-09-27 15:01:59 +03:00
|
|
|
<Section title="Download the desktop application" className="fill">
|
2025-09-27 01:01:06 +03:00
|
|
|
<div className="architecture-switch">
|
|
|
|
|
<span>Architecture:</span>
|
|
|
|
|
|
|
|
|
|
<div class="toggle-wrapper">
|
|
|
|
|
{(["x64", "arm64"] as const).map(arch => (
|
|
|
|
|
<a
|
|
|
|
|
href="#"
|
|
|
|
|
className={`arch ${arch === currentArch ? "active" : ""}`}
|
|
|
|
|
onClick={() => setCurrentArch(arch)}
|
|
|
|
|
>{arch}</a>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2025-09-27 00:46:51 +03:00
|
|
|
<div className="grid-3-cols download-desktop">
|
2025-09-27 01:01:06 +03:00
|
|
|
{Object.entries(downloadMatrix.desktop).map(entry => <DownloadCard app="desktop" arch={currentArch} entry={entry} />)}
|
2025-09-27 00:46:51 +03:00
|
|
|
</div>
|
|
|
|
|
</Section>
|
|
|
|
|
|
|
|
|
|
<Section title="Set up a server for access on multiple devices">
|
2025-09-27 16:49:32 +03:00
|
|
|
<div className="grid-2-cols download-server">
|
2025-09-27 01:01:06 +03:00
|
|
|
{Object.entries(downloadMatrix.server).map(entry => <DownloadCard app="server" arch={currentArch} entry={entry} />)}
|
2025-09-27 00:46:51 +03:00
|
|
|
</div>
|
|
|
|
|
</Section>
|
|
|
|
|
</>
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function DownloadCard({ app, arch, entry: [ platform, entry ] }: { app: App, arch: Architecture, entry: [string, DownloadMatrixEntry] }) {
|
|
|
|
|
function unwrapText(text: string | Record<Architecture, string>) {
|
|
|
|
|
return (typeof text === "string" ? text : text[arch]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const allDownloads = Object.entries(entry.downloads);
|
2025-09-27 16:39:10 +03:00
|
|
|
const recommendedDownloads = allDownloads.filter(download => download[1].recommended);
|
2025-09-27 00:46:51 +03:00
|
|
|
const restDownloads = allDownloads.filter(download => !download[1].recommended);
|
|
|
|
|
|
|
|
|
|
return (
|
2025-09-27 16:09:16 +03:00
|
|
|
<Card title={<>
|
|
|
|
|
{unwrapText(entry.title)}
|
|
|
|
|
{entry.helpUrl && (
|
|
|
|
|
<Link
|
|
|
|
|
className="more-info"
|
|
|
|
|
href={entry.helpUrl}
|
|
|
|
|
openExternally
|
|
|
|
|
>
|
|
|
|
|
<Icon svg={helpIcon} />
|
|
|
|
|
</Link>
|
|
|
|
|
)}
|
|
|
|
|
</>} className="download-card">
|
2025-09-27 00:46:51 +03:00
|
|
|
{unwrapText(entry.description)}
|
|
|
|
|
|
2025-09-27 16:23:12 +03:00
|
|
|
{entry.quickStartCode && (
|
|
|
|
|
<pre className="quick-start">
|
|
|
|
|
<code>{entry.quickStartCode}</code>
|
|
|
|
|
</pre>
|
|
|
|
|
)}
|
|
|
|
|
|
2025-09-27 00:46:51 +03:00
|
|
|
<div class="download-options">
|
2025-09-27 16:39:10 +03:00
|
|
|
<div className="recommended-options">
|
|
|
|
|
{recommendedDownloads.map(recommendedDownload => (
|
|
|
|
|
<Button
|
|
|
|
|
className="recommended"
|
|
|
|
|
href={buildDownloadUrl(app, platform as Platform, recommendedDownload[0], arch)}
|
|
|
|
|
text={recommendedDownload[1].name}
|
|
|
|
|
openExternally={!!recommendedDownload[1].url}
|
|
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
2025-09-27 00:46:51 +03:00
|
|
|
|
|
|
|
|
<div class="other-options">
|
|
|
|
|
{restDownloads.map(download => (
|
2025-09-27 15:57:01 +03:00
|
|
|
<Link
|
|
|
|
|
href={buildDownloadUrl(app, platform as Platform, download[0], arch)}
|
2025-09-27 15:58:37 +03:00
|
|
|
openExternally={!!download[1].url}
|
2025-09-27 15:57:01 +03:00
|
|
|
>
|
|
|
|
|
{download[1].name}
|
|
|
|
|
</Link>
|
2025-09-27 00:46:51 +03:00
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</Card>
|
|
|
|
|
)
|
|
|
|
|
}
|