diff --git a/app.go b/app.go index 773d064..3b21460 100644 --- a/app.go +++ b/app.go @@ -37,6 +37,7 @@ const ( // Failsafe is the fallback when Primary returns not-found or errs. keyLookupPrimary = "lookup.primary" keyLookupFailsafe = "lookup.failsafe" + keyLookupImages = "lookup.download_images" // 1 = expose QRZ ImageURL to UI keyStationCallsign = "station.callsign" keyStationOperator = "station.operator" @@ -119,13 +120,14 @@ type StationSettings struct { // Primary / Failsafe hold a provider name ("qrz" | "hamqth" | "") to // route lookups: primary first, failsafe on not-found / error. type LookupSettings struct { - QRZUser string `json:"qrz_user"` - QRZPassword string `json:"qrz_password"` - HamQTHUser string `json:"hamqth_user"` - HamQTHPassword string `json:"hamqth_password"` - Primary string `json:"primary"` - Failsafe string `json:"failsafe"` - CacheTTLDays int `json:"cache_ttl_days"` + QRZUser string `json:"qrz_user"` + QRZPassword string `json:"qrz_password"` + HamQTHUser string `json:"hamqth_user"` + HamQTHPassword string `json:"hamqth_password"` + Primary string `json:"primary"` + Failsafe string `json:"failsafe"` + DownloadImages bool `json:"download_images"` // show QRZ profile pictures in the UI + CacheTTLDays int `json:"cache_ttl_days"` } // App is the application context bound to the Wails runtime. @@ -503,9 +505,33 @@ func (a *App) LookupCallsign(callsign string) (lookup.Result, error) { if errors.Is(err, lookup.ErrNotFound) { return lookup.Result{}, fmt.Errorf("callsign not found") } + // Respect the user's "Download profile images" setting: even if the + // cache holds the URL we hide it when the toggle is off so the + // frontend doesn't render the (which would still fetch from + // QRZ). Cheap to check per call — settings is in-memory after init. + if err == nil && r.ImageURL != "" { + if s, _ := a.GetLookupSettings(); !s.DownloadImages { + r.ImageURL = "" + } + } return r, err } +// OpenExternalURL opens a URL in the user's default browser. Wails ships +// runtime.BrowserOpenURL for exactly this — used by the QRZ.com icon +// next to the callsign field, the future Clublog/HamQTH shortcuts, etc. +func (a *App) OpenExternalURL(url string) error { + url = strings.TrimSpace(url) + if url == "" { + return fmt.Errorf("empty URL") + } + if !strings.HasPrefix(url, "http://") && !strings.HasPrefix(url, "https://") { + return fmt.Errorf("only http(s) URLs allowed, got %q", url) + } + wruntime.BrowserOpenURL(a.ctx, url) + return nil +} + // GetLookupSettings returns current credentials and cache TTL. func (a *App) GetLookupSettings() (LookupSettings, error) { if a.settings == nil { @@ -513,7 +539,7 @@ func (a *App) GetLookupSettings() (LookupSettings, error) { } m, err := a.settings.GetMany(a.ctx, keyQRZUser, keyQRZPassword, keyHQUser, keyHQPassword, - keyCacheTTL, keyLookupPrimary, keyLookupFailsafe) + keyCacheTTL, keyLookupPrimary, keyLookupFailsafe, keyLookupImages) if err != nil { return LookupSettings{}, err } @@ -528,6 +554,7 @@ func (a *App) GetLookupSettings() (LookupSettings, error) { HamQTHPassword: m[keyHQPassword], Primary: m[keyLookupPrimary], Failsafe: m[keyLookupFailsafe], + DownloadImages: m[keyLookupImages] == "1", CacheTTLDays: ttl, }, nil } @@ -553,6 +580,7 @@ func (a *App) SaveLookupSettings(s LookupSettings) error { keyCacheTTL: strconv.Itoa(s.CacheTTLDays), keyLookupPrimary: s.Primary, keyLookupFailsafe: s.Failsafe, + keyLookupImages: boolStr(s.DownloadImages), } { if err := a.settings.Set(a.ctx, k, v); err != nil { return err diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 0582fc3..efeadf9 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,6 +1,6 @@ import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { - AlertCircle, Antenna, CheckCircle2, Clock, Compass, Hash, Loader2, Lock, + AlertCircle, Antenna, CheckCircle2, Clock, Compass, ExternalLink, Hash, Loader2, Lock, Maximize2, Minimize2, Pencil, RadioTower, RefreshCw, Send, Settings, Square, Trash2, Unlock, X, } from 'lucide-react'; @@ -15,6 +15,7 @@ import { GetCATState, SetCATFrequency, SetCATMode, SwitchCATRig, RefreshCtyDat, RotatorGoTo, RotatorStop, + OpenExternalURL, GetCATSettings, } from '../wailsjs/go/main/App'; import { EventsOn, EventsOff } from '../wailsjs/runtime/runtime'; @@ -555,6 +556,8 @@ export default function App() { function resetAutoFill() { setName(''); setQth(''); setCountry(''); setGrid(''); + setWb(null); + setLookupResult(null); setDetails((d) => ({ ...d, state: '', cnty: '', address: '', @@ -1010,6 +1013,21 @@ export default function App() {