diff --git a/webterm/server.go b/webterm/server.go index 9396ca5..70426fe 100644 --- a/webterm/server.go +++ b/webterm/server.go @@ -28,8 +28,9 @@ const ( wsReadTimeout = 90 * time.Second wsPingPeriod = 30 * time.Second stdinWriteTimeout = 2 * time.Second - screenshotCacheSeconds = 300 * time.Millisecond - maxScreenshotCacheTTL = 20 * time.Second + screenshotCacheSeconds = 300 * time.Millisecond + maxScreenshotCacheTTL = 20 * time.Second + screenshotEvictInterval = 60 * time.Second ) type ServerOptions struct { @@ -1336,13 +1337,22 @@ func (s *LocalServer) handleRoot(w http.ResponseWriter, r *http.Request) { } catch (_) {} } + const activeSparklineURLBySlug = {}; function refreshSparklines() { if (!composeMode) return; for (const tile of tiles) { const card = cardsBySlug[tile.slug]; - if (card && card.sparkline) { - card.sparkline.src = '/cpu-sparkline.svg?container=' + encodeURIComponent(tile.slug) + '&width=80&height=16&_t=' + Date.now(); - } + if (!card || !card.sparkline) continue; + const slug = tile.slug; + const url = '/cpu-sparkline.svg?container=' + encodeURIComponent(slug) + '&width=80&height=16&_t=' + Date.now(); + fetch(url).then(r => r.ok ? r.blob() : null).then(blob => { + if (!blob) return; + const prev = activeSparklineURLBySlug[slug]; + const objectURL = URL.createObjectURL(blob); + activeSparklineURLBySlug[slug] = objectURL; + if (card.sparkline) card.sparkline.src = objectURL; + if (prev) URL.revokeObjectURL(prev); + }).catch(() => {}); } } @@ -1379,6 +1389,20 @@ func (s *LocalServer) handleRoot(w http.ResponseWriter, r *http.Request) { URL.revokeObjectURL(activeObjectURLBySlug[key]); delete activeObjectURLBySlug[key]; } + for (const key in activeSparklineURLBySlug) { + URL.revokeObjectURL(activeSparklineURLBySlug[key]); + delete activeSparklineURLBySlug[key]; + } + for (const key in thumbnailCache) { + delete thumbnailCache[key]; + } + for (const key in pendingRefresh) { + clearTimeout(pendingRefresh[key]); + delete pendingRefresh[key]; + } + for (const key in etagBySlug) { + delete etagBySlug[key]; + } if (tiles.length === 0) { grid.innerHTML = '