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() {