From bc3fac9a3f9cbf1fa5e8085f10687101d15d3f8f Mon Sep 17 00:00:00 2001 From: GitHub Copilot Date: Thu, 26 Feb 2026 20:29:20 +0000 Subject: [PATCH] fix: refresh all dashboard thumbnails on tab return and add periodic fallback MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two issues caused stale thumbnails on the dashboard: 1. Returning to the dashboard tab only processed the (empty) refresh queue — it never triggered a full refresh. Now, if the dashboard was hidden for more than 3 seconds, all ETags are cleared and refreshAll() is called so every tile fetches a fresh screenshot. 2. If SSE activity events were missed (e.g. during reconnect), tiles would never update until the next terminal activity. Added a 10s periodic fallback that calls refreshAll() when the dashboard is visible, ensuring tiles stay reasonably current even without SSE. --- webterm/server.go | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/webterm/server.go b/webterm/server.go index 431b6d5..392b093 100644 --- a/webterm/server.go +++ b/webterm/server.go @@ -1486,9 +1486,24 @@ func (s *LocalServer) handleRoot(w http.ResponseWriter, r *http.Request) { return document.visibilityState === 'visible'; } + let dashboardHiddenAt = 0; + function onDashboardFocusChanged() { if (dashboardCanRequestScreenshots()) { - processRefreshQueue(); + // If the dashboard was hidden for more than a few seconds, + // clear ETags and refresh all tiles so the user sees current state. + const away = dashboardHiddenAt ? (Date.now() - dashboardHiddenAt) : 0; + dashboardHiddenAt = 0; + if (away > 3000) { + for (const key in etagBySlug) { + delete etagBySlug[key]; + } + refreshAll(); + } else { + processRefreshQueue(); + } + } else { + dashboardHiddenAt = Date.now(); } } @@ -1496,6 +1511,13 @@ func (s *LocalServer) handleRoot(w http.ResponseWriter, r *http.Request) { window.addEventListener('focus', onDashboardFocusChanged); window.addEventListener('blur', onDashboardFocusChanged); + // Periodic fallback: refresh all tiles every 10s in case SSE events were missed. + setInterval(() => { + if (dashboardCanRequestScreenshots()) { + refreshAll(); + } + }, 10000); + function processRefreshQueue() { if (refreshQueue.length === 0 || !dashboardCanRequestScreenshots()) return;