Hide meaningless SDR power control #19

Merged
sjg merged 2 commits from fix/sdr-power-header-alignment into main 2026-08-01 11:26:02 +02:00
3 changed files with 17 additions and 31 deletions
@@ -334,13 +334,18 @@ function applyCapabilities(caps) {
const txAudioBtn = document.getElementById("tx-audio-btn"); const txAudioBtn = document.getElementById("tx-audio-btn");
const txVolSlider = document.getElementById("tx-vol"); const txVolSlider = document.getElementById("tx-vol");
const txVolControl = txVolSlider ? txVolSlider.closest(".vol-label") : null; const txVolControl = txVolSlider ? txVolSlider.closest(".vol-label") : null;
const hasPowerControl = !caps.filter_controls;
if (txPowerCol) { if (txPowerCol) {
txPowerCol.style.display = ""; txPowerCol.style.display = (caps.tx || hasPowerControl || caps.lockable) ? "" : "none";
const label = txPowerCol.querySelector(".label span"); const label = txPowerCol.querySelector(".label span");
if (label) label.textContent = caps.tx ? "Transmit / Power" : "Power / Tuning"; if (label) {
label.textContent = caps.tx && hasPowerControl ? "Transmit / Power"
: caps.tx ? "Transmit / Tuning"
: hasPowerControl ? "Power / Tuning" : "Tuning";
}
} }
if (pttBtn) pttBtn.style.display = caps.tx ? "" : "none"; if (pttBtn) pttBtn.style.display = caps.tx ? "" : "none";
if (powerBtn) powerBtn.style.display = ""; if (powerBtn) powerBtn.style.display = hasPowerControl ? "" : "none";
if (lockBtn) lockBtn.style.display = caps.lockable ? "" : "none"; if (lockBtn) lockBtn.style.display = caps.lockable ? "" : "none";
if (txMetersRow) txMetersRow.style.display = caps.tx ? "" : "none"; if (txMetersRow) txMetersRow.style.display = caps.tx ? "" : "none";
if (txAudioBtn) txAudioBtn.style.display = caps.tx ? "" : "none"; if (txAudioBtn) txAudioBtn.style.display = caps.tx ? "" : "none";
@@ -1231,7 +1231,7 @@ small { color: var(--text-muted); }
} }
.top-bar-actions { .top-bar-actions {
display: flex; display: flex;
align-items: center; align-items: flex-start;
gap: 0.45rem 0.6rem; gap: 0.45rem 0.6rem;
min-width: 0; min-width: 0;
flex-wrap: wrap; flex-wrap: wrap;
@@ -1406,7 +1406,7 @@ small { color: var(--text-muted); }
.header-rig-switch { .header-rig-switch {
display: grid; display: grid;
grid-template-columns: minmax(0, 1fr); grid-template-columns: minmax(0, 1fr);
align-items: center; align-items: start;
gap: 0.35rem; gap: 0.35rem;
} }
.header-rig-summary { .header-rig-summary {
@@ -1428,6 +1428,7 @@ small { color: var(--text-muted); }
background: var(--input-bg); background: var(--input-bg);
color: var(--text); color: var(--text);
font-size: 0.85rem; font-size: 0.85rem;
align-self: start;
} }
.header-rig-switch button { .header-rig-switch button {
height: 2rem; height: 2rem;
@@ -2948,8 +2949,7 @@ button.is-active {
#ptt-btn.is-active { background: var(--accent-red) !important; border-color: var(--accent-red) !important; color: white !important; } #ptt-btn.is-active { background: var(--accent-red) !important; border-color: var(--accent-red) !important; color: white !important; }
.is-busy { cursor: progress !important; opacity: 0.68; } .is-busy { cursor: progress !important; opacity: 0.68; }
.operator-layout-picker { .operator-layout-picker {
display: inline-grid; display: inline-flex;
grid-template-columns: auto auto;
align-items: center; align-items: center;
min-height: 2rem; min-height: 2rem;
padding-left: 0.6rem; padding-left: 0.6rem;
@@ -2979,17 +2979,6 @@ button.is-active {
} }
.operator-layout-picker:focus-within { border-color: var(--accent-green); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-green) 20%, transparent); } .operator-layout-picker:focus-within { border-color: var(--accent-green); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent-green) 20%, transparent); }
.operator-layout-picker select:focus-visible { outline: 0; } .operator-layout-picker select:focus-visible { outline: 0; }
.operator-layout-description {
grid-column: 1 / -1;
max-width: 22rem;
padding: 0 0.55rem 0.35rem 0;
color: var(--text-muted);
font-size: var(--fs-xs);
font-weight: 500;
letter-spacing: 0;
line-height: 1.35;
text-transform: none;
}
.advanced-radio-controls { .advanced-radio-controls {
margin-top: var(--space-3); margin-top: var(--space-3);
border: 1px solid color-mix(in srgb, var(--border-light) 75%, transparent); border: 1px solid color-mix(in srgb, var(--border-light) 75%, transparent);
@@ -126,10 +126,10 @@
}; };
const layouts = { const layouts = {
compact: { label: "Compact", description: "Essential tuning and audio controls", advanced: false, preferredTab: "main" }, compact: { label: "Compact", advanced: false, preferredTab: "main" },
broadcast: { label: "Broadcast", description: "WFM, RDS, stereo and interference monitoring", unavailable: "Broadcast requires an enumerated WFM-capable receiver", advanced: false, preferredTab: "main", capability: "broadcast" }, broadcast: { label: "Broadcast", unavailable: "Broadcast requires an enumerated WFM-capable receiver", advanced: false, preferredTab: "main", capability: "broadcast" },
digital: { label: "Digital", description: "Decoder status, messages and background decoding", unavailable: "Digital requires a compatible rig mode and an available decoder", advanced: false, preferredTab: "digital-modes", capability: "digital" }, digital: { label: "Digital", unavailable: "Digital requires a compatible rig mode and an available decoder", advanced: false, preferredTab: "digital-modes", capability: "digital" },
full: { label: "Full controls", description: "Every control supported by the selected rig", advanced: true, preferredTab: "main" }, full: { label: "Full controls", advanced: true, preferredTab: "main" },
}; };
const layoutCapabilities = { broadcast: false, digital: false }; const layoutCapabilities = { broadcast: false, digital: false };
let activeRigId = null; let activeRigId = null;
@@ -151,12 +151,6 @@
return unavailable.length ? `Unavailable: ${unavailable.map(layout => layout.unavailable).join("; ")}.` : ""; return unavailable.length ? `Unavailable: ${unavailable.map(layout => layout.unavailable).join("; ")}.` : "";
} }
function updateLayoutDescription(layout) {
const description = document.getElementById("operator-layout-description");
if (!description) return;
description.textContent = [layout.description, unavailableLayoutMessage()].filter(Boolean).join(" · ");
}
function refreshLayoutOptions() { function refreshLayoutOptions() {
const select = document.getElementById("operator-layout-select"); const select = document.getElementById("operator-layout-select");
if (!select) return; if (!select) return;
@@ -170,7 +164,6 @@
select.value = available ? previous : "compact"; select.value = available ? previous : "compact";
if (!available && previous !== "compact") api.applyLayout("compact", { persist: false }); if (!available && previous !== "compact") api.applyLayout("compact", { persist: false });
select.title = unavailableLayoutMessage(); select.title = unavailableLayoutMessage();
updateLayoutDescription(layouts[select.value] || layouts.compact);
} }
api.setLayoutCapabilities = function setLayoutCapabilities(capabilities = {}) { api.setLayoutCapabilities = function setLayoutCapabilities(capabilities = {}) {
@@ -202,7 +195,6 @@
if (options.persist !== false) localStorage.setItem(layoutStorageKey(), document.body.dataset.operatorLayout); if (options.persist !== false) localStorage.setItem(layoutStorageKey(), document.body.dataset.operatorLayout);
const details = document.getElementById("advanced-radio-controls"); const details = document.getElementById("advanced-radio-controls");
if (details) details.open = layout.advanced; if (details) details.open = layout.advanced;
updateLayoutDescription(layout);
if (options.navigate && typeof window.navigateToTab === "function") { if (options.navigate && typeof window.navigateToTab === "function") {
window.navigateToTab(layout.preferredTab); window.navigateToTab(layout.preferredTab);
} }
@@ -213,7 +205,7 @@
if (actions && !document.getElementById("operator-layout-select")) { if (actions && !document.getElementById("operator-layout-select")) {
const label = document.createElement("label"); const label = document.createElement("label");
label.className = "operator-layout-picker"; label.className = "operator-layout-picker";
label.innerHTML = '<span class="visually-hidden">Operator layout</span><select id="operator-layout-select" aria-label="Operator layout" aria-describedby="operator-layout-description"></select><span id="operator-layout-description" class="operator-layout-description"></span>'; label.innerHTML = '<span class="visually-hidden">Operator layout</span><select id="operator-layout-select" aria-label="Operator layout"></select>';
const select = label.querySelector("select"); const select = label.querySelector("select");
const savedLayout = savedLayoutName(); const savedLayout = savedLayoutName();
actions.insertBefore(label, actions.firstChild); actions.insertBefore(label, actions.firstChild);