- Wheels/readouts now add max(MediaQuery.padding.left/right) on both sides
symmetrically (HTML prototype: max(env(safe-area-inset-left),
env(safe-area-inset-right))), so a front-camera cutout in landscape
doesn't sit behind the altitude wheel, and both sides stay in sync.
- WaypointListPanel is now pushed via Navigator (PageRouteBuilder + fade)
instead of being an internal Stack overlay in PlanScreen. It was
rendering *under* AppShell's TopModeBar before, since TopModeBar is
always the last (topmost) child of AppShell's own Stack regardless of
what PlanScreen draws internally - a plain bool flag inside PlanScreen
had no way to paint above a sibling higher up the tree. A pushed route
paints above the entire invoking route's content by construction, so
this was the actual fix rather than reshuffling Z-order inside PlanScreen.
- Extracted DefaultDroneProfile (T1 Ranger constants) out of PlanScreen's
private statics into lib/domain/mission/, since WaypointListPanel now
needs the same values to compute its own route geometry reactively
(previously passed down as a vertexBad/altMin/altMax/... snapshot, which
would have gone stale while the panel was open across a route boundary).
- Bottom bar now has the prototype's rgba(15,15,15,0.72) background
(previously fully transparent outside the stats pill), and gained
MiniAltitudeProfile - the non-interactive height-profile sparkline
that sits above the stats row.
- Added the Altitude/Speed full-screen chart tabs (FullValueChart):
drag any waypoint's point to adjust its altitude/speed, X position
proportional to cumulative route distance, matching the prototype's
buildFullChart()/attachChartDrag(). Terrain overlay and wind diamonds
from the prototype aren't ported - terrain (doc 3.9) and wind (doc 3.8)
systems don't exist yet in the Flutter app.
- RouteGeometry now also exposes legClimbBad (was computed internally but
not surfaced), needed by both the mini profile and the chart tabs.
Discovered while updating the widget tests: a single tester.pump() after
tapping something that triggers Navigator.push/pop isn't enough - the
push/pop itself needs a frame to register before a duration-based pump
can animate it, so both are needed in sequence. Added 2 new tests for the
chart tabs; all 17 tests and flutter analyze pass. Verified all four
changes on the Pixel_10a emulator: wheels, opaque bottom bar with the
mini profile, the list panel now fully covering the top bar (confirmed by
its complete absence while the panel is open), and dragging points on
both chart tabs.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- RouteGeometry (lib/domain/mission/route_geometry.dart): physically
grounded flight path - straight segments + tangential arcs at each
course change, sized from the drone's minimum turn radius (doc 3.7/4.6),
replacing a naive spline that would suggest unrealistic turn radii.
Marks a vertex "bad" (turn angle >= 160°, tangent length exceeding 90%
of either adjacent leg, or exceeding the waypoint's catch radius) and a
leg "bad" when the required climb/descent rate exceeds the drone's
max climb/descent rate. Pure Dart, no Flutter dependency, so it stays
usable if the mission domain is ever split into its own package (4.22).
Wind-based turn-radius correction from the prototype isn't ported yet -
the wind system (doc 3.8) doesn't exist in the Flutter app.
- MissionMap now draws each RouteSegment as its own Polyline, colored red
when bad instead of a single plain white line; waypoint markers turn red
too when their vertex is bad.
- ValueWheel: vertical drag-to-adjust tape control (HTML prototype's
#altWheel/#spdWheel), custom-painted tick marks, blue center indicator,
gradient fade at top/bottom. Wired into PlanScreen on both screen edges
with Alt/Speed readouts.
- curAlt/curSpeed now live in PlanScreen state instead of fixed constants:
dropping a new waypoint uses whatever the wheels are currently set to;
entering editing mode on an existing waypoint loads its values into the
wheels; adjusting a wheel while editing writes live into that waypoint
(provider gained setAltitude/setSpeed to match the existing
moveWaypoint/toggleAction pattern).
Added dedicated unit tests for the geometry (empty list, straight line,
feasible 90° turn producing a line-arc-line segment sequence, an
infeasible near-180° turn, and an infeasible descent rate) rather than
relying on eyeballing it on the emulator - this is exactly the kind of
ported-math correctness that's hard to verify visually but easy to get
subtly wrong. All 11 tests (previous 6 + these 5) and flutter analyze
pass. Also manually verified the wheels on the Pixel_10a emulator: drag
changes the value and the on-screen readout in real time.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>