diff --git a/client/app.js b/client/app.js index 805b422..f2436a9 100644 --- a/client/app.js +++ b/client/app.js @@ -15,6 +15,41 @@ const els = { discordStart: document.getElementById("discordStart"), }; +function defaultApiBase() { + // 1) URL query override: …/index.html?api=http://host:9080 + try { + const qs = new URLSearchParams(window.location.search); + const qApi = qs.get("api"); + if (qApi) return qApi.replace(/\/+$/, ""); + } catch {} + + // 2) Meta override in index.html: + const m = document.querySelector('meta[name="gc-api-base"]'); + if (m && m.content) return m.content.replace(/\/+$/, ""); + + // 3) Heuristic from frontend origin + try { + const u = new URL(window.location.href); + const proto = u.protocol; + const host = u.hostname; // no port + const portStr = u.port; // "" if default (80/443) + const bracketHost = host.includes(":") ? `[${host}]` : host; // IPv6-safe + + const port = portStr ? parseInt(portStr, 10) : null; + let apiPort = port; + + // Known frontend→API mappings + if (port === 8082) apiPort = 8080; + else if (port === 9082) apiPort = 9080; + else if (port) apiPort = Math.max(1, port - 2); // generic “minus two” fallback + + return apiPort ? `${proto}//${bracketHost}:${apiPort}` : `${proto}//${bracketHost}`; + } catch { + return window.location.origin.replace(/\/+$/, ""); + } +} + + const LS_KEY = "gc_client_config_v1"; const POSTS_KEY = "gc_posts_index_v1"; @@ -33,7 +68,17 @@ function saveConfig(c){ localStorage.setItem(LS_KEY, JSON.stringify(c)); Object. function getPosts(){ try { return JSON.parse(localStorage.getItem(POSTS_KEY)) ?? []; } catch { return []; } } function setPosts(v){ localStorage.setItem(POSTS_KEY, JSON.stringify(v)); renderPosts(); } function norm(u){ return (u||"").replace(/\/+$/,""); } -function applyConfig(){ els.shardUrl.value = cfg.url ?? location.origin; els.bearer.value = cfg.bearer ?? ""; els.passphrase.value = cfg.passphrase ?? ""; } +function applyConfig() { + // If no URL saved yet, detect a sensible default and persist it + if (!cfg.url) { + const detected = defaultApiBase(); // uses ?api=…, , or port heuristic + cfg.url = detected; + try { localStorage.setItem(LS_KEY, JSON.stringify(cfg)); } catch {} + } + els.shardUrl.value = cfg.url; + els.bearer.value = cfg.bearer ?? ""; + els.passphrase.value = cfg.passphrase ?? ""; +} async function checkHealth() { if (!cfg.url) return; els.health.textContent = "Checking…"; @@ -151,8 +196,18 @@ async function delServer(p) { } async function discordStart() { + // Last-resort auto-fill if user didn’t hit Save + if (!cfg.url) { + const derived = defaultApiBase(); + if (derived) { + cfg.url = derived; + try { localStorage.setItem(LS_KEY, JSON.stringify(cfg)); } catch {} + els.shardUrl.value = derived; + } + } if (!cfg.url) { alert("Set shard URL first."); return; } - const r = await fetch(cfg.url + "/v1/auth/discord/start", { headers: { "X-GC-3P-Assent":"1" }}); + + const r = await fetch(cfg.url + "/v1/auth/discord/start", { headers: { "X-GC-3P-Assent": "1" }}); if (!r.ok) { alert("Discord SSO not available"); return; } const j = await r.json(); location.href = j.url; diff --git a/client/index.html b/client/index.html index 35263d3..e35f7d1 100644 --- a/client/index.html +++ b/client/index.html @@ -4,6 +4,9 @@