perf(lotw): stop asking for the QSL details by default

A tester compared LogHX's two download options on the same account: two minutes
for the confirmations, twenty for the confirmations with QSO details. OpsLog was
always sending qso_qsldetail=yes — LogHX's slow option — which is the whole of
the wait people were reporting.

Marking a confirmation needs call, date, band and mode; the detail adds the QSL
date and the station's grid, state and county. Now a choice, off by default, and
forced on when the download is also ADDING the QSOs it cannot find — the one
case where those fields have no other source.
This commit is contained in:
2026-08-28 08:54:42 +02:00
parent b24f880d62
commit 65cae0d822
7 changed files with 75 additions and 7 deletions
+15 -2
View File
@@ -8,7 +8,7 @@ import {
Select, SelectTrigger, SelectValue, SelectContent, SelectItem,
} from '@/components/ui/select';
import { cn } from '@/lib/utils';
import { GetLoTWDownloadAllCalls, SetLoTWDownloadAllCalls, OpenExternalURL, FindQSOsForUpload, UploadQSOsManual, DownloadConfirmations, CancelConfirmations, ImportHamlogConfirmations, ExportHamlogUnmatched, OpenADIFFile, SaveADIFFile, SyncPOTAHunterLog, ListQSO, BulkUpdateQSL, UploadCallsign, GetSlotStats } from '../../wailsjs/go/main/App';
import { GetLoTWQSLDetail, SetLoTWQSLDetail, GetLoTWDownloadAllCalls, SetLoTWDownloadAllCalls, OpenExternalURL, FindQSOsForUpload, UploadQSOsManual, DownloadConfirmations, CancelConfirmations, ImportHamlogConfirmations, ExportHamlogUnmatched, OpenADIFFile, SaveADIFFile, SyncPOTAHunterLog, ListQSO, BulkUpdateQSL, UploadCallsign, GetSlotStats } from '../../wailsjs/go/main/App';
import { Input } from '@/components/ui/input';
import { RecentQSOsGrid } from '@/components/RecentQSOsGrid';
import { EventsOn } from '../../wailsjs/runtime/runtime';
@@ -257,7 +257,13 @@ export function QSLManagerPanel({ onEditQSO, actions, paperRequest }: {
const [addNotFound, setAddNotFound] = useState(false);
// LoTW only: pull the whole account rather than this profile's callsign.
const [lotwAllCalls, setLotwAllCalls] = useState(false);
useEffect(() => { GetLoTWDownloadAllCalls().then((v: boolean) => setLotwAllCalls(!!v)).catch(() => {}); }, []);
// LoTW only: ask for the QSL dates and station details. Ten times slower to
// build, so it is a choice rather than the default it used to be.
const [lotwDetail, setLotwDetail] = useState(false);
useEffect(() => {
GetLoTWDownloadAllCalls().then((v: boolean) => setLotwAllCalls(!!v)).catch(() => {});
GetLoTWQSLDetail().then((v: boolean) => setLotwDetail(!!v)).catch(() => {});
}, []);
// Download date window: 'last' = incremental since last pull, 'date' = from a
// chosen date, 'all' = everything.
const [sinceMode, setSinceMode] = useState<'last' | 'date' | 'all'>('last');
@@ -751,6 +757,13 @@ export function QSLManagerPanel({ onEditQSO, actions, paperRequest }: {
<Checkbox checked={addNotFound} onCheckedChange={(c) => setAddNotFound(!!c)} />
{t('qslm.addNotFound')}
</label>
{service === 'lotw' && (
<label className="flex items-center gap-1.5 text-[11px] text-muted-foreground cursor-pointer" title={t('qslm.lotwDetailTitle')}>
<Checkbox checked={lotwDetail || addNotFound} disabled={addNotFound}
onCheckedChange={(c) => { setLotwDetail(!!c); SetLoTWQSLDetail(!!c); }} />
{t('qslm.lotwDetail')}
</label>
)}
{service === 'lotw' && (
<label className="flex items-center gap-1.5 text-[11px] text-muted-foreground cursor-pointer" title={t('qslm.lotwAllCallsTitle')}>
<Checkbox checked={lotwAllCalls} onCheckedChange={(c) => { setLotwAllCalls(!!c); SetLoTWDownloadAllCalls(!!c); }} />
+4
View File
@@ -130,6 +130,8 @@ const en: Dict = {
'icmp.scopeNoStream': 'This radio does not send its scope over CI-V — its own screen still works.',
'gen.miles': 'Distances in miles', 'gen.milesHint': '(instead of kilometres)',
'qslm.qrzTitle': 'Open this callsign on QRZ.com',
'qslm.lotwDetail': 'QSL details',
'qslm.lotwDetailTitle': 'Ask LoTW for the QSL date and the station details (grid, state, county) as well as the confirmation. LoTW takes about ten times longer to build that report — two minutes against twenty on the same account — and marking a confirmation needs none of it. Forced on when adding the QSOs not found, which have no other source for those fields.',
'qslm.lotwAllCalls': 'All my callsigns',
'qslm.lotwAllCallsTitle': "Download the confirmations of every callsign on the LoTW account, not just this profile's. A QSO made as F4BPO/P or TM2Q is confirmed at LoTW but never reaches an F4BPO profile without this.",
'awp.filterSlotsNotCfmd': 'Slots to confirm', 'awp.slotGap': 'slots to confirm',
@@ -626,6 +628,8 @@ const fr: Dict = {
'icmp.scopeNoStream': "Cette radio n'envoie pas son scope en CI-V — son propre écran fonctionne toujours.",
'gen.miles': 'Distances en miles', 'gen.milesHint': '(au lieu des kilomètres)',
'qslm.qrzTitle': 'Ouvrir cet indicatif sur QRZ.com',
'qslm.lotwDetail': 'Détails QSL',
'qslm.lotwDetailTitle': "Demander à LoTW la date du QSL et les détails de la station (locator, état, comté) en plus de la confirmation. LoTW met environ dix fois plus longtemps à construire ce rapport — deux minutes contre vingt sur le même compte — et marquer une confirmation n'en a pas besoin. Forcé quand on ajoute les QSO absents, qui n'ont pas d'autre source pour ces champs.",
'qslm.lotwAllCalls': 'Tous mes indicatifs',
'qslm.lotwAllCallsTitle': "Télécharger les confirmations de tous les indicatifs du compte LoTW, pas seulement celui du profil. Un QSO fait en F4BPO/P ou TM2Q est confirmé chez LoTW mais n'atteint jamais un profil F4BPO sans cette option.",
'awp.filterSlotsNotCfmd': 'Slots à confirmer', 'awp.slotGap': 'slots à confirmer',
+4
View File
@@ -505,6 +505,8 @@ export function GetLiveStations():Promise<Array<main.LiveStation>>;
export function GetLoTWDownloadAllCalls():Promise<boolean>;
export function GetLoTWQSLDetail():Promise<boolean>;
export function GetLoTWUsersStatus():Promise<main.LoTWUsersStatus>;
export function GetLogFilePath():Promise<string>;
@@ -1161,6 +1163,8 @@ export function SetLinkedAmps(arg1:Array<string>):Promise<void>;
export function SetLoTWDownloadAllCalls(arg1:boolean):Promise<void>;
export function SetLoTWQSLDetail(arg1:boolean):Promise<void>;
export function SetMotorFollow(arg1:boolean,arg2:number,arg3:string):Promise<void>;
export function SetOpsLogQSLReceived(arg1:number,arg2:boolean):Promise<void>;
+8
View File
@@ -950,6 +950,10 @@ export function GetLoTWDownloadAllCalls() {
return window['go']['main']['App']['GetLoTWDownloadAllCalls']();
}
export function GetLoTWQSLDetail() {
return window['go']['main']['App']['GetLoTWQSLDetail']();
}
export function GetLoTWUsersStatus() {
return window['go']['main']['App']['GetLoTWUsersStatus']();
}
@@ -2262,6 +2266,10 @@ export function SetLoTWDownloadAllCalls(arg1) {
return window['go']['main']['App']['SetLoTWDownloadAllCalls'](arg1);
}
export function SetLoTWQSLDetail(arg1) {
return window['go']['main']['App']['SetLoTWQSLDetail'](arg1);
}
export function SetMotorFollow(arg1, arg2, arg3) {
return window['go']['main']['App']['SetMotorFollow'](arg1, arg2, arg3);
}