feat: Super Check Partial + N+1 helper; fix Flex binding to SmartSDR CAT; telemetry callsign wait

- SCP/N+1: new internal/scp downloads the community MASTER.SCP master list and a
  docked two-column widget shows, as you type a call, the known calls containing it
  (Partial) and the calls one edit away (N+1) — click to fix a busted call. Opt-in
  in Settings → General; top-bar toggle; queried debounced on callsign input.
- Flex: OpsLog's GUI-client detection was too loose and could bind to "SmartSDR CAT"
  (or DAX) — both carry "smartsdr" in the program name — instead of the real GUI
  client, making SmartSDR CAT drop and reconnect in a loop while OpsLog was open.
  Now it binds only to a real SmartSDR/Maestro GUI client (e.g. a FLEX-8600M's
  integrated screen) and excludes cat/dax; dropped the risky empty-program fallback.
- Telemetry: on a fresh install the callsign isn't set at launch, so the once-a-day
  heartbeat recorded the machine UUID. Now it waits (~10 min) for the operator to
  enter their callsign before sending, falling back to the UUID only if none appears.
This commit is contained in:
2026-07-25 20:05:33 +02:00
parent 7e08553e6e
commit 51e279887d
12 changed files with 619 additions and 7 deletions
+2
View File
@@ -283,6 +283,7 @@ const en: Dict = {
'es.potaHint': 'Update your QSOs with the park reference from your pota.app hunter log. Paste your session token: log in at pota.app, open the browser DevTools → Network tab, click any api.pota.app request, and copy the full Authorization header value. The token expires after a while — re-copy it if the sync fails.', 'es.sessionToken': 'Session token', 'es.saving': 'Saving…', 'es.saveToken': 'Save token', 'es.potaThen': 'Then run the sync from the QSL Manager tab → service POTA hunter log (you can see and fix unmatched QSOs there).',
'es.soon': 'soon', 'es.comingSoon': '{name} — coming soon', 'es.notWired': "This external service isn't wired up yet.",
'lotw.usersTitle': 'LoTW user list', 'lotw.usersHint': "Downloads ARRL's public list of LoTW users + their last-upload date, to show a colour-coded LoTW badge next to a callsign (green < 1 week · amber 14 weeks · red > 30 days).", 'lotw.usersDownload': 'Download LoTW user list', 'lotw.usersDownloading': 'Downloading…', 'lotw.usersLoaded': '{n} users loaded · updated {date}', 'lotw.usersNone': 'Not downloaded yet — the badge stays hidden until you do.',
'scp.title': 'Super Check Partial', 'scp.partial': 'Partial', 'scp.close': 'Close', 'scp.fill': 'Fill {call}', 'scp.none': 'No match', 'scp.typeMore': 'Type a call…', 'scp.noList': 'Download the SCP list in Settings → General.', 'scp.enable': 'Super Check Partial / N+1 callsign helper', 'scp.settingsHint': 'Downloads the community MASTER.SCP master list and shows a two-column widget as you type a call: Partial (known calls containing what you typed) and N+1 (calls one character away) — to spot and fix a busted call.', 'scp.download': 'Update SCP list', 'scp.downloading': 'Downloading…', 'scp.loaded': '{n} calls loaded · updated {date}', 'scp.notLoaded': 'Not downloaded yet.',
'hw.connecting': 'Connecting…', 'hw.testConn': 'Test connection', 'hw.sending': 'Sending…', 'hw.testRotator': 'Test (point to 0°)',
// Profiles panel
'prof.deleteConfirm': 'Delete profile "{name}"? All its settings will be lost.', 'prof.dupPrompt': 'Name for the new profile (copy of "{name}"):', 'prof.dupSuffix': '{name} Copy', 'prof.newPrompt': 'Name for the new profile:', 'prof.newDefault': 'New profile',
@@ -648,6 +649,7 @@ const fr: Dict = {
'es.potaHint': "Met à jour tes QSO avec la référence du parc depuis ton carnet chasseur pota.app. Colle ton jeton de session : connecte-toi sur pota.app, ouvre les DevTools du navigateur → onglet Network, clique sur une requête api.pota.app, et copie toute la valeur de l'en-tête Authorization. Le jeton expire au bout d'un moment — recopie-le si la synchro échoue.", 'es.sessionToken': 'Jeton de session', 'es.saving': 'Enregistrement…', 'es.saveToken': 'Enregistrer le jeton', 'es.potaThen': "Puis lance la synchro depuis l'onglet Gestionnaire QSL → service POTA hunter log (tu peux y voir et corriger les QSO non appariés).",
'es.soon': 'bientôt', 'es.comingSoon': '{name} — bientôt', 'es.notWired': "Ce service externe n'est pas encore branché.",
'lotw.usersTitle': 'Liste des utilisateurs LoTW', 'lotw.usersHint': "Télécharge la liste publique ARRL des utilisateurs LoTW + leur date de dernier upload, pour afficher un badge LoTW coloré à côté d'un indicatif (vert < 1 semaine · ambre 14 semaines · rouge > 30 j).", 'lotw.usersDownload': 'Télécharger la liste LoTW', 'lotw.usersDownloading': 'Téléchargement…', 'lotw.usersLoaded': '{n} utilisateurs chargés · maj {date}', 'lotw.usersNone': 'Pas encore téléchargée — le badge reste caché tant que ce nest pas fait.',
'scp.title': 'Super Check Partial', 'scp.partial': 'Partiel', 'scp.close': 'Fermer', 'scp.fill': 'Remplir {call}', 'scp.none': 'Aucun', 'scp.typeMore': 'Tape un indicatif…', 'scp.noList': 'Télécharge la liste SCP dans Réglages → Général.', 'scp.enable': 'Assistant indicatifs Super Check Partial / N+1', 'scp.settingsHint': "Télécharge la liste communautaire MASTER.SCP et affiche un widget en 2 colonnes pendant que tu tapes un indicatif : Partiel (indicatifs connus contenant ce que tu tapes) et N+1 (indicatifs à une lettre près) — pour repérer et corriger un call busté.", 'scp.download': 'Mettre à jour la liste SCP', 'scp.downloading': 'Téléchargement…', 'scp.loaded': '{n} indicatifs chargés · maj {date}', 'scp.notLoaded': 'Pas encore téléchargée.',
'hw.connecting': 'Connexion…', 'hw.testConn': 'Tester la connexion', 'hw.sending': 'Envoi…', 'hw.testRotator': 'Tester (pointer vers 0°)',
'prof.deleteConfirm': 'Supprimer le profil « {name} » ? Tous ses réglages seront perdus.', 'prof.dupPrompt': 'Nom du nouveau profil (copie de « {name} ») :', 'prof.dupSuffix': '{name} Copie', 'prof.newPrompt': 'Nom du nouveau profil :', 'prof.newDefault': 'Nouveau profil',
'prof.hint': "Bascule entre tes identités d'opération (maison / portable / SOTA / contest). Choisis un profil ici, puis édite ses champs dans les autres sections (Informations station, etc.) — les changements sont enregistrés sur le profil sélectionné.", 'prof.active': 'ACTIF', 'prof.duplicate': 'Dupliquer', 'prof.delete': 'Supprimer', 'prof.profileName': 'Nom du profil',