From 371550d07262bf728744e95bda6f8001b3403af0 Mon Sep 17 00:00:00 2001 From: EtienneLescot Date: Sat, 17 Oct 2026 11:18:00 +0200 Subject: [PATCH] feat(website): offer the Windows ARM64 installer on /download/ Every release since 2.1.0 ships an -arm64.exe beside the x64 one. The page now lists it under the Windows card, and the build fails if a latest release lacks it, like every other kind. --- website/i18n/code.source.json | 2 + website/i18n/de/code.json | 6 +++ website/i18n/es/code.json | 6 +++ website/i18n/fr/code.json | 6 +++ website/i18n/ja/code.json | 6 +++ website/i18n/pt-BR/code.json | 6 +++ website/i18n/zh-CN/code.json | 6 +++ website/i18n/zh-TW/code.json | 6 +++ website/src/lib/download-target.test.ts | 2 +- website/src/lib/release.test.ts | 53 +++++++++++++------------ website/src/lib/release.ts | 4 +- website/src/pages/download.tsx | 8 ++++ 12 files changed, 83 insertions(+), 28 deletions(-) diff --git a/website/i18n/code.source.json b/website/i18n/code.source.json index e10f54a98..5e0b032d3 100644 --- a/website/i18n/code.source.json +++ b/website/i18n/code.source.json @@ -9,6 +9,8 @@ "download.windows.store.sublabel": "Recommended · signed by Microsoft", "download.windows.exe.label": "Windows 10 & 11", "download.windows.exe.sublabel": "Installer · .exe · unsigned", + "download.windows.arm.label": "Windows on ARM", + "download.windows.arm.sublabel": "ARM64 · .exe · unsigned", "download.windows.footnote": "System audio is captured without extra drivers. Integrated graphics older than ~8th-gen Intel (or the AMD Ryzen 2000 series equivalent) may hit known recording-stop issues — see {systemRequirements}.", "download.windows.footnote.systemRequirements": "system requirements", "download.linux.deb.sublabel": "Package · .deb", diff --git a/website/i18n/de/code.json b/website/i18n/de/code.json index eb1d17eeb..e884293ee 100644 --- a/website/i18n/de/code.json +++ b/website/i18n/de/code.json @@ -1089,6 +1089,12 @@ "message": "#5 Produkt des Tages", "description": "The launch's rank on Product Hunt (October 11, 2026). Keep the #5." }, + "download.windows.arm.label": { + "message": "Windows auf ARM" + }, + "download.windows.arm.sublabel": { + "message": "ARM64 · .exe · nicht signiert" + }, "home.agents.copied": { "message": "Kopiert" }, diff --git a/website/i18n/es/code.json b/website/i18n/es/code.json index fd0858600..ab8f788e8 100644 --- a/website/i18n/es/code.json +++ b/website/i18n/es/code.json @@ -1089,6 +1089,12 @@ "message": "#5 Producto del día", "description": "The launch's rank on Product Hunt (October 11, 2026). Keep the #5." }, + "download.windows.arm.label": { + "message": "Windows en ARM" + }, + "download.windows.arm.sublabel": { + "message": "ARM64 · .exe · sin firmar" + }, "home.agents.copied": { "message": "Copiado" }, diff --git a/website/i18n/fr/code.json b/website/i18n/fr/code.json index cf169d4c6..b1efdefb3 100644 --- a/website/i18n/fr/code.json +++ b/website/i18n/fr/code.json @@ -1089,6 +1089,12 @@ "message": "#5 Produit du jour", "description": "The launch's rank on Product Hunt (October 11, 2026). Keep the #5." }, + "download.windows.arm.label": { + "message": "Windows sur ARM" + }, + "download.windows.arm.sublabel": { + "message": "ARM64 · .exe · non signé" + }, "home.agents.copied": { "message": "Copié" }, diff --git a/website/i18n/ja/code.json b/website/i18n/ja/code.json index 3fc43d083..18be8cec1 100644 --- a/website/i18n/ja/code.json +++ b/website/i18n/ja/code.json @@ -1089,6 +1089,12 @@ "message": "本日のプロダクト 第5位", "description": "The launch's rank on Product Hunt (October 11, 2026). Keep the #5." }, + "download.windows.arm.label": { + "message": "Windows on ARM" + }, + "download.windows.arm.sublabel": { + "message": "ARM64 · .exe · 署名なし" + }, "home.agents.copied": { "message": "コピーしました" }, diff --git a/website/i18n/pt-BR/code.json b/website/i18n/pt-BR/code.json index cd11b9ccf..f9c7f3a62 100644 --- a/website/i18n/pt-BR/code.json +++ b/website/i18n/pt-BR/code.json @@ -1089,6 +1089,12 @@ "message": "#5 Produto do dia", "description": "The launch's rank on Product Hunt (October 11, 2026). Keep the #5." }, + "download.windows.arm.label": { + "message": "Windows no ARM" + }, + "download.windows.arm.sublabel": { + "message": "ARM64 · .exe · sem assinatura" + }, "home.agents.copied": { "message": "Copiado" }, diff --git a/website/i18n/zh-CN/code.json b/website/i18n/zh-CN/code.json index dd1cac3e6..c99f81eb1 100644 --- a/website/i18n/zh-CN/code.json +++ b/website/i18n/zh-CN/code.json @@ -1089,6 +1089,12 @@ "message": "今日产品第 5 名", "description": "The launch's rank on Product Hunt (October 11, 2026). Keep the #5." }, + "download.windows.arm.label": { + "message": "Windows on ARM" + }, + "download.windows.arm.sublabel": { + "message": "ARM64 · .exe · 未签名" + }, "home.agents.copied": { "message": "已复制" }, diff --git a/website/i18n/zh-TW/code.json b/website/i18n/zh-TW/code.json index 95a07baba..44c9302bb 100644 --- a/website/i18n/zh-TW/code.json +++ b/website/i18n/zh-TW/code.json @@ -1089,6 +1089,12 @@ "message": "今日產品第 5 名", "description": "The launch's rank on Product Hunt (October 11, 2026). Keep the #5." }, + "download.windows.arm.label": { + "message": "Windows on ARM" + }, + "download.windows.arm.sublabel": { + "message": "ARM64 · .exe · 未簽署" + }, "home.agents.copied": { "message": "已複製" }, diff --git a/website/src/lib/download-target.test.ts b/website/src/lib/download-target.test.ts index e940ac28c..65c9eba69 100644 --- a/website/src/lib/download-target.test.ts +++ b/website/src/lib/download-target.test.ts @@ -159,7 +159,7 @@ test("a download click names the asset kind and the release, and other links are version: "v2.0.0", file: "Openscreen-mac-arm64.dmg", }); - assert.equal(downloadClick(`${base}/Openscreen-Setup-arm64.exe`)?.kind, "other"); + assert.equal(downloadClick(`${base}/Openscreen-Setup-arm64.exe`)?.kind, "windowsArm"); assert.equal(downloadClick(STORE_INSTALLER_URL)?.kind, "store"); assert.equal(downloadClick("https://github.com/getopenscreen/openscreen/releases/latest"), null); assert.equal(downloadClick(STORE_URL), null); diff --git a/website/src/lib/release.test.ts b/website/src/lib/release.test.ts index 9d20a75d2..15dffceb3 100644 --- a/website/src/lib/release.test.ts +++ b/website/src/lib/release.test.ts @@ -10,32 +10,40 @@ const release = (...names: string[]): LatestRelease => ({ assets: names.map((name) => ({ name, url: `https://example.test/${name}`, size: 1 })), }); -// The asset list of v1.11.0, the release whose .dmg names the old patterns missed. -const V1_11_0 = release( - "Openscreen-macOS-Apple-Silicon-1.11.0.dmg", - "Openscreen-macOS-Intel-1.11.0.dmg", - "Openscreen.Setup.1.11.0.exe", - "Openscreen-Linux-1.11.0.deb", - "Openscreen-Linux-1.11.0.rpm", - "Openscreen-Linux-1.11.0.pacman", - "Openscreen-Linux-1.11.0.AppImage", - "latest.yml", +// The asset list of v2.1.0, updater files included: the first release with an arm64 installer. +const V2_1_0 = release( + "latest-linux.yml", "latest-mac.yml", + "latest.yml", + "Openscreen-Linux-2.1.0.AppImage", + "Openscreen-Linux-2.1.0.AppImage.zsync", + "Openscreen-Linux-2.1.0.deb", + "Openscreen-Linux-2.1.0.pacman", + "Openscreen-Linux-2.1.0.rpm", + "Openscreen-Mac-arm64-2.1.0.zip", + "Openscreen-Mac-x64-2.1.0.zip", + "Openscreen-macOS-Apple-Silicon-2.1.0.dmg", + "Openscreen-macOS-Intel-2.1.0.dmg", + "Openscreen.Setup.2.1.0-arm64.exe", + "Openscreen.Setup.2.1.0-arm64.exe.blockmap", + "Openscreen.Setup.2.1.0-x64.exe", + "Openscreen.Setup.2.1.0-x64.exe.blockmap", ); -test("each kind resolves to exactly one v1.11.0 asset", () => { +test("each kind resolves to exactly one v2.1.0 asset", () => { const expected: Record = { - macArm: "Openscreen-macOS-Apple-Silicon-1.11.0.dmg", - macIntel: "Openscreen-macOS-Intel-1.11.0.dmg", - windows: "Openscreen.Setup.1.11.0.exe", - deb: "Openscreen-Linux-1.11.0.deb", - rpm: "Openscreen-Linux-1.11.0.rpm", - pacman: "Openscreen-Linux-1.11.0.pacman", - appImage: "Openscreen-Linux-1.11.0.AppImage", + macArm: "Openscreen-macOS-Apple-Silicon-2.1.0.dmg", + macIntel: "Openscreen-macOS-Intel-2.1.0.dmg", + windows: "Openscreen.Setup.2.1.0-x64.exe", + windowsArm: "Openscreen.Setup.2.1.0-arm64.exe", + deb: "Openscreen-Linux-2.1.0.deb", + rpm: "Openscreen-Linux-2.1.0.rpm", + pacman: "Openscreen-Linux-2.1.0.pacman", + appImage: "Openscreen-Linux-2.1.0.AppImage", }; for (const kind of Object.keys(ASSET_PATTERNS) as AssetKind[]) { - assert.equal(findAsset(V1_11_0, kind)?.name, expected[kind], kind); - const matches = V1_11_0?.assets.filter((a) => ASSET_PATTERNS[kind].test(a.name)) ?? []; + assert.equal(findAsset(V2_1_0, kind)?.name, expected[kind], kind); + const matches = V2_1_0?.assets.filter((a) => ASSET_PATTERNS[kind].test(a.name)) ?? []; assert.equal(matches.length, 1, `${kind} is ambiguous`); } }); @@ -46,11 +54,6 @@ test("the 1.7.0 .dmg names still resolve", () => { assert.equal(findAsset(old, "macIntel")?.name, "Openscreen-Mac-x64-1.7.0.dmg"); }); -test("windows takes the x64 installer once a release also ships an arm64 one", () => { - const both = release("Openscreen.Setup.2.1.0-arm64.exe", "Openscreen.Setup.2.1.0-x64.exe"); - assert.equal(findAsset(both, "windows")?.name, "Openscreen.Setup.2.1.0-x64.exe"); -}); - test("a missing asset or a failed lookup gives null, which the page turns into /releases/latest", () => { assert.equal(findAsset(release("Openscreen.Setup.1.11.0.exe"), "macArm"), null); assert.equal(findAsset(null, "windows"), null); diff --git a/website/src/lib/release.ts b/website/src/lib/release.ts index 3dae770c2..b8933b06c 100644 --- a/website/src/lib/release.ts +++ b/website/src/lib/release.ts @@ -40,9 +40,9 @@ export type AppLanguage = { lang: string; name: string }; export const ASSET_PATTERNS = { macArm: /mac.*(arm64|apple-silicon).*\.dmg$/i, macIntel: /mac.*(x64|intel).*\.dmg$/i, - // The x64 installer. A release also carries an -arm64.exe, which an x64 PC cannot run; - // Windows on ARM runs the x64 one under emulation. + // The x64 installer. A release also carries an -arm64.exe, which an x64 PC cannot run. windows: /^(?!.*arm64).*\.exe$/i, + windowsArm: /arm64\.exe$/i, deb: /\.deb$/i, rpm: /\.rpm$/i, pacman: /\.pacman$/i, diff --git a/website/src/pages/download.tsx b/website/src/pages/download.tsx index 145eaf065..f5f9fae9d 100644 --- a/website/src/pages/download.tsx +++ b/website/src/pages/download.tsx @@ -95,6 +95,14 @@ function getPlatforms(windowsStoreUrl: string): PlatformSpec[] { message: "Installer · .exe · unsigned", }), }, + { + kind: "windowsArm", + label: translate({ id: "download.windows.arm.label", message: "Windows on ARM" }), + sublabel: translate({ + id: "download.windows.arm.sublabel", + message: "ARM64 · .exe · unsigned", + }), + }, ], footnote: (