fix(chase): switching the rules invalidates every resolved verdict
The frontend caches statuses and only asks about unknown keys, so flipping the chase mode left half the screen judged under the old rules until a restart — which read as the mode not working. The backend now broadcasts an invalidation and the panels re-ask as rows repaint. The entity badges also say their name with a question mark, dashed, when the need is only a missing QSL — the 50% opacity was invisible on a filled chip.
This commit is contained in:
@@ -19947,6 +19947,12 @@ func (a *App) SaveChaseSettings(cs ChaseSettings) error {
|
||||
a.clusterStatusMu.Lock()
|
||||
a.clusterStatusIdx = nil
|
||||
a.clusterStatusMu.Unlock()
|
||||
// The frontend caches resolved verdicts and only asks about unknown keys —
|
||||
// without this it kept judging half the screen under the OLD rules until a
|
||||
// restart, which read as the new mode simply not working.
|
||||
if a.ctx != nil {
|
||||
wruntime.EventsEmit(a.ctx, "spotstatus:invalidate")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3862,6 +3862,12 @@ export default function App() {
|
||||
// The DX Call was cleared in WSJT-X / JTDX / MSHV → clear our entry to match.
|
||||
// Only when something is actually in the entry, so an idle digital app doesn't
|
||||
// wipe a call being typed by hand.
|
||||
const unsubStatusInval = EventsOn('spotstatus:invalidate', () => {
|
||||
// The chase rules changed: every resolved verdict is stale. Cleared, and
|
||||
// the flushes re-ask as rows repaint.
|
||||
setSpotStatus({});
|
||||
spotStatusRef.current = {};
|
||||
});
|
||||
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.
|
||||
@@ -3925,7 +3931,7 @@ export default function App() {
|
||||
const file = String(p?.file ?? '').replace(/^.*[\\/]/, '');
|
||||
showToast(file ? t('adifmon.toastFrom', { n, file }) : t('adifmon.toast', { n }));
|
||||
});
|
||||
return () => { unsubDX?.(); unsubRC?.(); unsubClear?.(); unsubFlexSpot?.(); unsubTciSpot?.(); unsubProg?.(); unsubBulk?.(); unsubLog?.(); unsubAdifMon?.(); };
|
||||
return () => { unsubDX?.(); unsubRC?.(); unsubClear?.(); unsubStatusInval?.(); unsubFlexSpot?.(); unsubTciSpot?.(); unsubProg?.(); unsubBulk?.(); unsubLog?.(); unsubAdifMon?.(); };
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
|
||||
@@ -1151,8 +1151,9 @@ export function DecodesPanel({ decodes, txMsgs, txState, txStates, spotStatus, o
|
||||
{entities.map((b) => (
|
||||
<span key={b.label}
|
||||
title={e?.unconf_status ? t('dec.unconfTip') : undefined}
|
||||
className={cn('rounded px-1 py-px text-[10px] font-bold uppercase tracking-wide shrink-0', b.cls, e?.unconf_status && 'opacity-50')}>
|
||||
{t(b.label)}
|
||||
className={cn('rounded px-1 py-px text-[10px] font-bold uppercase tracking-wide shrink-0', b.cls,
|
||||
e?.unconf_status && 'opacity-60 border border-dashed border-current bg-transparent')}>
|
||||
{t(b.label)}{e?.unconf_status ? '?' : ''}
|
||||
</span>
|
||||
))}
|
||||
{extras.map((b) => {
|
||||
|
||||
Reference in New Issue
Block a user