From 9c33feecfa0a0f848a1828bbfc6216d85c860210 Mon Sep 17 00:00:00 2001 From: Gregory Salaun Date: Tue, 11 Aug 2026 13:08:04 +0200 Subject: [PATCH] feat(ui): PSK Reporter chip in the status bar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Beside the rig and amplifier chips, before ON AIR, because it is the same kind of fact they report: a link that is either up or it is not. Clicking it opens the settings that control it, like the amplifier chips do. Shown ONLY while the opening watch is on. A permanently grey chip for a feature nobody enabled is clutter, and the bar is 28 px tall — every chip in it has to earn its width. Green once decodes are arriving, amber while connected but silent: those are different states and an operator wondering why no opening has been announced needs to tell them apart. The count itself is in the tooltip, not on the chip — it moves several times a second on an open band, and a number flickering in the corner of the eye is a distraction rather than information. --- changelog.json | 4 ++-- frontend/src/App.tsx | 31 +++++++++++++++++++++++++++++++ frontend/src/lib/i18n.tsx | 4 ++-- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/changelog.json b/changelog.json index 711b264..833aab4 100644 --- a/changelog.json +++ b/changelog.json @@ -8,7 +8,7 @@ "Shared CAT is steadier and now diagnoses itself. It survives a rig answering \"busy\" just after transmit instead of dropping the link, stops repeating a PTT state the client never changed, and logs a plain explanation when another program has taken its port or when a client is set to a rig model instead of Hamlib NET rigctl. It also answers the lock-mode and stop-morse commands some clients send around every transmit, instead of refusing them.", "Web publishing now offers every field a QSO carries, awards included — 123 instead of 23 — from a searchable dropdown, with the chosen columns listed above it in publication order. Choose carefully: the page is public and the list includes addresses and e-mail.", "Band-opening detection no longer ignores long paths. It capped them at 2400 km on the assumption that anything further was not a single hop; multi-hop sporadic E is ordinary on 6 m, so the openings most worth hearing about were the ones being discarded. Direction still decides — a second hop leaves the sector the first one entered.", - "Band-opening detection now has the data it needs. Switching on \"Watch for band openings\" (Settings › DX Cluster) subscribes to the PSK Reporter feed — every station on the air reporting what it decodes, rather than the handful of VHF spots a cluster carries — and adds the two RBN nodes if they are missing. Pick the bands to watch: 12, 10, 6, 4 and 2 m." + "Band-opening detection now has the data it needs. Switching on \"Watch for band openings\" (Settings › DX Cluster) subscribes to the PSK Reporter feed — every station on the air reporting what it decodes, rather than the handful of VHF spots a cluster carries — and adds the two RBN nodes if they are missing. Pick the bands to watch: 12, 10, 6, 4 and 2 m. An MQTT chip in the status bar, beside the rig and amplifier, shows the feed is alive." ], "fr": [ "Décodes digitaux : le carré locator d une station pouvait être enregistré comme son indicatif quand le texte du message sortait de l ordinaire. Un grid à la place de l indicatif est maintenant refusé.", @@ -16,7 +16,7 @@ "Le CAT partagé est plus solide et se diagnostique tout seul. Il survit à un rig qui répond « occupé » juste après une émission au lieu de lâcher le lien, cesse de répéter un état PTT que le client n a pas changé, et écrit une explication claire quand un autre programme lui a pris son port ou qu un client est réglé sur un modèle de rig au lieu de Hamlib NET rigctl. Il répond aussi aux commandes de verrouillage et d arrêt du morse que certains logiciels envoient à chaque émission, au lieu de les refuser.", "La publication web propose désormais tous les champs d un QSO, awards compris — 123 au lieu de 23 — depuis une liste déroulante cherchable, les colonnes choisies étant listées au-dessus dans l ordre de publication. À choisir avec soin : la page est publique et la liste contient adresses et e-mails.", "La détection d ouverture n ignore plus les longues distances. Elle plafonnait à 2400 km en supposant qu au-delà ce n était plus un saut simple ; l Es à sauts multiples est ordinaire sur 6 m, donc les ouvertures les plus intéressantes étaient précisément celles qu on jetait. C est toujours la direction qui tranche — un second saut repart dans le secteur où le premier est arrivé.", - "La détection d ouverture dispose enfin des données qu il lui faut. Activer « Surveiller les ouvertures de bande » (Paramètres › Cluster DX) souscrit au flux PSK Reporter — toutes les stations en l air qui rapportent ce qu elles décodent, au lieu des quelques spots VHF que porte un cluster — et ajoute les deux nœuds RBN s ils manquent. Les bandes surveillées se choisissent : 12, 10, 6, 4 et 2 m." + "La détection d ouverture dispose enfin des données qu il lui faut. Activer « Surveiller les ouvertures de bande » (Paramètres › Cluster DX) souscrit au flux PSK Reporter — toutes les stations en l air qui rapportent ce qu elles décodent, au lieu des quelques spots VHF que porte un cluster — et ajoute les deux nœuds RBN s ils manquent. Les bandes surveillées se choisissent : 12, 10, 6, 4 et 2 m. Une pastille MQTT dans la barre d état, à côté du rig et de l ampli, montre que le flux est vivant." ] }, { diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 9da3320..a7733a4 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -51,6 +51,7 @@ import { ReportLiveActivity, LiveLastQSOAgeSec, GetAmpStatuses, AmpOperate, GetFlexState, FlexAmpOperate, + GetPSKReporterStatus, } from '../wailsjs/go/main/App'; import { Combobox } from '@/components/ui/combobox'; import { applyAwardRefs } from '@/lib/awardRefs'; @@ -1709,6 +1710,16 @@ export default function App() { const [showSettings, setShowSettings] = useState(false); // Re-read the "beam on map" toggle when Preferences closes (it's edited there). useEffect(() => { if (!showSettings) setShowBeamOnMap(localStorage.getItem('opslog.showBeamOnMap') !== '0'); }, [showSettings]); + // PSK Reporter feed, for the status-bar chip. Polled slowly: the chip only + // says up or down, and the count behind it is a tooltip. + const [pskr, setPskr] = useState(null); + useEffect(() => { + const load = () => { GetPSKReporterStatus().then(setPskr).catch(() => {}); }; + load(); + const t = window.setInterval(load, 10000); + return () => window.clearInterval(t); + }, []); + // "ON AIR" status-bar badge: mirrors the multi-op live status this operator // publishes — online (blinking) when a QSO was logged in the last 5 min, else // offline. Publishing is always on for a shared MySQL logbook (no user toggle: @@ -6854,6 +6865,26 @@ export default function App() { ); })} + {/* PSK Reporter, next to the hardware chips because it is the same + kind of fact: a link that is either up or it is not. Shown ONLY + when the opening watch is on — a permanently grey chip for a + feature nobody enabled is clutter, and the bar is 28 px. + + The decode count is in the tooltip rather than the chip: it moves + several times a second on an open band, and a number flickering in + the corner of the eye is not information, it is a distraction. */} + {pskr?.running && ( + + )} {/* ON AIR badge: "did I log a QSO in the last 5 min" — meaningful on ANY logbook backend (only the live_status PUBLISHING is MySQL-specific), so it is always shown. Gating it on MySQL made it vanish for diff --git a/frontend/src/lib/i18n.tsx b/frontend/src/lib/i18n.tsx index e3fbc8f..d755d53 100644 --- a/frontend/src/lib/i18n.tsx +++ b/frontend/src/lib/i18n.tsx @@ -15,7 +15,7 @@ const en: Dict = { // Menu bar 'prop.title': 'Propagation', 'prop.geomag': 'Geomag', 'prop.refresh': 'Refresh space weather', 'live.onAir': 'On air', 'live.offline': 'Offline', - 'live.onAirTip': 'On air — a QSO was logged in the last 5 minutes (published to the live status)', + 'pskr.tip': 'PSK Reporter — {n} decodes received on {bands}. Click for settings.', 'live.onAirTip': 'On air — a QSO was logged in the last 5 minutes (published to the live status)', 'live.offlineTip': 'Offline — no QSO logged in the last 5 minutes', 'live.stationsTitle': 'Stations on air', 'live.stationsEmpty': 'No station reporting yet.', 'live.stationsHide': 'Hide', 'upd.available': 'OpsLog v{v} available', 'upd.current': "You're on v{v}.", @@ -451,7 +451,7 @@ const en: Dict = { const fr: Dict = { 'prop.title': 'Propagation', 'prop.geomag': 'Géomag', 'prop.refresh': 'Actualiser la météo spatiale', 'live.onAir': 'On air', 'live.offline': 'Hors ligne', - 'live.onAirTip': "On air — un QSO a été loggé dans les 5 dernières minutes (publié dans le statut live)", + 'pskr.tip': 'PSK Reporter — {n} décodages reçus sur {bands}. Cliquer pour les réglages.', 'live.onAirTip': "On air — un QSO a été loggé dans les 5 dernières minutes (publié dans le statut live)", 'live.offlineTip': 'Hors ligne — aucun QSO loggé depuis 5 minutes', 'live.stationsTitle': 'Stations on air', 'live.stationsEmpty': 'Aucune station ne reporte pour le moment.', 'live.stationsHide': 'Masquer', 'rate.title': 'Rythme QSO (QSO/heure) — projeté sur les 10 / 60 dernières minutes',