From 612cb67438bed1b7c6d23c76a46f2205db7a686d Mon Sep 17 00:00:00 2001 From: rouggy Date: Mon, 31 Aug 2026 11:39:02 +0200 Subject: [PATCH] =?UTF-8?q?fix(kpa):=20a=20settings=20save=20must=20not=20?= =?UTF-8?q?flick=20the=20KPA500's=20power=20switch=20=E2=80=94=20and=20the?= =?UTF-8?q?=20maps=20stay=20under=20the=20menus?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit startAmps tore down and rebuilt every amplifier client on any settings save, and closing a COM port makes the Windows driver drop DTR/RTS. On a KPA500 those lines ARE the power switch — so 'save' meant 'amplifier off twenty seconds later', exactly F1TPL's report, and the fix that held the lines while OPEN couldn't survive a close. An amplifier whose config is unchanged now keeps its running client across saves; the others still rebuild. Also: isolate on the FT Map panel — Leaflet's z-1000 panes were painting over the menu bar and the Preferences dialog, as the grid map's own comment warned. --- app.go | 46 ++++++++++++++++++++++---- changelog.json | 8 +++-- frontend/src/components/FTMapPanel.tsx | 5 ++- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/app.go b/app.go index 9926ded..744d89a 100644 --- a/app.go +++ b/app.go @@ -18677,19 +18677,51 @@ func (a *App) startAmps() { old := a.ampInsts a.ampInsts = map[string]*ampInst{} a.ampsMu.Unlock() - for _, inst := range old { + a.pgxl, a.spe, a.acom = nil, nil, nil + list, err := a.GetAmplifiers() + if err != nil { + for _, inst := range old { + go inst.stopAll() + } + return + } + // An amplifier whose configuration did not change keeps its RUNNING client + // across a settings save. Rebuilding closes the serial port, and closing a + // COM port makes the Windows driver drop DTR/RTS — which on a KPA500 is the + // POWER SWITCH: every save of any Settings page was switching the amplifier + // off (F1TPL's report). Reuse also spares the other amps a reconnect blink. + reused := map[string]bool{} + for _, c := range list { + if !c.Enabled { + continue + } + if o, ok := old[c.ID]; ok && o.cfg == c { + reused[c.ID] = true + if o.pgxl != nil && a.pgxl == nil { + a.pgxl = o.pgxl + } + if o.spe != nil && a.spe == nil { + a.spe = o.spe + } + if o.acom != nil && a.acom == nil { + a.acom = o.acom + } + a.ampsMu.Lock() + a.ampInsts[c.ID] = o + a.ampsMu.Unlock() + } + } + for id, inst := range old { + if reused[id] { + continue + } // Stop() can block up to the dial timeout waiting for an in-progress // connect; tear down in the background so saving Settings (this runs on // the Wails RPC goroutine) doesn't freeze the UI. go inst.stopAll() } - a.pgxl, a.spe, a.acom = nil, nil, nil - list, err := a.GetAmplifiers() - if err != nil { - return - } for _, c := range list { - if !c.Enabled { + if !c.Enabled || reused[c.ID] { continue } isPGXL := c.Type == "" || c.Type == "pgxl" diff --git a/changelog.json b/changelog.json index ae06f7d..37a8782 100644 --- a/changelog.json +++ b/changelog.json @@ -5,12 +5,16 @@ "en": [ "QSL Manager: Club Log confirmations — downloads your log matches (getmatches API) and stamps two new columns, ClubLog match status and match date, available everywhere: table columns, filters, bulk edit and the QSO editor.", "Super Check Partial: option to merge Club Log’s weekly call list (~180k calls heard on the air in the last 3 years) with MASTER.SCP.", - "Fixed: opening the app could silently stop at startup (settings showing as default, “db not initialized”) when a database migration targeted a table that database no longer holds — migrations now skip what does not apply, and a startup failure is written to the log." + "Fixed: opening the app could silently stop at startup (settings showing as default, “db not initialized”) when a database migration targeted a table that database no longer holds — migrations now skip what does not apply, and a startup failure is written to the log.", + "FT Map / Grid squares: the map no longer floats above the menus and the Preferences dialog.", + "KPA500: saving ANY settings page no longer power-cycles the amplifier. A save rebuilt every amplifier connection, and closing the COM port drops DTR/RTS — the KPA500’s power switch. An unchanged amplifier now keeps its running connection across saves." ], "fr": [ "QSL Manager : confirmations Club Log — télécharge vos matches de log (API getmatches) et remplit deux nouvelles colonnes, statut et date de match ClubLog, disponibles partout : colonnes du tableau, filtres, édition groupée et éditeur de QSO.", "Super Check Partial : option pour fusionner la liste hebdomadaire de Club Log (~180k indicatifs entendus sur l’air ces 3 dernières années) avec MASTER.SCP.", - "Corrigé : l’application pouvait se figer silencieusement au démarrage (réglages par défaut, « db not initialized ») quand une migration visait une table absente de cette base — les migrations ignorent désormais ce qui ne s’applique pas, et un échec de démarrage est écrit dans le log." + "Corrigé : l’application pouvait se figer silencieusement au démarrage (réglages par défaut, « db not initialized ») quand une migration visait une table absente de cette base — les migrations ignorent désormais ce qui ne s’applique pas, et un échec de démarrage est écrit dans le log.", + "FT Map / Grid squares : la carte ne passe plus au-dessus des menus et de la fenêtre Préférences.", + "KPA500 : sauvegarder n’importe quelle page des réglages n’éteint plus l’ampli. Une sauvegarde reconstruisait chaque connexion d’ampli, et fermer le port COM relâche DTR/RTS — l’interrupteur d’alimentation du KPA500. Un ampli inchangé garde désormais sa connexion à travers les sauvegardes." ] }, { diff --git a/frontend/src/components/FTMapPanel.tsx b/frontend/src/components/FTMapPanel.tsx index 1d25dce..07885c8 100644 --- a/frontend/src/components/FTMapPanel.tsx +++ b/frontend/src/components/FTMapPanel.tsx @@ -119,7 +119,10 @@ export function FTMapPanel({ decodes, myGrid }: { decodes: FTMapDecode[]; myGrid const bands = [...new Set(decodes.map((d) => (d.band ?? '').toLowerCase()).filter(Boolean))]; return ( -
+ // isolate: Leaflet stacks its panes and controls up to z-index 1000, which + // beat the app menus and the Settings dialog. A stacking context of our own + // keeps all of it inside this panel. +
{/* Basemap picker, MainMap's own vocabulary. */}