diff --git a/discord/index.html b/discord/index.html index ccf9257..cd2b6f0 100644 --- a/discord/index.html +++ b/discord/index.html @@ -20,7 +20,7 @@ - + diff --git a/js/core.js b/js/core.js index 7f4a285..29e3937 100644 --- a/js/core.js +++ b/js/core.js @@ -1,6 +1,6 @@ -// Ari was here uwu -// Professional boob lover -// girls kissing,,, +/* Ari was here uwu + * Professional boob lover + * girls kissing,,, */ console.log(` ⣿⣿⣿⠏⣴⣿⣿⣿⣿⡿⠟⢹⣿⣿⣿⡿⠋⣠⣾⣿⣿⣿⣿⣿⣿⣿⣿⣷⣦⡉⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⢇⣾⣿⣿⣿⡿⢋⢀⣴⣿⣿⡿⠋⠀⠘⣿⣿⣿⣿⣿⠿⣿⣿⣿⣿⣿⣿⣿⣦⣤⣀⠻⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ @@ -35,10 +35,10 @@ console.log(` ⣿⣿⣿⣿⣿⣿⣿⣿⣧⡀⢹⣿⣿⣧⢹⡄⠘⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⢇⣿⢿⣷⡄⠘⣿⣿⣿⣿⠇⣾⣿⣦⣤⡀⢸⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⣷⣤⣈⡙⠻⢿⡇⠀⢿⣇⢻⡆⢿⡀⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣧⡀⡜⢁⣤⡘⣿⣿⡿⢠⣿⣿⣿⣿⠁⣿⣿⣿⣿⣿⣿⣿⣿ ⣿⣿⣿⣿⡿⢿⣿⣿⣿⣿⡀⠘⣿⣄⢻⡘⡇⢸⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣧⣸⣿⡀⠀⣷⡘⣿⠇⣼⣿⣿⣿⡿⢸⣿⣿⣿⣿⣿⣿⣿⣿`); -// mmmmmmmmmmmmmmmmm girls kissing,,,,, +/* mmmmmmmmmmmmmmmmm girls kissing,,,,, */ document.querySelectorAll("[data-href]").forEach((el) => { - // cursor handled in css ([data-href] + [role="link"]) so the custom PNG isn't overridden + /* Cursor is handled in CSS ([data-href] + [role="link"]) so the custom PNG isn't overridden. */ if (!el.hasAttribute("role")) el.setAttribute("role", "link"); if (!el.hasAttribute("tabindex")) el.setAttribute("tabindex", "0"); @@ -59,7 +59,7 @@ document.querySelectorAll("[data-href]").forEach((el) => { /* ========================== flavors.js ========================= */ (function flavors() { - // Metadata only — colors are defined in the per-flavor CSS files. + /* Metadata only, colors are defined in the per-flavor CSS files. */ const FLAVORS = { mocha: { label: "Mocha", dot: "#f5c2e7" }, macchiato: { label: "Macchiato", dot: "#f5bde6" }, @@ -73,33 +73,33 @@ document.querySelectorAll("[data-href]").forEach((el) => { function apply(name) { const f = FLAVORS[name] || FLAVORS.mocha; - root.setAttribute("data-flavor", name); // CSS does the rest + root.setAttribute("data-flavor", name); /* CSS does the rest */ const meta = document.querySelector('meta[name="theme-color"]'); if (meta) meta.setAttribute("content", f.dot); } let current = ls.getItem("ctpFlavor"); if (!ORDER.includes(current)) current = "mocha"; - apply(current); // the snippet already set this to avoid a flash + apply(current); /* the snippet already set this to avoid a flash */ - // ---- top-right corner icon button ---- + /* ---- top-right corner icon button ---- */ const bar = document.createElement("div"); bar.className = "beta-bar"; bar.innerHTML = ` `; - // Group the single-item widgets (discord + theme toggle) into one - // top bar. On mobile they sit side by side; on desktop both stay - // position:fixed, so this wrapper is zero-size and invisible. + /* Group the single-item widgets (discord + theme toggle) into one top + * bar. On mobile they sit side by side, on desktop both stay + * position:fixed, so this wrapper ends up zero-size and invisible. */ let topbar = document.querySelector(".topbar"); if (!topbar) { topbar = document.createElement("div"); topbar.className = "topbar"; document.body.insertBefore(topbar, document.body.firstChild); const dc = document.getElementById("discord"); - // Don't hijack the presence card when it's the centerpiece of the - // dedicated /discord page (it lives inside .presence-stage there). + /* Don't hijack the presence card when it's the centerpiece of the + * dedicated /discord page (it lives inside .presence-stage there). */ if (dc && !dc.closest(".presence-stage")) topbar.appendChild(dc); } topbar.appendChild(bar); @@ -109,7 +109,7 @@ document.querySelectorAll("[data-href]").forEach((el) => { function paintBtn() { const f = FLAVORS[current]; - icon.src = `/assets/theme/${current}.png`; // e.g. /assets/theme/mocha.png + icon.src = `/assets/theme/${current}.png`; /* e.g. /assets/theme/mocha.png */ icon.alt = f.label; btn.title = `Theme: ${f.label} (click to cycle)`; } @@ -122,7 +122,7 @@ document.querySelectorAll("[data-href]").forEach((el) => { paintBtn(); }); - // ---- cat collection button (sits next to the theme button) ---- + /* ---- cat collection button (sits next to the theme button) ---- */ const catBtn = document.createElement("button"); catBtn.className = "beta-btn"; catBtn.id = "cat-btn"; @@ -138,7 +138,7 @@ document.querySelectorAll("[data-href]").forEach((el) => { })(); /* ===================== cat.js (oneko.js) ======================= */ -// oneko.js: https://github.com/adryd325/oneko.js +/* oneko.js: https://github.com/adryd325/oneko.js */ (function oneko() { const isReducedMotion = @@ -296,7 +296,7 @@ document.querySelectorAll("[data-href]").forEach((el) => { let lastFrameTimestamp; function onAnimationFrame(timestamp) { - // Stops execution if the neko element is removed from DOM + /* Stop running if the neko element is removed from the DOM. */ if (!nekoEl.isConnected) { return; } @@ -323,7 +323,7 @@ document.querySelectorAll("[data-href]").forEach((el) => { function idle() { idleTime += 1; - // every ~ 20 seconds + /* Roughly every 20 seconds. */ if ( idleTime > 10 && Math.floor(Math.random() * 200) == 0 && @@ -392,7 +392,7 @@ document.querySelectorAll("[data-href]").forEach((el) => { if (idleTime > 1) { setSprite("alert", 0); - // count down after being alerted before moving + /* Count down after being alerted, before moving. */ idleTime = Math.min(idleTime, 7); idleTime -= 1; return; @@ -422,23 +422,23 @@ const BASE_SPRITE = "/assets/oneko/classics/classic.png"; let CAT_MODES = []; -// Order the category sections appear in the menu +/* Order the category sections appear in within the menu. */ const CATEGORY_ORDER = ["Classics", "Pride", "Cats", "Romance", "Gaming", "Pokémon", "Other Animals", "Things", "Rare"]; -// click-count goals (total clicks on the cat) +/* Click-count goals (total clicks on the cat). */ const CLICK_GOALS = { filter: 13, romance: 69, weed: 420 }; -const SPRITE = BASE_SPRITE; // base sprite used for filter modes + previews -const IDLE_POS = "-97px -97px"; // idle frame, inset 1px to avoid neighbour-frame bleed +const SPRITE = BASE_SPRITE; /* base sprite used for filter modes + previews */ +const IDLE_POS = "-97px -97px"; /* idle frame, inset 1px to avoid neighbour-frame bleed */ const spriteFor = (c) => c.sprite || BASE_SPRITE; (async function catModes() { try { - // index.json lists which per-folder configs to load (one per oneko folder) + /* index.json lists which per-folder configs to load, one per oneko folder. */ const index = await fetch("/js/on/index.json").then((r) => { if (!r.ok) throw new Error(`index.json (${r.status})`); return r.json(); }); - // load every /js/on/.json and merge them into one list + /* Load every /js/on/.json and merge them into one list. */ const lists = await Promise.all( index.map((name) => fetch(`/js/on/${name}.json`) @@ -455,19 +455,19 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; if (!oneko) return; oneko.style.pointerEvents = "auto"; - // cursor handled in css (#oneko) so the custom pointer PNG isn't overridden + /* Cursor is handled in CSS (#oneko) so the custom pointer PNG isn't overridden. */ const ls = window.localStorage; let clicks = parseInt(ls.getItem("onekoClicks") || "0", 10); let mode = parseInt(ls.getItem("onekoMode") || "0", 10); - // permanently-earned methods (konami, gold, pokemon, + any click goal hit) + /* Permanently-earned methods (konami, gold, pokemon, plus any click goal hit). */ let unlocks; try { unlocks = new Set(JSON.parse(ls.getItem("onekoUnlocks") || "[]")); } catch (e) { unlocks = new Set(); } const saveUnlocks = () => ls.setItem("onekoUnlocks", JSON.stringify([...unlocks])); - // Returns true if a method was newly unlocked (false if already had it) + /* Returns true if a method was newly unlocked, false if already had it. */ function unlockMethod(key) { if (unlocks.has(key)) return false; unlocks.add(key); @@ -481,7 +481,7 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; const key = methodOf(CAT_MODES[i]); if (key === "gay") return true; if (key in CLICK_GOALS) return clicks >= CLICK_GOALS[key] || unlocks.has(key); - return unlocks.has(key); // konami / gold / pokemon + return unlocks.has(key); /* konami / gold / pokemon */ }; const unlockedIndices = () => CAT_MODES.map((_, i) => i).filter(isUnlocked); @@ -492,7 +492,7 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; oneko.style.filter = c.filter || "none"; }; - /* ---------- picker overlay (no visible trigger — press C to find it) ---------- */ + /* ---- picker overlay (no visible trigger, press C to find it) ---- */ const overlay = document.createElement("div"); overlay.className = "cat-picker"; overlay.hidden = true; @@ -526,14 +526,14 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; function renderGrid() { grid.innerHTML = ""; - // bucket cat indices by category + /* Bucket cat indices by category. */ const byCat = {}; CAT_MODES.forEach((c, i) => { const cat = c.category || "Classics"; (byCat[cat] = byCat[cat] || []).push(i); }); - // known categories first (in order), then any stragglers + /* Known categories first, in order, then any stragglers. */ const order = CATEGORY_ORDER.filter((c) => byCat[c]) .concat(Object.keys(byCat).filter((c) => !CATEGORY_ORDER.includes(c))); @@ -569,7 +569,7 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; const closePicker = () => (overlay.hidden = true); const togglePicker = () => (overlay.hidden ? openPicker() : closePicker()); - // let other scripts (e.g. the theme-bar button) open the cat menu + /* Let other scripts (e.g. the theme-bar button) open the cat menu. */ window.toggleCatPicker = togglePicker; overlay @@ -579,7 +579,7 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; if (e.target === overlay) closePicker(); }); document.addEventListener("keydown", (e) => { - // ignore while typing in a field or with modifier keys held + /* Ignore while typing in a field or with a modifier key held. */ const typing = /^(INPUT|TEXTAREA|SELECT)$/.test(document.activeElement?.tagName || ""); if (e.key === "Escape" && !overlay.hidden) { closePicker(); @@ -596,7 +596,7 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; } }); - /* ---------- toast ---------- */ + /* ---- toast ---- */ let toastEl, toastTimer; function toast(msg) { if (!toastEl) { @@ -612,22 +612,23 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; toastTimer = setTimeout(() => toastEl.classList.remove("show"), 1700); } - /* ---------- squeak / boop sound on click ---------- */ + /* ---- squeak / boop sound on click ---- */ const boop = new Audio("/assets/oneko/boop.mp3"); boop.preload = "auto"; function playBoop() { try { - boop.currentTime = 0; // rewind so rapid clicks each squeak - boop.play().catch(() => { }); // ignore autoplay/missing-file errors + boop.currentTime = 0; /* rewind so rapid clicks each squeak */ + boop.play().catch(() => { }); /* ignore autoplay/missing-file errors */ } catch (e) { /* no-op */ } } - /* ---------- init + cat click ---------- */ - if (!isUnlocked(mode)) mode = 0; // fall back to Classic if current is locked + /* ---- init + cat click ---- */ + if (!isUnlocked(mode)) mode = 0; /* fall back to Classic if current is locked */ apply(mode); - // Clicking the cat no longer changes its look — it only counts toward - // the click-based unlocks (13 / 69 / 420). Pick a cat from the menu. + /* Clicking the cat no longer changes its look, it only counts toward + * the click-based unlocks (13 / 69 / 420). Pick a cat from the menu + * instead. */ oneko.addEventListener("click", (e) => { e.preventDefault(); e.stopPropagation(); @@ -635,20 +636,20 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; clicks += 1; ls.setItem("onekoClicks", String(clicks)); - // Did this click hit a click-count goal exactly? (13 / 69 / 420) + /* Did this click hit a click-count goal exactly? (13 / 69 / 420) */ for (const key in CLICK_GOALS) { if (clicks === CLICK_GOALS[key]) { unlocks.add(key); saveUnlocks(); const idx = CAT_MODES.findIndex((c) => methodOf(c) === key); const name = idx >= 0 ? CAT_MODES[idx].name : key; - toast(`✨ Unlocked: ${name}! — open the cat menu 🐱`); + toast(`✨ Unlocked: ${name}! Open the cat menu 🐱`); if (!overlay.hidden) renderGrid(); } } }); - /* ---------- Konami code → press Enter to confirm ---------- */ + /* ---- Konami code, press Enter to confirm ---- */ const KONAMI = ["ArrowUp", "ArrowUp", "ArrowDown", "ArrowDown", "ArrowLeft", "ArrowRight", "ArrowLeft", "ArrowRight", "b", "a"]; let kProg = 0, kArmed = false; @@ -671,11 +672,11 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; toast("Konami code… press Enter ↵"); } } else { - kProg = key === KONAMI[0] ? 1 : 0; // allow a fresh start on ↑ + kProg = key === KONAMI[0] ? 1 : 0; /* allow a fresh start on ↑ */ } }); - /* ---------- Gold → opened the site while Discord status is Idle ---------- */ + /* ---- Gold: opened the site while Discord status is Idle ---- */ const dc = document.getElementById("discord"); if (dc) { const checkIdle = () => { @@ -688,7 +689,7 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; .observe(dc, { attributes: true, attributeFilter: ["data-status"] }); } - /* ---------- Pokémon → find & click the hidden pokéball ---------- */ + /* ---- Pokémon: find and click the hidden pokéball ---- */ const poke = document.getElementById("pokeball-secret"); if (poke) { poke.addEventListener("click", (e) => { @@ -698,10 +699,10 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; }); } - /* ---------- Timer → keep the page open for a while ---------- */ - // Counts only while the tab is visible; resets each visit, but once the - // goal is reached the unlock is saved for good. - const TIMER_GOAL_MS = 5 * 60 * 1000; // 5 minutes + /* ---- Timer: keep the page open for a while ---- + * Counts only while the tab is visible, and resets each visit, but + * once the goal is reached the unlock is saved for good. */ + const TIMER_GOAL_MS = 5 * 60 * 1000; /* 5 minutes */ if (!unlocks.has("timer")) { let elapsed = 0; let last = Date.now(); @@ -712,8 +713,8 @@ const spriteFor = (c) => c.sprite || BASE_SPRITE; last = now; if (elapsed >= TIMER_GOAL_MS) { clearInterval(timer); - if (unlockMethod("timer")) toast("✨ Patience pays off — timer cats unlocked!"); + if (unlockMethod("timer")) toast("✨ Patience pays off, timer cats unlocked!"); } }, 1000); } -})(); +})(); \ No newline at end of file diff --git a/js/dev-info.js b/js/dev-info.js index 6a397f1..73c0b3b 100644 --- a/js/dev-info.js +++ b/js/dev-info.js @@ -1,7 +1,7 @@ (function () { "use strict"; - // ====== PASTE YOUR EMBEDDABLE JSON SHARE URLS HERE =================== + /* Paste your embeddable JSON share URLs here. */ var WAKATIME = { codingActivity: "https://wakatime.com/share/@doughmination/9dcc5b5c-ed3d-4896-bfa3-87737fa70930.json", languages: "https://wakatime.com/share/@doughmination/8354e3f8-b458-452b-aa06-839f303d4904.json", @@ -9,11 +9,10 @@ editors: "https://wakatime.com/share/@doughmination/38dba24b-d2de-4d50-9b09-83642c01c33e.json", operatingSystems: "https://wakatime.com/share/@doughmination/a69f00cb-e38e-4de1-aa42-eec71dc6d658.json" }; - // How many rows to show in each ranked list. + /* How many rows to show in each ranked list. */ var MAX_ROWS = 8; - // ===================================================================== - // ---- JSONP loader --------------------------------------------------- + /* ---- JSONP loader ---- */ var seq = 0; function jsonp(url, timeoutMs) { return new Promise(function (resolve, reject) { @@ -36,7 +35,7 @@ }); } - // ---- helpers -------------------------------------------------------- + /* ---- helpers ---- */ function fmt(seconds) { seconds = Math.max(0, Math.round(seconds || 0)); var h = Math.floor(seconds / 3600); @@ -50,8 +49,8 @@ return (p < 10 ? Math.round(p * 10) / 10 : Math.round(p)) + "%"; } - // Value shown at the end of a bar: real time when the embed provides it, - // otherwise the percentage share. + /* Value shown at the end of a bar: real time when the embed provides it, + * otherwise the percentage share. */ function valueLabel(d, hasSeconds) { if (hasSeconds && (d.total_seconds || 0) > 0) return d.text || fmt(d.total_seconds); if (typeof d.percent === "number") return pctLabel(d.percent); @@ -66,15 +65,15 @@ if (m && text) { m.textContent = text; m.hidden = false; } } - // Render a ranked list of horizontal bars into a container. + /* Render a ranked list of horizontal bars into a container. */ function renderBars(containerId, items) { var box = el(containerId); if (!box) return; if (!items || !items.length) { failSection(box, "No data yet."); return; } - // Share embeds for languages/categories/editors/OS often return only - // {name, percent, color} with no seconds — so fall back to percent for - // both the bar width and the value label when time isn't provided. + /* Share embeds for languages/categories/editors/OS often return only + * {name, percent, color} with no seconds, so we fall back to percent + * for both the bar width and the value label when time isn't given. */ var hasSeconds = items.some(function (d) { return d && (d.total_seconds || 0) > 0; }); var rows = items @@ -122,7 +121,7 @@ showSection(box); } - // Render the 7-day vertical bar chart + headline total. + /* Render the 7 day vertical bar chart and the headline total. */ function renderWeek(days) { var box = el("waka-week"); if (!box) return; @@ -171,12 +170,15 @@ showSection(box); } - // ---- shape parsers (defensive: WakaTime embed shapes vary) ---------- - // Categorical embeds (languages/categories/editors/OS) -> data:[{name,total_seconds,percent,color,text}] + /* ---- shape parsers ---- + * Defensive, because WakaTime's embed shapes vary between endpoints. */ + + /* Categorical embeds (languages/categories/editors/OS) -> + * data: [{name, total_seconds, percent, color, text}] */ function asCategorical(json) { var data = json && json.data; if (!Array.isArray(data)) return []; - // Some embeds nest under data.; flatten the first array we find. + /* Some embeds nest under data., so flatten the first array we find. */ if (data.length && data[0] && data[0].name === undefined && Array.isArray(data[0])) { data = data[0]; } @@ -191,7 +193,7 @@ }); } - // Coding-activity embed -> array of {label, short, total} + /* Coding activity embed -> array of {label, short, total} */ function asDays(json) { var data = json && json.data; if (!Array.isArray(data)) return []; @@ -199,17 +201,18 @@ data.forEach(function (d) { var seconds = 0, dateStr = ""; if (d.grand_total && typeof d.grand_total.total_seconds === "number") { - seconds = d.grand_total.total_seconds; // daily-summaries shape + seconds = d.grand_total.total_seconds; /* daily-summaries shape */ } else if (typeof d.total_seconds === "number") { - seconds = d.total_seconds; // flat shape + seconds = d.total_seconds; /* flat shape */ } if (d.range && (d.range.date || d.range.text)) { dateStr = d.range.date || d.range.text; } else if (d.date) { dateStr = d.date; } - // Anchor bare YYYY-MM-DD to local noon so the weekday label doesn't - // slip a day in timezones west of UTC (where it'd parse as UTC midnight). + /* Anchor a bare YYYY-MM-DD to local noon so the weekday label doesn't + * slip a day in timezones west of UTC, where it would otherwise parse + * as UTC midnight. */ var dateForParse = /^\d{4}-\d{2}-\d{2}$/.test(dateStr) ? dateStr + "T12:00:00" : dateStr; var dt = dateStr ? new Date(dateForParse) : null; var label = dt && !isNaN(dt) ? dt.toDateString() : (dateStr || ""); @@ -221,7 +224,7 @@ return out; } - // ---- orchestration -------------------------------------------------- + /* ---- orchestration ---- */ function load(url, onData, fallbackBoxId) { if (!url) return Promise.resolve(null); return jsonp(url).then(function (json) { @@ -277,7 +280,7 @@ }, "waka-os")); } - // If no coding-activity embed was set, hide the headline total card. + /* If no coding-activity embed was set, hide the headline total card. */ if (!WAKATIME.codingActivity) { var totEl = el("waka-total"); if (totEl) totEl.hidden = true; @@ -292,10 +295,11 @@ init(); } - // ---- anchor links: open the targeted
and scroll to it -------- - // Sections are collapsible (and some are populated/un-hidden async), so a - // plain #hash won't reliably reveal them. Open + scroll on load and on - // hashchange, retrying briefly while late content settles in. + /* ---- anchor links ---- + * Open the targeted
and scroll to it. Sections are collapsible + * (and some get populated/unhidden async), so a plain #hash won't reliably + * reveal them. We open and scroll on load and on hashchange, retrying + * briefly while late content settles in. */ function openFromHash() { var id = (location.hash || "").slice(1); if (!id) return; @@ -316,4 +320,4 @@ openFromHash(); } window.addEventListener("hashchange", openFromHash); -})(); +})(); \ No newline at end of file diff --git a/js/discord.js b/js/discord.js index 339d9e2..866271f 100644 --- a/js/discord.js +++ b/js/discord.js @@ -745,7 +745,6 @@ // ---- data source: Doughmination Restful API (sole source) --------------- // Returns presence + full profile (incl. theme_colors + display_name_styles) - // in a single call. Lanyard + dstn.to were removed. const SELF_BASE = "https://restful.doughmination.uk/v1/users/"; const SELF_POLL_MS = opts.pollMs || 20000; // presence refresh cadence let selfTimer = null; @@ -864,12 +863,12 @@ (function friends() { "use strict"; - // Each friend is rendered as a full — but smaller — presence card, built by - // the shared factory above (window.PresenceCard). Cards pull live - // presence (status, activity, badges, banner, bio, connections, wishlist…) - // from the same Doughmination Restful API the main card uses. - // NOTE: now lives in the same file as the factory (formerly discord.js), - // so load order is no longer a concern — this IIFE just runs second. + /* Each friend is rendered as a full — but smaller — presence card, built by + * the shared factory above (window.PresenceCard). Cards pull live + * presence (status, activity, badges, banner, bio, connections, wishlist…) + * from the same Doughmination Restful API the main card uses. + * NOTE: now lives in the same file as the factory (formerly discord.js), + * so load order is no longer a concern — this IIFE just runs second. */ var FRIENDS = [ { diff --git a/js/fronting.js b/js/fronting.js index cf56959..dd7ec0a 100644 --- a/js/fronting.js +++ b/js/fronting.js @@ -1,10 +1,9 @@ -/* ===================================================================== - * fronting.js — homepage "who's fronting" box. +/* fronting.js * - * Polls the system's PluralKit-style API for the current fronter(s) and - * renders a small card. Each member links to their page on the system - * site. Refreshes every 30s so switches show without a reload. - * ===================================================================== */ + * Homepage "who's fronting" box. Polls the system's PluralKit-style API + * for the current fronter(s) and renders a small card. Each member links + * to their page on the system site. Refreshes every 30s so switches show + * up without needing a reload. */ (function fronting() { "use strict"; @@ -18,12 +17,12 @@ return String(s == null ? "" : s) .replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); } - // member.color is a 6-char hex string (no leading #), may be null. + /* member.color is a 6-char hex string with no leading #, and may be null. */ function colorHex(c) { return /^[0-9a-fA-F]{6}$/.test(c || "") ? "#" + c : null; } - // ---- build the shell ---------------------------------------------------- + /* ---- build the shell ---- */ const card = document.createElement("section"); card.id = "fronting"; card.className = "fronting-card"; @@ -59,7 +58,7 @@ function render(members) { if (!Array.isArray(members) || !members.length) { - // No one registered as fronting — keep the box but say so. + /* No one registered as fronting, keep the box up but say so. */ membersEl.innerHTML = 'no one is currently fronting'; card.hidden = false; return; @@ -78,8 +77,9 @@ failed = false; }) .catch(function () { - // On first failure hide the box quietly; if it was already showing, - // leave the last-known fronters up rather than flashing an error. + /* On the first failure, hide the box quietly. If it was already + * showing, leave the last known fronters up instead of flashing + * an error. */ if (!failed && card.hidden) card.hidden = true; failed = true; }); @@ -87,9 +87,9 @@ load(); const timer = setInterval(load, POLL_MS); - // Refresh immediately when the tab becomes visible again. + /* Refresh immediately when the tab becomes visible again. */ document.addEventListener("visibilitychange", function () { if (!document.hidden) load(); }); window.addEventListener("beforeunload", function () { clearInterval(timer); }); -})(); +})(); \ No newline at end of file diff --git a/js/guestbook.js b/js/guestbook.js index ec6224f..9d531a3 100644 --- a/js/guestbook.js +++ b/js/guestbook.js @@ -1,7 +1,7 @@ (function (global) { "use strict"; - // ---- config (from the