[feat](trx-frontend-http): set the squelch on the spectrum, in dB
CI / lint (push) Successful in 2m19s
CI / test (push) Successful in 8m41s
CI / frontend (push) Failing after 31s
CI / reuse (push) Successful in 2s

The threshold is in dB, and since the squelch fix that is the scale the
spectrum axis and the S-meter are labelled in — so the control belongs
on the plot, at the level it gates.  A dashed line spans the spectrum at
its threshold with a grip that reads it out, dragged like the bandwidth
edges, green while the signal is above it and amber while it gates.
Arrow keys move it a dB at a time for anyone not using a mouse.

The audio row keeps a compact version: the dB, an indicator lit from the
same meter the DSP compares against, Auto, and an enable toggle that no
longer doubles as the level.  The slider ran 0-100% over that dB range,
which gave the operator a number with nothing on screen to relate it to,
and zero meant "disabled", so turning the squelch off to listen threw
the threshold away.  Auto now says which level it picked.

Two things the browser could only show once it was on the plot: the grip
landed underneath the split control at the right edge, which swallowed
its pointer, and dragging to the foot of the axis hid the line — and the
grip with it — instead of pinning it where it could be dragged back.

The fixture could not exercise any of this: /audio answered 404, which
hides the audio row and the control inside it, and the status carried no
filter block, which is what tells the client the rig has a squelch at
all.  Both now look like an SDR, and the spectrum test drives the line.

Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
sjg
2026-08-03 23:20:19 +02:00
parent 25b9c31c9b
commit aefd36c4b1
6 changed files with 524 additions and 199 deletions
@@ -1845,6 +1845,106 @@ small { color: var(--text-muted); }
color: var(--text-muted);
line-height: 1;
}
/* Squelch: a threshold in dB, the unit the spectrum's own axis is labelled in,
with a dot showing whether the gate is passing audio right now. The old
percentage was a number with nothing on screen to relate it to. */
.sql-control {
display: inline-flex;
align-items: center;
gap: 0.35rem;
color: var(--text-muted);
font-size: 0.82rem;
white-space: nowrap;
}
.sql-title {
font-weight: 700;
letter-spacing: 0.02em;
}
.sql-state {
width: 0.5rem;
height: 0.5rem;
border-radius: 50%;
flex-shrink: 0;
background: color-mix(in srgb, var(--text-muted) 45%, transparent);
transition: background var(--dur-fast) var(--ease-standard),
box-shadow var(--dur-fast) var(--ease-standard);
}
.sql-state[data-state="open"] {
background: var(--status-ok);
box-shadow: 0 0 0 0.14rem color-mix(in srgb, var(--status-ok) 25%, transparent);
}
.sql-state[data-state="closed"] {
background: var(--accent-yellow);
box-shadow: 0 0 0 0.14rem color-mix(in srgb, var(--accent-yellow) 22%, transparent);
}
.sql-db {
display: inline-flex;
align-items: baseline;
gap: 0.2rem;
}
.sql-db input {
width: 3.4rem;
height: 1.5rem;
min-height: 0;
padding: 0 0.3rem;
font-size: 0.78rem;
font-variant-numeric: tabular-nums;
text-align: right;
border: 1px solid var(--border-light);
border-radius: 4px;
background: var(--input-bg);
color: var(--text);
}
.sql-db-unit {
font-size: 0.68rem;
}
.sql-control button[aria-pressed="true"] {
border-color: color-mix(in srgb, var(--accent-green) 55%, var(--border-light));
color: var(--accent-text);
}
/* The line is the control: it spans the plot at its threshold and carries its
own grip, so the level is set where the noise it has to clear is visible. */
.spectrum-squelch-line {
position: absolute;
left: 0;
right: 0;
height: 0;
/* Above the overlays that share the plot: the split control sits at the
right edge on z-index 9 and would otherwise swallow the grip's pointer. */
z-index: 10;
border-top: 1px dashed color-mix(in srgb, var(--accent-yellow) 75%, transparent);
pointer-events: none;
}
.spectrum-squelch-line[data-state="open"] {
border-top-color: color-mix(in srgb, var(--status-ok) 80%, transparent);
}
.spectrum-squelch-grip {
position: absolute;
/* Clear of the split control's column so the two never sit on top of each
other, whatever height the threshold is at. */
right: 3.6rem;
top: -0.72rem;
padding: 0.05rem 0.35rem;
border-radius: 3px;
border: 1px solid color-mix(in srgb, var(--accent-yellow) 60%, var(--border-light));
background: color-mix(in srgb, var(--card-bg) 88%, transparent);
color: var(--text);
font-size: 0.62rem;
font-weight: 700;
font-variant-numeric: tabular-nums;
line-height: 1.3;
cursor: ns-resize;
pointer-events: auto;
user-select: none;
touch-action: none;
}
.spectrum-squelch-line[data-state="open"] .spectrum-squelch-grip {
border-color: color-mix(in srgb, var(--status-ok) 60%, var(--border-light));
}
.spectrum-squelch-grip:focus-visible {
outline: 2px solid var(--accent-text);
outline-offset: 1px;
}
.sql-auto-btn {
font-size: 0.68rem;
padding: 0 5px;