Site: show downloads across every release [skip ci]
/release.json adds the sum of every release asset's downloads; the update manifests are the apps' checks, not downloads. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
87c42fde0e
commit
854c360ea1
7 files changed
+81
-26
No files matched your search
+10
-3
@@ -7,7 +7,7 @@ import { night } from "./night.ts";
|
||||
import { rhythm } from "./rhythm.ts";
|
||||
import { playground } from "./play.ts";
|
||||
import { film } from "./film.ts";
|
||||
import { said, speak, type Lang } from "./text.ts";
|
||||
import { said, speak, word, type Lang } from "./text.ts";
|
||||
import { RELEASES, latest } from "./release.ts";
|
||||
|
||||
const REPO = "https://git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice";
|
||||
@@ -36,10 +36,11 @@ const footer = document.createElement("footer");
|
||||
footer.id = "download";
|
||||
const version = document.createElement("h2");
|
||||
version.textContent = "Ely Office";
|
||||
void latest().then((v) => (version.textContent = `Ely Office ${v}`));
|
||||
const count = said("p", "count");
|
||||
count.hidden = true;
|
||||
const get = said("a", "get");
|
||||
get.href = RELEASES;
|
||||
footer.append(version, said("p", "platforms"), said("p", "needs"), said("p", "unsigned"), get);
|
||||
footer.append(version, count, said("p", "platforms"), said("p", "needs"), said("p", "unsigned"), get);
|
||||
|
||||
const toggle = said("button", "other");
|
||||
toggle.className = "lang";
|
||||
@@ -57,3 +58,9 @@ main.append(section, playground(), shelf, film());
|
||||
app.append(night(), toggle, main, footer);
|
||||
say(lang);
|
||||
reveal([shelf]);
|
||||
void latest().then(({ version: v, downloads }) => {
|
||||
version.textContent = `Ely Office ${v}`;
|
||||
count.dataset.n = String(downloads);
|
||||
count.textContent = word(lang, "count", downloads);
|
||||
count.hidden = false;
|
||||
});
|
||||
+5
-4
@@ -1,10 +1,11 @@
|
||||
// Gitea redirects this to the newest release.
|
||||
export const RELEASES = "https://git.zacharyzhang.com/ZacharyZhang-NY/ElyOffice/releases/latest";
|
||||
|
||||
/** The newest release's version, from the worker. */
|
||||
export async function latest(): Promise<string> {
|
||||
export type Release = { version: string; downloads: number };
|
||||
|
||||
/** The newest release and all downloads, from the worker. */
|
||||
export async function latest(): Promise<Release> {
|
||||
const res = await fetch("/release.json");
|
||||
if (!res.ok) throw new Error(`release.json: ${res.status} ${await res.text()}`);
|
||||
const { version } = (await res.json()) as { version: string };
|
||||
return version;
|
||||
return (await res.json()) as Release;
|
||||
}
|
||||
+10
-1
@@ -17,6 +17,7 @@ const en = {
|
||||
needs: "macOS 14 or later, Apple silicon.",
|
||||
unsigned: "Not notarized. If macOS blocks the app, open System Settings › Privacy & Security and click Open Anyway.",
|
||||
get: "Download",
|
||||
count: "{n} downloads so far.",
|
||||
other: "中文",
|
||||
roads: "Drag a file down the road.",
|
||||
fileDoc: "ElyDoc file",
|
||||
@@ -53,6 +54,7 @@ const zh: typeof en = {
|
||||
needs: "macOS 14 或更新,Apple 芯片。",
|
||||
unsigned: "未经公证。macOS 拦下应用时,打开“系统设置 › 隐私与安全性”,点“仍要打开”。",
|
||||
get: "前往下载",
|
||||
count: "已下载 {n} 次。",
|
||||
other: "English",
|
||||
roads: "把文件沿着路拖过去。",
|
||||
fileDoc: "ElyDoc 文件",
|
||||
@@ -83,10 +85,17 @@ export function said<K extends keyof HTMLElementTagNameMap>(tag: K, key: Key): H
|
||||
return el;
|
||||
}
|
||||
|
||||
/** `key` in `lang`, with `n` written for {n}. */
|
||||
export function word(lang: Lang, key: Key, n?: number): string {
|
||||
const text = TEXT[lang][key];
|
||||
return n === undefined ? text : text.replace("{n}", n.toLocaleString(lang === "zh" ? "zh-CN" : "en"));
|
||||
}
|
||||
|
||||
/** Writes every keyed text in `lang`. */
|
||||
export function speak(lang: Lang): void {
|
||||
document.documentElement.lang = lang === "zh" ? "zh-CN" : "en";
|
||||
for (const el of document.querySelectorAll<HTMLElement>("[data-t]")) {
|
||||
el.textContent = TEXT[lang][el.dataset.t as Key];
|
||||
const { n } = el.dataset;
|
||||
el.textContent = word(lang, el.dataset.t as Key, n === undefined ? undefined : Number(n));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user