fix(spot): spot the references worth chasing, not the derived ones
The comment came out "SSB WAC EU WAZ 15 WPX HA5" — the QSO's materialised award_refs hold both kinds, and I took them all. Those four are what every reader of the spot derives from the callsign in their head. They spent the whole 30-character comment saying nothing and buried SOTA HA/KM-018, the one reference anyone would have acted on. Computed awards are now filtered out with the same rule the QSO editor uses (isComputedAwardField), which is why they are the ones it lists on the left and not in its read-only panel. The field map moves from a ref to state as well: a ref left the first spot of a session computing before GetAwardDefs had answered. Also opens 0.25.2, since 0.25.1 shipped before the spot work, and sets the default mode list to SSB, CW, FT8, FT4, FT2, RTTY, PSK31, FM. AM and DIGITALVOICE stay in the catalogue but are no longer selected on a fresh install. FT2 joins the digital family everywhere its siblings are listed — report list, RST defaults, Flex power class — so it gets dB reports rather than the 59 an unknown mode falls back to.
This commit is contained in:
+26
-18
@@ -141,7 +141,9 @@ type CATState = Omit<catModels.RigState, 'convertValues'>;
|
||||
// threshold is bypassed while filtering — see buildActiveFilter).
|
||||
const FILTERED_LIMIT_CAP = 10000;
|
||||
const DEFAULT_BANDS = ['160m','80m','60m','40m','30m','20m','17m','15m','12m','10m','6m','2m','70cm','23cm'];
|
||||
const DEFAULT_MODES = ['SSB','CW','FT8','FT4','RTTY','PSK31','AM','FM','DIGITALVOICE'];
|
||||
// Mirrors defaultModes in app.go — the fallback used before the backend answers.
|
||||
// AM and DIGITALVOICE stay in the catalogue but are not offered by default.
|
||||
const DEFAULT_MODES = ['SSB','CW','FT8','FT4','FT2','RTTY','PSK31','FM'];
|
||||
// Modes the QSO recorder captures (phone only). Mirrors recordableMode() in
|
||||
// app.go — digital modes carry no useful audio, and CW has no DAX audio on Flex,
|
||||
// so neither is recorded (no REC badge / timer for them).
|
||||
@@ -311,7 +313,7 @@ function modeAccent(mode?: string): string {
|
||||
type RSTLists = { phone: string[]; cw: string[]; digital: string[] };
|
||||
function rstCategory(mode: string): keyof RSTLists {
|
||||
const m = (mode || '').toUpperCase();
|
||||
const digital = ['FT8', 'FT4', 'JT65', 'JT9', 'JS8', 'Q65', 'MSK144', 'FST4', 'FST4W', 'MFSK', 'OLIVIA', 'JT4', 'WSPR'];
|
||||
const digital = ['FT8', 'FT4', 'FT2', 'JT65', 'JT9', 'JS8', 'Q65', 'MSK144', 'FST4', 'FST4W', 'MFSK', 'OLIVIA', 'JT4', 'WSPR'];
|
||||
if (digital.includes(m)) return 'digital';
|
||||
if (['CW', 'RTTY', 'PSK31', 'PSK63', 'PSK', 'PSK125'].includes(m)) return 'cw';
|
||||
return 'phone';
|
||||
@@ -2086,6 +2088,24 @@ export default function App() {
|
||||
const [showScp, setShowScp] = useState(() => localStorage.getItem('opslog.showScp') !== '0');
|
||||
const [showBeamOnMap, setShowBeamOnMap] = useState(() => localStorage.getItem('opslog.showBeamOnMap') !== '0');
|
||||
|
||||
// Award code → scanned field (e.g. POTA→pota_ref, WWFF→wwff). Used to route
|
||||
// picked award references to the QSO field/extras each award actually reads.
|
||||
const awardFieldRef = useRef<Record<string, string>>({});
|
||||
// The same map as state, because the spot comment has to be recomputed once it
|
||||
// arrives — a ref would leave the first Send Spot of a session with no
|
||||
// references at all, or with the computed ones it is meant to filter out.
|
||||
const [awardFields, setAwardFields] = useState<Record<string, string>>({});
|
||||
useEffect(() => {
|
||||
GetAwardDefs()
|
||||
.then((defs) => {
|
||||
const m: Record<string, string> = {};
|
||||
for (const d of (defs ?? []) as any[]) m[String(d.code).toUpperCase()] = String(d.field || '').toLowerCase();
|
||||
awardFieldRef.current = m;
|
||||
setAwardFields(m);
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
// Award references offered to the Send Spot window, as cluster-ready strings.
|
||||
//
|
||||
// The entry panel holds them as "CODE@REF;CODE@REF" while the QSO is being
|
||||
@@ -2094,23 +2114,11 @@ export default function App() {
|
||||
// the station still in the field — and fall back to the last logged QSO, which
|
||||
// is where the callsign and frequency defaults come from too.
|
||||
const spotEntryRefs = useMemo(() => {
|
||||
const entry = spotRefList(parseManualRefs(details.award_refs ?? ''));
|
||||
const entry = spotRefList(parseManualRefs(details.award_refs ?? ''), awardFields);
|
||||
if (entry.length) return entry;
|
||||
return spotRefList(parseAwardRefs(qsos[0]?.award_refs));
|
||||
}, [details.award_refs, qsos]);
|
||||
return spotRefList(parseAwardRefs(qsos[0]?.award_refs), awardFields);
|
||||
}, [details.award_refs, qsos, awardFields]);
|
||||
|
||||
// Award code → scanned field (e.g. POTA→pota_ref, WWFF→wwff). Used to route
|
||||
// picked award references to the QSO field/extras each award actually reads.
|
||||
const awardFieldRef = useRef<Record<string, string>>({});
|
||||
useEffect(() => {
|
||||
GetAwardDefs()
|
||||
.then((defs) => {
|
||||
const m: Record<string, string> = {};
|
||||
for (const d of (defs ?? []) as any[]) m[String(d.code).toUpperCase()] = String(d.field || '').toLowerCase();
|
||||
awardFieldRef.current = m;
|
||||
})
|
||||
.catch(() => {});
|
||||
}, []);
|
||||
|
||||
// === Clock ===
|
||||
const [utcNow, setUtcNow] = useState('');
|
||||
@@ -7242,7 +7250,7 @@ export default function App() {
|
||||
freqKHz: q.freq_hz ? Math.round((q.freq_hz / 1000) * 10) / 10 : 0,
|
||||
mode: q.mode ?? '',
|
||||
band: q.band,
|
||||
refs: spotRefList(parseAwardRefs(q.award_refs)),
|
||||
refs: spotRefList(parseAwardRefs(q.award_refs), awardFields),
|
||||
}))}
|
||||
onSend={async (call, freqKHz, comment) => {
|
||||
await SendClusterSpot(call, freqKHz, comment);
|
||||
|
||||
Reference in New Issue
Block a user