The rigs and antennas are already declared once, in Settings ▸ Operating conditions — a station per rig with its antennas hanging off it — and then typed again into every contact. That is work, and it is a source of spellings that do not match: "IC-7610", "IC 7610" and "ic7610" are three different rigs to an award, to a filter, and to anyone reading the log later. Both fields now offer that list, in the entry form and in the QSO editor, and the antenna field offers the antennas of the rig that was picked because that is the structure the tree already has. It falls back to all of them for a rig the tree does not know, so an operator typing a borrowed rig is still offered their own antennas rather than nothing. Free text stays allowed throughout — a contact made from somebody else's station, or imported from another logger, carries a rig that was never in this tree and must still be loggable. Same rule the satellite-name field follows. And the decodes list gains a ceiling of two thousand rows. The rolling half hour was never a limit on a crowded evening — three decoders put several thousand rows inside it — and the panel slows down long before the age cut removes any of them, because each row is a layout, a status lookup and a distance. Past the ceiling the oldest go: what has already been scrolled past, rather than the period being read. Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
67 lines
2.6 KiB
TypeScript
67 lines
2.6 KiB
TypeScript
// The station's own rigs and antennas, for the MY_RIG and MY_ANTENNA fields.
|
|
//
|
|
// They are already defined once, in Settings ▸ Operating conditions — a station
|
|
// per rig, with the antennas hanging off it. Typing them again into every
|
|
// contact is both work and a source of spellings that do not match: "IC-7610",
|
|
// "IC 7610" and "ic7610" are three different rigs to an award, a filter and to
|
|
// anyone reading the log later.
|
|
//
|
|
// So the two fields offer what the operator has already declared. FREE TEXT
|
|
// stays allowed: a QSO made from somebody else's station, or imported from
|
|
// another logger, carries a rig that was never in this tree and must still be
|
|
// loggable — the same rule the satellite-name field follows.
|
|
import { useEffect, useState } from 'react';
|
|
import { ListOperatingTree } from '../../wailsjs/go/main/App';
|
|
|
|
export type OperatingLists = {
|
|
rigs: string[];
|
|
// Every antenna in the profile, whichever rig it belongs to.
|
|
antennas: string[];
|
|
// The antennas of ONE rig. Falls back to all of them for a rig that is not in
|
|
// the tree — an operator typing a borrowed rig's name should still be offered
|
|
// their own antennas rather than nothing.
|
|
antennasFor: (rig: string) => string[];
|
|
};
|
|
|
|
const EMPTY: OperatingLists = { rigs: [], antennas: [], antennasFor: () => [] };
|
|
|
|
function build(stations: any[]): OperatingLists {
|
|
const rigs: string[] = [];
|
|
const byRig = new Map<string, string[]>();
|
|
const all = new Set<string>();
|
|
for (const st of stations ?? []) {
|
|
const name = String(st?.name ?? '').trim();
|
|
const ants = ((st?.antennas ?? []) as any[])
|
|
.map((a) => String(a?.name ?? '').trim())
|
|
.filter(Boolean);
|
|
if (name) {
|
|
rigs.push(name);
|
|
byRig.set(name.toUpperCase(), ants);
|
|
}
|
|
for (const a of ants) all.add(a);
|
|
}
|
|
const antennas = [...all];
|
|
return {
|
|
rigs,
|
|
antennas,
|
|
antennasFor: (rig: string) => byRig.get(String(rig ?? '').trim().toUpperCase()) ?? antennas,
|
|
};
|
|
}
|
|
|
|
// useOperatingLists reads the tree when the component mounts, and again whenever
|
|
// `reloadKey` changes — pass something that moves when Preferences close, so a
|
|
// rig added there is offered without a restart.
|
|
export function useOperatingLists(reloadKey?: unknown): OperatingLists {
|
|
const [lists, setLists] = useState<OperatingLists>(EMPTY);
|
|
useEffect(() => {
|
|
let live = true;
|
|
ListOperatingTree()
|
|
.then((st: any) => { if (live) setLists(build(st ?? [])); })
|
|
// An empty list simply leaves both fields as free text, which is what they
|
|
// were before they had a list at all.
|
|
.catch(() => {});
|
|
return () => { live = false; };
|
|
}, [reloadKey]);
|
|
return lists;
|
|
}
|