()
| 9105 | |
| 9106 | // OPTIMIZATION: Reduce dashboard refresh frequency (was 15s, now 20s) |
| 9107 | // Background sync runs every 15s, so 20s refresh is sufficient |
| 9108 | autoRefreshIntervals.dashboard = setInterval(() => { |
| 9109 | if (currentTab === 'dashboard') { |
| 9110 | loadDashboardData(); |
| 9111 | } |
| 9112 | }, 20000); // Every 20 seconds when on dashboard (reduced from 15s) |
| 9113 | |
| 9114 | // Set up periodic update checking |
| 9115 | autoRefreshIntervals.updates = setInterval(() => { |
| 9116 | checkForUpdatesQuiet(); |
| 9117 | }, 300000); // Every 5 minutes |
| 9118 | |
| 9119 | // OPTIMIZATION: Defer initial update check (was 5s, now 30s) |
| 9120 | // Not critical for initial dashboard load |
| 9121 | setTimeout(() => { |
| 9122 | checkForUpdatesQuiet(); |
| 9123 | }, 30000); // Check 30 seconds after page load (deferred from 5s) |
| 9124 | |
| 9125 | setPwnStatusPollInterval(PWN_STATUS_POLL_INTERVAL); |
| 9126 | } |
| 9127 | |
| 9128 | function initializeMobileMenu() { |
| 9129 | const menuBtn = document.getElementById('mobile-menu-btn'); |
| 9130 | const mobileMenu = document.getElementById('mobile-menu'); |
| 9131 | |
| 9132 | if (menuBtn && mobileMenu) { |
| 9133 | menuBtn.addEventListener('click', () => { |
| 9134 | mobileMenu.classList.toggle('hidden'); |
| 9135 | }); |
| 9136 | } |
| 9137 | |
| 9138 | // Auto-collapse: switch between desktop nav and hamburger based on overflow |
| 9139 | const desktopNav = document.getElementById('desktop-nav'); |
| 9140 | if (!desktopNav || !menuBtn) return; |
| 9141 | |
| 9142 | function updateNavMode() { |
| 9143 | // Temporarily show desktop nav offscreen to measure natural width |
| 9144 | desktopNav.style.position = 'absolute'; |
| 9145 | desktopNav.style.visibility = 'hidden'; |
| 9146 | desktopNav.style.whiteSpace = 'nowrap'; |
| 9147 | desktopNav.classList.remove('hidden'); |
| 9148 | desktopNav.classList.add('flex'); |
| 9149 | |
| 9150 | // Sum widths of visible buttons |
| 9151 | let totalWidth = 0; |
| 9152 | const gap = 4; // gap-1 = 0.25rem = 4px |
| 9153 | let visibleCount = 0; |
| 9154 | for (const btn of desktopNav.children) { |
| 9155 | if (!btn.classList.contains('hidden')) { |
| 9156 | totalWidth += btn.scrollWidth; |
| 9157 | visibleCount++; |
| 9158 | } |
| 9159 | } |
| 9160 | totalWidth += Math.max(0, visibleCount - 1) * gap; |
| 9161 | |
| 9162 | // Reset temp styles |
| 9163 | desktopNav.style.position = ''; |
| 9164 | desktopNav.style.visibility = ''; |
no test coverage detected