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 2c4a0e4..66a6e63 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 @@ -3181,15 +3181,57 @@ function clearSpectrumCanvas() { ctx.fillRect(0, 0, spectrumCanvas.width, spectrumCanvas.height); } +function formatOverlayPs(ps) { + const padded = String(ps ?? "") + .slice(0, 8) + .padEnd(8, " "); + return padded.replaceAll(" ", "_"); +} + +function formatOverlayPi(pi) { + return pi != null + ? `PI 0x${pi.toString(16).toUpperCase().padStart(4, "0")}` + : "PI --"; +} + +function formatOverlayPty(pty) { + return pty != null ? `PTY ${pty}` : "PTY --"; +} + +async function copyRdsPsToClipboard() { + const ps = lastSpectrumData?.rds?.program_service?.trim(); + if (!ps) { + showHint("No RDS PS", 1200); + return; + } + try { + await navigator.clipboard.writeText(ps); + showHint(`Copied ${ps}`, 1200); + } catch (_) { + showHint("Clipboard failed", 1500); + } +} + +if (rdsPsOverlay) { + rdsPsOverlay.addEventListener("click", () => { copyRdsPsToClipboard(); }); +} +const rdsPsValueEl = document.getElementById("rds-ps"); +if (rdsPsValueEl) { + rdsPsValueEl.addEventListener("click", () => { copyRdsPsToClipboard(); }); +} + function updateRdsPsOverlay(rds) { // Overview strip overlay if (rdsPsOverlay) { const ps = rds?.program_service?.trim(); if (ps) { - rdsPsOverlay.textContent = ps; + rdsPsOverlay.innerHTML = + `${escapeMapHtml(formatOverlayPs(ps))}` + + `${escapeMapHtml(formatOverlayPi(rds?.pi))} ยท ${escapeMapHtml(formatOverlayPty(rds?.pty))}`; positionRdsPsOverlay(); - rdsPsOverlay.style.display = "block"; + rdsPsOverlay.style.display = "flex"; } else { + rdsPsOverlay.innerHTML = ""; rdsPsOverlay.style.display = "none"; } } 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 e81d66f..e911fb3 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 @@ -418,7 +418,7 @@ small { color: var(--text-muted); } margin-bottom: 0; padding: 0.25rem 0 0.15rem; position: relative; - z-index: 3; + z-index: 6; } .header-main { display: inline-flex; @@ -427,7 +427,7 @@ small { color: var(--text-muted); } max-width: min(100%, 46rem); padding: 0.35rem 0.8rem 0.4rem 0.45rem; margin-left: -0.3rem; - transform: translateY(-2px); + transform: translateY(-10px); border-radius: 0.95rem; background: color-mix(in srgb, var(--card-bg) 56%, transparent); backdrop-filter: blur(12px) saturate(125%); @@ -455,10 +455,8 @@ small { color: var(--text-muted); } left: 50%; transform: translate(-50%, 0); z-index: 5; - pointer-events: none; - font-family: 'DSEG14 Classic', monospace; - font-size: clamp(1rem, 2.2vw, 1.45rem); - letter-spacing: 0.08em; + pointer-events: auto; + cursor: pointer; color: var(--text-heading); padding: 0.22rem 0.6rem 0.16rem; border: 1px solid color-mix(in srgb, var(--border-light) 72%, transparent); @@ -470,11 +468,33 @@ small { color: var(--text-muted); } 0 8px 18px color-mix(in srgb, #000000 16%, transparent), inset 0 1px 0 color-mix(in srgb, #ffffff 10%, transparent); text-shadow: 0 1px 10px color-mix(in srgb, var(--bg) 68%, transparent); - white-space: nowrap; + display: flex; + flex-direction: column; + align-items: center; + gap: 0.08rem; + text-align: center; max-width: min(88vw, 22rem); overflow: hidden; text-overflow: ellipsis; } +.rds-ps { + cursor: pointer; +} +.rds-ps-main { + display: block; + font-family: 'DSEG14 Classic', monospace; + font-size: clamp(1rem, 2.2vw, 1.45rem); + letter-spacing: 0.08em; + white-space: pre; +} +.rds-ps-meta { + display: block; + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; + font-size: clamp(0.58rem, 1.1vw, 0.78rem); + letter-spacing: 0.04em; + color: var(--text-muted); + white-space: nowrap; +} .overview-toolbar { display: flex; align-items: center;