From 3f4ebf18a8606bc2ea535a98b7ad276dcf631a5d Mon Sep 17 00:00:00 2001 From: TARS Date: Fri, 3 Jul 2026 20:13:24 +0200 Subject: [PATCH] fix(sidebar): refresh timestamp labels on tab return Add a dedicated visibilitychange hook for the 60s relative-time refresh poll so skipped hidden-tab ticks repaint immediately when the tab becomes visible, even when no streaming poll is active. --- static/sessions.js | 11 +++++++++-- tests/test_webui_external_refresh_frontend.py | 11 +++++++++++ 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/static/sessions.js b/static/sessions.js index 43321332..73560c49 100644 --- a/static/sessions.js +++ b/static/sessions.js @@ -4595,6 +4595,7 @@ const _activeSessionExternalRefreshMs = 30000; let _streamingPollTimer = null; let _sessionTimeRefreshTimer = null; let _streamingPollVisibilityHandler = null; +let _sessionTimeRefreshVisibilityHandler = null; let _activeSessionExternalRefreshTimer = null; let _activeSessionExternalRefreshInFlight = false; let _deferredActiveSessionExternalRefreshReason = ''; @@ -4646,11 +4647,17 @@ function stopStreamingPoll(){ function ensureSessionTimeRefreshPoll(){ if(_sessionTimeRefreshTimer) return; _sessionTimeRefreshTimer = setInterval(() => { - // Relative-time labels only matter when visible; the tab-shown refresh in - // startStreamingPoll re-renders the list (and its timestamps) on return. + // Relative-time labels only matter when visible; the visibilitychange + // handler below refreshes timestamps immediately when the tab is shown. if(typeof document !== 'undefined' && document.hidden) return; renderSessionListFromCache(); }, _sessionTimeRefreshMs); + if(typeof document !== 'undefined' && !_sessionTimeRefreshVisibilityHandler){ + _sessionTimeRefreshVisibilityHandler = () => { + if(!document.hidden) renderSessionListFromCache(); + }; + document.addEventListener('visibilitychange', _sessionTimeRefreshVisibilityHandler); + } } function _deferActiveSessionExternalRefresh(reason){ diff --git a/tests/test_webui_external_refresh_frontend.py b/tests/test_webui_external_refresh_frontend.py index 4d4ff68e..395c5737 100644 --- a/tests/test_webui_external_refresh_frontend.py +++ b/tests/test_webui_external_refresh_frontend.py @@ -79,6 +79,17 @@ def test_active_session_external_refresh_has_focus_and_visibility_hooks(): assert "ensureActiveSessionExternalRefreshPoll();" in SESSIONS_JS +def test_session_time_refresh_has_own_visibility_hook(): + """Skipped hidden-tab timestamp ticks must refresh immediately on return.""" + start = SESSIONS_JS.find("function ensureSessionTimeRefreshPoll()") + assert start != -1 + block = SESSIONS_JS[start:start + 900] + assert "_sessionTimeRefreshVisibilityHandler" in SESSIONS_JS + assert "document.addEventListener('visibilitychange', _sessionTimeRefreshVisibilityHandler);" in block + assert "if(!document.hidden) renderSessionListFromCache();" in block + assert "startStreamingPoll re-renders the list" not in block + + def test_session_list_external_refresh_uses_sse_invalidation_not_polling(): """New sessions should refresh the sidebar from server invalidation events.""" assert "async function refreshSessionList(reason='manual', opts={})" in SESSIONS_JS