From 06554ba172b1e726fbee70399de15ccd7cba8bbf Mon Sep 17 00:00:00 2001 From: dborup Date: Mon, 20 Jul 2026 07:11:43 +0200 Subject: [PATCH] feat: Domestic/Foreign filter on the Nodes page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The unfiltered node list is dominated by foreign-flagged nodes (#730 geo_filter classification) on deployments with heavy cross-border traffic — hard to see which of 1500+ listed nodes are actually local. Adds an All/Domestic/Foreign filter-group next to the existing Status filter, narrowing on each node's `foreign` boolean, persisted to localStorage like the other Nodes-page filters. --- public/nodes.js | 26 ++++ test-all.sh | 1 + test-nodes-geo-scope-filter.js | 226 +++++++++++++++++++++++++++++++++ 3 files changed, 253 insertions(+) create mode 100644 test-nodes-geo-scope-filter.js diff --git a/public/nodes.js b/public/nodes.js index 7613706d..dc2c449d 100644 --- a/public/nodes.js +++ b/public/nodes.js @@ -82,6 +82,11 @@ } let lastHeard = localStorage.getItem('meshcore-nodes-last-heard') || ''; let statusFilter = localStorage.getItem('meshcore-nodes-status-filter') || 'all'; + // 'all' | 'domestic' | 'foreign' — domestic/foreign split on the `foreign` + // flag (#730 geo_filter classification: self-reported GPS outside the + // configured box). The unfiltered node list can be dominated by foreign + // nodes, making it hard to see which ones are actually local. + let geoScope = localStorage.getItem('meshcore-nodes-geo-scope') || 'all'; let wsHandler = null; let detailMap = null; @@ -1236,6 +1241,9 @@ return getNodeStatus(role, lastMs) === statusFilter; }); } + // Geo scope filter (domestic vs foreign, #730 `foreign` flag) + if (geoScope === 'domestic') filtered = filtered.filter(n => !n.foreign); + else if (geoScope === 'foreign') filtered = filtered.filter(n => n.foreign); nodes = filtered; // Defensive filter: hide nodes with obviously corrupted data @@ -1304,6 +1312,11 @@ +
+ + + +