|
7 | 7 | import InfoTip from './shared/InfoTip.svelte'; |
8 | 8 | import { uiStore } from '../stores/ui.svelte'; |
9 | 9 | import { beamStore, isInsideBeam } from '../stores/beam.svelte'; |
10 | | - import { rotatorStore, PARK_PRESETS, type ParkPreset, type PassEndAction } from '../stores/rotator.svelte'; |
| 10 | + import { rotatorStore, PARK_PRESETS, ANTENNA_PRESETS, type ParkPreset, type PassEndAction } from '../stores/rotator.svelte'; |
11 | 11 | import { timeStore } from '../stores/time.svelte'; |
12 | 12 | import { satColorRgba } from '../constants'; |
13 | 13 | import { ViewMode } from '../types'; |
|
89 | 89 | let rateDisplay = $derived(`${(rotatorStore.updateIntervalMs / 1000).toFixed(1)}s`); |
90 | 90 | let tolDisplay = $derived(`${rotatorStore.tolerance.toFixed(1)}°`); |
91 | 91 |
|
| 92 | + let activeAntennaPreset = $derived.by(() => { |
| 93 | + for (const [key, p] of Object.entries(ANTENNA_PRESETS)) { |
| 94 | + if (beamStore.beamWidth === p.beamWidth && rotatorStore.tolerance === p.tolerance && rotatorStore.updateIntervalMs === p.updateMs) |
| 95 | + return key; |
| 96 | + } |
| 97 | + return null; |
| 98 | + }); |
| 99 | +
|
| 100 | + function applyAntennaPreset(key: string) { |
| 101 | + const p = ANTENNA_PRESETS[key]; |
| 102 | + if (!p) return; |
| 103 | + beamStore.setBeamWidth(p.beamWidth); |
| 104 | + rotatorStore.setTolerance(p.tolerance); |
| 105 | + rotatorStore.setUpdateInterval(p.updateMs); |
| 106 | + } |
| 107 | +
|
92 | 108 | // In sky view, rotate the radar so the viewer's look direction is at the top |
93 | 109 | let headingRad = $derived(uiStore.viewMode === ViewMode.VIEW_SKY ? uiStore.skyHeading : 0); |
94 | 110 |
|
|
880 | 896 |
|
881 | 897 | {:else} |
882 | 898 | <div class="setup-panel"> |
| 899 | + <h4 class="section-header">Antenna</h4> |
| 900 | + <div class="rot-row"> |
| 901 | + <label>Preset<InfoTip>Sets beam width, tolerance, and update rate for common antenna types.</InfoTip></label> |
| 902 | + <div class="antenna-presets"> |
| 903 | + {#each Object.entries(ANTENNA_PRESETS) as [key, p]} |
| 904 | + <Button size="xs" active={activeAntennaPreset === key} onclick={() => applyAntennaPreset(key)}>{p.label}</Button> |
| 905 | + {/each} |
| 906 | + </div> |
| 907 | + </div> |
| 908 | + <div class="rot-row antenna-summary"> |
| 909 | + <span>Beam {beamStore.beamWidth}°</span> |
| 910 | + <span>Tolerance {rotatorStore.tolerance}°</span> |
| 911 | + <span>Rate {rateDisplay}</span> |
| 912 | + </div> |
| 913 | + |
883 | 914 | <h4 class="section-header">Connection</h4> |
884 | 915 | <div class="rot-row"> |
885 | 916 | <label>Mode</label> |
|
922 | 953 | {/if} |
923 | 954 |
|
924 | 955 | <Slider label="Update rate" display={rateDisplay} |
925 | | - min={100} max={5000} step={100} value={rotatorStore.updateIntervalMs} |
| 956 | + min={100} max={20000} step={100} value={rotatorStore.updateIntervalMs} |
926 | 957 | oninput={(e) => rotatorStore.setUpdateInterval(Number((e.target as HTMLInputElement).value))} /> |
927 | 958 |
|
928 | 959 | {#snippet tolTip()}<InfoTip>Minimum error before sending a new position command. Reduces wear on the rotator gears. Set to 0 for continuous tracking.</InfoTip>{/snippet} |
929 | 960 | <Slider label="Tolerance" display={tolDisplay} tip={tolTip} |
930 | | - min={0} max={5} step={0.1} value={rotatorStore.tolerance} |
| 961 | + min={0} max={10} step={0.5} value={rotatorStore.tolerance} |
931 | 962 | oninput={(e) => rotatorStore.setTolerance(Number((e.target as HTMLInputElement).value))} /> |
932 | 963 |
|
933 | 964 | <div class="rot-row"> |
|
1252 | 1283 | gap: 4px; |
1253 | 1284 | } |
1254 | 1285 |
|
| 1286 | + /* ── Antenna presets ── */ |
| 1287 | + .antenna-presets { |
| 1288 | + display: flex; |
| 1289 | + gap: 2px; |
| 1290 | + } |
| 1291 | + .antenna-summary { |
| 1292 | + gap: 10px; |
| 1293 | + justify-content: flex-start; |
| 1294 | + font-size: 9px; |
| 1295 | + color: var(--text-muted); |
| 1296 | + font-variant-numeric: tabular-nums; |
| 1297 | + } |
| 1298 | +
|
1255 | 1299 | /* ── Setup tab ── */ |
1256 | 1300 | .setup-panel { |
1257 | 1301 | padding: 8px; |
|
0 commit comments