diff --git a/OpsLog-res.syso b/OpsLog-res.syso deleted file mode 100644 index 79a0989..0000000 Binary files a/OpsLog-res.syso and /dev/null differ diff --git a/app.go b/app.go index 31a16ce..88aa9ef 100644 --- a/app.go +++ b/app.go @@ -7698,7 +7698,9 @@ func (a *App) startUltrabeam() { a.ubFollowStop = nil } if a.ultrabeam != nil { - a.ultrabeam.Stop() + // Background teardown so saving Settings doesn't block on an in-progress + // connect (Stop waits for the dial timeout). + go a.ultrabeam.Stop() a.ultrabeam = nil } s, err := a.GetUltrabeamSettings() @@ -7896,7 +7898,9 @@ func (a *App) SaveAntGeniusSettings(s AntGeniusSettings) error { // startAntGenius stops any existing client and starts a fresh one if enabled. func (a *App) startAntGenius() { if a.antgenius != nil { - a.antgenius.Stop() + // Background teardown so saving Settings doesn't block on an in-progress + // connect (Stop waits for the dial timeout). + go a.antgenius.Stop() a.antgenius = nil } s, err := a.GetAntGeniusSettings() @@ -7932,7 +7936,7 @@ func (a *App) AntGeniusDeselect(port int) error { return a.antgenius.Activate(port, 0) } -// ── PowerGenius XL (4O3A) amplifier fan control (TCP, default port 9006) ───── +// ── PowerGenius XL (4O3A) amplifier fan control (TCP, default port 9008) ───── // PGXLSettings is the JSON shape for the Hardware → PowerGenius panel. type PGXLSettings struct { @@ -7942,7 +7946,7 @@ type PGXLSettings struct { } func (a *App) GetPGXLSettings() (PGXLSettings, error) { - out := PGXLSettings{Port: 9006} + out := PGXLSettings{Port: 9008} if a.settings == nil { return out, fmt.Errorf("db not initialized") } @@ -7963,7 +7967,7 @@ func (a *App) SavePGXLSettings(s PGXLSettings) error { return fmt.Errorf("db not initialized") } if s.Port <= 0 || s.Port > 65535 { - s.Port = 9006 + s.Port = 9008 } for k, v := range map[string]string{ keyPGXLEnabled: boolStr(s.Enabled), @@ -7981,7 +7985,10 @@ func (a *App) SavePGXLSettings(s PGXLSettings) error { // startPGXL stops any existing client and starts a fresh one if enabled. func (a *App) startPGXL() { if a.pgxl != nil { - a.pgxl.Stop() + // 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 a.pgxl.Stop() a.pgxl = nil } s, err := a.GetPGXLSettings() diff --git a/frontend/src/components/FlexPanel.tsx b/frontend/src/components/FlexPanel.tsx index f5c7caa..38420b4 100644 --- a/frontend/src/components/FlexPanel.tsx +++ b/frontend/src/components/FlexPanel.tsx @@ -217,7 +217,7 @@ export function FlexPanel() { }, []); // PowerGenius XL direct connection (fan mode), independent of the Flex link. - const [pg, setPg] = useState<{ connected: boolean; fan_mode?: string }>({ connected: false }); + const [pg, setPg] = useState<{ connected: boolean; fan_mode?: string; host?: string; last_error?: string }>({ connected: false }); useEffect(() => { let alive = true; const tick = async () => { try { const s: any = await GetPGXLStatus(); if (alive) setPg(s || { connected: false }); } catch {} }; @@ -441,15 +441,18 @@ export function FlexPanel() { {st.amp_operate ? 'Amplifier is in line (transmitting through PA).' : 'Amplifier bypassed (standby).'} - {/* Fan mode — only when the PowerGenius direct connection is up - (configured in Settings → PowerGenius). */} - {pg.connected && ( -