On-board package hover traces from the carrier's current position (ISS-040)
CI / build + unit + e2e (pull_request) Successful in 7m11s

This commit is contained in:
2026-09-20 09:16:06 +00:00
parent f44e7aa0f5
commit 3024606ac8
6 changed files with 155 additions and 4 deletions
+12 -2
View File
@@ -8,7 +8,7 @@ import { DEFAULT_STYLE_ID, STYLES, STYLE_STORAGE_KEY, isStyleId, localAssetsAvai
import type { GeoJsonFeatureCollection } from '../lib/airports';
import type { StateSnapshot } from '../lib/game/state';
import type { HoverTarget } from './hoverTypes';
import { hoverRouteGeoJson, planesGeoJson, routesGeoJson, type AirportCoord, type PlaneFeatureProps } from '../lib/mapData';
import { hoverRouteGeoJson, hoverTraceGeoJson, planesGeoJson, routesGeoJson, type AirportCoord, type PlaneFeatureProps } from '../lib/mapData';
import { weatherFor } from '../lib/weather';
import { approxLocalTime } from '../lib/localTime';
@@ -100,6 +100,9 @@ export default function FlightMap({ state, hovered, applySnapshot }: MapProps) {
useEffect(() => {
stateRef.current = state ?? null;
applyDynamicRef.current();
// ISS-040 (v0.23.2): re-apply the hover too, so an on-board package's trace follows a moving
// carrier between polls while hovered — idempotent and cheap (one small setData + ring filters).
applyHoverRef.current();
}, [state]);
// ISS-002 (v0.15.0): hover highlight — same ref + effect pattern as the snapshot above.
@@ -138,7 +141,14 @@ export default function FlightMap({ state, hovered, applySnapshot }: MapProps) {
// ICAOs (package origin→dest / relocate fromIcao→toIcao); empty when either endpoint is unknown.
const hoverSource = map.getSource(HOVER_ROUTES_SOURCE_ID) as maplibregl.GeoJSONSource | undefined;
if (hoverSource) {
void hoverSource.setData(hoverRouteGeoJson(fromIcao, toIcao, airportsIndexRef.current ?? new Map()));
// ISS-040 (v0.23.2): an on-board package's trace starts from the carrier plane's LIVE position,
// not its origin airport — identical to before while grounded at the pickup, different once it
// has departed with cargo still loaded. No carrier in state yet → fall back to the ICAO trace.
const idx = airportsIndexRef.current ?? new Map();
const carrier = h?.kind === 'package' && h.planeId ? stateRef.current?.planes.find((p) => p.id === h.planeId) : undefined;
void hoverSource.setData(
carrier ? hoverTraceGeoJson({ lat: carrier.lat, lon: carrier.lon }, toIcao, idx) : hoverRouteGeoJson(fromIcao, toIcao, idx),
);
}
// Package hovers ring BOTH endpoints (v0.15.0 behavior); 'route' hovers ring the TARGET only —
// the relocation's destination is what ISS-027 asks to see. Plane hovers ring nothing.