diff --git a/.dev.vars.example b/.dev.vars.example index d5e8a1f..9afce7d 100644 --- a/.dev.vars.example +++ b/.dev.vars.example @@ -15,3 +15,13 @@ SPOTIFY_REFRESH_TOKEN= # currently-reading widget — personal token from https://hardcover.app/account/api HARDCOVER_TOKEN= + +# "the counter" — all-time pageviews + visitors from Umami. needs the website id +# plus EITHER an api key OR a share-url id. leave all blank to hide the block. +UMAMI_WEBSITE_ID= +# api base — default is Umami Cloud; self-hosted: https:///api +UMAMI_URL= +# mode A: an api key (Umami Cloud account → api keys) +UMAMI_API_KEY= +# mode B (no key): enable "Share URL" on the website, put its id here +UMAMI_SHARE_ID= diff --git a/src/components/Clock.astro b/src/components/Clock.astro index 1e54de9..c6bc4bd 100644 --- a/src/components/Clock.astro +++ b/src/components/Clock.astro @@ -1,62 +1,111 @@ --- -const TZ = "America/New_York"; +import { Icon } from "astro-icon/components"; +const TZ = "America/New_York"; const now = new Date(); -const parts = (opts: Intl.DateTimeFormatOptions) => +const fmt = (opts: Intl.DateTimeFormatOptions) => new Intl.DateTimeFormat("en-US", { timeZone: TZ, ...opts }).formatToParts(now); -const hh = parts({ hour: "2-digit", hour12: false }).find((p) => p.type === "hour")?.value ?? "--"; -const mm = parts({ minute: "2-digit" }).find((p) => p.type === "minute")?.value ?? "--"; -const zone = - parts({ timeZoneName: "short" }).find((p) => p.type === "timeZoneName")?.value ?? "ET"; +const t = fmt({ hour: "numeric", minute: "2-digit", hour12: true }); +const hour = t.find((p) => p.type === "hour")?.value ?? "--"; +const minute = t.find((p) => p.type === "minute")?.value ?? "--"; +const mer = (t.find((p) => p.type === "dayPeriod")?.value ?? "").toUpperCase(); +const zone = fmt({ timeZoneName: "short" }).find((p) => p.type === "timeZoneName")?.value ?? "ET"; --- - +
+ +
diff --git a/src/scripts/music.ts b/src/scripts/music.ts index f0f95de..ca54bfa 100644 --- a/src/scripts/music.ts +++ b/src/scripts/music.ts @@ -30,6 +30,8 @@ const mmss = (ms: number): string => { const $ = (id: string) => document.getElementById(id); const esc = (s: string): string => s.replace(/[&<>"]/g, (c) => ({ "&": "&", "<": "<", ">": ">", '"': """ })[c]!); +const clamp = (s: string, n = 22): string => + s.length > n ? s.slice(0, n - 1).trimEnd() + "…" : s; function renderNowPlaying(np: NP): void { const section = $("np-section"); @@ -162,7 +164,8 @@ async function load(): Promise { if (label) { if (np?.isPlaying) { trigger.classList.add("music__trigger--live"); - label.textContent = np.title; + label.textContent = clamp(np.title); + trigger.title = `${np.title} — ${np.artist}`; if (sub) sub.textContent = np.artist; if (bar && fill && np.progressMs != null && np.durationMs) { fill.style.setProperty("--p", `${Math.min(100, (np.progressMs / np.durationMs) * 100)}%`); @@ -170,7 +173,8 @@ async function load(): Promise { } } else if (np?.playedAt) { label.textContent = "last played"; - if (sub) sub.textContent = `${np.title} · ${np.artist}`; + trigger.title = `${np.title} — ${np.artist}`; + if (sub) sub.textContent = `${clamp(np.title, 26)} · ${np.artist}`; } else { label.textContent = "top tracks"; if (sub) sub.textContent = "last 4 weeks";