mirror of
https://github.com/priyanshujain/margin.git
synced 2026-10-02 19:17:03 +00:00
changes
This commit is contained in:
1 parent
b4097cc47f
commit
61bd7cf6e5
6 files changed
+94
-121
No files matched your search
@@ -1,10 +1,12 @@
|
||||
---
|
||||
import { site, platforms } from "../data/site";
|
||||
import { getRelease } from "../data/release";
|
||||
|
||||
interface Props {
|
||||
large?: boolean;
|
||||
}
|
||||
const { large = false } = Astro.props;
|
||||
const release = await getRelease();
|
||||
---
|
||||
|
||||
<div class="dl">
|
||||
@@ -26,7 +28,7 @@ const { large = false } = Astro.props;
|
||||
platforms.map((p) => (
|
||||
<a
|
||||
class="dl__chip"
|
||||
href={site.releasesUrl}
|
||||
href={release.urls[p.id]}
|
||||
data-download-os={p.id}
|
||||
rel="noopener"
|
||||
download
|
||||
@@ -57,6 +59,7 @@ const { large = false } = Astro.props;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: none;
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
background: #ffffff;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
---
|
||||
import { site } from "../data/site";
|
||||
import { site, platforms } from "../data/site";
|
||||
import { getRelease } from "../data/release";
|
||||
|
||||
const { repo, releasesUrl } = site;
|
||||
const { urls, version } = await getRelease();
|
||||
const matches = Object.fromEntries(platforms.map((p) => [p.id, p.match]));
|
||||
---
|
||||
|
||||
<script define:vars={{ repo, releasesUrl }}>
|
||||
const SUFFIXES = {
|
||||
mac: [".dmg"],
|
||||
windows: [".msi", ".exe"],
|
||||
linux: [".AppImage", ".deb", ".rpm"],
|
||||
};
|
||||
<script define:vars={{ repo, releasesUrl, urls, version, matches }}>
|
||||
const LABELS = { mac: "macOS", windows: "Windows", linux: "Linux" };
|
||||
|
||||
function detectOS() {
|
||||
@@ -21,32 +20,31 @@ const { repo, releasesUrl } = site;
|
||||
}
|
||||
|
||||
function pickAsset(assets, os) {
|
||||
for (const sfx of SUFFIXES[os] || []) {
|
||||
for (const sfx of matches[os] || []) {
|
||||
const hit = assets.find((a) => a.name.toLowerCase().endsWith(sfx.toLowerCase()));
|
||||
if (hit) return hit.browser_download_url;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
const os = detectOS();
|
||||
function apply(map, ver) {
|
||||
const os = detectOS();
|
||||
document.querySelectorAll("[data-download]").forEach((el) => {
|
||||
const label = el.querySelector("[data-dl-label]");
|
||||
if (label) label.textContent = "Download for " + LABELS[os];
|
||||
if (map[os]) el.href = map[os];
|
||||
});
|
||||
document.querySelectorAll("[data-download-os]").forEach((el) => {
|
||||
const url = map[el.dataset.downloadOs];
|
||||
if (url) el.href = url;
|
||||
});
|
||||
document.querySelectorAll(".dl__os [data-download-os]").forEach((el) => {
|
||||
if (el.dataset.downloadOs === os) el.remove();
|
||||
});
|
||||
if (ver) document.querySelectorAll("[data-version]").forEach((el) => (el.textContent = ver));
|
||||
}
|
||||
|
||||
document.querySelectorAll("[data-download]").forEach((el) => {
|
||||
el.dataset.detectedOs = os;
|
||||
const label = el.querySelector("[data-dl-label]");
|
||||
if (label) label.textContent = "Download for " + LABELS[os];
|
||||
});
|
||||
|
||||
document.querySelectorAll(".dl__alt [data-download-os]").forEach((el) => {
|
||||
if (el.dataset.downloadOs === os) el.remove();
|
||||
});
|
||||
|
||||
document.querySelectorAll("[data-osrow]").forEach((row) => {
|
||||
const primary = row.querySelector(`[data-download-os="${os}"]`);
|
||||
if (primary) {
|
||||
primary.classList.add("is-detected");
|
||||
row.prepend(primary);
|
||||
}
|
||||
});
|
||||
apply(urls, version);
|
||||
|
||||
(async () => {
|
||||
try {
|
||||
@@ -56,23 +54,11 @@ const { repo, releasesUrl } = site;
|
||||
if (!res.ok) return;
|
||||
const data = await res.json();
|
||||
const assets = data.assets || [];
|
||||
const version = data.tag_name || "";
|
||||
|
||||
document.querySelectorAll("[data-download]").forEach((el) => {
|
||||
const url = pickAsset(assets, el.dataset.detectedOs || os);
|
||||
if (url) el.href = url;
|
||||
});
|
||||
document.querySelectorAll("[data-download-os]").forEach((el) => {
|
||||
const url = pickAsset(assets, el.dataset.downloadOs);
|
||||
if (url) el.href = url;
|
||||
});
|
||||
if (version) {
|
||||
document.querySelectorAll("[data-version]").forEach((el) => {
|
||||
el.textContent = version;
|
||||
});
|
||||
}
|
||||
const fresh = {};
|
||||
for (const os of Object.keys(matches)) fresh[os] = pickAsset(assets, os) || urls[os] || releasesUrl;
|
||||
apply(fresh, data.tag_name || version);
|
||||
} catch (e) {
|
||||
/* keep the releases-page fallback links */
|
||||
/* keep the build-time links */
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
@@ -1,14 +1,17 @@
|
||||
---
|
||||
import { site } from "../data/site";
|
||||
import { getRelease } from "../data/release";
|
||||
import Logo from "./Logo.astro";
|
||||
|
||||
const release = await getRelease();
|
||||
|
||||
const cols = [
|
||||
{
|
||||
title: "Get Margin",
|
||||
links: [
|
||||
{ label: "Download for macOS", href: site.releasesUrl, os: "mac" },
|
||||
{ label: "Download for Windows", href: site.releasesUrl, os: "windows" },
|
||||
{ label: "Download for Linux", href: site.releasesUrl, os: "linux" },
|
||||
{ label: "Download for macOS", href: release.urls.mac, os: "mac" },
|
||||
{ label: "Download for Windows", href: release.urls.windows, os: "windows" },
|
||||
{ label: "Download for Linux", href: release.urls.linux, os: "linux" },
|
||||
],
|
||||
},
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
import AppWindow from "./AppWindow.astro";
|
||||
import DownloadButtons from "./DownloadButtons.astro";
|
||||
import OfferBadge from "./OfferBadge.astro";
|
||||
import { site, platforms } from "../data/site";
|
||||
---
|
||||
|
||||
<section class="hero">
|
||||
@@ -21,25 +21,7 @@ import { site, platforms } from "../data/site";
|
||||
</div>
|
||||
|
||||
<div class="container hero__get" id="download">
|
||||
<div class="hero__buttons" data-osrow>
|
||||
{
|
||||
platforms.map((p) => (
|
||||
<a
|
||||
class="osbtn"
|
||||
href={site.releasesUrl}
|
||||
data-download-os={p.id}
|
||||
rel="noopener"
|
||||
download
|
||||
>
|
||||
<img class="osbtn__icon" src={`/logos/${p.logo}`} alt="" />
|
||||
<span>Download for {p.label}</span>
|
||||
</a>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
<p class="hero__meta">
|
||||
<span data-version>v0.1.2</span> · Works offline · No account
|
||||
</p>
|
||||
<DownloadButtons large />
|
||||
<div class="hero__offer">
|
||||
<OfferBadge />
|
||||
</div>
|
||||
@@ -75,62 +57,9 @@ import { site, platforms } from "../data/site";
|
||||
margin-top: clamp(24px, 3vw, 32px);
|
||||
scroll-margin-top: 96px;
|
||||
}
|
||||
.hero__buttons {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
gap: 12px;
|
||||
}
|
||||
.osbtn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
padding: 0.82em 1.35em;
|
||||
background: #ffffff;
|
||||
border: 1px solid var(--line-strong);
|
||||
border-radius: 999px;
|
||||
color: #23201b;
|
||||
font-family: var(--font-ui);
|
||||
font-size: 1rem;
|
||||
font-weight: 600;
|
||||
box-shadow: var(--shadow-page);
|
||||
transition:
|
||||
transform 0.18s var(--ease),
|
||||
box-shadow 0.18s var(--ease),
|
||||
border-color 0.18s var(--ease);
|
||||
}
|
||||
.osbtn:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: var(--shadow-pop);
|
||||
}
|
||||
.osbtn.is-detected {
|
||||
border-color: var(--ink);
|
||||
}
|
||||
.osbtn__icon {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
flex: none;
|
||||
object-fit: contain;
|
||||
}
|
||||
.hero__meta {
|
||||
margin: 16px 0 0;
|
||||
font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
|
||||
font-size: 0.8rem;
|
||||
color: var(--ink-faint);
|
||||
text-align: center;
|
||||
}
|
||||
.hero__offer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 22px;
|
||||
}
|
||||
@media (max-width: 480px) {
|
||||
.hero__buttons {
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.osbtn {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,52 @@
|
||||
// Resolves the latest GitHub release to a direct download URL per OS, at build
|
||||
// time. The picked file follows each platform's `match` order in site.ts.
|
||||
// Falls back to the releases page if the release can't be read.
|
||||
|
||||
import { site, platforms } from "./site";
|
||||
|
||||
type Asset = { name: string; browser_download_url: string };
|
||||
|
||||
export type Release = {
|
||||
version: string;
|
||||
urls: Record<string, string>;
|
||||
};
|
||||
|
||||
function pickAsset(assets: Asset[], match: string[]): string | null {
|
||||
for (const sfx of match) {
|
||||
const hit = assets.find((a) => a.name.toLowerCase().endsWith(sfx.toLowerCase()));
|
||||
if (hit) return hit.browser_download_url;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function fallback(): Release {
|
||||
return {
|
||||
version: "",
|
||||
urls: Object.fromEntries(platforms.map((p) => [p.id, site.releasesUrl])),
|
||||
};
|
||||
}
|
||||
|
||||
async function fetchRelease(): Promise<Release> {
|
||||
try {
|
||||
const res = await fetch(`https://api.github.com/repos/${site.repo}/releases/latest`, {
|
||||
headers: { Accept: "application/vnd.github+json" },
|
||||
signal: AbortSignal.timeout(8000),
|
||||
});
|
||||
if (!res.ok) return fallback();
|
||||
const data = await res.json();
|
||||
const assets: Asset[] = data.assets || [];
|
||||
const urls = Object.fromEntries(
|
||||
platforms.map((p) => [p.id, pickAsset(assets, p.match) ?? site.releasesUrl]),
|
||||
);
|
||||
return { version: data.tag_name ?? "", urls };
|
||||
} catch {
|
||||
return fallback();
|
||||
}
|
||||
}
|
||||
|
||||
let cached: Promise<Release> | null = null;
|
||||
|
||||
export function getRelease(): Promise<Release> {
|
||||
cached ??= fetchRelease();
|
||||
return cached;
|
||||
}
|
||||
@@ -39,8 +39,8 @@ export type Platform = {
|
||||
|
||||
export const platforms: Platform[] = [
|
||||
{ id: "mac", label: "macOS", logo: "macos.svg", match: [".dmg"] },
|
||||
{ id: "windows", label: "Windows", logo: "windows.svg", match: [".msi", ".exe"] },
|
||||
{ id: "linux", label: "Linux", logo: "linux.svg", match: [".AppImage", ".deb", ".rpm"] },
|
||||
{ id: "windows", label: "Windows", logo: "windows.svg", match: [".exe", ".msi"] },
|
||||
{ id: "linux", label: "Linux", logo: "linux.svg", match: [".deb", ".AppImage", ".rpm"] },
|
||||
];
|
||||
|
||||
// Full-color store logos, served from /public/logos. Shown on white tiles so
|
||||
|
||||
Reference in new issue
Block a user