diff --git a/src/meshcore_hub/web/templates/map.html b/src/meshcore_hub/web/templates/map.html index 027c9fe..1c495d9 100644 --- a/src/meshcore_hub/web/templates/map.html +++ b/src/meshcore_hub/web/templates/map.html @@ -76,6 +76,12 @@ +
+ +
- 💬 - Chat -
-
- 📡 - Repeater -
-
- 🪧 - Room -
-
- 📍 - Other +
+ Node
@@ -146,6 +140,10 @@ // Maximum radius (km) from anchor point for bounds calculation const MAX_BOUNDS_RADIUS_KM = 20; + // Padding for fitBounds - more padding on mobile for tighter zoom + const isMobile = window.innerWidth < 768; + const BOUNDS_PADDING = isMobile ? [150, 150] : [100, 100]; + // Calculate distance between two points in km (Haversine formula) function getDistanceKm(lat1, lon1, lat2, lon2) { const R = 6371; // Earth's radius in km @@ -185,15 +183,6 @@ // formatRelativeTime is provided by /static/js/utils.js - // Get emoji marker based on node type - function getNodeEmoji(node) { - const type = normalizeType(node.adv_type); - if (type === 'chat') return '💬'; - if (type === 'repeater') return '📡'; - if (type === 'room') return '🪧'; - return '📍'; - } - // Get display name for node type function getTypeDisplay(node) { const type = normalizeType(node.adv_type); @@ -209,13 +198,12 @@ const relativeTime = formatRelativeTime(node.last_seen); const timeDisplay = relativeTime ? ` (${relativeTime})` : ''; - // Use logo for infrastructure nodes, emoji for others + // Use logo for infrastructure nodes, blue circle for others let iconHtml; if (node.is_infra) { iconHtml = `Infra`; } else { - const emoji = getNodeEmoji(node); - iconHtml = `${emoji}`; + iconHtml = `
`; } return L.divIcon({ @@ -246,10 +234,10 @@ const typeDisplay = getTypeDisplay(node); - // Use logo for infrastructure nodes, emoji for others + // Use logo for infrastructure nodes, blue circle for others const iconHtml = node.is_infra ? `Infra` - : getNodeEmoji(node); + : ``; return `
@@ -278,14 +266,19 @@ const categoryFilter = document.getElementById('filter-category').value; const typeFilter = document.getElementById('filter-type').value; const memberFilter = document.getElementById('filter-member').value; + const showChat = document.getElementById('show-chat').checked; // Filter nodes const filteredNodes = allNodes.filter(node => { + // Hide chat/companion nodes unless checkbox is checked + const nodeType = normalizeType(node.adv_type); + if (!showChat && nodeType === 'chat') return false; + // Category filter (infrastructure only) if (categoryFilter === 'infra' && !node.is_infra) return false; // Type filter (case-insensitive) - if (typeFilter && normalizeType(node.adv_type) !== typeFilter) return false; + if (typeFilter && nodeType !== typeFilter) return false; // Member filter - match node's member_id tag to selected member_id if (memberFilter) { @@ -340,7 +333,7 @@ } const bounds = L.latLngBounds(nodesToFit.map(n => [n.lat, n.lon])); - map.fitBounds(bounds, { padding: [100, 100] }); + map.fitBounds(bounds, { padding: BOUNDS_PADDING }); } else if (mapCenter.lat !== 0 || mapCenter.lon !== 0) { map.setView([mapCenter.lat, mapCenter.lon], 10); } @@ -376,6 +369,7 @@ document.getElementById('filter-category').value = ''; document.getElementById('filter-type').value = ''; document.getElementById('filter-member').value = ''; + document.getElementById('show-chat').checked = false; document.getElementById('show-labels').checked = false; updateLabelVisibility(); applyFilters(); @@ -396,6 +390,7 @@ document.getElementById('filter-category').addEventListener('change', applyFilters); document.getElementById('filter-type').addEventListener('change', applyFilters); document.getElementById('filter-member').addEventListener('change', applyFilters); + document.getElementById('show-chat').addEventListener('change', applyFilters); document.getElementById('show-labels').addEventListener('change', updateLabelVisibility); document.getElementById('clear-filters').addEventListener('click', clearFilters); @@ -435,14 +430,14 @@ const infraNodes = allNodes.filter(n => n.is_infra); if (infraNodes.length > 0) { const bounds = L.latLngBounds(infraNodes.map(n => [n.lat, n.lon])); - map.fitBounds(bounds, { padding: [100, 100] }); + map.fitBounds(bounds, { padding: BOUNDS_PADDING }); } else if (allNodes.length > 0) { // Use radius filter to exclude outliers const anchor = getAnchorPoint(allNodes); const nearbyNodes = getNodesWithinRadius(allNodes, anchor.lat, anchor.lon, MAX_BOUNDS_RADIUS_KM); const nodesToFit = nearbyNodes.length > 0 ? nearbyNodes : allNodes; const bounds = L.latLngBounds(nodesToFit.map(n => [n.lat, n.lon])); - map.fitBounds(bounds, { padding: [100, 100] }); + map.fitBounds(bounds, { padding: BOUNDS_PADDING }); } // Apply filters (won't re-center since we just did above) diff --git a/src/meshcore_hub/web/templates/node_detail.html b/src/meshcore_hub/web/templates/node_detail.html index 5e17c9f..58391aa 100644 --- a/src/meshcore_hub/web/templates/node_detail.html +++ b/src/meshcore_hub/web/templates/node_detail.html @@ -3,6 +3,7 @@ {% block title %}{{ network_name }} - Node Details{% endblock %} {% block extra_head %} +