Let JS own the live status labels instead of sharing them with data-i18n
#chain-status-label and #draw-label carried a data-i18n attribute *and* were written from live state by app.js, so a language switch had both mechanisms fighting over them: applyStaticTranslations reset each to its static default and the next poll put the real value back. On the draw label that was a flicker. On the status bar it was a false statement — with the connection down, the bar went back to claiming "connecting" until a further fetch failed, up to a full poll interval later. The attribute is gone from both. The status bar is now rendered from remembered state (last payload, plus whether we're in the offline state) rather than straight from the response that triggered it, so a language switch repaints it correctly and immediately, with no fetch involved. logout() also stops wiping the chosen language: localStorage.clear() took plm_lang with it, dropping the user back to the browser-detected default on the one screen where they'd have to go find the switcher again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+34
-2
@@ -159,11 +159,36 @@ const CHAIN_STATUS_KEYS = {
|
|||||||
paying_out: 'chain.status.paying_out',
|
paying_out: 'chain.status.paying_out',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// The bar is rendered from remembered state rather than straight from the
|
||||||
|
// response that triggered it, so a language switch can repaint it immediately
|
||||||
|
// instead of waiting for the next poll. That wait used to make it lie: with the
|
||||||
|
// connection down, switching language reset the label to "connecting" until a
|
||||||
|
// further fetch failed.
|
||||||
|
let lastChainData = null;
|
||||||
|
let chainOffline = false;
|
||||||
|
|
||||||
function updateChainStatusBar(data) {
|
function updateChainStatusBar(data) {
|
||||||
|
lastChainData = data;
|
||||||
|
chainOffline = false;
|
||||||
|
renderChainStatusBar();
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderChainStatusBar() {
|
||||||
const dot = document.getElementById('chain-status-dot');
|
const dot = document.getElementById('chain-status-dot');
|
||||||
const label = document.getElementById('chain-status-label');
|
const label = document.getElementById('chain-status-label');
|
||||||
const block = document.getElementById('chain-block');
|
const block = document.getElementById('chain-block');
|
||||||
|
|
||||||
|
if (chainOffline) {
|
||||||
|
dot.className = 'status-dot status-offline';
|
||||||
|
label.textContent = t('chain.connectionLost');
|
||||||
|
return; // block height deliberately left showing its last known value
|
||||||
|
}
|
||||||
|
if (lastChainData === null) {
|
||||||
|
label.textContent = t('chain.connecting');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const data = lastChainData;
|
||||||
|
|
||||||
// The dot's color/pulse only distinguishes waiting/open/drawing (that's all
|
// The dot's color/pulse only distinguishes waiting/open/drawing (that's all
|
||||||
// the CSS defines) — closing and paying_out both pulse like drawing, they
|
// the CSS defines) — closing and paying_out both pulse like drawing, they
|
||||||
// just get their own text label below.
|
// just get their own text label below.
|
||||||
@@ -189,8 +214,8 @@ const STALE_AFTER_FAILURES = 2;
|
|||||||
let consecutiveFetchFailures = 0;
|
let consecutiveFetchFailures = 0;
|
||||||
|
|
||||||
function showConnectionLost() {
|
function showConnectionLost() {
|
||||||
document.getElementById('chain-status-dot').className = 'status-dot status-offline';
|
chainOffline = true;
|
||||||
document.getElementById('chain-status-label').textContent = t('chain.connectionLost');
|
renderChainStatusBar();
|
||||||
}
|
}
|
||||||
|
|
||||||
function noteFetchOutcome(ok) {
|
function noteFetchOutcome(ok) {
|
||||||
@@ -575,7 +600,12 @@ function resetToLoggedOutUI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function logout() {
|
function logout() {
|
||||||
|
// The chosen language is a device preference, not session state — clearing it
|
||||||
|
// on logout would drop the user back to the browser-detected default on the
|
||||||
|
// very screen where they'd have to find the switcher again.
|
||||||
|
const lang = localStorage.getItem(LANG_STORAGE_KEY);
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
|
if (lang) localStorage.setItem(LANG_STORAGE_KEY, lang);
|
||||||
resetToLoggedOutUI();
|
resetToLoggedOutUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -774,6 +804,7 @@ function connectRoundEvents() {
|
|||||||
// those are built from server data + t() rather than fixed markup.
|
// those are built from server data + t() rather than fixed markup.
|
||||||
function onLanguageChange() {
|
function onLanguageChange() {
|
||||||
renderBetButton();
|
renderBetButton();
|
||||||
|
renderChainStatusBar(); // repaints from remembered state, without waiting for the next poll
|
||||||
if (token) {
|
if (token) {
|
||||||
refreshRound();
|
refreshRound();
|
||||||
refreshMe();
|
refreshMe();
|
||||||
@@ -787,5 +818,6 @@ function onLanguageChange() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderBetButton();
|
renderBetButton();
|
||||||
|
renderChainStatusBar();
|
||||||
connectRoundEvents();
|
connectRoundEvents();
|
||||||
initAuthState();
|
initAuthState();
|
||||||
|
|||||||
@@ -59,7 +59,10 @@
|
|||||||
<div class="chain-bar" id="chain-bar">
|
<div class="chain-bar" id="chain-bar">
|
||||||
<span class="chain-status-pill">
|
<span class="chain-status-pill">
|
||||||
<span class="status-dot" id="chain-status-dot"></span>
|
<span class="status-dot" id="chain-status-dot"></span>
|
||||||
<span id="chain-status-label" data-i18n="chain.connecting">Connecting…</span>
|
<!-- No data-i18n on this one or on #draw-label below: both are written by
|
||||||
|
app.js from live state, and letting applyStaticTranslations() also own
|
||||||
|
them made a language switch flash (or, here, assert) a stale value. -->
|
||||||
|
<span id="chain-status-label">Connecting…</span>
|
||||||
</span>
|
</span>
|
||||||
<span class="chain-bar-right">
|
<span class="chain-bar-right">
|
||||||
<span class="chain-block mono" id="chain-block">—</span>
|
<span class="chain-block mono" id="chain-block">—</span>
|
||||||
@@ -157,7 +160,7 @@
|
|||||||
|
|
||||||
<div class="draw-state" id="draw-state">
|
<div class="draw-state" id="draw-state">
|
||||||
<div class="draw-spinner"></div>
|
<div class="draw-spinner"></div>
|
||||||
<div class="draw-label" id="draw-label" data-i18n="draw.defaultLabel">Estrazione del vincitore in corso…</div>
|
<div class="draw-label" id="draw-label">Drawing the winner…</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="hidden" id="draw-result"></div>
|
<div class="hidden" id="draw-result"></div>
|
||||||
|
|||||||
Reference in New Issue
Block a user