[feat](trx-frontend-http): intercept freq/mode changes for virtual channels
When on a non-primary (virtual) channel, redirect freq and mode changes to the channel metadata API instead of the server: - vchan.js: add vchanIsOnVirtual(), vchanSetChannelFreq/Mode(); expose window.vchanInterceptMode() hook; wrap window.setRigFrequency so all callers (jog, freq input, bookmarks, spectrum click) are automatically redirected without modification - app.js: check vchanInterceptMode() in applyModeFromPicker() before posting /set_mode - bookmarks.js: check vchanInterceptMode() for mode in bmApply(); setRigFrequency() redirect is automatic via the vchan.js wrapper; bandwidth and decoder toggles still apply regardless of channel Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Signed-off-by: Stan Grams <sjg@haxx.space>
This commit is contained in:
@@ -3119,6 +3119,10 @@ async function applyModeFromPicker() {
|
||||
modeEl.disabled = true;
|
||||
showHint("Setting mode…");
|
||||
try {
|
||||
if (typeof vchanInterceptMode === "function" && await vchanInterceptMode(mode)) {
|
||||
showHint("Channel mode set", 1500);
|
||||
return;
|
||||
}
|
||||
await postPath(`/set_mode?mode=${encodeURIComponent(mode)}`);
|
||||
showHint("Mode set", 1500);
|
||||
if (mode.toUpperCase() === "WFM") {
|
||||
|
||||
@@ -277,7 +277,11 @@ async function bmDelete(id) {
|
||||
|
||||
async function bmApply(bm) {
|
||||
try {
|
||||
const onVirtual = typeof vchanInterceptMode === "function"
|
||||
&& await vchanInterceptMode(bm.mode);
|
||||
if (!onVirtual) {
|
||||
await postPath("/set_mode?mode=" + encodeURIComponent(bm.mode));
|
||||
}
|
||||
if (typeof modeEl !== "undefined" && modeEl) {
|
||||
modeEl.value = String(bm.mode || "").toUpperCase();
|
||||
}
|
||||
@@ -290,12 +294,14 @@ async function bmApply(bm) {
|
||||
syncBandwidthInput(bm.bandwidth_hz);
|
||||
}
|
||||
}
|
||||
// setRigFrequency is wrapped by vchan.js to redirect to the channel API
|
||||
// when on a virtual channel, so this call works correctly in both cases.
|
||||
if (typeof setRigFrequency === "function") {
|
||||
await setRigFrequency(bm.freq_hz);
|
||||
} else {
|
||||
await postPath("/set_freq?hz=" + bm.freq_hz);
|
||||
}
|
||||
// Toggle decoders when in DIG mode
|
||||
// Toggle decoders when in DIG mode.
|
||||
if (bm.mode === "DIG" && Array.isArray(bm.decoders)) {
|
||||
const statusResp = await fetch("/status");
|
||||
if (statusResp.ok) {
|
||||
|
||||
@@ -168,3 +168,70 @@ function vchanApplyCapabilities(caps) {
|
||||
if (!row) return;
|
||||
row.style.display = (caps && caps.filter_controls) ? "" : "none";
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Freq / mode interception
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Returns true when the active channel is a non-primary (virtual) channel.
|
||||
function vchanIsOnVirtual() {
|
||||
if (!vchanActiveId || vchanChannels.length === 0) return false;
|
||||
return vchanActiveId !== vchanChannels[0].id;
|
||||
}
|
||||
|
||||
async function vchanSetChannelFreq(freqHz) {
|
||||
if (!vchanRigId || !vchanActiveId) return;
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`/channels/${encodeURIComponent(vchanRigId)}/${encodeURIComponent(vchanActiveId)}/freq`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ freq_hz: Math.round(freqHz) }),
|
||||
}
|
||||
);
|
||||
if (!resp.ok) console.warn("vchan: set freq failed", resp.status);
|
||||
} catch (e) {
|
||||
console.error("vchan: set freq error", e);
|
||||
}
|
||||
}
|
||||
|
||||
async function vchanSetChannelMode(mode) {
|
||||
if (!vchanRigId || !vchanActiveId) return;
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`/channels/${encodeURIComponent(vchanRigId)}/${encodeURIComponent(vchanActiveId)}/mode`,
|
||||
{
|
||||
method: "PUT",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ mode }),
|
||||
}
|
||||
);
|
||||
if (!resp.ok) console.warn("vchan: set mode failed", resp.status);
|
||||
} catch (e) {
|
||||
console.error("vchan: set mode error", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Called by app.js (applyModeFromPicker) and bookmarks.js (bmApply) before
|
||||
// sending /set_mode to the server. Returns true if the change was handled
|
||||
// by the virtual channel (caller should skip the server request).
|
||||
window.vchanInterceptMode = async function(mode) {
|
||||
if (!vchanIsOnVirtual()) return false;
|
||||
await vchanSetChannelMode(mode);
|
||||
return true;
|
||||
};
|
||||
|
||||
// Wrap setRigFrequency (defined in app.js, loaded before this file) so that
|
||||
// frequency changes are redirected to the active virtual channel instead of
|
||||
// the server when on a non-primary channel.
|
||||
(function() {
|
||||
const _orig = window.setRigFrequency;
|
||||
window.setRigFrequency = async function(freqHz) {
|
||||
if (vchanIsOnVirtual()) {
|
||||
await vchanSetChannelFreq(freqHz);
|
||||
return;
|
||||
}
|
||||
if (typeof _orig === "function") return _orig(freqHz);
|
||||
};
|
||||
})();
|
||||
|
||||
Reference in New Issue
Block a user