Commit Graph
240 Commits
Author SHA1 Message Date
rouggy 8538f48259 feat: Publish-to-catalog export for awards (edit in UI, version, ship to team)
Adds ExportAwardForCatalog(code, version): writes the selected award as a
catalog-format JSON ({"def":…,"references":…}) stamped with a version and with
user_edited cleared, ready to paste over internal/award/catalog/<code>.json. A
new release then propagates the change to the whole team via mergeCatalog —
unedited copies auto-upgrade, edited ones are offered the update.

UI: a version input + "Publish to catalog…" button in the award editor footer,
defaulting to one past the award's current version.
2026-07-20 14:20:30 +02:00
rouggy 77a752efe3 chore: release v0.20.4 2026-07-20 12:06:32 +02:00
rouggy 781fbfaa30 fix: wire up File - Exit (was disabled and had no handler)
The File menu's Exit item was hard-disabled and its action had no case in the
menu dispatcher, so it did nothing. Enable it and route file.exit to QuitApp,
which runs the same graceful beforeClose shutdown as the window close button.
2026-07-20 12:05:12 +02:00
rouggy 61c11c0fe3 fix: clear entry-form award refs when the callsign is wiped
Live award detection merges pickable refs into award_refs per call, but nothing
dropped them when the call was cleared, so a previous call's ref lingered onto
the next (IT9AOT's ref still showing after typing F4BPO, both listed in the F3
Awards tab). Clear award_refs the moment the callsign field is emptied.
2026-07-20 11:57:04 +02:00
rouggy 64b746f007 feat: materialize award references into the QSO row (award_refs column)
Award refs are now computed once and stored on the QSO as a JSON column
(award_refs, e.g. {"DDFM":"74","WAJA":"12"}) instead of recomputing the whole
award engine on every grid page load. Written on log/edit/UDP-import and
bulk-recomputed when an award definition or reference list changes; a one-time
per-logbook backfill materializes pre-existing QSOs. The grid reads the column
directly like any other field, so it's fast and available everywhere (including
the shared MySQL logbook).

Also fix per-profile grid column layout: the DB copy was already per-profile,
but the localStorage cache used one global namespace and shadowed it, so a
profile switch kept the previous profile's columns/widths. gridPrefs now scopes
the cache by active profile id and the grids remount on profile:changed.
2026-07-20 11:51:49 +02:00
rouggy 9e4f43f648 fix: offline operators removed from live_status + award-column visibility
Live status: when an operator goes offline (no QSO in the window) OpsLog now
DELETEs its live_status row instead of just flipping online=0, so a status page
that lists present/recent rows shows them as gone without having to read the
online column — the whole point of the feature. The row reappears on the next
QSO.

Recent QSOs columns: toggling an award column (e.g. DDFM) rebuilt columnDefs and
made AG Grid re-apply every colDef hide default, so hidden non-award columns
(QTH/Grid) came back and restoringRef stayed stuck true (saving off). The
restore-saved-state effect now also runs on awardShown changes, so the other
columns keep the user's visibility.
2026-07-20 09:55:14 +02:00
rouggy 5f044b959e chore: release v0.20.3 2026-07-20 01:25:28 +02:00
rouggy 68a49be8c1 feat: rate meter OP/Team display, on-air-only station widget, column-filter count
Rate meter: on a shared MySQL logbook it now shows two lines — OP (the active
operator, accent) and Team (all operators, foreground) — each with the 10/60-min
QSOs/hour; single-op keeps the one-line display.

Live-stations widget: only stations currently on air are listed (offline ones
are hidden rather than greyed).

Recent QSOs footer: 'Showing X of Y' now reflects the AG-Grid COLUMN filters
(the funnel icons) — the grid reports its displayed row count, so filtering a
column shows how many QSOs remain instead of always the full total.
2026-07-20 01:08:17 +02:00
rouggy 8eb82d6cdb feat: QSO rate meter — per-operator AND team totals
GetQSORate now returns both the active operator's rate (their own performance)
and the whole station's rate (all operators combined). RecentRateBreakdown
computes both in one scan of the recent rows (per-operator + all-operators),
replacing RecentRate.
2026-07-20 01:08:17 +02:00
rouggy 59e6570f17 chore: release v0.20.2 2026-07-19 19:11:06 +02:00
rouggy 24eaf597fd fix: ON AIR badge correct at launch + faster to appear
At launch nothing is in memory yet, so the badge showed offline even with a
recent QSO. liveLastQSOTime is now authoritative: it takes the most recent of
the in-memory stamp AND the DB (this operator's last QSO — covers a contact
from the shared logbook or one logged before launch), used by both the
published status and the badge. The badge polls the backend every 5 s (down
from 15) and on each qso:logged, so it shows on air within a few seconds and
flips online instantly on a new contact.
2026-07-19 18:35:18 +02:00
rouggy 9156acea5f feat: ON AIR status-bar badge + auto-updater UI (10-min check, progress)
ON AIR badge (bottom status bar, shown when live-status publishing is on): a
blinking red light + "On air" when a QSO was logged in the last 5 min, dim
"Offline" otherwise. Seeded at launch from LiveLastQSOAgeSec so it's right
immediately, flips online on qso:logged, expires via a 10s tick.

Auto-updater UI: the update check now also runs every 10 minutes, and the
update notification downloads and installs in-app — a live progress bar
(update:progress) then OpsLog restarts on the new build. Falls back to opening
the release page when there's no auto-download asset or on error (retry).
Regenerated bindings for DownloadAndApplyUpdate / LiveLastQSOAgeSec.
2026-07-19 18:15:07 +02:00
rouggy 4ab4f70349 fix: no duplicate logs on repeat Enter + ESC stops the callsign lookup
Duplicate logs: `saving` is React state (async), so a burst of Enter presses /
clicks fired before the re-render each ran a full AddQSO and logged the same
QSO several times when a slow lookup made logging take a moment. A synchronous
savingRef guard now ignores the repeat immediately.

ESC: clearing the entry (ESC) left the "looking up" spinner turning and let a
still in-flight lookup re-populate the field afterwards. resetEntry now cancels
the pending lookup debounce, hides the spinner at once, and bumps a generation
counter so a late lookup result is discarded instead of applied.
2026-07-19 17:42:27 +02:00
rouggy 0a9a09bec2 chore: release v0.20.1 2026-07-19 03:12:35 +02:00
rouggy 34ec91684e fix: restrict RST fields to valid report values
The RST comboboxes allowed free text, so a report typed by hand that isn't in
the mode's list (e.g. "600") was committed. Drop allowFreeText on the four RST
fields (QSO entry + edit modal) and make commit-on-type push a value only when
it's actually in the list; a leftover invalid entry reverts to the last valid
value on blur. Programmatically filled values (FT8 SNR over UDP, presets) are
unaffected — only manual typing is constrained.
2026-07-19 03:12:12 +02:00
rouggy 11f1e332f7 feat: modernise the Statistics panel with colour
Headline KPI tiles are now tinted cards: a soft colour wash, a corner glow and
a left accent bar, each tile its own hue (QSOs blue, calls teal, DXCC violet,
continents orange, confirmed green) — the number itself stays in foreground ink
for full contrast on every theme. Chart cards gain a soft shadow and a coloured
dot in the header matching the section.

Charts are no longer all-blue: BY MODE colours each bar by the categorical
palette (modes are real categories, like the continents donut), and the other
horizontal-bar charts take their card's accent (top entities green, operators
violet, stations orange) instead of a single blue. Single-hue-per-series
discipline is kept; only genuine categories get per-bar colour.
2026-07-19 03:12:00 +02:00
rouggy d38c783dcc chore: release v0.20.0 2026-07-19 02:34:23 +02:00
rouggy c825caa7a8 feat: relay auto-control by frequency / band (PstRotator-style)
Automatically switches the Station Control relay boards from the rig's
current frequency / band. Each relay carries one rule: off (manual), a
frequency window (ON inside [lo,hi] kHz, OFF outside), or a set of bands
(ON on those bands, OFF elsewhere). Evaluated on every CAT frequency/band
change; a relay is only switched when its desired state actually changed,
so tuning within a range doesn't hammer the board.

A cached atomic flag keeps the CAT hot path a no-op when the feature is off
(important during FT8 slice churn). Saving re-applies from the live
frequency so a changed rule takes effect immediately.

New Settings → Hardware → Relay auto-control section: master enable plus a
per-relay mode (Off / Frequency / Band) with kHz range inputs or band
chips, per configured relay board. i18n EN + FR. Azimuth/Time modes (the
other two PstRotator tabs) are left for later.
2026-07-19 01:57:56 +02:00
rouggy 215652570c fix: blank ADIF monitor settings panel (hooks in a called-as-function panel)
PANELS[selected]() invokes each settings panel as a plain function, so a panel
must not call hooks. ADIFMonitorPanel uses useState/useEffect/useI18n, which
broke the Rules of Hooks and blanked the section. Render it through JSX
(() => <ADIFMonitorPanel />) so it mounts as a real component with its own
hook context — same pattern as the Flex panel.
2026-07-19 01:51:21 +02:00
rouggy 79552bfae1 fix: Club Log status R->Y->R flicker on UDP auto-log
A UDP auto-logged QSO shows its Club Log (and other) upload status flick
R->Y->R even though the upload succeeds. Two refreshes race: the immediate
one after the UDP log reads the QSO at "R", the debounced one after
extsvc:uploaded reads it at "Y"; variable MySQL latency lets the older (R)
result resolve last and clobber the newer (Y) data.

Guard refresh() with a monotonic sequence number so only the most recently
issued refresh may apply its result — an older in-flight refresh is dropped.
Fixes the same class of stale-clobber for every confirmation column.
2026-07-19 01:47:39 +02:00
rouggy 8fc04563e1 feat: ADIF monitor — auto-import QSOs from watched external ADIF files
Watches a configurable list of external ADIF files (fldigi RTTY logbook,
N1MM, VarAC…) and imports newly appended QSOs automatically. Each record
goes through the existing UDP-log path, so it gets full enrichment, ±2-minute
dedup (shared udpLogMu, can't race the UDP auto-log) and automatic upload to
the configured external services — no per-file toggles like Log4OM.

A newly added file starts at its current size (offset -1 sentinel → size on
first scan), so the QSOs already in it are NOT bulk-imported; only contacts
logged after it was added come in. Reads only up to the last complete <eor>
so a half-written record waits. Handles truncation/rotation (re-reads from 0,
dedup protects) and persists per-file offsets without clobbering a concurrent
UI edit of the file list.

New Settings → ADIF monitor section: master enable + add/remove/toggle files.
Backend emits adifmon:imported → the grid refreshes and a toast reports the
count. i18n EN + FR.
2026-07-19 01:35:00 +02:00
rouggy 19993bafc1 feat: header rate/propagation colours + CW macro word space
Header: colour the propagation indices semantically (SFI/SSN green when
strong; A/K green quiet → yellow unsettled → red storm) and glow the QSO-rate
numbers the brand accent when active, dim to muted when idle.

WinKeyer/Icom CW: append a trailing word space to each macro send so two
macros fired back-to-back don't run together in the keyer buffer ("CQ"+"TEST"
→ "CQTEST"). The keyer keys the space at the current speed, so it scales with
WPM. Only the macro path is affected — send-on-type stays per-character.
2026-07-19 00:59:05 +02:00
rouggy 14c87f7fa9 chore: regenerate Wails bindings for GetQSORate / QSORate 2026-07-18 21:53:44 +02:00
rouggy 9d4ccb9254 feat: QSO rate meter (10/60 min) in the header
Opt-in via Settings→General (portable pref opslog.showQsoRate). Shows the
contest-style QSO rate in QSOs/hour, projected from the trailing 10-minute
(count ×6) and 60-minute windows, between the widget icons and propagation.

Backend: qso.RecentRate counts QSOs whose start time falls in each trailing
window, scanning only the last 400 rows (cheap on a large log); App.GetQSORate
exposes the 10/60-min counts. Frontend refreshes on qso:logged and a 30s tick.

The meter shares the propagation grid cell — the header is a fixed 6-column
grid, so adding it as its own child pushed profile/band-map/compact onto a
second row. i18n EN + FR.
2026-07-18 21:51:51 +02:00
rouggy d30b305ff2 chore: release v0.19.9 2026-07-18 19:32:17 +02:00
rouggyandClaude Opus 4.8 5abe4bd0c3 fix: restore theme on restart + consistent spot pills + red DVK TX
theme: self-heal the persisted theme after mount. The synchronous boot
read only looks at localStorage, which is empty when the WebView cleared
its storage or when syncPortablePrefs ran before the backend wired its
settings store (GetUIPref returned "" with no error) — so a restart could
silently land on the default light theme. ThemeProvider now re-reads the
portable pref from the DB once the backend is up (retrying briefly to ride
out a slow startup) and applies it, without clobbering a manual pick.

ClusterGrid: the Call cell now uses a danger pill for NEW DXCC, consistent
with the NEW BAND / NEW MODE pills, instead of a full-cell red fill. cellChip
inherits the column's font size (no fixed 9px / height) so a pill around a
callsign stays the same size as the plain callsigns beside it.

DvkPanel: the voice-keyer TX indicator (LED + label) is red while
transmitting, not orange.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-18 19:28:55 +02:00
rouggyandClaude Opus 4.8 3ed9f29d9a feat: never drop cluster spots + theme-aware spot badges + FR settings
Backend: replace the bounded cluster-event channel (which dropped spots
under RBN bursts once enrichment/UI fell behind) with an unbounded
clusterQueue (slice + sync.Cond). The socket-read goroutine still never
blocks, but a burst now grows the backlog and drains instead of losing
spots. Head compaction keeps a sustained burst from growing the backing
array without bound.

ClusterGrid: drop all hard-coded light-theme hex colours (Time, Country,
Spotter, Comment, POTA, band/mode fills) for semantic CSS-var tokens so
they read correctly on every theme. Replace the heavy full-cell band/mode
fills with small rounded pills (cellChip). Only NEW MODE pills the mode
cell — NEW SLOT (band and mode each worked, just not together) no longer
highlights the mode cell, which wrongly implied the mode was new.

App: stage incoming spots ~50ms and resolve their slot status before
inserting, so a row paints with its badge already on instead of flashing
plain text then flipping to a pill. Self-spot toast still fires per spot.

i18n: translate the General settings that were still English — telemetry
and live-status toggles, the Main view pane pickers and their options.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-18 18:20:06 +02:00
rouggyandClaude Opus 4.8 04eaa91bd8 chore: drop the station-owner note under the BY OPERATOR chart
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-18 17:12:59 +02:00
rouggyandClaude Opus 4.8 443698b507 feat: per-operator filter in the statistics dashboard
New Operator picker next to the contest picker, populated with the operators
actually present in the log. Selecting one recomputes every statistic for that
operator — QSO/DXCC totals, top countries, continent split, by band/mode, and
the rate/best-60. "— Station owner —" buckets QSOs logged with no OPERATOR set.
Shown only when the log has more than one operator.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-18 17:11:52 +02:00
rouggyandClaude Opus 4.8 db2908b3ef fix: RIT Ctrl+arrow tuning also works while the QSO entry field has focus
The radio-style Ctrl+left/right RIT shortcut skipped any focused input/textarea
(to preserve word navigation), but that's exactly where the operator's focus is
mid-QSO. Now only the RIT offset row itself is skipped; text-field word nav is
overridden only while RIT is engaged.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
2026-07-18 14:33:55 +02:00
rouggy a1be0dfe68 feat: Added color per band in statistics as well as number of qso 2026-07-18 04:48:26 +02:00
rouggy ac4039393d feat: RIT back to 0 once a qso is logged 2026-07-18 04:06:43 +02:00
rouggy bb53085c21 fix: wider space for country names in statistics 2026-07-18 03:52:14 +02:00
rouggy 031dfa8f46 feat: Adding show password for SMTP server 2026-07-17 20:50:05 +02:00
rouggy 6322a425d8 feat: Added columns selection in the Net Control 2026-07-17 20:21:29 +02:00
rouggy 9f08df1c39 fix: fix a bug adjusting the length of Ultrabeam 2026-07-17 20:19:54 +02:00
rouggy aeeb658269 fix: Improved status badges in cluster 2026-07-17 19:35:30 +02:00
rouggy 8e088576c7 fix: Better matching of the counties for the USA-CA 2026-07-17 16:28:32 +02:00
rouggy eb2ff8ed59 feat: New badges in cluster view for new Counties and new POTA 2026-07-17 15:28:36 +02:00
rouggy dd3b51a2ae feat: Added support for US Counties in OpsLog / Extra feature with DXHunter 2026-07-17 13:23:35 +02:00
rouggy 1a155e3627 fix: bugs 2026-07-17 11:55:40 +02:00
rouggy cd13921322 fix: QSL Manager properly calculating new slot (Digi modes are grouped together) 2026-07-16 23:26:04 +02:00
rouggy 46e3619a38 fix: relocated Lotw and Alerts 2026-07-16 22:56:21 +02:00
rouggy dcf006905c fix: QTH field is wider to see the full city names 2026-07-16 22:47:24 +02:00
rouggy 7cf2dfeaf9 feat: For steppir & Ultrabeam,possibility to change each element length 2026-07-16 22:32:29 +02:00
rouggy 69229964f4 fix: bug 2026-07-16 22:13:21 +02:00
rouggy 09848adddc feat: Added Ultrabeam/Steppir to Station Control with function to retract elements. 2026-07-16 22:10:36 +02:00
rouggy f853dd479e chore: release v0.19.8 2026-07-16 22:02:37 +02:00
rouggy 829c236d6c feat: New Station Control, allow to control Webswitch 1216H or KMTronic 2026-07-16 22:01:07 +02:00
rouggy c9fd1379e1 feat: While using Flex & Steppir or Ultrabeam can prevent transmit when antenna is moving 2026-07-16 19:51:25 +02:00