38b048ad41
Sync (FlyWithLua companions in plugins/ + server/fmssync.js): - FMS flight-plan two-way sync (App <-> in-sim FMS) via fms-sync.lua - G1000 UI-state publish (page/range/inset) via ui-sync.lua + CDI source, baro, map-range follow - Terrain awareness: elevation grid probe (terrain-probe.lua) -> red/yellow MFD overlay vs aircraft altitude PFD: - AFCS mode annunciation bar from autopilot _status datarefs - CDI source GPS/VLOC colouring, BRG1/BRG2 pointers + DME windows, marker beacons - magenta speed/altitude trend vectors, selected-altitude alerting - time-based (frame-rate-independent) smoothing for attitude/heading/tapes MFD: - nav data bar (DTK/ETE/active leg), airways overlay from earth_awy.dat, compass rose anchored to the ownship Dialogs (NEAREST/FLIGHTPLAN/DIRECT-TO/PROCEDURES): - flat, square, embedded G1000 look (no shadow/rounded/transparency) - compact lower-right placement, no close X (softkey toggles), single window - NEAREST 2-line entries (ILS/VFR, COM freq, runway length), PROC action menu Service worker: network-first HTML so reloads pick up new builds (cache v2). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
49 lines
2.0 KiB
React
49 lines
2.0 KiB
React
import React from 'react';
|
||
import { num } from '../api/useXplane.js';
|
||
|
||
// Touch-friendly radio tuner, styled like our KAP 140 (green LCD) + the desktop
|
||
// launcher (macOS-dark chrome). Tunes the STANDBY frequency and swaps it active
|
||
// via X-Plane's own per-radio commands (no unit-sensitive frequency writes).
|
||
const fmt = (v, isCom) => (num(v) / 100).toFixed(isCom ? 3 : 2);
|
||
|
||
export default function RadioTuner({ values, command, radio, onClose }) {
|
||
const { id, label, isCom } = radio;
|
||
const sb = values[`${id}Sb`];
|
||
const act = values[id];
|
||
const cmd = (s) => command(`${id}${s}`);
|
||
return (
|
||
<div className="dlg-backdrop" onClick={onClose}>
|
||
<div className="rtuner" onClick={(e) => e.stopPropagation()}>
|
||
<div className="rt-head">
|
||
<span className="rt-title">{label}</span>
|
||
<span className="rt-kind">{isCom ? 'COM' : 'NAV'}</span>
|
||
</div>
|
||
|
||
<div className="rt-lcd">
|
||
<div className="rt-f"><span>ACTIVE</span><b className="act">{fmt(act, isCom)}</b></div>
|
||
<button className="rt-swap" onClick={() => cmd('Swap')} title="Aktiv ↔ Standby">⇆</button>
|
||
<div className="rt-f right"><span>STANDBY</span><b className="sby">{fmt(sb, isCom)}</b></div>
|
||
</div>
|
||
|
||
<div className="rt-tune">
|
||
<div className="rt-row">
|
||
<span className="rt-unit">MHz</span>
|
||
<button className="rt-step" onClick={() => cmd('CoarseDown')}>−</button>
|
||
<button className="rt-step" onClick={() => cmd('CoarseUp')}>+</button>
|
||
</div>
|
||
<div className="rt-row">
|
||
<span className="rt-unit">kHz</span>
|
||
<button className="rt-step" onClick={() => cmd('FineDown')}>−</button>
|
||
<button className="rt-step" onClick={() => cmd('FineUp')}>+</button>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="rt-actions">
|
||
<button className="rt-btn primary" onClick={() => cmd('Swap')}>⇆ Auf Aktiv</button>
|
||
<button className="rt-btn" onClick={onClose}>Schließen</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
);
|
||
}
|