mirror of
https://github.com/smittix/intercept.git
synced 2026-06-13 00:03:33 -07:00
Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 367048e853 | |||
| 406ca28304 | |||
| f889c53d92 | |||
| b0af1d16d2 |
+4
-1
@@ -2,11 +2,14 @@
|
|||||||
|
|
||||||
All notable changes to iNTERCEPT will be documented in this file.
|
All notable changes to iNTERCEPT will be documented in this file.
|
||||||
|
|
||||||
## [2.22.2] - 2026-02-23
|
## [2.22.3] - 2026-02-23
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
- Waterfall control panel rendered as unstyled text for up to 20 seconds on first visit — CSS is now loaded eagerly with the rest of the page assets
|
- Waterfall control panel rendered as unstyled text for up to 20 seconds on first visit — CSS is now loaded eagerly with the rest of the page assets
|
||||||
- WebSDR globe failed to render on first page load — initialization now waits for a layout frame before mounting the WebGL renderer, ensuring the container has non-zero dimensions
|
- WebSDR globe failed to render on first page load — initialization now waits for a layout frame before mounting the WebGL renderer, ensuring the container has non-zero dimensions
|
||||||
|
- Waterfall monitor audio took minutes to start — `_waitForPlayback` now only reports success on actual audio playback (`playing`/`timeupdate`), not from the WAV header alone (`loadeddata`/`canplay`)
|
||||||
|
- Waterfall monitor could not be stopped — `stopMonitor()` now pauses audio and updates the UI immediately instead of waiting for the backend stop request (which blocked for 1+ seconds during SDR process cleanup)
|
||||||
|
- Stopping the waterfall no longer shows a stale "WebSocket closed before ready" message — the `onclose` handler now detects intentional closes
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,19 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
# Application version
|
# Application version
|
||||||
VERSION = "2.22.2"
|
VERSION = "2.22.3"
|
||||||
|
|
||||||
# Changelog - latest release notes (shown on welcome screen)
|
# Changelog - latest release notes (shown on welcome screen)
|
||||||
CHANGELOG = [
|
CHANGELOG = [
|
||||||
{
|
{
|
||||||
"version": "2.22.2",
|
"version": "2.22.3",
|
||||||
"date": "February 2026",
|
"date": "February 2026",
|
||||||
"highlights": [
|
"highlights": [
|
||||||
"Waterfall control panel no longer shows as unstyled text on first visit",
|
"Waterfall control panel no longer shows as unstyled text on first visit",
|
||||||
"WebSDR globe renders correctly on first page load without requiring a refresh",
|
"WebSDR globe renders correctly on first page load without requiring a refresh",
|
||||||
|
"Waterfall monitor audio no longer takes minutes to start — playback detection now waits for real audio data instead of just the WAV header",
|
||||||
|
"Waterfall monitor stop is now instant — audio pauses and UI updates immediately instead of waiting for backend cleanup",
|
||||||
|
"Stopping the waterfall no longer shows a stale 'WebSocket closed before ready' message",
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "intercept"
|
name = "intercept"
|
||||||
version = "2.21.1"
|
version = "2.22.3"
|
||||||
description = "Signal Intelligence Platform - Pager/433MHz/ADS-B/Satellite/WiFi/Bluetooth"
|
description = "Signal Intelligence Platform - Pager/433MHz/ADS-B/Satellite/WiFi/Bluetooth"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
requires-python = ">=3.9"
|
requires-python = ">=3.9"
|
||||||
|
|||||||
+486
-484
File diff suppressed because it is too large
Load Diff
@@ -900,19 +900,27 @@ const Waterfall = (function () {
|
|||||||
resolve(ok);
|
resolve(ok);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onReady = () => finish(true);
|
// Only treat actual playback as success. `loadeddata` and
|
||||||
|
// `canplay` fire when just the WAV header arrives — before any
|
||||||
|
// real audio samples have been decoded — which caused the
|
||||||
|
// monitor to report "started" while the stream was still silent.
|
||||||
|
const onReady = () => {
|
||||||
|
if (player.currentTime > 0 || (!player.paused && player.readyState >= 4)) {
|
||||||
|
finish(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
const onFail = () => finish(false);
|
const onFail = () => finish(false);
|
||||||
const events = ['playing', 'timeupdate', 'canplay', 'loadeddata'];
|
const events = ['playing', 'timeupdate'];
|
||||||
const failEvents = ['error', 'abort', 'stalled', 'ended'];
|
const failEvents = ['error', 'abort', 'stalled', 'ended'];
|
||||||
|
|
||||||
events.forEach((evt) => player.addEventListener(evt, onReady));
|
events.forEach((evt) => player.addEventListener(evt, onReady));
|
||||||
failEvents.forEach((evt) => player.addEventListener(evt, onFail));
|
failEvents.forEach((evt) => player.addEventListener(evt, onFail));
|
||||||
|
|
||||||
timer = setTimeout(() => {
|
timer = setTimeout(() => {
|
||||||
finish(!player.paused && (player.currentTime > 0 || player.readyState >= 2));
|
finish(!player.paused && player.currentTime > 0);
|
||||||
}, timeoutMs);
|
}, timeoutMs);
|
||||||
|
|
||||||
if (!player.paused && (player.currentTime > 0 || player.readyState >= 2)) {
|
if (!player.paused && player.currentTime > 0) {
|
||||||
finish(true);
|
finish(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2571,6 +2579,7 @@ const Waterfall = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (attempt < maxAttempts) {
|
if (attempt < maxAttempts) {
|
||||||
|
_setMonitorState(`Waiting for audio stream (attempt ${attempt}/${maxAttempts})...`);
|
||||||
await _wait(220 * attempt);
|
await _wait(220 * attempt);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -2813,12 +2822,9 @@ const Waterfall = (function () {
|
|||||||
clearTimeout(_monitorRetuneTimer);
|
clearTimeout(_monitorRetuneTimer);
|
||||||
_audioConnectNonce += 1;
|
_audioConnectNonce += 1;
|
||||||
|
|
||||||
try {
|
// Immediately pause audio and update the UI so the user gets instant
|
||||||
await fetch('/receiver/audio/stop', { method: 'POST' });
|
// feedback. The backend cleanup (which can block for 1-2 s while the
|
||||||
} catch (_) {
|
// SDR process group is reaped) happens afterwards.
|
||||||
// Ignore backend stop errors
|
|
||||||
}
|
|
||||||
|
|
||||||
_stopSmeter();
|
_stopSmeter();
|
||||||
_setUnlockVisible(false);
|
_setUnlockVisible(false);
|
||||||
_audioUnlockRequired = false;
|
_audioUnlockRequired = false;
|
||||||
@@ -2836,6 +2842,13 @@ const Waterfall = (function () {
|
|||||||
_setVisualStatus('READY');
|
_setVisualStatus('READY');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Backend stop is fire-and-forget; UI is already updated above.
|
||||||
|
try {
|
||||||
|
await fetch('/receiver/audio/stop', { method: 'POST' });
|
||||||
|
} catch (_) {
|
||||||
|
// Ignore backend stop errors
|
||||||
|
}
|
||||||
|
|
||||||
if (resumeWaterfall && _active) {
|
if (resumeWaterfall && _active) {
|
||||||
_resumeWaterfallAfterMonitor = false;
|
_resumeWaterfallAfterMonitor = false;
|
||||||
await start();
|
await start();
|
||||||
@@ -2983,6 +2996,8 @@ const Waterfall = (function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
_ws.onclose = () => {
|
_ws.onclose = () => {
|
||||||
|
// stop() sets _ws = null before the async onclose fires.
|
||||||
|
if (!_ws) return;
|
||||||
if (!_wsOpened && _active) {
|
if (!_wsOpened && _active) {
|
||||||
// Wait for timeout-based fallback; avoid flapping to SSE on brief close/retry.
|
// Wait for timeout-based fallback; avoid flapping to SSE on brief close/retry.
|
||||||
_setStatus('WebSocket closed before ready. Waiting to retry/fallback...');
|
_setStatus('WebSocket closed before ready. Waiting to retry/fallback...');
|
||||||
|
|||||||
@@ -2936,7 +2936,7 @@
|
|||||||
<script src="{{ url_for('static', filename='js/core/voice-alerts.js') }}?v={{ version }}&r=voicefix2"></script>
|
<script src="{{ url_for('static', filename='js/core/voice-alerts.js') }}?v={{ version }}&r=voicefix2"></script>
|
||||||
<script src="{{ url_for('static', filename='js/core/keyboard-shortcuts.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/core/keyboard-shortcuts.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/core/cheat-sheets.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/core/cheat-sheets.js') }}"></script>
|
||||||
<script src="{{ url_for('static', filename='js/modes/waterfall.js') }}?v={{ version }}&r=wfdeck20"></script>
|
<script src="{{ url_for('static', filename='js/modes/waterfall.js') }}?v={{ version }}&r=wfdeck21"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// ============================================
|
// ============================================
|
||||||
|
|||||||
Reference in New Issue
Block a user