feat: Super Check Partial + N+1 helper; fix Flex binding to SmartSDR CAT; telemetry callsign wait
- SCP/N+1: new internal/scp downloads the community MASTER.SCP master list and a docked two-column widget shows, as you type a call, the known calls containing it (Partial) and the calls one edit away (N+1) — click to fix a busted call. Opt-in in Settings → General; top-bar toggle; queried debounced on callsign input. - Flex: OpsLog's GUI-client detection was too loose and could bind to "SmartSDR CAT" (or DAX) — both carry "smartsdr" in the program name — instead of the real GUI client, making SmartSDR CAT drop and reconnect in a loop while OpsLog was open. Now it binds only to a real SmartSDR/Maestro GUI client (e.g. a FLEX-8600M's integrated screen) and excludes cat/dax; dropped the risky empty-program fallback. - Telemetry: on a fresh install the callsign isn't set at launch, so the once-a-day heartbeat recorded the machine UUID. Now it waits (~10 min) for the operator to enter their callsign before sending, falling back to the UUID only if none appears.
This commit is contained in:
+59
-2
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
||||
import {
|
||||
Activity, AlertCircle, Antenna, Bell, CheckCircle2, Clock, CloudOff, Compass, Database, Ear, Eraser, Gauge, Hash, Loader2, Lock,
|
||||
Maximize2, Minimize2, Mic, MessageSquare, Pencil, Radio, RadioTower, RefreshCw, Satellite, Send, Settings, SlidersHorizontal, Square, Terminal, Trash2, Unlock, X, Zap,
|
||||
Maximize2, Minimize2, Mic, MessageSquare, Pencil, Radio, RadioTower, RefreshCw, Satellite, Send, Settings, SlidersHorizontal, SpellCheck, Square, Terminal, Trash2, Unlock, X, Zap,
|
||||
} from 'lucide-react';
|
||||
|
||||
import {
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
GetUltrabeamStatus, SetUltrabeamDirection,
|
||||
GetAntGeniusStatus, GetAntGeniusSettings, AntGeniusActivate,
|
||||
GetTunerGeniusStatus, GetTunerGeniusSettings, TunerGeniusAutotune, TunerGeniusSetBypass, TunerGeniusSetOperate, TunerGeniusActivate,
|
||||
GetScpStatus, ScpLookup,
|
||||
OpenExternalURL,
|
||||
ConnectAllClusters, DisconnectAllClusters, GetClusterStatus, SendClusterCommand,
|
||||
ListClusterServers, ClusterSpotStatuses, SendClusterSpot,
|
||||
@@ -71,6 +72,7 @@ import { FlexPanel } from '@/components/FlexPanel';
|
||||
import { IcomPanel } from '@/components/IcomPanel';
|
||||
import { AntGeniusPanel, type AGStatus } from '@/components/AntGeniusPanel';
|
||||
import { TunerGeniusPanel, type TGStatus } from '@/components/TunerGeniusPanel';
|
||||
import { ScpPanel, type ScpResult } from '@/components/ScpPanel';
|
||||
import { FilterBuilder, type QueryFilter } from '@/components/FilterBuilder';
|
||||
import { AwardsPanel } from '@/components/AwardsPanel';
|
||||
import { StatsPanel } from '@/components/StatsPanel';
|
||||
@@ -473,6 +475,10 @@ export default function App() {
|
||||
const [agEnabled, setAgEnabled] = useState(false);
|
||||
const [tgStatus, setTgStatus] = useState<TGStatus>({ connected: false });
|
||||
const [tgEnabled, setTgEnabled] = useState(false);
|
||||
// Super Check Partial / N+1
|
||||
const [scpEnabled, setScpEnabled] = useState(false);
|
||||
const [scpCount, setScpCount] = useState(0);
|
||||
const [scpResult, setScpResult] = useState<ScpResult>({});
|
||||
// Per-port optimistic selection that the status poll must not revert until the
|
||||
// device confirms it (or it expires) — otherwise a stale poll right after a
|
||||
// click reverts the UI and the click looks like it did nothing.
|
||||
@@ -1555,6 +1561,7 @@ export default function App() {
|
||||
const [showRotor, setShowRotor] = useState(() => localStorage.getItem('opslog.showRotor') !== '0');
|
||||
const [showAntGenius, setShowAntGenius] = useState(() => localStorage.getItem('opslog.showAntGenius') !== '0');
|
||||
const [showTuner, setShowTuner] = useState(() => localStorage.getItem('opslog.showTuner') !== '0');
|
||||
const [showScp, setShowScp] = useState(() => localStorage.getItem('opslog.showScp') !== '0');
|
||||
const [showBeamOnMap, setShowBeamOnMap] = useState(() => localStorage.getItem('opslog.showBeamOnMap') !== '0');
|
||||
|
||||
// Award code → scanned field (e.g. POTA→pota_ref, WWFF→wwff). Used to route
|
||||
@@ -1786,6 +1793,31 @@ export default function App() {
|
||||
TunerGeniusActivate(ch).catch((e) => setError(String(e?.message ?? e)));
|
||||
};
|
||||
|
||||
// Super Check Partial: poll the enabled flag + list size so the widget shows up
|
||||
// once the operator turns SCP on and the master list has downloaded.
|
||||
useEffect(() => {
|
||||
let alive = true;
|
||||
const load = async () => {
|
||||
try { const s: any = await GetScpStatus(); if (alive && s) { setScpEnabled(!!s.enabled); setScpCount(s.count || 0); } } catch {}
|
||||
};
|
||||
load();
|
||||
const id = window.setInterval(load, 3000);
|
||||
const off = EventsOn('scp:updated', load);
|
||||
return () => { alive = false; window.clearInterval(id); off(); };
|
||||
}, []);
|
||||
// Query SCP/N+1 as the callsign changes (debounced). Skipped when disabled or
|
||||
// the widget is hidden, so we don't hit the backend for nothing.
|
||||
useEffect(() => {
|
||||
if (!scpEnabled || !showScp) { setScpResult({}); return; }
|
||||
const c = callsign.trim();
|
||||
if (c.length < 2) { setScpResult({}); return; }
|
||||
let alive = true;
|
||||
const id = window.setTimeout(async () => {
|
||||
try { const r: any = await ScpLookup(c); if (alive && r) setScpResult(r as ScpResult); } catch {}
|
||||
}, 120);
|
||||
return () => { alive = false; window.clearTimeout(id); };
|
||||
}, [callsign, scpEnabled, showScp]);
|
||||
|
||||
// RX band auto-follows the TX band (only differs for cross-band work).
|
||||
useEffect(() => { setBandRx(band); }, [band]);
|
||||
|
||||
@@ -4330,6 +4362,20 @@ export default function App() {
|
||||
{showTuner && tgStatus.connected && <span className="absolute -top-0.5 -right-0.5 size-2 rounded-full bg-success" />}
|
||||
</button>
|
||||
)}
|
||||
{scpEnabled && (
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => { const v = !showScp; setShowScp(v); writeUiPref('opslog.showScp', v ? '1' : '0'); }}
|
||||
title={showScp ? 'Super Check Partial — shown · click to hide' : 'Super Check Partial · click to show'}
|
||||
className={cn(
|
||||
'relative inline-flex items-center justify-center size-7 rounded-md border transition-colors',
|
||||
showScp ? 'border-success-border bg-success-muted text-success-muted-foreground hover:bg-success-muted'
|
||||
: 'border-border text-muted-foreground hover:bg-muted',
|
||||
)}
|
||||
>
|
||||
<SpellCheck className="size-4" />
|
||||
</button>
|
||||
)}
|
||||
{chatAvailable && (
|
||||
<button
|
||||
type="button"
|
||||
@@ -4801,7 +4847,7 @@ export default function App() {
|
||||
{/* Reserved free space to the right. The WinKeyer CW keyer and/or the
|
||||
Digital Voice Keyer take this slot when enabled (Log4OM-style);
|
||||
otherwise it shows the QRZ profile photo. */}
|
||||
{!compact && (chatShown || wkEnabled || dvkEnabled || lookupResult?.image_url || (showRotor && (rotatorHeading.enabled || dxPath)) || (showAntGenius && agEnabled) || (showTuner && tgEnabled) || (showLiveStations && dbConn?.backend === 'mysql')) && (
|
||||
{!compact && (chatShown || wkEnabled || dvkEnabled || lookupResult?.image_url || (showRotor && (rotatorHeading.enabled || dxPath)) || (showAntGenius && agEnabled) || (showTuner && tgEnabled) || (showScp && scpEnabled) || (showLiveStations && dbConn?.backend === 'mysql')) && (
|
||||
// relative + absolute inner (like the F1-F5 panel): a taller widget (e.g.
|
||||
// the DVK with Auto CQ) can't grow the row — the row height stays set by
|
||||
// the entry strip and each widget fills that height, scrolling inside.
|
||||
@@ -4900,6 +4946,17 @@ export default function App() {
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{showScp && scpEnabled && (
|
||||
<div className="w-[240px] shrink-0 min-h-0">
|
||||
<ScpPanel
|
||||
result={scpResult}
|
||||
currentCall={callsign}
|
||||
count={scpCount}
|
||||
onPick={(c) => onCallsignInput(c, { force: true })}
|
||||
onClose={() => { setShowScp(false); writeUiPref('opslog.showScp', '0'); }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
{dvkEnabled && (
|
||||
<div className="w-[320px] shrink-0 min-h-0">
|
||||
<DvkPanel
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { SpellCheck, X } from 'lucide-react';
|
||||
import { cn } from '@/lib/utils';
|
||||
import { useI18n } from '@/lib/i18n';
|
||||
|
||||
export type ScpResult = { partial?: string[]; nplus1?: string[] };
|
||||
|
||||
// ScpPanel — Super Check Partial + N+1 callsign helper, split in two columns.
|
||||
// Left: master calls that CONTAIN what you've typed (spot/correct a call). Right:
|
||||
// calls one edit away (busted-call check). Clicking a suggestion fills the entry.
|
||||
export function ScpPanel({ result, currentCall, count, onPick, onClose }: {
|
||||
result: ScpResult;
|
||||
currentCall: string;
|
||||
count: number; // master-list size (0 = list not downloaded yet)
|
||||
onPick: (call: string) => void;
|
||||
onClose: () => void;
|
||||
}) {
|
||||
const { t } = useI18n();
|
||||
const cur = (currentCall || '').trim().toUpperCase();
|
||||
const partial = result.partial ?? [];
|
||||
const nplus1 = result.nplus1 ?? [];
|
||||
|
||||
const Col = ({ title, tone, calls, empty }: { title: string; tone: string; calls: string[]; empty: string }) => (
|
||||
<div className="flex-1 min-w-0 flex flex-col">
|
||||
<div className={cn('text-[10px] font-bold uppercase tracking-wider px-1.5 py-1 border-b border-border/50', tone)}>{title}</div>
|
||||
<div className="flex-1 min-h-0 overflow-y-auto p-1 space-y-0.5">
|
||||
{calls.length === 0 ? (
|
||||
<div className="text-[10px] text-muted-foreground/70 italic px-1 py-1">{empty}</div>
|
||||
) : calls.map((c) => (
|
||||
<button key={c} type="button" onClick={() => onPick(c)}
|
||||
title={t('scp.fill', { call: c })}
|
||||
className={cn('w-full text-left rounded px-1.5 py-0.5 font-mono text-xs transition-colors',
|
||||
c === cur ? 'bg-success/20 text-success font-bold'
|
||||
: 'hover:bg-primary/15 text-foreground/90')}>
|
||||
{c}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="h-full flex flex-col rounded-xl border border-border bg-gradient-to-b from-card to-muted/30 shadow-sm overflow-hidden">
|
||||
<div className="flex items-center gap-2 px-3 py-2 border-b border-border/60 bg-muted/40 shrink-0">
|
||||
<SpellCheck className={cn('size-4', count > 0 ? 'text-primary' : 'text-muted-foreground')} />
|
||||
<span className="text-xs font-bold uppercase tracking-[0.18em] text-foreground/80">{t('scp.title')}</span>
|
||||
<span className="flex-1" />
|
||||
<button type="button" onClick={onClose} className="text-muted-foreground hover:text-foreground transition-colors" title={t('scp.close')}>
|
||||
<X className="size-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
{count === 0 ? (
|
||||
<div className="flex-1 min-h-0 flex items-center justify-center text-[11px] text-muted-foreground italic text-center px-3">
|
||||
{t('scp.noList')}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex-1 min-h-0 flex divide-x divide-border/60">
|
||||
<Col title={t('scp.partial')} tone="text-primary" calls={partial} empty={t('scp.typeMore')} />
|
||||
<Col title="N+1" tone="text-warning" calls={nplus1} empty={t('scp.none')} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@@ -39,6 +39,7 @@ import {
|
||||
GetPOTAToken, SavePOTAToken,
|
||||
TestLoTWUpload, ListTQSLStationLocations,
|
||||
DownloadLoTWUsers, GetLoTWUsersStatus,
|
||||
GetScpStatus, SetScpEnabled, DownloadScp,
|
||||
DownloadULSCounties, ULSStatus, BackfillUSCounties,
|
||||
ComputeStationInfo,
|
||||
GetUIPref, SetUIPref,
|
||||
@@ -1253,6 +1254,21 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
catch (e: any) { setLotwTest({ ok: false, msg: String(e?.message ?? e) }); }
|
||||
finally { setLotwUsersBusy(false); }
|
||||
};
|
||||
// Super Check Partial / N+1 callsign helper: enabled flag + master-list status.
|
||||
const [scp, setScp] = useState<{ enabled: boolean; count: number; updated?: string }>({ enabled: false, count: 0 });
|
||||
const [scpBusy, setScpBusy] = useState(false);
|
||||
useEffect(() => { GetScpStatus().then((s) => setScp(s as any)).catch(() => {}); }, []);
|
||||
const toggleScp = async (on: boolean) => {
|
||||
setScp((s) => ({ ...s, enabled: on }));
|
||||
setScpBusy(true);
|
||||
try { await SetScpEnabled(on); const s = await GetScpStatus(); setScp(s as any); } catch {}
|
||||
finally { setScpBusy(false); }
|
||||
};
|
||||
const downloadScp = async () => {
|
||||
setScpBusy(true);
|
||||
try { await DownloadScp(); const s = await GetScpStatus(); setScp(s as any); } catch {}
|
||||
finally { setScpBusy(false); }
|
||||
};
|
||||
// US Counties (offline FCC ULS) — download progress arrives via events.
|
||||
const [ulsStatus, setUlsStatus] = useState<{ count: number; updated_at?: string }>({ count: 0 });
|
||||
const [ulsBusy, setUlsBusy] = useState(false);
|
||||
@@ -4761,6 +4777,28 @@ export function SettingsModal({ onClose, onSaved, initialSection, onMainPaneChan
|
||||
<Checkbox checked={showBeamMap} onCheckedChange={(c) => { const v = !!c; setShowBeamMap(v); writeUiPref('opslog.showBeamOnMap', v ? '1' : '0'); }} />
|
||||
{t('gen.showBeam')}
|
||||
</label>
|
||||
|
||||
{/* Super Check Partial / N+1 — downloads the community MASTER.SCP list and
|
||||
shows a two-column callsign helper (partial matches + one-edit calls). */}
|
||||
<div className="border-t border-border/60 pt-3 space-y-2">
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
||||
<Checkbox checked={scp.enabled} disabled={scpBusy} onCheckedChange={(c) => toggleScp(!!c)} />
|
||||
{t('scp.enable')}
|
||||
</label>
|
||||
<p className="text-[11px] text-muted-foreground">{t('scp.settingsHint')}</p>
|
||||
{scp.enabled && (
|
||||
<div className="flex items-center gap-3">
|
||||
<Button variant="outline" size="sm" onClick={downloadScp} disabled={scpBusy}>
|
||||
<ArrowDown className="size-3.5" /> {scpBusy ? t('scp.downloading') : t('scp.download')}
|
||||
</Button>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{scp.count > 0
|
||||
? t('scp.loaded', { n: scp.count.toLocaleString(), date: scp.updated ? new Date(scp.updated).toLocaleDateString() : '?' })
|
||||
: t('scp.notLoaded')}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<label className="flex items-center gap-2 text-sm cursor-pointer">
|
||||
<Checkbox checked={startEqEnd} onCheckedChange={(c) => { const v = !!c; setStartEqEnd(v); writeUiPref('opslog.startEqualsEnd', v ? '1' : '0'); }} />
|
||||
{t('gen.startEqEnd')} <span className="text-xs text-muted-foreground">{t('gen.startEqEndHint')}</span>
|
||||
|
||||
@@ -283,6 +283,7 @@ const en: Dict = {
|
||||
'es.potaHint': 'Update your QSOs with the park reference from your pota.app hunter log. Paste your session token: log in at pota.app, open the browser DevTools → Network tab, click any api.pota.app request, and copy the full Authorization header value. The token expires after a while — re-copy it if the sync fails.', 'es.sessionToken': 'Session token', 'es.saving': 'Saving…', 'es.saveToken': 'Save token', 'es.potaThen': 'Then run the sync from the QSL Manager tab → service POTA hunter log (you can see and fix unmatched QSOs there).',
|
||||
'es.soon': 'soon', 'es.comingSoon': '{name} — coming soon', 'es.notWired': "This external service isn't wired up yet.",
|
||||
'lotw.usersTitle': 'LoTW user list', 'lotw.usersHint': "Downloads ARRL's public list of LoTW users + their last-upload date, to show a colour-coded LoTW badge next to a callsign (green < 1 week · amber 1–4 weeks · red > 30 days).", 'lotw.usersDownload': 'Download LoTW user list', 'lotw.usersDownloading': 'Downloading…', 'lotw.usersLoaded': '{n} users loaded · updated {date}', 'lotw.usersNone': 'Not downloaded yet — the badge stays hidden until you do.',
|
||||
'scp.title': 'Super Check Partial', 'scp.partial': 'Partial', 'scp.close': 'Close', 'scp.fill': 'Fill {call}', 'scp.none': 'No match', 'scp.typeMore': 'Type a call…', 'scp.noList': 'Download the SCP list in Settings → General.', 'scp.enable': 'Super Check Partial / N+1 callsign helper', 'scp.settingsHint': 'Downloads the community MASTER.SCP master list and shows a two-column widget as you type a call: Partial (known calls containing what you typed) and N+1 (calls one character away) — to spot and fix a busted call.', 'scp.download': 'Update SCP list', 'scp.downloading': 'Downloading…', 'scp.loaded': '{n} calls loaded · updated {date}', 'scp.notLoaded': 'Not downloaded yet.',
|
||||
'hw.connecting': 'Connecting…', 'hw.testConn': 'Test connection', 'hw.sending': 'Sending…', 'hw.testRotator': 'Test (point to 0°)',
|
||||
// Profiles panel
|
||||
'prof.deleteConfirm': 'Delete profile "{name}"? All its settings will be lost.', 'prof.dupPrompt': 'Name for the new profile (copy of "{name}"):', 'prof.dupSuffix': '{name} Copy', 'prof.newPrompt': 'Name for the new profile:', 'prof.newDefault': 'New profile',
|
||||
@@ -648,6 +649,7 @@ const fr: Dict = {
|
||||
'es.potaHint': "Met à jour tes QSO avec la référence du parc depuis ton carnet chasseur pota.app. Colle ton jeton de session : connecte-toi sur pota.app, ouvre les DevTools du navigateur → onglet Network, clique sur une requête api.pota.app, et copie toute la valeur de l'en-tête Authorization. Le jeton expire au bout d'un moment — recopie-le si la synchro échoue.", 'es.sessionToken': 'Jeton de session', 'es.saving': 'Enregistrement…', 'es.saveToken': 'Enregistrer le jeton', 'es.potaThen': "Puis lance la synchro depuis l'onglet Gestionnaire QSL → service POTA hunter log (tu peux y voir et corriger les QSO non appariés).",
|
||||
'es.soon': 'bientôt', 'es.comingSoon': '{name} — bientôt', 'es.notWired': "Ce service externe n'est pas encore branché.",
|
||||
'lotw.usersTitle': 'Liste des utilisateurs LoTW', 'lotw.usersHint': "Télécharge la liste publique ARRL des utilisateurs LoTW + leur date de dernier upload, pour afficher un badge LoTW coloré à côté d'un indicatif (vert < 1 semaine · ambre 1–4 semaines · rouge > 30 j).", 'lotw.usersDownload': 'Télécharger la liste LoTW', 'lotw.usersDownloading': 'Téléchargement…', 'lotw.usersLoaded': '{n} utilisateurs chargés · maj {date}', 'lotw.usersNone': 'Pas encore téléchargée — le badge reste caché tant que ce n’est pas fait.',
|
||||
'scp.title': 'Super Check Partial', 'scp.partial': 'Partiel', 'scp.close': 'Fermer', 'scp.fill': 'Remplir {call}', 'scp.none': 'Aucun', 'scp.typeMore': 'Tape un indicatif…', 'scp.noList': 'Télécharge la liste SCP dans Réglages → Général.', 'scp.enable': 'Assistant indicatifs Super Check Partial / N+1', 'scp.settingsHint': "Télécharge la liste communautaire MASTER.SCP et affiche un widget en 2 colonnes pendant que tu tapes un indicatif : Partiel (indicatifs connus contenant ce que tu tapes) et N+1 (indicatifs à une lettre près) — pour repérer et corriger un call busté.", 'scp.download': 'Mettre à jour la liste SCP', 'scp.downloading': 'Téléchargement…', 'scp.loaded': '{n} indicatifs chargés · maj {date}', 'scp.notLoaded': 'Pas encore téléchargée.',
|
||||
'hw.connecting': 'Connexion…', 'hw.testConn': 'Tester la connexion', 'hw.sending': 'Envoi…', 'hw.testRotator': 'Tester (pointer vers 0°)',
|
||||
'prof.deleteConfirm': 'Supprimer le profil « {name} » ? Tous ses réglages seront perdus.', 'prof.dupPrompt': 'Nom du nouveau profil (copie de « {name} ») :', 'prof.dupSuffix': '{name} Copie', 'prof.newPrompt': 'Nom du nouveau profil :', 'prof.newDefault': 'Nouveau profil',
|
||||
'prof.hint': "Bascule entre tes identités d'opération (maison / portable / SOTA / contest). Choisis un profil ici, puis édite ses champs dans les autres sections (Informations station, etc.) — les changements sont enregistrés sur le profil sélectionné.", 'prof.active': 'ACTIF', 'prof.duplicate': 'Dupliquer', 'prof.delete': 'Supprimer', 'prof.profileName': 'Nom du profil',
|
||||
|
||||
Vendored
+9
@@ -24,6 +24,7 @@ import {udp} from '../models';
|
||||
import {lotwusers} from '../models';
|
||||
import {lookup} from '../models';
|
||||
import {netctl} from '../models';
|
||||
import {scp} from '../models';
|
||||
|
||||
export function ACOMSetOperate(arg1:boolean):Promise<void>;
|
||||
|
||||
@@ -173,6 +174,8 @@ export function DownloadConfirmations(arg1:string,arg2:boolean,arg3:string):Prom
|
||||
|
||||
export function DownloadLoTWUsers():Promise<number>;
|
||||
|
||||
export function DownloadScp():Promise<number>;
|
||||
|
||||
export function DownloadULSCounties():Promise<void>;
|
||||
|
||||
export function DuplicateProfile(arg1:number,arg2:string):Promise<profile.Profile>;
|
||||
@@ -459,6 +462,8 @@ export function GetRotatorSettings():Promise<main.RotatorSettings>;
|
||||
|
||||
export function GetSPEStatus():Promise<spe.Status>;
|
||||
|
||||
export function GetScpStatus():Promise<main.ScpStatus>;
|
||||
|
||||
export function GetSecretStatus():Promise<main.SecretStatus>;
|
||||
|
||||
export function GetSlotStats():Promise<qso.SlotStats>;
|
||||
@@ -855,6 +860,8 @@ export function SaveUltrabeamSettings(arg1:main.UltrabeamSettings):Promise<void>
|
||||
|
||||
export function SaveWinkeyerSettings(arg1:main.WinkeyerSettings):Promise<void>;
|
||||
|
||||
export function ScpLookup(arg1:string):Promise<scp.Result>;
|
||||
|
||||
export function SearchAwardReferences(arg1:string,arg2:string,arg3:number,arg4:number):Promise<Array<awardref.Ref>>;
|
||||
|
||||
export function SendChatMessage(arg1:string):Promise<main.ChatMessage>;
|
||||
@@ -889,6 +896,8 @@ export function SetDVKLabel(arg1:number,arg2:string):Promise<void>;
|
||||
|
||||
export function SetPassphrase(arg1:string):Promise<void>;
|
||||
|
||||
export function SetScpEnabled(arg1:boolean):Promise<void>;
|
||||
|
||||
export function SetTelemetryEnabled(arg1:boolean):Promise<void>;
|
||||
|
||||
export function SetUIPref(arg1:string,arg2:string):Promise<void>;
|
||||
|
||||
@@ -298,6 +298,10 @@ export function DownloadLoTWUsers() {
|
||||
return window['go']['main']['App']['DownloadLoTWUsers']();
|
||||
}
|
||||
|
||||
export function DownloadScp() {
|
||||
return window['go']['main']['App']['DownloadScp']();
|
||||
}
|
||||
|
||||
export function DownloadULSCounties() {
|
||||
return window['go']['main']['App']['DownloadULSCounties']();
|
||||
}
|
||||
@@ -870,6 +874,10 @@ export function GetSPEStatus() {
|
||||
return window['go']['main']['App']['GetSPEStatus']();
|
||||
}
|
||||
|
||||
export function GetScpStatus() {
|
||||
return window['go']['main']['App']['GetScpStatus']();
|
||||
}
|
||||
|
||||
export function GetSecretStatus() {
|
||||
return window['go']['main']['App']['GetSecretStatus']();
|
||||
}
|
||||
@@ -1662,6 +1670,10 @@ export function SaveWinkeyerSettings(arg1) {
|
||||
return window['go']['main']['App']['SaveWinkeyerSettings'](arg1);
|
||||
}
|
||||
|
||||
export function ScpLookup(arg1) {
|
||||
return window['go']['main']['App']['ScpLookup'](arg1);
|
||||
}
|
||||
|
||||
export function SearchAwardReferences(arg1, arg2, arg3, arg4) {
|
||||
return window['go']['main']['App']['SearchAwardReferences'](arg1, arg2, arg3, arg4);
|
||||
}
|
||||
@@ -1730,6 +1742,10 @@ export function SetPassphrase(arg1) {
|
||||
return window['go']['main']['App']['SetPassphrase'](arg1);
|
||||
}
|
||||
|
||||
export function SetScpEnabled(arg1) {
|
||||
return window['go']['main']['App']['SetScpEnabled'](arg1);
|
||||
}
|
||||
|
||||
export function SetTelemetryEnabled(arg1) {
|
||||
return window['go']['main']['App']['SetTelemetryEnabled'](arg1);
|
||||
}
|
||||
|
||||
@@ -2720,6 +2720,22 @@ export namespace main {
|
||||
this.com_port = source["com_port"];
|
||||
}
|
||||
}
|
||||
export class ScpStatus {
|
||||
enabled: boolean;
|
||||
count: number;
|
||||
updated?: string;
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new ScpStatus(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.enabled = source["enabled"];
|
||||
this.count = source["count"];
|
||||
this.updated = source["updated"];
|
||||
}
|
||||
}
|
||||
export class SecretStatus {
|
||||
has_passphrase: boolean;
|
||||
unlocked: boolean;
|
||||
@@ -4323,6 +4339,25 @@ export namespace qso {
|
||||
|
||||
}
|
||||
|
||||
export namespace scp {
|
||||
|
||||
export class Result {
|
||||
partial: string[];
|
||||
nplus1: string[];
|
||||
|
||||
static createFrom(source: any = {}) {
|
||||
return new Result(source);
|
||||
}
|
||||
|
||||
constructor(source: any = {}) {
|
||||
if ('string' === typeof source) source = JSON.parse(source);
|
||||
this.partial = source["partial"];
|
||||
this.nplus1 = source["nplus1"];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export namespace solar {
|
||||
|
||||
export class Data {
|
||||
|
||||
Reference in New Issue
Block a user