[fix](trx-frontend-http): focus longest qso map paths
Let users click longest-QSO cards to isolate a single contact path on the map and click again to restore all visible contact paths. Also remove the extra inner panel styling from decode map tooltips so the popup renders as a single container. Verification: node --check src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js Verification: git diff --check -- src/trx-client/trx-frontend/trx-frontend-http/assets/web/app.js src/trx-client/trx-frontend/trx-frontend-http/assets/web/style.css Co-authored-by: OpenAI Codex <codex@openai.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -3796,6 +3796,7 @@ const MAP_QSO_SUMMARY_LIMIT = 5;
|
||||
const stationMarkers = new Map();
|
||||
const locatorMarkers = new Map();
|
||||
const decodeContactPaths = new Map();
|
||||
let selectedMapQsoKey = null;
|
||||
const mapMarkers = new Set();
|
||||
const DEFAULT_MAP_SOURCE_FILTER = { ais: true, vdes: true, aprs: true, bookmark: false, ft8: true, wspr: true };
|
||||
const mapFilter = { ...DEFAULT_MAP_SOURCE_FILTER };
|
||||
@@ -4490,11 +4491,22 @@ function ensureDecodeContactPathRendered(entry) {
|
||||
if (typeof entry.line.bringToBack === "function") entry.line.bringToBack();
|
||||
}
|
||||
|
||||
function decodeContactPathBaseVisible(entry) {
|
||||
return mapDecodeContactPathsEnabled
|
||||
&& decodeLocatorPathVisibility(entry.sourceGrid)
|
||||
&& decodeLocatorPathVisibility(entry.targetGrid);
|
||||
}
|
||||
|
||||
function syncDecodeContactPathVisibility() {
|
||||
if (selectedMapQsoKey) {
|
||||
const selectedEntry = decodeContactPaths.get(selectedMapQsoKey);
|
||||
if (!selectedEntry || !decodeContactPathBaseVisible(selectedEntry)) {
|
||||
selectedMapQsoKey = null;
|
||||
}
|
||||
}
|
||||
for (const entry of decodeContactPaths.values()) {
|
||||
const visible = mapDecodeContactPathsEnabled
|
||||
&& decodeLocatorPathVisibility(entry.sourceGrid)
|
||||
&& decodeLocatorPathVisibility(entry.targetGrid);
|
||||
const visible = decodeContactPathBaseVisible(entry)
|
||||
&& (!selectedMapQsoKey || entry.pathKey === selectedMapQsoKey);
|
||||
if (!visible) {
|
||||
clearDecodeContactPathRender(entry);
|
||||
continue;
|
||||
@@ -6073,6 +6085,7 @@ function rebuildDecodeContactPaths() {
|
||||
const prev = decodeContactPaths.get(key);
|
||||
if (prev && prev.tsMs > msg.tsMs) continue;
|
||||
decodeContactPaths.set(key, {
|
||||
pathKey: key,
|
||||
source: msg.source,
|
||||
target: msg.target,
|
||||
sourceGrid: msg.sourceGrid,
|
||||
@@ -6098,8 +6111,7 @@ function renderMapQsoSummary() {
|
||||
const entries = Array.from(decodeContactPaths.values())
|
||||
.filter((entry) => entry
|
||||
&& Number.isFinite(entry.distanceKm)
|
||||
&& decodeLocatorPathVisibility(entry.sourceGrid)
|
||||
&& decodeLocatorPathVisibility(entry.targetGrid))
|
||||
&& decodeContactPathBaseVisible(entry))
|
||||
.sort((a, b) => {
|
||||
const distanceDelta = Number(b.distanceKm) - Number(a.distanceKm);
|
||||
if (Math.abs(distanceDelta) > 0.001) return distanceDelta;
|
||||
@@ -6107,6 +6119,10 @@ function renderMapQsoSummary() {
|
||||
})
|
||||
.slice(0, MAP_QSO_SUMMARY_LIMIT);
|
||||
|
||||
if (selectedMapQsoKey && !entries.some((entry) => entry.pathKey === selectedMapQsoKey)) {
|
||||
selectedMapQsoKey = null;
|
||||
}
|
||||
|
||||
if (entries.length === 0) {
|
||||
const empty = document.createElement("div");
|
||||
empty.className = "map-qso-summary-empty";
|
||||
@@ -6117,8 +6133,15 @@ function renderMapQsoSummary() {
|
||||
|
||||
const fragment = document.createDocumentFragment();
|
||||
entries.forEach((entry, index) => {
|
||||
const card = document.createElement("article");
|
||||
const card = document.createElement("button");
|
||||
card.type = "button";
|
||||
card.className = "map-qso-card";
|
||||
card.classList.toggle("is-selected", entry.pathKey === selectedMapQsoKey);
|
||||
card.setAttribute("aria-pressed", entry.pathKey === selectedMapQsoKey ? "true" : "false");
|
||||
card.addEventListener("click", () => {
|
||||
selectedMapQsoKey = selectedMapQsoKey === entry.pathKey ? null : entry.pathKey;
|
||||
syncDecodeContactPathVisibility();
|
||||
});
|
||||
|
||||
const head = document.createElement("div");
|
||||
head.className = "map-qso-card-head";
|
||||
|
||||
@@ -1329,6 +1329,8 @@ small { color: var(--text-muted); }
|
||||
}
|
||||
.map-qso-card {
|
||||
display: flex;
|
||||
appearance: none;
|
||||
width: 100%;
|
||||
flex-direction: column;
|
||||
gap: 0.5rem;
|
||||
min-width: 0;
|
||||
@@ -1336,6 +1338,21 @@ small { color: var(--text-muted); }
|
||||
border-radius: 0.75rem;
|
||||
border: 1px solid color-mix(in srgb, var(--border-light) 74%, transparent);
|
||||
background: color-mix(in srgb, var(--card-bg) 78%, transparent);
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
transition: border-color 120ms ease, background 120ms ease, transform 120ms ease, box-shadow 120ms ease;
|
||||
}
|
||||
.map-qso-card:hover {
|
||||
border-color: color-mix(in srgb, var(--accent-green) 38%, var(--border-light));
|
||||
background: color-mix(in srgb, var(--card-bg) 70%, transparent);
|
||||
}
|
||||
.map-qso-card.is-selected {
|
||||
border-color: color-mix(in srgb, var(--accent-green) 62%, var(--border-light));
|
||||
background: color-mix(in srgb, var(--accent-green) 10%, var(--card-bg));
|
||||
box-shadow: 0 0 0 1px color-mix(in srgb, var(--accent-green) 18%, transparent);
|
||||
}
|
||||
.map-qso-card:active {
|
||||
transform: translateY(1px);
|
||||
}
|
||||
.map-qso-card-head {
|
||||
display: flex;
|
||||
@@ -1934,11 +1951,8 @@ body.map-fake-fullscreen-active {
|
||||
max-width: 26rem;
|
||||
max-height: min(22rem, 60vh);
|
||||
overflow: auto;
|
||||
padding: 0.55rem 0.65rem;
|
||||
border-radius: 0.65rem;
|
||||
background: color-mix(in srgb, var(--card-bg) 84%, transparent);
|
||||
padding: 0.1rem 0.05rem 0.05rem;
|
||||
color: var(--text);
|
||||
box-shadow: 0 10px 24px rgba(0, 0, 0, 0.28);
|
||||
}
|
||||
.decode-locator-tip-title {
|
||||
color: var(--accent-yellow);
|
||||
|
||||
Reference in New Issue
Block a user