From c86d9792cc8f0029d9593f71fcbd0f4d00d69c1f Mon Sep 17 00:00:00 2001 From: "Eric Meehan -X (ermeehan - ACTALENT SERVICES LLC at Cisco)" Date: Sun, 18 Oct 2026 16:18:30 -0400 Subject: [PATCH] social --- static/app.js | 47 +++++++++++++++++++++++++++++++++++++++++++++++ static/index.html | 14 ++++++++++++++ static/style.css | 23 +++++++++++++++++++++++ 3 files changed, 84 insertions(+) diff --git a/static/app.js b/static/app.js index dd32f2c..6e83f37 100644 --- a/static/app.js +++ b/static/app.js @@ -8,6 +8,7 @@ let clockOffset = 0; // serverTime - clientTime let token = localStorage.getItem(TOKEN_KEY); let statsLoaded = false; let subscribed = false; +let currentShareText = ""; async function api(method, path, body) { const headers = { "Content-Type": "application/json" }; @@ -36,6 +37,45 @@ function formatPrecise(ms) { return `${formatMs(ms).slice(0, -3)}.${String(Math.max(0, ms) % 1000).padStart(3, "0")}`; } +function updateShareLinks() { + if (!currentShareText) return; + const gameUrl = new URL(location.pathname, location.origin).href; + const facebookUrl = new URL("https://www.facebook.com/sharer/sharer.php"); + facebookUrl.searchParams.set("u", gameUrl); + facebookUrl.searchParams.set("quote", currentShareText); + $("share-facebook").href = facebookUrl.href; + + const xUrl = new URL("https://twitter.com/intent/tweet"); + xUrl.searchParams.set("text", currentShareText); + xUrl.searchParams.set("url", gameUrl); + $("share-x").href = xUrl.href; + + const blueskyUrl = new URL("https://bsky.app/intent/compose"); + blueskyUrl.searchParams.set("text", `${currentShareText} ${gameUrl}`); + $("share-bluesky").href = blueskyUrl.href; + + const instanceInput = $("mastodon-instance"); + const mastodonLink = $("share-mastodon"); + const shareError = $("share-error"); + try { + const instance = new URL(instanceInput.value.trim()); + if (instance.protocol !== "https:" || !instance.hostname || instance.username || instance.password) { + throw new Error("Enter an HTTPS Mastodon instance URL."); + } + const mastodonUrl = new URL("/share", instance.origin); + mastodonUrl.searchParams.set("text", `${currentShareText} ${gameUrl}`); + mastodonLink.href = mastodonUrl.href; + mastodonLink.removeAttribute("aria-disabled"); + mastodonLink.tabIndex = 0; + shareError.textContent = ""; + } catch { + mastodonLink.removeAttribute("href"); + mastodonLink.setAttribute("aria-disabled", "true"); + mastodonLink.tabIndex = -1; + shareError.textContent = "Enter an HTTPS Mastodon instance URL to enable sharing."; + } +} + function zoneFor(remaining) { return game.zones.find((z) => remaining > z.remaining_to_ms) ?? game.zones[game.zones.length - 1]; } @@ -200,11 +240,16 @@ async function loadStats() { $("the-button").addEventListener("click", async () => { const btn = $("the-button"); btn.disabled = true; + $("share-controls").hidden = true; + currentShareText = ""; try { const r = await api("POST", "/api/press"); game.deadline = r.deadline; + currentShareText = `I pushed the button at ${formatPrecise(r.press.remaining_ms)}.`; $("press-result").textContent = `You pressed in the ${r.press.zone} zone with ${formatPrecise(r.press.remaining_ms)} remaining: +${r.press.points} points`; + updateShareLinks(); + $("share-controls").hidden = false; await loadMe(); } catch (e) { $("press-result").textContent = e.message; @@ -214,6 +259,8 @@ $("the-button").addEventListener("click", async () => { } }); +$("mastodon-instance").addEventListener("input", updateShareLinks); + $("register-form").addEventListener("submit", async (ev) => { ev.preventDefault(); $("register-error").textContent = ""; diff --git a/static/index.html b/static/index.html index c03cb8e..610de40 100644 --- a/static/index.html +++ b/static/index.html @@ -27,6 +27,20 @@

+