From 73d6a08c075a91fa3fbc9837cd70c4dedbc5bb0e Mon Sep 17 00:00:00 2001 From: you Date: Wed, 18 Mar 2026 22:57:15 +0000 Subject: [PATCH] Fix nav bar auto-hide leaking to other pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit navTimeout was local to init() — destroy() couldn't clear it, so the 4s timeout would fire after navigation and hide the nav on other pages. Now uses module-scoped _navCleanup; destroy clears timeout and removes mousemove/touchstart/click listeners from live page element. --- public/live.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/public/live.js b/public/live.js index 3f4709f..052321c 100644 --- a/public/live.js +++ b/public/live.js @@ -12,6 +12,7 @@ let soundEnabled = false; let showGhostHops = localStorage.getItem('live-ghost-hops') !== 'false'; let _onResize = null; + let _navCleanup = null; // === VCR State Machine === const VCR = { @@ -540,14 +541,15 @@ setInterval(updateTimeline, 5000); // Auto-hide nav - let navTimeout = null; const topNav = document.querySelector('.top-nav'); if (topNav) { topNav.style.position = 'fixed'; topNav.style.width = '100%'; topNav.style.zIndex = '1100'; } + _navCleanup = { timeout: null, fn: null }; function showNav() { if (topNav) topNav.classList.remove('nav-autohide'); - clearTimeout(navTimeout); - navTimeout = setTimeout(() => { if (topNav) topNav.classList.add('nav-autohide'); }, 4000); + clearTimeout(_navCleanup.timeout); + _navCleanup.timeout = setTimeout(() => { if (topNav) topNav.classList.add('nav-autohide'); }, 4000); } + _navCleanup.fn = showNav; const livePage = document.querySelector('.live-page'); if (livePage) { livePage.addEventListener('mousemove', showNav); @@ -1000,6 +1002,16 @@ if (_onResize) { window.removeEventListener('resize', _onResize); window.removeEventListener('orientationchange', _onResize); } const topNav = document.querySelector('.top-nav'); if (topNav) { topNav.classList.remove('nav-autohide'); topNav.style.position = ''; topNav.style.width = ''; topNav.style.zIndex = ''; } + if (_navCleanup) { + clearTimeout(_navCleanup.timeout); + const livePage = document.querySelector('.live-page'); + if (livePage && _navCleanup.fn) { + livePage.removeEventListener('mousemove', _navCleanup.fn); + livePage.removeEventListener('touchstart', _navCleanup.fn); + livePage.removeEventListener('click', _navCleanup.fn); + } + _navCleanup = null; + } nodesLayer = pathsLayer = animLayer = heatLayer = null; nodeMarkers = {}; nodeData = {}; recentPaths = [];