fix: waterfall monitor state desync on frequency change and restart

When changing frequency with shared monitor active, the monitor retune
could be silently dropped if a previous retune was still in-flight,
leaving the UI stuck on "Starting <freq>". After stopping and restarting
the waterfall, the monitor button could remain disabled because
_startingMonitor was never reset and _monitorRetuneTimer was not cleared.

- Cancel in-flight monitor start when queuing a new retune
- Always clear _pendingSharedMonitorRearm in started handler
- Clear _monitorRetuneTimer and reset _startingMonitor in stop()
This commit is contained in:
Smittix
2026-02-23 21:35:34 +00:00
parent 365333d425
commit 2e6bb8882f
+18 -3
View File
@@ -1797,9 +1797,14 @@ const Waterfall = (function () {
function _queueMonitorRetune(delayMs) { function _queueMonitorRetune(delayMs) {
if (!_monitoring) return; if (!_monitoring) return;
clearTimeout(_monitorRetuneTimer); clearTimeout(_monitorRetuneTimer);
// If a monitor start is already in-flight, invalidate it so the
// new retune can proceed once the finally-block resets the flag.
if (_startingMonitor) {
_audioConnectNonce += 1;
}
_monitorRetuneTimer = setTimeout(() => { _monitorRetuneTimer = setTimeout(() => {
_startMonitorInternal({ wasRunningWaterfall: false, retuneOnly: true }).catch(() => {}); _startMonitorInternal({ wasRunningWaterfall: false, retuneOnly: true }).catch(() => {});
}, delayMs); }, _startingMonitor ? Math.max(delayMs, 250) : delayMs);
} }
function _isSharedMonitorActive() { function _isSharedMonitorActive() {
@@ -2453,9 +2458,11 @@ const Waterfall = (function () {
} }
_setStatus(`Streaming ${_startMhz.toFixed(4)} - ${_endMhz.toFixed(4)} MHz`); _setStatus(`Streaming ${_startMhz.toFixed(4)} - ${_endMhz.toFixed(4)} MHz`);
_setVisualStatus('RUNNING'); _setVisualStatus('RUNNING');
if (_pendingSharedMonitorRearm && _monitoring && _monitorSource === 'waterfall') { if (_pendingSharedMonitorRearm) {
_pendingSharedMonitorRearm = false; _pendingSharedMonitorRearm = false;
_queueMonitorRetune(120); if (_monitoring && _monitorSource === 'waterfall') {
_queueMonitorRetune(120);
}
} }
} else if (msg.status === 'tuned') { } else if (msg.status === 'tuned') {
if (_onRetuneRequired(msg)) return; if (_onRetuneRequired(msg)) return;
@@ -3021,9 +3028,17 @@ const Waterfall = (function () {
async function stop({ keepStatus = false } = {}) { async function stop({ keepStatus = false } = {}) {
stopScan('Scan stopped', { silent: keepStatus }); stopScan('Scan stopped', { silent: keepStatus });
clearTimeout(_retuneTimer); clearTimeout(_retuneTimer);
clearTimeout(_monitorRetuneTimer);
_clearWsFallbackTimer(); _clearWsFallbackTimer();
_wsOpened = false; _wsOpened = false;
_pendingSharedMonitorRearm = false; _pendingSharedMonitorRearm = false;
// Reset in-flight monitor start flag so the button is not left
// disabled after a waterfall stop/restart cycle.
if (_startingMonitor) {
_audioConnectNonce += 1;
_startingMonitor = false;
_syncMonitorButtons();
}
if (_ws) { if (_ws) {
try { try {