social
This commit is contained in:
parent
36d619c470
commit
c86d9792cc
@@ -8,6 +8,7 @@ let clockOffset = 0; // serverTime - clientTime
|
|||||||
let token = localStorage.getItem(TOKEN_KEY);
|
let token = localStorage.getItem(TOKEN_KEY);
|
||||||
let statsLoaded = false;
|
let statsLoaded = false;
|
||||||
let subscribed = false;
|
let subscribed = false;
|
||||||
|
let currentShareText = "";
|
||||||
|
|
||||||
async function api(method, path, body) {
|
async function api(method, path, body) {
|
||||||
const headers = { "Content-Type": "application/json" };
|
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")}`;
|
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) {
|
function zoneFor(remaining) {
|
||||||
return game.zones.find((z) => remaining > z.remaining_to_ms) ?? game.zones[game.zones.length - 1];
|
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 () => {
|
$("the-button").addEventListener("click", async () => {
|
||||||
const btn = $("the-button");
|
const btn = $("the-button");
|
||||||
btn.disabled = true;
|
btn.disabled = true;
|
||||||
|
$("share-controls").hidden = true;
|
||||||
|
currentShareText = "";
|
||||||
try {
|
try {
|
||||||
const r = await api("POST", "/api/press");
|
const r = await api("POST", "/api/press");
|
||||||
game.deadline = r.deadline;
|
game.deadline = r.deadline;
|
||||||
|
currentShareText = `I pushed the button at ${formatPrecise(r.press.remaining_ms)}.`;
|
||||||
$("press-result").textContent =
|
$("press-result").textContent =
|
||||||
`You pressed in the ${r.press.zone} zone with ${formatPrecise(r.press.remaining_ms)} remaining: +${r.press.points} points`;
|
`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();
|
await loadMe();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
$("press-result").textContent = e.message;
|
$("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) => {
|
$("register-form").addEventListener("submit", async (ev) => {
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
$("register-error").textContent = "";
|
$("register-error").textContent = "";
|
||||||
|
|||||||
@@ -27,6 +27,20 @@
|
|||||||
<section id="button-section">
|
<section id="button-section">
|
||||||
<button id="the-button" class="zone-green" disabled>PRESS</button>
|
<button id="the-button" class="zone-green" disabled>PRESS</button>
|
||||||
<p id="press-result" aria-live="polite"></p>
|
<p id="press-result" aria-live="polite"></p>
|
||||||
|
<div id="share-controls" hidden>
|
||||||
|
<p>Share your press:</p>
|
||||||
|
<div class="share-links">
|
||||||
|
<a id="share-facebook" class="share-link" target="_blank" rel="noopener noreferrer">Facebook</a>
|
||||||
|
<a id="share-x" class="share-link" target="_blank" rel="noopener noreferrer">X</a>
|
||||||
|
<a id="share-bluesky" class="share-link" target="_blank" rel="noopener noreferrer">Bluesky</a>
|
||||||
|
</div>
|
||||||
|
<label for="mastodon-instance">Mastodon instance</label>
|
||||||
|
<div class="share-links">
|
||||||
|
<input id="mastodon-instance" type="url" value="https://mastodon.social" aria-label="Mastodon instance URL">
|
||||||
|
<a id="share-mastodon" class="share-link" target="_blank" rel="noopener noreferrer">Share on Mastodon</a>
|
||||||
|
</div>
|
||||||
|
<p id="share-error" class="error" aria-live="polite"></p>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="register-section" hidden>
|
<section id="register-section" hidden>
|
||||||
|
|||||||
@@ -102,6 +102,29 @@ input, form button {
|
|||||||
padding: 0.4rem 0.8rem;
|
padding: 0.4rem 0.8rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.share-links {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
gap: 0.5rem;
|
||||||
|
margin: 0.5rem 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-link {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 0.45rem 0.8rem;
|
||||||
|
border: 1px solid #bbb;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #fff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.share-link:hover, .share-link:focus-visible { background: #666; }
|
||||||
|
.share-link[aria-disabled="true"] { opacity: 0.5; pointer-events: none; }
|
||||||
|
#mastodon-instance { max-width: 100%; }
|
||||||
|
#share-controls label { display: block; }
|
||||||
|
|
||||||
.error { color: var(--red); }
|
.error { color: var(--red); }
|
||||||
|
|
||||||
#rules { text-align: left; font-size: 0.9rem; color: #ccc; }
|
#rules { text-align: left; font-size: 0.9rem; color: #ccc; }
|
||||||
|
|||||||
Reference in New Issue
Block a user