diff --git a/src/renderer-vod-hover.ts b/src/renderer-vod-hover.ts index a57793b..f754d6e 100644 --- a/src/renderer-vod-hover.ts +++ b/src/renderer-vod-hover.ts @@ -21,6 +21,20 @@ let pendingHoverVodId: string | null = null; const HOVER_DEBOUNCE_MS = 220; const FRAME_INTERVAL_MS = 600; const FRAMES_TO_CYCLE = 4; +// Bounded cache — each storyboard data URL is ~50-200 KB, so an +// unbounded cache could balloon to hundreds of MB on a long browsing +// session through a streamer with thousands of VODs. FIFO eviction +// keeps the working set fresh without manual cleanup. +const MAX_CLIENT_STORYBOARD_CACHE = 100; + +function rememberStoryboard(vodId: string, sb: VodStoryboard | null): void { + vodStoryboardClientCache.set(vodId, sb); + if (vodStoryboardClientCache.size > MAX_CLIENT_STORYBOARD_CACHE) { + // Map iterator is insertion-ordered — first key is the oldest. + const oldestKey = vodStoryboardClientCache.keys().next().value as string | undefined; + if (oldestKey !== undefined) vodStoryboardClientCache.delete(oldestKey); + } +} function ensureVodHoverHandlersBound(): void { const grid = document.getElementById('vodGrid'); @@ -85,7 +99,7 @@ async function activateHoverPreview(card: HTMLElement, vodId: string): Promise