feat(sat): a wider frequency list, a resizable readout, one locator

Three things reported together from the tab.

The shipped frequency plan went from eleven satellites to twenty-five:
the eight Tevel FM cubesats, EO-88, AO-109, CAS-4A and 4B, TO-108,
GreenCube's single-frequency digipeater, and QO-100's wideband
transponder beside its narrowband one. It remains a starting point in a
file the operator can correct — a transponder gets switched and no
release should be needed to follow it — and the picker still lists every
bird in the element set when the "with a plan" filter is unticked.

The readout column drags to any width between 240 and 720 pixels,
double-clicks back to its default, and folds away entirely. How much map
against how much detail is the operator's call: watching a footprint
cross an ocean and working a pass want opposite things.

And the locator is no longer asked for twice. Passes are predicted from
the station locator, which is set once in Station information; the field
here was only ever for an antenna at another site, so it says so and sits
folded away. Nobody should have to wonder which of two locators is in
use.

Also: "Driven by" is two columns wide. "OpsLog (EasyComm II)" did not fit
in a third of the row, and a truncated choice is a choice that cannot be
read.
This commit is contained in:
2026-09-07 22:36:48 +02:00
parent 76022ff91c
commit b478cbfd2a
6 changed files with 388 additions and 33 deletions
+21 -11
View File
@@ -4531,11 +4531,6 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
</div>
<div className="space-y-5 max-w-xl">
<div className="grid grid-cols-3 gap-3">
<div className="space-y-1">
<Label>{t('satset.grid')}</Label>
<Input className="font-mono" placeholder={t('satset.gridPlaceholder')}
value={satCfg.grid ?? ''} onChange={(e) => set('grid', e.target.value.toUpperCase())} />
</div>
<div className="space-y-1">
<Label>{t('satset.altM')}</Label>
<Input className="font-mono" value={String(satCfg.alt_m ?? 0)}
@@ -4546,16 +4541,28 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
<Input className="font-mono" value={String(satCfg.min_el ?? 10)}
onChange={(e) => set('min_el', num(e.target.value))} />
</div>
</div>
<p className="text-xs text-muted-foreground">{t('satset.gridHint')}</p>
<div className="grid grid-cols-3 gap-3">
<div className="space-y-1">
<Label>{t('satset.windowH')}</Label>
<Input className="font-mono" value={String(satCfg.window_h ?? 24)}
onChange={(e) => set('window_h', num(e.target.value))} />
</div>
</div>
<p className="text-xs text-muted-foreground">{t('satset.altHint')}</p>
{/* The locator is NOT repeated here: it is the station's, set once in
Station information, and the passes are predicted from it. This is
the exception an antenna at another site and it says so, so
nobody has to wonder which of two locators is in use. */}
<details className="text-sm">
<summary className="cursor-pointer text-muted-foreground hover:text-foreground">
{t('satset.otherSite')}
</summary>
<div className="mt-2 flex items-center gap-3">
<Input className="font-mono w-40" placeholder={t('satset.gridPlaceholder')}
value={satCfg.grid ?? ''} onChange={(e) => set('grid', e.target.value.toUpperCase())} />
<span className="text-xs text-muted-foreground">{t('satset.otherSiteHint')}</span>
</div>
</details>
<div className="border-t border-border/60 pt-4 space-y-3">
<h4 className="text-sm font-semibold text-foreground">{t('satset.rotor')}</h4>
@@ -4569,8 +4576,11 @@ function SettingsModalImpl({ onClose, onSaved, initialSection, onMainPaneChanged
<>
{/* Who drives the mast. Not a detail: a station already running
PstRotator must NOT have OpsLog on the same cable as well. */}
<div className="grid grid-cols-3 gap-3">
<div className="space-y-1">
<div className="grid grid-cols-4 gap-3">
{/* Two columns wide: "OpsLog (EasyComm II)" does not fit in a
third of the row, and a truncated choice is a choice an
operator cannot read. */}
<div className="space-y-1 col-span-2">
<Label>{t('satset.rotType')}</Label>
<Select value={satCfg.rot_type || 'easycomm'} onValueChange={(v) => set('rot_type', v)}>
<SelectTrigger className="h-9"><SelectValue /></SelectTrigger>