diff --git a/tests/test_video_wishlist_clear.py b/tests/test_video_wishlist_clear.py index 6e154a75..01bd1863 100644 --- a/tests/test_video_wishlist_clear.py +++ b/tests/test_video_wishlist_clear.py @@ -143,3 +143,12 @@ def test_nav_badge_uses_the_endpoint_total_not_a_partial_sum(): assert "refreshBadge();" in sc and "refreshBadge();" in syc assert "state.counts.movie + state.counts.episode" not in _JS # old partial-total math gone assert "/api/video/wishlist/counts" in _JS # the endpoint is the source + + +def test_nav_badge_polls_for_server_side_wishlist_changes(): + # a finished download removes its wishlist item server-side and fires no frontend event, + # so the badge must poll the count to stay honest (faster while downloads are active). + assert "function scheduleBadgePoll(" in _JS + assert "_vdpgAnyActive" in _JS # polls quicker while downloads run + assert "document.hidden" in _JS # paused when the tab is hidden + assert "scheduleBadgePoll();" in _JS # started from init diff --git a/webui/static/video/video-wishlist.js b/webui/static/video/video-wishlist.js index 953295da..da63413f 100644 --- a/webui/static/video/video-wishlist.js +++ b/webui/static/video/video-wishlist.js @@ -600,11 +600,25 @@ function onShown(e) { if (e && e.detail === PAGE_ID) { state.page = 1; load(); refreshYtCount(); } } + // The nav badge also has to track wishlist changes that happen SERVER-SIDE — when a + // download finishes it removes its item from the wishlist, and that fires no frontend + // 'changed' event. So poll the authoritative count: quicker while downloads are active + // (the downloads page exposes _vdpgAnyActive), slower when idle, paused when hidden. + function scheduleBadgePoll() { + var active = (typeof window._vdpgAnyActive === 'function') && window._vdpgAnyActive(); + if (scheduleBadgePoll._t) clearTimeout(scheduleBadgePoll._t); + scheduleBadgePoll._t = setTimeout(function () { + if (!document.hidden) refreshBadge(); + scheduleBadgePoll(); + }, active ? 8000 : 30000); + } + function init() { wire(); document.addEventListener('soulsync:video-page-shown', onShown); refreshBadge(); refreshYtCount(); + scheduleBadgePoll(); } if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init);