Auto-install Lua, smooth all panels, airspace overlay + launcher region picker

FlyWithLua auto-install: bridge drops fms-sync/ui-sync/terrain-probe into
X-Plane's FlyWithLua Scripts dir on startup and self-updates (content-compare).
Graceful when no X-Plane / no FlyWithLua. /api/lua/install + status in health.
Desktop app bundles the scripts and passes LUA_SRC_DIR to the sidecar.

Smoothing: shared useEased/useEasedAngle hook (api/ease.js) with render-bail on
settle. VFR steam gauges now interpolate to 60fps instead of stepping at the
~10Hz value stream. MFD ownship no longer vibrates — position/heading eased in a
single rAF loop, follow-pan without animated-panTo pile-up (pauses on range zoom).

Airspace overlay: server/airspace.js loads per-region GeoJSON, classifies
(B/C/D/TMA/CTR/MOA/Restricted/Prohibited/Danger), bbox query, and downloads
regions on demand — FAA (US, key-free) and OpenAIP (Europe, user key). New
AIRSPACE softkey draws chart-coloured boundaries (B blue, C magenta, D dashed),
non-interactive so map-clicks still drop waypoints. Launcher gains a "Lufträume"
section to pick/download regions via the running bridge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 13:57:50 +02:00
parent b2fab0c374
commit 9aba24978b
16 changed files with 572 additions and 77 deletions
+17
View File
@@ -87,3 +87,20 @@ input:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px r
.link:hover { text-decoration: underline; }
.link:disabled { color: var(--mut); cursor: default; text-decoration: none; }
.update-badge { display: inline-block; width: 7px; height: 7px; border-radius: 50%; background: var(--green); margin-left: 6px; box-shadow: 0 0 6px var(--green); vertical-align: middle; }
/* airspace region picker (in the live card) */
.asp-wrap { margin-top: 12px; border-top: 1px solid var(--line-soft); padding-top: 10px; }
.asp-wrap > summary { cursor: pointer; color: var(--txt2); font-size: 13px; font-weight: 600; list-style: none; }
.asp-wrap > summary::-webkit-details-marker { display: none; }
.asp-wrap > summary::before { content: '▸ '; color: var(--mut); }
.asp-wrap[open] > summary::before { content: '▾ '; }
.asp-body { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; }
.asp-note { color: var(--mut); font-size: 12px; line-height: 1.4; margin: 0; }
.asp-note a { color: var(--green); }
#aspKey { width: 100%; }
.asp-list { display: flex; flex-direction: column; gap: 6px; }
.asp-row { display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 10px;
background: var(--bg2); border: 1px solid var(--line-soft); border-radius: 8px; padding: 7px 10px; }
.asp-name { color: var(--txt2); font-size: 13px; }
.asp-name em { color: var(--mut); font-style: normal; font-size: 11px; }
.asp-count { color: var(--mut); font-size: 12px; min-width: 56px; text-align: right; }