|
11 | 11 | import { beamStore } from '../stores/beam.svelte'; |
12 | 12 | import { satColorCss } from '../constants'; |
13 | 13 | import type { SelectedSatInfo } from '../types'; |
| 14 | + import type { SatellitePass } from '../passes/pass-types'; |
| 15 | + import { fmtCountdownCompact } from '../format'; |
| 16 | +
|
| 17 | + /** Find the next upcoming (or active) pass for a satellite */ |
| 18 | + function nextPass(noradId: number, passes: SatellitePass[], epoch: number): SatellitePass | null { |
| 19 | + // Active pass first |
| 20 | + for (const p of passes) { |
| 21 | + if (p.satNoradId === noradId && epoch >= p.aosEpoch && epoch <= p.losEpoch) return p; |
| 22 | + } |
| 23 | + // Next upcoming |
| 24 | + for (const p of passes) { |
| 25 | + if (p.satNoradId === noradId && p.aosEpoch > epoch) return p; |
| 26 | + } |
| 27 | + return null; |
| 28 | + } |
| 29 | +
|
| 30 | + function aosLabel(noradId: number): string | null { |
| 31 | + const epoch = uiStore.passListEpoch; |
| 32 | + if (!epoch) return null; |
| 33 | + const pass = nextPass(noradId, uiStore.passes, epoch); |
| 34 | + if (!pass) return null; |
| 35 | + if (epoch >= pass.aosEpoch && epoch <= pass.losEpoch) return 'LIVE'; |
| 36 | + const sec = (pass.aosEpoch - epoch) * 86400; |
| 37 | + return fmtCountdownCompact(sec); |
| 38 | + } |
14 | 39 |
|
15 | 40 | let expandedSats = $state(new Set<number>()); |
16 | 41 | let searchQuery = $state(''); |
|
191 | 216 | onchange={() => uiStore.toggleSatVisibility(sat.noradId)} /> |
192 | 217 | <!-- svelte-ignore a11y_click_events_have_key_events a11y_no_static_element_interactions --> |
193 | 218 | <span class="sat-name" onclick={() => toggle(sat.noradId)}>{sat.name}</span> |
194 | | - <span class="pill">{fmt(sat.altKm, 0)} km</span> |
195 | | - <span class="pill">{fmt(sat.speedKmS, 2)} km/s</span> |
| 219 | + <span class="pill">Alt {fmt(sat.altKm, 0)} km</span> |
| 220 | + {#if aosLabel(sat.noradId) != null} |
| 221 | + {@const label = aosLabel(sat.noradId)!} |
| 222 | + <span class="pill aos-pill" class:aos-live={label === 'LIVE'}>{label === 'LIVE' ? 'LIVE' : `AOS ${label}`}</span> |
| 223 | + {/if} |
196 | 224 | <button class="expand-btn" onclick={() => toggle(sat.noradId)} title={expandedSats.has(sat.noradId) ? 'Collapse' : 'Expand'}> |
197 | 225 | <svg viewBox="0 0 10 6" width="8" height="5" fill="currentColor" class:rotated={expandedSats.has(sat.noradId)}> |
198 | 226 | <polygon points="0,0 10,0 5,6"/> |
|
206 | 234 | <span class="dl">NORAD ID</span><span class="dv">{sat.noradId}</span> |
207 | 235 | <span class="dl">Latitude</span><span class="dv">{fmt(sat.latDeg, 2)}°</span> |
208 | 236 | <span class="dl">Longitude</span><span class="dv">{fmt(sat.lonDeg, 2)}°</span> |
| 237 | + <span class="dl">Speed</span><span class="dv">{fmt(sat.speedKmS, 2)} km/s</span> |
209 | 238 | <span class="dl">Ang. rate</span><span class="dv">{(sat.angularRateDegS ?? 0).toFixed(2)}°/s</span> |
210 | 239 | {#if sat.magStr !== null} |
211 | 240 | <span class="dl">Magnitude</span><span class="dv">{sat.magStr}</span> |
|
362 | 391 | white-space: nowrap; |
363 | 392 | flex-shrink: 0; |
364 | 393 | } |
| 394 | + .aos-pill { |
| 395 | + color: var(--text-muted); |
| 396 | + } |
| 397 | + .aos-live { |
| 398 | + color: var(--live); |
| 399 | + } |
365 | 400 | .expand-btn { |
366 | 401 | background: none; |
367 | 402 | border: none; |
|
0 commit comments