fix(udp): edge-detect the decoder's DX Call stream

WSJT-X restates the same DX Call in every Status packet, and a spot clicked
in OpsLog put that call into the last-UDP memory (deliberately, for another
case) — so the guard let the decoder's next restatement straight through and
the entry snapped back to old news. The decoder's stream now only counts when
its value CHANGES; a clear over there resets the edge so re-selecting the
same station still lands. Explicit picks (N1MM, remote, spot relays) are
untouched.
This commit is contained in:
2026-08-30 15:29:07 +02:00
parent 3c59507bc3
commit 997bc81d5e
2 changed files with 19 additions and 2 deletions
+4 -2
View File
@@ -6,13 +6,15 @@
"Bulk operations work on any size of selection — setting a field, fixing frequencies, deleting, marking uploads and exporting the selection all failed with “too many SQL variables” past a few tens of thousands of QSOs. Statements are now issued in slices.",
"Elecraft console: the power meter reads in real watts. The K3s bargraph is relative to a range that flips at 12 W — calibrated against a real radios full table, the PC setting picks the range and the bar converts to watts.",
"Watchlist: a visual pass toward DXHunters look — pink callsigns, counter pills, quieter cards with a hover, the ⚡ back on the DXpedition badge.",
"WSJT-X / JTDX: OpsLog can highlight decodes in the decoders own Band Activity window from your log — watchlist members pink, new DXCC green, new band orange (option in Settings → Connections). And a freshly-started decoder is asked to replay its on-screen decodes, so the FT decodes panel starts full."
"WSJT-X / JTDX: OpsLog can highlight decodes in the decoders own Band Activity window from your log — watchlist members pink, new DXCC green, new band orange (option in Settings → Connections). And a freshly-started decoder is asked to replay its on-screen decodes, so the FT decodes panel starts full.",
"WSJT-X / JTDX / MSHV: only a CHANGED DX Call updates the entry — the decoder re-broadcasts the same call endlessly, and it kept overwriting a spot clicked in OpsLog."
],
"fr": [
"Les opérations groupées fonctionnent quelle que soit la taille de la sélection — définir un champ, corriger des fréquences, supprimer, marquer les uploads et exporter la sélection échouaient avec « too many SQL variables » au-delà de quelques dizaines de milliers de QSO. Les requêtes sont désormais émises par tranches.",
"Console Elecraft : le wattmètre lit en vrais watts. Le bargraph du K3 est relatif à une gamme qui bascule à 12 W — calibré sur la table complète dune vraie radio, le réglage PC choisit la gamme et la barre se convertit en watts.",
"Watchlist : une passe visuelle vers le look DXHunter — indicatifs roses, compteurs en pastilles, cartes plus feutrées avec survol, le ⚡ de retour sur le badge DXpedition.",
"WSJT-X / JTDX : OpsLog peut surligner les décodages dans la fenêtre Band Activity du décodeur selon votre log — watchlist en rose, nouveau DXCC en vert, nouvelle bande en orange (option dans Réglages → Connections). Et un décodeur fraîchement détecté rejoue ses décodages à l’écran, donc le panneau FT decodes démarre plein."
"WSJT-X / JTDX : OpsLog peut surligner les décodages dans la fenêtre Band Activity du décodeur selon votre log — watchlist en rose, nouveau DXCC en vert, nouvelle bande en orange (option dans Réglages → Connections). Et un décodeur fraîchement détecté rejoue ses décodages à l’écran, donc le panneau FT decodes démarre plein.",
"WSJT-X / JTDX / MSHV : seul un DX Call qui CHANGE met à jour la saisie — le décodeur rediffuse le même call sans fin, et il écrasait un spot cliqué dans OpsLog."
]
},
{
+15
View File
@@ -2667,6 +2667,11 @@ export default function App() {
// "the field still shows the previous broadcast" (safe to update) from "the
// user has typed a different call" (must not clobber).
const lastUdpCallRef = useRef('');
// Edge detection for the DECODER'S stream: WSJT-X/JTDX/MSHV re-broadcast the
// same DX Call in every Status packet, seconds apart, forever. Applying each
// one meant a spot clicked in OpsLog was overwritten moments later by the
// decoder restating old news. Only a CHANGE in this stream is an event.
const lastWsjtEdgeRef = useRef('');
// When the entered callsign turns out to be worked-before, jump to the
// Worked-before tab so the history is front-and-centre. Only once per call,
@@ -3796,6 +3801,13 @@ export default function App() {
// Anything that isn't WSJT-X (N1MM, ADIF, a panadapter/cluster click relayed
// over UDP…) is an explicit pick → force it over an existing call.
const force = String(p?.service ?? '').toLowerCase() !== 'wsjt';
if (!force) {
// The decoder's stream: same value as last time = no edge = no update.
// Only a changed DX Call is the operator doing something over there.
const upper = String(p?.call ?? '').trim().toUpperCase();
if (upper && upper === lastWsjtEdgeRef.current) return;
lastWsjtEdgeRef.current = upper;
}
// External app moved to a new station → fresh recording for the new target.
if (applyUdpCall(p?.call, force)) restartRecordingForNewTarget(String(p?.call ?? ''));
});
@@ -3806,6 +3818,9 @@ export default function App() {
// Only when something is actually in the entry, so an idle digital app doesn't
// wipe a call being typed by hand.
const unsubClear = EventsOn('udp:clear_call', () => {
// The decoder cleared its DX Call: the next call it announces — even the
// same one re-selected — is a fresh edge.
lastWsjtEdgeRef.current = '';
if (callsignRef.current?.value?.trim() || callsign.trim()) resetEntry();
});
// Clicked one of OpsLog's spots on the FlexRadio panadapter → fill the call