This commit is contained in:
2026-10-23 10:23:03 -04:00
parent 84b363b863
commit c4d9d1b86c
10 changed files with 625 additions and 22 deletions
+44 -2
View File
@@ -3,9 +3,18 @@
const TOKEN_KEY = "thebutton-token";
const $ = (id) => document.getElementById(id);
const callbackParams = new URLSearchParams(window.location.hash.slice(1));
const callbackError = callbackParams.get("oidc_error");
if (callbackError) {
history.replaceState(null, "", window.location.pathname + window.location.search);
}
let game = null; // latest /api/state payload
let clockOffset = 0; // serverTime - clientTime
let token = localStorage.getItem(TOKEN_KEY);
let oidcMode = false;
let oidcLoginUrl = "";
let oidcRegisterUrl = "";
let statsLoaded = false;
let subscribed = false;
let currentShareText = "";
@@ -238,12 +247,19 @@ function renderSections() {
const id = button.dataset.section;
button.hidden = !available[id];
button.setAttribute("aria-expanded", String(selectedSection === id));
if (id === "account-section") button.textContent = token ? "Your score" : "Log in / Join";
if (id === "account-section") button.textContent = token ? "Your score" : oidcMode ? "Sign in" : "Log in / Join";
});
document.querySelectorAll("[data-panel]").forEach((panel) => {
panel.hidden = panel.id !== selectedSection;
});
$("mailing-list").hidden = !token || subscribed;
$("register-section").hidden = !!token || oidcMode;
$("oidc-login-section").hidden = !!token || !oidcMode;
if (oidcMode) {
$("oidc-login-link").href = oidcLoginUrl;
$("oidc-register-link").href = oidcRegisterUrl || "#";
$("oidc-register-link").hidden = !oidcRegisterUrl;
}
$("chat-form").hidden = !token;
$("chat-login").hidden = !!token;
$("section-hint").hidden = selectedSection !== null;
@@ -434,7 +450,6 @@ async function refreshState() {
function updateButton() {
$("the-button").disabled = !token || !game || game.ended;
$("register-section").hidden = !!token;
$("me-section").hidden = !token;
$("my-subscribed").hidden = !token || !subscribed;
renderSections();
@@ -936,6 +951,32 @@ $("the-button").addEventListener("click", async () => {
$("mastodon-instance").addEventListener("input", updateShareLinks);
async function loadAuthConfig() {
try {
const response = await fetch("/api/config", { cache: "no-store" });
if (!response.ok) return;
const config = await response.json();
oidcMode = config.auth_mode === "oidc";
if (oidcMode) {
token = null;
localStorage.removeItem(TOKEN_KEY);
}
oidcLoginUrl = config.login_url || "";
oidcRegisterUrl = config.register_url || "";
renderSections();
if (callbackError) {
const errorMessage = callbackError === "access_denied"
? "This account is not authorized to play The Button."
: callbackError === "account_link_required"
? "A game account with this name already exists. Ask a moderator to link your eom.dev identity so your scores are preserved."
: "Sign-in didn't complete. Please try again.";
$("oidc-error").textContent = errorMessage;
}
} catch {
// Keep the local login UI available if the server has no OIDC config endpoint.
}
}
$("register-form").addEventListener("submit", async (ev) => {
ev.preventDefault();
$("register-error").textContent = "";
@@ -991,6 +1032,7 @@ $("subscribe-form").addEventListener("submit", async (ev) => {
});
(async function init() {
await loadAuthConfig();
await refreshState();
await loadMe();
requestAnimationFrame(tick);
+7
View File
@@ -164,6 +164,13 @@
</div>
</div>
<div id="oidc-login-section" class="panel-body" hidden>
<p class="fine-print">Your account is managed by eom.dev. Sign in with the same identity used for your other services.</p>
<div class="form-actions"><a id="oidc-login-link" class="primary-button" href="/auth/oidc/login">Sign in with eom.dev <span aria-hidden="true">&rarr;</span></a></div>
<p id="oidc-error" class="error" role="status"></p>
<p class="fine-print">New here? <a id="oidc-register-link" href="https://lists.eom.dev/accounts/register/">Create an eom.dev account</a>.</p>
</div>
<div id="me-section" hidden>
<header class="panel-header score-header">
<div><p class="eyebrow">YOUR PART IN THE EXPERIMENT</p>