diff --git a/meshview/templates/nodelist.html b/meshview/templates/nodelist.html index 593b0b0..c68c1ba 100644 --- a/meshview/templates/nodelist.html +++ b/meshview/templates/nodelist.html @@ -26,7 +26,6 @@ table { width: max-content; /* table keeps its natural width */ min-width: 100%; /* won't shrink smaller than viewport */ } - th, td { padding: 10px; border: 1px solid #333; @@ -104,21 +103,6 @@ select, .export-btn, .search-box, .clear-btn { font-weight: bold; color: white; } -.node-status { - margin-left: 10px; - padding: 2px 8px; - border-radius: 12px; - border: 1px solid #2a6a8a; - background: #0d2a3a; - color: #9fd4ff; - font-size: 0.9em; - display: inline-block; - opacity: 0; - transition: opacity 0.15s ease-in-out; -} -.node-status.active { - opacity: 1; -} /* Favorite stars */ .favorite-star { @@ -251,7 +235,6 @@ select, .export-btn, .search-box, .clear-btn { Showing 0 nodes - @@ -322,11 +305,6 @@ let allNodes = []; let sortColumn = "short_name"; let sortAsc = true; let showOnlyFavorites = false; -let favoritesSet = new Set(); -let isBusy = false; -let statusHideTimer = null; -let statusShownAt = 0; -const minStatusMs = 300; const headers = document.querySelectorAll("thead th"); const keyMap = [ @@ -342,38 +320,22 @@ function debounce(fn, delay = 250) { }; } -function nextFrame() { - return new Promise(resolve => requestAnimationFrame(() => resolve())); -} - -function loadFavorites() { +function getFavorites() { const favorites = localStorage.getItem('nodelist_favorites'); - if (!favorites) { - favoritesSet = new Set(); - return; - } - - try { - const parsed = JSON.parse(favorites); - favoritesSet = new Set(Array.isArray(parsed) ? parsed : []); - } catch (err) { - console.warn("Failed to parse favorites, resetting.", err); - favoritesSet = new Set(); - } + return favorites ? JSON.parse(favorites) : []; } -function saveFavorites() { - localStorage.setItem('nodelist_favorites', JSON.stringify([...favoritesSet])); +function saveFavorites(favs) { + localStorage.setItem('nodelist_favorites', JSON.stringify(favs)); } function toggleFavorite(nodeId) { - if (favoritesSet.has(nodeId)) { - favoritesSet.delete(nodeId); - } else { - favoritesSet.add(nodeId); - } - saveFavorites(); + let favs = getFavorites(); + const idx = favs.indexOf(nodeId); + if (idx >= 0) favs.splice(idx, 1); + else favs.push(nodeId); + saveFavorites(favs); } function isFavorite(nodeId) { - return favoritesSet.has(nodeId); + return getFavorites().includes(nodeId); } function timeAgoFromMs(msTimestamp) { @@ -395,7 +357,6 @@ function timeAgoFromMs(msTimestamp) { document.addEventListener("DOMContentLoaded", async function() { await loadTranslationsNodelist(); - loadFavorites(); const tbody = document.getElementById("node-table-body"); const mobileList = document.getElementById("mobile-node-list"); @@ -406,7 +367,6 @@ document.addEventListener("DOMContentLoaded", async function() { const firmwareFilter = document.getElementById("firmware-filter"); const searchBox = document.getElementById("search-box"); const countSpan = document.getElementById("node-count"); - const statusSpan = document.getElementById("node-status"); const exportBtn = document.getElementById("export-btn"); const clearBtn = document.getElementById("clear-btn"); const favoritesBtn = document.getElementById("favorites-btn"); @@ -414,8 +374,6 @@ document.addEventListener("DOMContentLoaded", async function() { let lastIsMobile = (window.innerWidth <= 768); try { - setStatus("Loading nodes…"); - await nextFrame(); const res = await fetch("/api/nodes?days_active=3"); if (!res.ok) throw new Error("Failed to fetch nodes"); @@ -446,13 +404,11 @@ document.addEventListener("DOMContentLoaded", async function() { populateFilters(allNodes); applyFilters(); // ensures initial sort + render uses same path updateSortIcons(); - setStatus(""); } catch (err) { tbody.innerHTML = `