The conninfo that authorises the RX stream goes out during the login,
before the audio socket exists — it has to, since it is what authorises
it. So the rig is told to send audio to :50003 while nothing is bound
there, gets an ICMP port-unreachable back, backs off, and the audio turns
up only when its own retry timer comes round: twenty to thirty seconds by
the operator's watch, ninety in one log.
It is sent once more the moment the port is listening, which is the same
message the session already carries — RS-BA1 repeats it too. The audio
dial moved above the pumps, because after ctrlPump is running the
control-stream auth state belongs to it.
"I turned the sound back on and nothing comes out of the speakers", with
a log that reports success at every step: the network audio stream up,
664-byte packets arriving, the monitor started. The render goroutine's
error was thrown away — a device unplugged, renamed by Windows or unable
to open at 16 kHz fails exactly there, silently.
It is logged now, with the device id. Two once-only lines either side of
it say whether the decoded audio is reaching a running monitor or
arriving with nobody listening, which separates a device fault from the
speakers simply being switched off.
The guard I added for services with no credentials demanded one, and
nobody has ever set it: OpsLog carries its own Club Log APPLICATION key
(clublogAppAPIKey), so the account is an email, a password and the
logbook callsign. An operator whose live upload had been working for
months was told the service was not configured the moment he sent QSOs by
hand after an import.
Written in app.go, the rules drifted from the uploaders on the first try.
They now live in internal/extsvc beside the Upload* functions that
enforce them, each case mirroring that function's own guard — which also
caught Cloudlog, where the station profile is required and the check did
not ask for it. The message names the fields actually missing rather than
listing everything the service takes.
Audio off, and the IC-7760 still answers at connect and then never again:
twenty-eight commands sent, not one reply, packets still arriving on the
stream. A count says how much went unanswered and never which command
went out last — which is the one thing that can identify a frame this rig
does not tolerate, on a radio nobody here has.
The transport now keeps the command headers of the last eight frames and
prints them with the silence report.
The RX audio stream is experimental and shares the rig's session with
CI-V. The shape in an operator's log is unmistakable: audio packets
arriving by the hundred while not one CI-V reply comes back, the watchdog
tearing the session down, twenty seconds' pause, and the whole thing
again — read from outside as "the Icom keeps disconnecting", with
nothing pointing at the switch that would end it.
The log now says it, and names the setting. icomAudio counts what it has
delivered so the line distinguishes "audio is enabled" from "audio is
arriving", which is the half that makes it a suspect.
From an operator's log: an IC-7760 in standby, and OpsLog dialling and
dropping every forty seconds for as long as it was left there — control
link up, login OK, token renewed, and not one CI-V answer.
lastGoodAt bounds "the link answers but no CI-V comes back". It belongs
to a session and was never cleared when a new one opened, so a rig that
went to standby half an hour ago handed every fresh session a
half-hour-old last good read: past the grace before the first command was
even sent. Torn down at once, redialled twenty seconds later, torn down
again. Cleared on connect, the rule reads as it was written — silent
since connect is a rig in standby, and the session is kept so it can be
woken.
The console it is woken from was missing too. It appeared only once the
live CAT state said "icom", which a sleeping rig never says, so the ON
button was absent at the one moment it exists for. It now follows the
CONFIGURED radio — which also had to start following a radio switched
from the status bar, instead of waiting for a trip through Settings and a
Save that changed nothing.
An exported file was full of blank gaps: a record ran down a dozen lines
and the next appeared to start in the middle of the page. ADDRESS is a
multi-line field by the standard and callbooks and other loggers fill it
that way — "Kabul", four blank lines, "Afghanistan" — and the writer
copied the value out as it stood. The files were always valid, since ADIF
counts bytes; they were unreadable, and so was anything that quoted them.
Line breaks inside a value are now joined with a comma and tabs become
spaces, which is how an address reads on one line anyway. The length
prefix is computed after the flattening, so the record stays exact, and
every path through the writer gets it: the file exports, the uploads and
the record forwarded over UDP.
The changelog's 0.27.15 block also takes back the FT-map hover fix, which
landed after the 0.27.14 release commit and was sitting in that block.
The invisible circle that catches the clicks sits ON TOP of the dot, so
it takes the hover as well — and the tooltip was bound only to the dot
underneath. From the moment the stations became clickable, pointing at
one said nothing: the callsign, square and report an operator reads off
the map had simply gone.
The map draws a dot per decoded station and they did nothing. They now
answer the same two gestures as the decodes list, because the two are
views of the same list and a click has to mean the same thing on both:
one takes the callsign into the entry (and points the PSK Reporter panel
at it), two answer it.
The handlers were written inline on the list, so the map could not offer
them without a second copy — they are named once now and given to both.
Leaflet leaves the telling apart of click and dblclick to the handler, an
invisible marker three times the dot's radius takes the clicks (a
three-pixel dot is a fine mark and a poor target), and the double click
is stopped rather than merely unpropagated: the map zooms on one, and
answering a station is not a request to zoom in on it.
The rest between two series was two minutes — four overs on FT8, by
which time the DX has worked four other callers and half the time has
gone. It is now counted in the station's OWN overs and is one by default:
seven calls, one over listened through, and it goes again if the station
is still there. The deadline lands mid-cycle on purpose, so "sit out one
over" means one over rather than depending on a millisecond of clock
skew.
A period the target was DECODED in is never counted as a miss. A period
is judged more than once — decodes arrive in a burst and stragglers
follow — and a later judgement holds a partial view of it, not evidence
of absence: D2ACE answered in the very period the counter then read as a
miss.
The readout moved out of the Auto button and beside it. "Auto D2ACE 1/7
·1/3" read as one number, and the control changed width every period.
The callsign is now the biggest thing on the row, the calls and the
missed periods each carry a label, the miss count appears only once there
is one, and a station being waited for gets its own amber chip.
The world map was the only one that remembered anything. Panning and
zooming a map is the operator saying which part of the world they work,
and on the FT decodes map and the grid-square map that was thrown away on
every tab switch. Both now keep centre and zoom, through one shared
helper (lib/mapView) that the world map uses too, and the keys are
portable so a copied data folder brings the views with it.
The world map also waits for the station's square before it paints. It
drew the world at 0 degrees and then moved to the operator's longitude —
a screenful of Esri tiles fetched and discarded on every first run. It is
now built once, knowing where it is looking; a profile with no locator
gets the default view after two seconds rather than a blank panel.
Centred on 0 degrees it left an Australian looking at their own country
in the bottom-right corner, with the paths to everywhere they work
running off both edges. Centred on their own longitude the same map reads
the way their antenna does: the Americas to the east, Europe and Africa
to the west. Leaflet repeats the world horizontally, so this is a choice
of viewpoint and costs nothing — the tiles either side are the same
world, and unwrapLon already draws the arcs across the seam.
The latitude is damped rather than followed (a station at 69 north
centred on itself would spend half the map on the Arctic), the station's
square arrives after the map is built so it re-centres once when it
lands, and a view the operator has panned to themselves still wins.
An operator with a callsign in the field, switching FT8 to SSB, kept
"+00" as the report. The edited flag protects a report the operator
chose — 57 rather than 59 — and it was holding across a change of mode as
well, where it protects nothing: a decibel figure is not a weak SSB
report, it is not a report at all. Worse, anything that fills the field
from the rig sets that flag too (the S-meter readouts in the rig
consoles), so the field could be stuck in the wrong notation for the rest
of the QSO.
The flag now holds only while the report still belongs to the mode's
family. When it does not, the operator's own judgement is carried across
where it can be — 57 becomes 579, 599 becomes 59 — and the mode's preset
answers where it cannot.
Below 59+20 comes 59+15, then +10, +5, then a plain 59 and down through
58, 57. Stepping the S digit and leaving the suffix where it was turned
59+20 into 58+20, which nobody has ever said on the air. Five decibels at
a time above S9 — the same increment sMeterRST rounds an S-meter reading
to — and one S-unit below it.
The mouse wheel steps the RST fields — one S-unit on an RST or RS, one
decibel on a digital report, up for a better one — in the entry strip and
in the QSO editor. The dropdown beside them lists the reports worth
having to hand, not all 41 decibels, so the wheel works on the value
rather than walking the list. The listener is native and non-passive:
React attaches onWheel passively, where preventDefault does nothing and
the panel scrolls away under the field being adjusted.
PSK Reporter, whole-band scope: clicking a decode reset the report count
to zero. The window there is the BAND's — every FTx report on it,
filtered by target only when the analysis is drawn — and it was emptied
on every target change, throwing away an hour of evidence at the moment
the operator asked the question it answers. The narrow scope still clears
it: there the window is one station's, and keeping it would answer the
new question with the old station's evidence.
ZD8GB — watch-listed, six streams a period, two of them RR73 — was
refused as "parked" for the rest of the session. Parking answers "it
will not answer, stop wasting the evening on it", which is a fair verdict
about a station the LOG picked out and the wrong one about a station the
OPERATOR named: a DXpedition running a pileup takes more than two series
of calls to get through to, which is exactly why it is on the list. The
rest between series still applies, so it cannot monopolise the
transmitter — it simply never becomes ineligible.
Send to (right-click) now refuses a service with no credentials and says
which are missing. The upload runs on its own goroutine and reports into
the QSL Manager's console, which is not open when the command came from
the QSO list, so an upload to an unconfigured service looked exactly like
one that worked. The toast is also raised only once the backend has
accepted the request, and Cloudlog / Wavelog and HamQTH name themselves
in it.
Three field reports.
Icom CI-V address 00 could not be kept: zero was read as "not
configured" in all three places that validate it, so every save put the
rig back to the IC-7610's 0x98 — and the model dropdown followed, since
it is derived from the address rather than stored. Picking "Other
(custom address)" also had no effect of its own: the list re-derived
itself and snapped back to whatever rig matched. It now stays chosen.
Cloudlog/Wavelog showed "17m/17m" on ordinary FT8 contacts (OE6CLD).
Every QSO is stamped with a receive side equal to the transmit side, and
the uploaded record carried it; Wavelog draws band/band_rx whenever both
are there. In ADIF an absent BAND_RX means "same as transmit", so the
uploaded record now writes the receive side only when it differs. The
copy forwarded to another logger over UDP keeps writing it in full —
that is why it was stamped in the first place (Log4OM reads BAND_RX) —
through its own ForwardRecordADIF.
"S/F" in a spot comment joins superfox / sfox / F-H as FT8.
It went in after the 0.27.13 release commit, so the shipped build does not
contain it — and the entry had been folded into that block's fixes line,
where it claimed a fix nobody had. The 0.27.13 block is back to what was
released.
A decoder sends a period's decodes in a burst, and stragglers follow — a
deep decode a second behind the rest. The sweeper judged the burst and
CLEARED the buffer, so the straggler opened a fresh one under the same
period key and was judged on its own: the ladder applied to a handful of
late arrivals with the other thirty stations of that period nowhere in
sight, and often after the reply to the burst had already put us on the
air, where nothing can act on it at all.
The buffer now outlives the judgement. A period stays open until a decode
stamped with the NEXT slot arrives; a straggler appends to it and the
period is judged again, whole. Judged once per period otherwise — acDirty
says whether anything new has come in — and the same flag now answers the
dead-band case that the cleared buffer used to stand for.
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.
Reported from a real shack: JTDX decoding FT4 came through as Q65. A
Decode carries a one-character marker rather than a mode name, and the
forks do not agree on that one — so the character alone cannot answer,
and its wrong answer reached everything behind it: new mode, new slot,
the mode filter, all computed against a mode nobody was using.
The sending program's own Status settles it. It comes from that program,
names the mode in full, and is re-sent whenever it changes, so it knows
what is being decoded in a way one character never can. Only the
ambiguous marker consults it: the ones both forks agree on keep
answering from the table, Status or no Status, and with no Status at all
':' still reads as Q65 — WSJT-X's meaning, the older and commoner.
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.
Reported on an FTDX101MP: the slider sprang back to 100 W. The console
was not wrong about the rig — yaesuMaxPower already answered 200 for
that model, and the slider was drawn to it. The SET path carried its own
hard-coded 100, so asking for 200 W sent PC100, the radio obeyed, and
the next poll read back what had actually been set.
One ceiling now, the one the console draws to, so the two cannot say
different things. Pinned with the model list, including the unknown-rig
case: crediting a radio with power it does not have would be commands it
NAKs, so silence still means 100.
HAMLOG.online no longer issues API keys, and its upload API takes
nothing else. An operator without a key cannot obtain one, so the
auto-upload switch, the on-close sweep and the 'Send to' entry were all
arming something that could only fail — silently, once per QSO.
Closed at the source rather than hidden in the UI: the upload returns a
sentinel that says why, the manager stops routing to it and says so once
a session, and the manual path refuses with the same words. The settings
page states it plainly instead of showing a switch that does nothing.
Nothing else goes. Their confirmations arrive as an ADIF FILE and never
needed a key, so that import stays; the sent/received state already in
operators' logs stays readable, filterable and bulk-editable; and the
upload itself is kept whole as uploadHamlogLive, still covered by its
request-shape tests, against the day keys come back.
The one configured service the upload menu did not offer. Not because it
uploads one record at a time — QRZ, HAMLOG.online and HamQTH all do —
but because Cloudlog keeps no per-QSO sent status, on purpose: it
dedupes server-side, so re-sending is harmless and nothing has to be
remembered. The menu had been built around that status.
An explicit selection needs none of it. The operator picked the rows,
and the server refuses what it already has — which is exactly why the
missing column stops mattering the moment a human is choosing.
Reported with real callsigns: every Asiatic Russia contact logged CQ 17
/ ITU 30, whatever the operator's real zone. RU0LL and RA0FF are 19/34,
UA0SDX is 18/32, and QRZ.com had all three right.
Measured before touching anything: cty.dat answers 17/30 for RU0, RA0,
UA0 and UA9 alike — one representative pair for a country eight CQ zones
wide — while ClubLog's prefix table gives 19, 19, 18 and 17. The
reporter's instinct that no UA0 sits in CQ 17 was exactly right.
fillFromDXCC overrode the callbook's zones on purpose, and the reason
holds only for the country: QRZ returns the political nation where
cty.dat returns the DXCC entity. A zone answers a different question —
not what the callsign IS but where the station SITS — and there the
per-station page beats a country default. Zones now FILL rather than
override; the entity is untouched.
The cache made it worse by remembering our conclusion as though the page
had said it, so the wrong zones would have outlived this fix. A lookup
is now cached as the callbook returned it and the country file is
applied on read, which also lets a cty.dat update reach old rows.
Reported from a real import: every ZK2 contact came back New Zealand and
Niue vanished from a DXCC that had it confirmed. cty.dat is not wrong,
it is CURRENT — Niue moved to E6, so ZK2 reverted to New Zealand there.
ZK1 loses the Cook Islands the same way, and the reporter was right to
suspect more.
ClubLog's prefix table is date-ranged and still knows both, which is the
whole reason for enabling its country file. We consulted it only for
callsigns that already HAD a per-callsign exception — so a ZK2 with no
exception never reached it. It is now asked whenever no exception covers
the QSO's date.
Two limits keep the blast radius honest. It never overrules an exact
'=CALLSIGN' entry in cty.dat — that is somebody having looked at this
very callsign, and a prefix rule does not overrule it, which is why
Match now says how it matched. And where ClubLog has no answer (E6, TO5A
and their like are absent from its prefix table) cty.dat still decides,
because silence is not an answer. Measured before changing: on a sample
of thirty calls the two files agreed on twenty-eight, and both
disagreements were this bug. Opens 0.27.11.
A K3NG controller answered PuTTY perfectly and told OpsLog 'no reply to
C'. The reason is not the protocol: the client opened and CLOSED the
serial port for every single command, and an Arduino-based controller
resets when its port is opened — DTR pulses the reset pin. OpsLog was
rebooting it several times a second, and every command it sent landed in
a bootloader.
The port is opened once and held, per COM port, at package level: the
callers build a fresh Client per poll, so the port has to outlive them,
and a serial port is a single-owner resource in any case. A newly opened
port is given two seconds to boot before the first command, bytes left
from a previous exchange are drained rather than read as this command's
answer, and a failed exchange drops the port so the next starts from a
clean open instead of repeating the same silence.
Reply parsing was already right for both flavours and now has the real
strings to prove it, that controller's '+0140' among them.
A list whose rows can only be moved by a sixteen-pixel grip is a list
most people conclude cannot be moved at all. The grip stays as the sign
that it can, and the row itself now carries the gesture — plus a line on
the edge the row would take, because the question a dragging hand asks
is 'between which two', which a highlighted target does not answer.
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.
Only Kenwood implements it — TX1 is that family's second transmit
command — and every other backend keys the one way it knows. A checkbox
offered to all of them would change nothing on most, which is the same
dead furniture as ANT2 on a radio with one socket. Gated on the Kenwood
backend, and the label says so.
From a TS-590SG report: the voice keyer played through the rig's USB
codec and the radio transmitted silence. Its manual says why — 'TX P1,
0: SEND (normal transmission using the MIC input), 1: DATA SEND
(ACC2/USB input)' — and OpsLog only ever sent the bare TX, so the radio
dutifully opened a front microphone nobody was speaking into.
An option on the audio page, shown for CAT keying, says where the
keyer's audio actually arrives; the manager routes it to a backend that
draws the distinction and falls back to the ordinary key for every rig
where one PTT is all there is. Test PTT goes down the same path, so it
tests what will happen rather than something adjacent.
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.
From an IC-7300 report, four faults and one addition.
USB and LSB could not be commanded at all: modeCode knew 'SSB' — which
resolves the sideband from the band — and answered 'unsupported mode' to
the sideband names themselves. So an operator wanting USB on 40 m had no
way to say it, from the console or from anywhere else. They are separate
buttons now, and a rig reporting the folded ADIF 'SSB' still lights the
side its frequency implies.
The console offered controls the radio does not have: ANT1/ANT2 on a rig
with one socket, and a PSK button every non-7610-class Icom NAKs. Both
now follow the model, as the band buttons and attenuator steps already
did. Mic gain stops being phone-only — on USB-D it still sets what the
radio transmits at, so an operator who lives in FT8 had none.
CI-V address 0x00 was refused by a 'n > 0' test and silently replaced by
the IC-7610 default; an EMPTY setting is what means unconfigured, so the
parse error decides now, not the value. Plus the 60 m band button that
was missing.
The width was set for three characters, so the column grew when the
rotation came round to RTTY and every band beneath it moved — which the
eye reads as the matrix sliding rather than the row changing. Sized once
for the longest label it can show and pinned there, header spacer
included; past four characters (PSK31, MSK144) the type gives way
instead of the column.
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 panadapter has finite room: spots close in frequency are stacked
behind a '+' and only one is drawn, chosen by PRIORITY — a parameter
'spot add' accepts and OpsLog never sent. So a new entity sat invisible
behind three stations already in the log. DXHunter has sent it for
years; the tiers here are the same idea in the operator's own words:
the entity never worked (with my own callsign, for a multi-op), then
band/mode/slot, then the reference hunts, then everything else.
And a callsign already worked on this exact band and mode stops
advertising a need. Working it again cannot turn a missing QSL into a
confirmation — the QSO is already there — so shouting NEW DXCC over a
station worked an hour ago only teaches an operator to distrust the
colour. The need is real and stays on every OTHER station of the entity,
which is where it can be answered. Applied on both paths out of the
verdict, including the early one that leaves the loop first.
The FT map drew a strip of dead space along the bottom after a zoom.
Leaflet measures its container ONCE, at creation — which for this panel
is the instant the tab is selected, before the flex layout has settled —
and then asks for tiles to fit that stale size for ever. A ResizeObserver
hands it the real size, plus one pass after the first paint for the
layout that settles without ever firing a resize.
And the decode list's continent chips are the seven, fixed. Building
them from the feed meant a row that reshuffled itself every period — a
chip appeared when the first Asian station decoded and moved everything
sideways under the pointer — and it could not say what the filter was
capable of until something had been heard.
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.
Chase POTA, US counties, prefixes and grids were written for the cluster
and stayed there, so an operator who does not chase parks still met NEW
POTA in the FT decode list and in Chase new: the same badge withdrawn on
one screen and shouting on the next. The setting is about what is hunted.
One helper answers the question for every panel, keyed by both the status
field names and the shorter category names so a single call serves badges
and filter chips alike. Chase new also stops CATEGORISING a row by a
marker that is switched off, which had left rows listed with no visible
reason for being there. A new US state has no switch of its own, so it is
always allowed.
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.
A soundcard mode is USB with audio in the mic path, and that is what
most rigs need. Asking for the mode by NAME is the better answer on a
modern transceiver with a DATA position and the wrong one on an older
set, where the CAT layer resolves 'digital' to RTTY/FSK — OmniRig does
exactly that, per rig file, and there is no arguing with it from here.
The operator clicking an FT8 spot landed in FSK, which keys from a
mark/space generator and cannot pass FT8 at all.
Applied in SetCATMode, the one funnel every backend and every caller
goes through, so it holds for a spot click, the band map and the mode
selector alike. The QSO is still logged as FT8: this is what the radio
is put in, not what the contact was.
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.
It ran into a panel nobody was showing: the button never set showLog, so
the tab sat on 'Pick a service' while a 25000-QSO upload came and went.
Now it opens the console like every other action here, and the console
has something to say: the callsign it is scoped to and how many of the
logbook's QSOs that leaves (a two-callsign database sends one of them,
which is the whole explanation for a count that looks short), the
exported record count and file size, and HamQTH's own reply.
Plus the two facts that make the site's own number readable: HamQTH
accepts the file and imports it in the BACKGROUND, and it reports what
it made of each record by e-mail — never in the reply we get. An
operator comparing counts a minute later is not looking at a failure.
HAMLOG.online was wired into all three when it arrived; HamQTH shipped
with only its uploader and its editor row, so the log could not be asked
'which contacts have never gone there' — the question that precedes
every backlog upload — and a log uploaded to HamQTH by hand could not be
marked, leaving OpsLog offering to send every one of those contacts
again. Sent side only, both whitelists, both panels, two hidden-by-
default columns.