diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js index ffce0f6..706d687 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js @@ -3490,8 +3490,7 @@ async function switchRigFromSelect(selectEl) { if (typeof setSchedulerRig === "function") setSchedulerRig(lastActiveRigId); if (typeof setBackgroundDecodeRig === "function") setBackgroundDecodeRig(lastActiveRigId); if (typeof bmFetch === "function") bmFetch(document.getElementById("bm-category-filter")?.value || ""); - // Reconnect decode SSE so history is re-fetched with the new rig filter. - connectDecode(); + // Decode SSE and history are rig-independent — no reconnect needed. // Switch this session's rig and reconnect SSE to the new rig's // state channel. try { @@ -5026,13 +5025,30 @@ function syncDecodeContactPathVisibility() { updateMapPathsAnimationClass(); } -function setMapRadioPathTo(lat, lon, color, className = "aprs-radio-path") { +function _resolveReceiverLocation(rigIds) { + // Try to find location from the specific rig(s) that decoded this message + if (rigIds && rigIds.size) { + for (const rid of rigIds) { + const rig = serverRigs.find(r => r.remote === rid); + if (rig && rig.latitude != null && rig.longitude != null) { + return [rig.latitude, rig.longitude]; + } + } + } + // Fall back to active rig location + if (serverLat != null && serverLon != null) return [serverLat, serverLon]; + return null; +} + +function setMapRadioPathTo(lat, lon, color, className = "aprs-radio-path", rigIds) { clearMapRadioPath(); - if (!mapP2pRadioPathsEnabled || serverLat == null || serverLon == null || !Number.isFinite(lat) || !Number.isFinite(lon) || !aprsMap) { + if (!mapP2pRadioPathsEnabled || !Number.isFinite(lat) || !Number.isFinite(lon) || !aprsMap) { return; } + const src = _resolveReceiverLocation(rigIds); + if (!src) return; aprsRadioPath = L.polyline( - [[serverLat, serverLon], [lat, lon]], + [src, [lat, lon]], { color, opacity: 0.85, weight: 2, interactive: false, className } ).addTo(aprsMap); } @@ -5675,7 +5691,7 @@ function initAprsMap() { entry.track.addTo(aprsMap); } selectedAprsTrackCall = String(marker._aprsCall); - setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("aprs"), "aprs-radio-path"); + setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("aprs"), "aprs-radio-path", marker.__trxRigIds); return; } @@ -5687,7 +5703,7 @@ function initAprsMap() { refreshAisTrack(String(marker._aisMmsi), entry); selectedAisTrackMmsi = String(marker._aisMmsi); syncSelectedAisTrackVisibility(); - setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("ais"), "aprs-radio-path"); + setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("ais"), "aprs-radio-path", marker.__trxRigIds); return; } @@ -5696,18 +5712,20 @@ function initAprsMap() { const entry = vdesMarkers.get(String(marker._vdesKey)); if (!entry || !entry.msg) return; e.popup.setContent(buildVdesPopupHtml(entry.msg)); - setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("vdes"), "aprs-radio-path"); + setMapRadioPathTo(ll.lat, ll.lng, mapSourceColor("vdes"), "aprs-radio-path", marker.__trxRigIds); return; } - if (marker.__trxType === "bookmark" || marker.__trxType === "ft8" || marker.__trxType === "ft4" || marker.__trxType === "ft2" || marker.__trxType === "wspr") { + if (marker.__trxType === "ft8" || marker.__trxType === "ft4" || marker.__trxType === "ft2" || marker.__trxType === "wspr") { const center = locatorMarkerCenter(marker); if (center) { setSelectedLocatorMarker(marker); const lEntry = locatorEntryForMarker(marker); const lColor = lEntry ? locatorStyleForEntry(lEntry, locatorEntryCount(lEntry)).color : locatorFilterColor(marker.__trxType); - setMapRadioPathTo(center.lat, center.lon, lColor, "locator-radio-path"); + setMapRadioPathTo(center.lat, center.lon, lColor, "locator-radio-path", marker.__trxRigIds); } + } else if (marker.__trxType === "bookmark") { + setSelectedLocatorMarker(marker); } }); @@ -5978,9 +5996,11 @@ window.navigateToMapLocator = function(grid, preferredType = null) { if (center) { const targetZoom = Math.max(aprsMap.getZoom() || 0, 7); aprsMap.setView([center.lat, center.lon], targetZoom); - const fEntry = locatorEntryForMarker(marker); - const fColor = fEntry ? locatorStyleForEntry(fEntry, locatorEntryCount(fEntry)).color : locatorFilterColor(marker?.__trxType); - setMapRadioPathTo(center.lat, center.lon, fColor, "locator-radio-path"); + if (marker.__trxType !== "bookmark") { + const fEntry = locatorEntryForMarker(marker); + const fColor = fEntry ? locatorStyleForEntry(fEntry, locatorEntryCount(fEntry)).color : locatorFilterColor(marker?.__trxType); + setMapRadioPathTo(center.lat, center.lon, fColor, "locator-radio-path", marker.__trxRigIds); + } } setSelectedLocatorMarker(marker); if (typeof marker.openPopup === "function") marker.openPopup(); diff --git a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css index 341aff7..87a3ee9 100644 --- a/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css +++ b/src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css @@ -2606,16 +2606,44 @@ button:focus-visible, input:focus-visible, select:focus-visible { .signal-measure #sig-result { width: 100%; } - #spectrum-controls, + #spectrum-controls { + flex-direction: column; + align-items: stretch; + gap: 0.45rem; + padding-top: 0.45rem; + } #spectrum-bw-row, #spectrum-level-row { - display: grid; - grid-template-columns: minmax(0, 1fr); - justify-content: stretch; + display: flex; + flex-wrap: wrap; + gap: 0.35rem 0.4rem; } - #spectrum-controls { - gap: 0.5rem; - padding-top: 0.45rem; + #spectrum-bw-label, + #spectrum-floor-label, + #spectrum-peak-hold-label { + flex: 1 1 100%; + justify-content: space-between; + } + #spectrum-gamma-label { + flex: 1 1 100%; + justify-content: space-between; + } + #spectrum-gamma-input { + flex: 1 1 auto; + min-width: 3rem; + } + #spectrum-bw-input, + #spectrum-floor-input, + #overview-peak-hold { + flex: 1 1 auto; + min-width: 3rem; + box-sizing: border-box; + } + #spectrum-bw-set-btn, + #spectrum-bw-auto-btn, + #spectrum-bw-sweet-btn, + #spectrum-auto-btn { + flex: 1 1 auto; } .spectrum-edge-shift { width: 0.95rem; @@ -2630,24 +2658,6 @@ button:focus-visible, input:focus-visible, select:focus-visible { .spectrum-edge-shift-right { right: 0.2rem; } - #spectrum-bw-row, - #spectrum-level-row { - gap: 0.4rem; - } - #spectrum-bw-label, - #spectrum-floor-label, - #spectrum-gamma-label, - #spectrum-peak-hold-label { - width: 100%; - justify-content: space-between; - } - #spectrum-bw-input, - #spectrum-floor-input, - #overview-peak-hold { - width: 100%; - min-width: 0; - box-sizing: border-box; - } .aprs-controls, .ft8-controls, .cw-controls {