Callsign, band, mode, badge, age in reading order, and the widget widened
to 290 px so the badge and the age never squeeze the callsign. Two lines
made the panel twice as tall for the same three facts; the entry that
matched — which only differs when it is a prefix — moved into the row's
tooltip.
The watch list was a tab, and an operator working FT8 lives on the decodes
one: a station they had asked to be told about turned up on a screen they
were not looking at. The same answer is now docked in the widget strip,
above the tabs, reduced to what is worth acting on — on the air and still
needed, one row per band and mode, with the cluster's own NEW DXCC /
NEW BAND / NEW SLOT badge and a click that tunes. Off by default. The
"active and needed" answer costs a debounced query per visible slot, so it
is written once (lib/watchlistSpots) and the tab uses it too.
Auto-call:
- It answers a new prefix, county, state, square or park. Those markers
are orthogonal to the entity, they ranked as nothing-needed, and the
engine sat through a never-worked WPX prefix calling CQ. New rung at
the foot of the ladder, gated by the chase switches the badges use —
which meant making those switches portable, since the backend cannot
read localStorage.
- It calls THROUGH a pileup. Giving up the moment the DX answered
somebody else is precisely how a queue is not worked; the call and miss
counters already bound the effort, and a station in mid-exchange is
still never chosen as a new target.
The PSK Reporter panel now follows the station auto-call is waiting for:
the analysis takes a history query and a period or two to fill, so
starting it when the DX comes free is starting it too late.
Callbook lookup: a compound callsign with a page of its OWN keeps that
page's location. QRZ files HP/WE9G under exactly that form, with the
Panama square the station is operating from, and the rule that drops a
home address from a portable call was throwing it away. The record's own
country tells an operation's page from a home page.
Changelog: entries may open with [NEW], drawn as a pill in the What's new
dialog — a release is mostly fixes and the two or three genuinely new
things should not have to be found by reading all of it.
Six faults from an evening on 60 m, all in the same family: the engine
judging a station by what the log wants from it and forgetting what is
already under way.
- An exchange was abandoned mid-QSO. The reply lands in the same period
the ladder is re-read, and that period was judged before the reply was
taken into account, so a better-ranked caller took the slot from a
station that had just come back to us. The answer is settled first now,
and our own report counts as being inside the exchange too — which also
protects a QSO the operator started by hand.
- A station just picked started with misses against it. Its transmit slot
was unknown until a second decode, and with the parity unknown every
period counted, including the one spent transmitting to it.
- The freed slot after "it is working somebody else" was thrown away: the
period's decodes are in hand, so the next station is picked from them
rather than fifteen seconds later. Never mid-over.
- Auto-call is never armed from a stored setting — not at launch, not on
a profile switch. It is the one feature that puts the station on the
air by itself and OpsLog starts with Windows.
- It says what it is waiting for: a wanted station in a QSO with somebody
else now shows beside the Auto button instead of looking idle.
- Switching profile left the previous logbook's verdicts on screen. The
worked-index, chase-new and the frontend's cached verdicts are dropped
when the logbook changes.
FT decodes: distance column, a message addressed to you set whole in
green (the station you are calling keeps a tint — most of what it sends
goes to other people), badge order L / Wkd / WL, list cleared when the
RIG changes band.
Rotor: new world-map compass from EC1KD's design, with the Ultrabeam boom
and second lobe restored and the compact form preserved; the classic dial
is kept and Settings → Rotator chooses between them. Stop no longer
flickers on a rotor standing still — movement was inferred from a degree,
less than the jitter a controller reports at rest.
Decodes:
- one click SELECTS, two transmit. A single click handed the decode
straight to WSJT-X as a reply, so brushing a row while reading the
band started calling a station.
- the list empties for a receiver that changes band, and a receiver
column appears when more than one is feeding one merged list.
- the period clock turns red while transmitting: it is the one thing on
the screen that moves, so it is where the eye already is.
- a WL badge, after the LoTW "L" — one letter, always in the same
place, so the column does not shift from row to row.
- the auto-call switch, its target and its count, and the chase list:
naming the station you are waiting for is done while watching the
band, not in a settings tree.
Themes: DXHunter's slate with its own blue, and the same slate with
OpsLog's orange. Counted across its sources rather than guessed from
one panel — blue is 132 uses to violet's 25, and the violet is the PSK
Reporter panel alone.
Watchlist: drawn as DXHunter draws it — the callsign in the interface
font rather than monospaced, which is the difference that shows with
the two windows side by side.
FT Map: arcs no longer run off the side of the map. The map shows one
world, and a path crossing the antimeridian was drawn past 180° into
the blank space beside it — from VK that is most of them.
Cluster: "superfox", "fox/hound" and "F/H" in a comment are read as
FT8. They are WSJT-X's DXpedition transmit modes, and the comment fell
through to the band plan and came out DATA — which then decided the
band+mode verdict.
A decoder is named by what it IS: Nexus sends its packets as "Tempo",
the engine inside it, and OpsLog showed a program nobody has heard of.
Clicking one tuned the rig and zoomed the panadapter, and stopped there:
no mode on the entry, no RST preset, no park or summit reference, and —
the one that matters — no word to the decoding application. So picking
an FT4 station from Chase new while WSJT-X sat in FT8 left it decoding
FT8, which defeats the only thing the window is for.
It goes through handleSpotClick now rather than repeating a chosen half
of it, so the two can never drift apart again. The mode is handed over
where a cluster line would carry it in its comment, which is where that
handler looks for it.
A list in Appearance, in the row's own order, dragged to rearrange —
with QSO entry and the F1-F5 panel at its head, locked. They are not in
that row at all, and letting an operator push the thing they type into
behind a rotator dial is not a preference, it is a trap.
Implemented with flexbox ORDER rather than by moving the JSX: in a
component this size, reordering the tree would have moved every
condition, ref and hook with it. Each slot keeps its place in the source
and receives an order property, so a widget switched off still holds its
rank and returns where the operator left it.
An unknown key from a later version joins the end rather than the front,
and a key that no longer exists is dropped — an old preference can
neither reorder a widget it has never heard of nor hide one. Opens
0.27.10.
A decoding application that loses its CAT link keeps announcing the last
dial frequency it knew, and every decode after that carries a stale
band. Nothing downstream can tell: the entity verdicts, the band filter
and the FT map all believe it. Seen for real — MSHV kept saying 80 m,
and Korea read as a NEW BAND because on 80 m it would have been.
Said, not decided. Taking the rig's band instead would be wrong for
anyone decoding a second receiver on another band, and a warning costs
that setup nothing but a line to read past. Shown only while CAT is
actually connected: an empty band means there is nothing to compare
with, never that the rig is on no band. Opens 0.27.9.
One row per digital mode would be the honest layout, and there is no
height for it: the matrix sits in a fixed panel beside a dozen widgets.
So the row keeps its place and changes what it answers — DIG, then each
digital mode the operator's own list holds, in the order they put them
in, then back to DIG.
It costs no round trip. The query behind the matrix already grouped by
band AND mode; only the collapse to a class threw that away, so the same
cell is now published under the raw mode name too. Digital only: PH and
CW have nothing to cycle through.
On a specific mode the you-are-here mark follows THAT mode, or every FT4
entry would light whichever digital row the rotation happened to rest
on. A four-letter mode drops to 9px rather than widen a column sized for
three characters and push the whole matrix sideways. Opens 0.27.8.
The chase switches were born on the DX Cluster page because the cluster
was the only thing that drew their badges. They now decide what the FT
decode list and Chase new say as well, and settings that govern three
screens should not live under the name of one of them. They move to a
DXHunter page — named for what it is about, and for what is meant to
land beside it as more of DXHunter's ideas are ported over.
US states join the switchable markers, gated the same way as POTA,
counties, prefixes and squares: badge, filter chip and display marker,
all from the one chaseAllows question.
Reported as 'South Africa shows NEW BAND although I have worked 15m'.
The verdict was right — his hunt counts only LoTW and paper QSL, and no
15m contact is confirmed by either — but the badge drew SOLID, saying
'never worked here' about a band with four contacts in the log.
Proved with his own data: the confirmed ledger holds 10/12/17/20/30/40/80
and not 15, the all-QSO ledger holds 15m FT8 four times, and the backend
sets UnconfStatus correctly for exactly that case (new test, end to end
through ClusterSpotStatuses).
The flag died in the frontend. FOUR hand-written copies of the same
backend-result mapping, and they had drifted: the two that RE-fetch —
after a QSO is logged, and when a pane becomes visible — rebuilt each
entry without the unconf_* flags, so the first refresh after any contact
turned every dimmed badge solid for good. None of the four ever copied
grid_state either, so a known-but-unconfirmed square never dimmed at all.
One mapper now, used by all four.
Band and frequency have to agree — the log, every award and every upload
are read on the BAND — and an operator fixing a wrong frequency is not
also expecting to fix the band by hand. That is exactly how a QSO ends
up filed on 20m at 7 MHz. Both sides follow, TX and RX.
Only when the number lands in a known allocation, because half a
frequency is typed on the way to all of it and a band must never be
blanked by that. bandForMHz moves out of App.tsx into lib/bandplan,
where the two callers can share one answer instead of drifting.
The pills listed live SESSIONS, so disconnecting one made it vanish —
along with the only way back. They now list every enabled server, and a
server with no session shows as disconnected: the state you click to
undo. The address, known only while a session exists, drops out of the
tooltip rather than reading ':0'.
The colour already said connected; the word beside it said it again, in
the widest part of a row that has to hold five servers. It goes, and the
pills earn the job nothing else in the app had: reaching ONE cluster
without opening Settings. Click connects or drops that session — a
connecting one included, so a server retrying into a dead host can be
stopped. State, retry count, address and last error move into the
tooltip, where they cost no width.
A DXpeditions tab holding the two feeds the DX world announces itself
on: NG3K's ADXO (structured — dates, entity, calls, bands, modes, QSL
route) and DX-World's headlines. What a logger can say that a news
reader cannot is whether the operation is worth chasing, so every
announcement is put through the SAME verdict the cluster paints on a
spot — one badge, strongest wins, dimmed when the need is only a missing
QSL — with an 'only what I need' filter. One click watches every
callsign of an operation; the news headlines are mined for callsigns so
they can be watched the same way.
Parsers ported from DXHunter's and pinned with table tests against real
feed text: the 'as PJ2/W2APF' mining, the DXCC-prefix-first
normalisation without which no spot ever matches, both ADXO date forms,
and the '160-6m' span whose unit is written once (DXHunter read that as
6m alone and lost the low end).
Watchlist membership now announces itself app-wide, on the same card as
a new version: the bindings emit watchlist:changed, so a call added from
the cluster or this tab is confirmed where the operator is actually
looking — the panel's own inline message never was.
Chase POTA already withdrew its badge, filter chip and column when
unchecked; US counties and new prefixes now have the same switch, and
unchecking Chase new grids finally withdraws the NEW GRID badge too (the
backend stopped learning squares but the display kept shouting the ones
it knew — the setting is mirrored to localStorage so the display layer
can gate synchronously). All withdrawal happens at the display layer:
the facts keep being computed, so re-ticking a box needs no rescan.
An FTx menu between View and Tools gathers FT Decodes, FT Map and the
Grid squares map — three views of the same UDP feed that were buried in
Tools. And the watchlist spot rows swap the elastic country column for
fixed widths, so band, mode and frequency read as columns instead of
starting wherever each country name happened to end.
A new FT Map tab (Tools menu, beside FT decodes): every station decoded in
the last half hour drawn as a great-circle arc from the operator's own
square, coloured by band the way PSK Reporter taught everyone to read it,
fading with age, one arc per call (its freshest sighting), a tooltip with
call/grid/SNR, the MainMap basemap picker and a legend of only the bands on
screen.
Performance was the open question and it is answered structurally: the panel
mounts only while its tab is ACTIVE (zero cost otherwise), the map renders
canvas (one element, not one node per arc), arcs are capped at 300, and
redraws follow the decode list — every period, not every frame.
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.
The gap between worked and confirmed becomes visible everywhere. A Chase
setting on the DX Cluster page picks the mode; in new-plus-unconfirmed the
verdicts for DXCC/band/mode/slot, prefix, county and state are judged against
CONFIRMED-only ledgers built from the operator's chosen sources (LoTW, card,
eQSL, QRZ.com — HRDLog has no confirmation field in ADIF to offer), and a
need that exists only because a QSL never arrived is flagged Unconf: the
cluster and decode badges render it dimmed, the convention the grid hunt
introduced. The grid's own Chase selector folds into the global one; its
square-matching scope stays where it was, being grid-specific. One snapshot
key change rebuilds the cache when any of it flips.
The WAS gap made visible: a worked-states set joins the cluster status cache
(distinct states over the three US entities), the status entries carry a
NewState flag wherever the state resolves (log county first, ULS licence
second), and the decode panel gains the badge in its status column plus the
filter chip alongside NEW/BAND/MODE/GRID. Colour from the shared marker
palette, so the cluster can adopt it later without a second hue.
The voice keyer grows to F1-F12 — the UI was already data-driven, so the
count constant, the F-key range and the labels are the whole change.
And the preferences stop stuttering on a busy station: every spot batch,
decode batch and CAT snapshot re-rendered the entire App tree behind the
dialog — cluster grid, decodes panel, thousands of nodes — and the pointer
janked over the very panel the operator was trying to use. While Settings is
open the flushes park their batches in the pending refs (bounded) and CAT
repaints at most every two seconds; closing the dialog drains everything.
Configure (message 15), mode field only, every other field sent as
no-change: an FT4 spot clicked while WSJT-X sits in FT8 lands the operator
ready to decode instead of staring at gibberish. Sent to every instance
heard this session — one already in the right mode treats it as a no-op —
and only for modes the decoder actually speaks (FT8/FT4/JT65/JT9/MSK144/
Q65/FST4); CW and SSB are none of its business. Toggle in the Connections
panel, on by default.
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.
Message 13 paints callsigns in WSJT-X/JTDX's own Band Activity window with
verdicts from the same cluster status cache that colours the spot grid:
watchlist pink, new DXCC green, new band for its entity orange. Deduplicated
per instance+call+verdict, one datagram each; a verdict that lapses (the
operator worked them) clears that call, and turning the option off clears
everything via the protocol's CLEARALL!. Off by default, switch in the
Connections panel.
Message 7 asks a program heard for the first time this session to replay the
decodes already on its screen, so the FT decodes panel starts full instead of
empty until the next period. Replayed lines arrive marked not-new and are
shown but never auto-answered — the auto-caller now checks, on top of its
30-second freshness gate.
Two lookups race when a second callsign is typed before the first answered,
and the slow one landed last: the grid showed the previous call's QSOs under
the new call's name — LU5AVM's contact filed under LW8ETV, screenshot in
hand. A request token now discards any response that is not the newest.
It keeps 'not repeating' on a network rig and every guess at which guard was
tripping proved wrong. Each round now logs play / playing-flag / end / gap,
and every exit names its reason.
Over the network the rig's mode read fails now and then and the CAT push
blanks the mode for a poll or two; the auto-CQ loop treated that blank as
'not a phone mode' and stopped after the first call. Only a KNOWN non-phone
mode stops the loop now.
The CI-V keyer is the same 0x17 command on the same IcomController whatever
carries the link; only the warnings and enable checks insisted on the USB
backend, telling a network operator their working keyer would fail.
Two halves of the same station confusion. The entry form pre-filled MY_RIG
from the per-band default on every band change, so the log-time priority (the
radio that is keying beats the radio that was planned) never ran — the field
was no longer empty by the time the backend looked. The form now asks the
active radio first, through a new ActiveRadioMyRig binding.
And the manual record button started its capture from the From-radio sound
card unconditionally, where the automatic recorder already knew a network
Icom's audio is pushed from the 50003 stream: a manual take on the IC-7760
was a faithful recording of the Flex's DAX. Same source rule for both, and
the button is offered with no sound card at all when the network stream is
the source.
Two effects, wrong order: the ticking effect ran before the reset effect on a
new take, so its closure captured the PREVIOUS take's elapsed as its starting
point — the counter showed 0 for one second and then jumped back to thirty
minutes. Effects run in declaration order; the reset now comes first.
Double-clicking a cluster spot tuned the slice and zoomed the panadapter in
the same breath. On a cross-band jump SmartSDR moves the panadapter itself to
follow the slice, and that follow lands after — and overrides — a zoom sent in
the same instant, so the width the operator configured never appeared. A spot
clicked ON the panadapter never hit this, because the radio had already tuned
before our zoom arrived; the two paths now behave the same. The Chase new
panel's pick is sequenced identically.
Every other spot click — cluster grid, band map, watchlist, alert list — goes
through handleSpotClick, which applies the operator's per-mode panadapter
width after the tune. The Chase new panel had its own pick handler that tuned
and stopped there; it now makes the same view change, after the tune for the
same reason.
The F1 panel widens 560 → 600 px, the header row drops its outer padding and
wide gaps, and the country badge tightens — so 'Central African Republic' and
the NEW SLOT chip share one line instead of the chip dropping alone underneath.
The watchlist joins the Main-tab pane list (Settings → Main view), rendered in
a card like the other docked panels.
The three filters persist across tab switches — the component unmounts on every
switch, and filters that reset each time are filters nobody trusts.
Needed-only now hides the worked SPOT LINES as well as the all-worked cards,
which is DXHunter's own Not-Worked behaviour and the reported complaint: a
filter that says needed and still lists five green Worked rows answers a
different question than the one asked.
The add-row checkbox is relabelled 'as contest' — it marks the entry being
ADDED, and read as a filter beside the All/DX/Contest buttons it looked
redundant.
The concept, transplanted: a list of callsigns or prefixes being hunted,
matched against the live spot stream, one card per entry with the spots
underneath and the two questions that matter answered on every line — is this
slot still needed, and what is it worth (the cluster's own NEW badges, read
from the same status index).
The file is DXHunter's own watchlist.json, field for field, ClubLog block
included though phase 2 will fill it — a file that round-trips unchanged is the
whole of 'same format', and a test pins it with a real DXHunter entry. Global
(dataDir), not per profile.
CONTEST is per entry, not the global mode DXHunter has: a contest entry is
judged against the current UTC day — the boundary lives in the query's date
bound, so midnight needs no timer and resets nothing. Normal entries read the
same in-memory worked index the alerts use. Prefix matching is why RI0SP
catches RI0SP/MM, pinned by test.
Notify goes through the existing alert:fired event — the frontend already
toasts and sounds it — throttled to one alert per entry per two minutes,
because a DXpedition lights every skimmer on the planet.
Tab wired like NET Control: opt-in from Tools, persisted, closable. Single
click fills the callsign, double click works the spot — the cluster's own
gesture, kept.
An operator who does not chase parks does not want NEW POTA shouting from every
activator spot. Two switches (Settings → DX Cluster, on by default): off, the
marker is withdrawn at the display layer — applySpotDisplay, the same chokepoint
the grid, the band map and the filter read through — so the badge, the colour,
the filter chip and the reference column all go quiet together, and a new-band +
new-POTA spot reads NEW BAND alone. The facts keep being computed; only the
telling stops, so ticking the box back on needs no rescan.
Three from review. Aqua for NEW SLOT sat right next to the POTA green — it is
now the sky cyan the panadapter palette has shipped for new-slot all along.
The NEW COUNTY chip was green while its badge is violet, and NEW SLOT's chip
was still caution yellow: chips now carry the badge's own colour (color-mix for
the muted border/背景), because a filter that does not look like what it selects
has to be learned twice.
And the NEW CALL chip matched only the DISPLAYED status, which is manufactured
by the slot-highlight option — with that option off the chip matched nothing
and read as broken. It now filters on the fact itself (worked_slot false), so
it works either way.
The Send-spot dialog took catState.freq_hz, which is the TX frequency. Working
a DXpedition split, that is where WE transmit: the spot went out five up from
the DX, pointing the whole cluster at the pile-up instead of the station. The
RX frequency is where we listen — where the DX is — and is what a spot names.
The feature needs more rounds than the next release can wait for, so main goes
back to before it: the packages, bindings, migration, UI and i18n all move to
the feature/labels branch, which holds every commit. The 0.26.23 block keeps
only the Station column.
The 0031 migration may already have run on a machine that launched a dev build;
the two label tables it created are inert and the recorded migration row is
harmless — the runner only applies filenames it has, so re-adding the migration
when the branch merges will skip cleanly there and apply everywhere else.
The printing session in three steps. The worklist is the paper queue (ADIF
qsl_sent R/Q), grouped by callsign since several QSOs of one station share a
card. Each recipient is reviewed before anything prints: routing first — via
manager when qsl_via says so, direct when an address is known, bureau otherwise
— then the address itself, editable and fetchable from QRZ (the MANAGER's
address when routing says via). What is printed is the reviewed text verbatim,
not a re-resolution that could differ from what was checked.
One PDF per label kind, never one file for all: a roll printer holds one stock
at a time, and a file mixing 29 mm addresses with 62 mm QSO labels could not be
printed at all. Pages are rasterised by the designer's own renderer at the
stock's dpi and carried into the PDF untouched — internal/pdf is a hand-written
image-page writer (DeviceGray + flate: monochrome, lossless, no cgo) because
that is the entire need.
Bureau stations get no address label (no envelope); return labels are printed
one per envelope. Finishing offers the log update: QSL_SENT=Y, the chosen date,
via B or D per routing — through the same BulkUpdateQSL the paper view uses.
The designer's data model lives in internal/labels: STOCKS are the physical
roll in the printer (geometry in mm, margins, dpi — seeded with the common
Brother DK sizes, the QL family being what prompted the feature), TEMPLATES are
one design each, of two kinds: the QSO label glued on the card, whose repeating
table carries several contacts of the same station, and the address label for
the envelope, whose lines collapse when a variable is empty.
Everything is measured in millimetres — labels are sold in mm, and an operator
lining a design up against a physical sticker thinks in mm; pixels exist only in
the renderer, at the stock's dpi. The canvas renderer is shared between the
editor's preview and the future print path, so there is no second
implementation for the preview to disagree with.
The preview is fed with the log's latest contacts rather than lorem ipsum: real
data shows a too-narrow column immediately.
Printing (PDF, one page per label at exact size) is the next module; nothing
here prints yet.
The grouping keyed on the callsign alone, so every spot of a station outside the
first one's band and mode was dropped from the list. RI1FJL spotted on 17m CW,
20m, 30m, 12m and 15m FT8 showed as a single row: four slots gone from the one
view an operator uses to find them.
A duplicate is the dozen skimmers that all heard the same CQ — same station,
same band, same mode. The same station on another band is the opposite of a
duplicate; it is what the chaser is scanning for.
Every flush commits state the whole window re-renders on, and the window was a
flat 50 ms — twenty full renders a second under an RBN firehose. That is paid
everywhere else in the interface, and it is what a dropdown highlighting its
entries a beat behind the mouse actually is.
The window now follows the rate: 50 ms on a quiet cluster, where a spot should
appear the moment it arrives; 200 ms past five a second; 500 ms past twenty,
where half a second's delay on a line already scrolling past is invisible.
The pane drew its own title bar above the grid's toolbar, so the cluster spent
two lines on headers where Recent QSOs beside it spent one — in a pane often
only a few spots tall. The grid's toolbar now takes what the caller wants on its
left, and the pane passes its title, live count and Filters button there.
Reported by VK4DX.
The sixth CW engine, and the one the TCI backend was left without. A SunSDR
keys from the WebSocket that already carries the CAT: no WinKeyer, no second
serial port, nothing to wire.
CW_MACROS:0,<text>; send
CW_MACROS_SPEED:<wpm>; speed
CW_MACROS_STOP; abort
Confirmed against the TCI command table in ars-ka0s/eesdr-tci — the source that
settled SPOT. CW_MACROS rather than TCI 2.0's CW_MSG: it exists from 1.6, and
OpsLog resolves its own variables, so the before/after callsign fields have
nothing to carry.
Commas and semicolons are stripped before sending. They are the protocol's own
separators: a comma would become another argument, a semicolon would end the
command with the message half keyed and the rest parsed as a command.
Only the MACRO speed is set, not the paddle keyer's — an operator who set their
paddle to 28 wpm did not ask for it to change because a macro went out at 25.
And there is no backspace: TCI can stop a message but cannot un-type one, so the
type-ahead correction the Flex engine offers is absent rather than faked.
Everything is computed in kilometres and converted once at display time, in
lib/units — storing miles anywhere would give the same number two sources of
truth and a rounding error that grows with every hop.
The grids capture the unit inside their column definitions, header and formatter
both, so a change is published to them the way the date format already is;
without that a toggle would only appear after a language change or a restart.
The preference is portable, like the other display ones.
The SOTA feeds put the summit in the spot's own text, so there is nothing to
poll: a regex on the comment gives the reference, and clicking the spot writes
SOTA@<ref> into the award references the way a park already wrote POTA@<ref>.
The regex is narrow on purpose — association/region-NNN, anchored — because
POTA (US-4475), WWFF (DLFF-0001) and portable callsigns (DL/SP9DPM/P) share
that field and none of them is a summit. Pinned by a table test.
Off by default: the reference is only there on the summit feeds, and an empty
column for every operator who does not chase them is worse than a checkbox.
The chip read a.spe ?? a.acom ?? a.pgxl, so a KPA fell through to the
not-connected fallback: red on a working amplifier, and a click that opened the
settings instead of switching to STANDBY. Reported from a KPA500 whose panel
showed band, SWR and temperature at the same time.
The card's offline text also borrowed the Acom's string, so a KPA that dropped
its link announced itself as an Acom.