Add center reticle control for dropping waypoints

- ReticleButton: fixed-at-screen-center "+" circle (HTML prototype:
  #centerCluster/#reticleBtn), tapping it drops a waypoint at the current
  map center.
- CurrentMissionNotifier (Riverpod): holds the waypoint list for the
  mission being edited. Reactive single-value state per doc 4.16, so
  Riverpod rather than a new Bloc/Cubit.
- MissionMap now renders each waypoint as a CircleLayer marker (white
  border, dark fill, matching the prototype's L.circleMarker styling).
- PlanScreen owns the MapController needed to read the camera center on
  tap, and wires the reticle to the provider.

Default altitude/speed/catch-radius (60m / 15 m/s / 60m) are hardcoded to
the T1 Ranger default profile values from the prototype for now - TODO
once drone profile settings (doc 3.5) exist.

Verified with flutter analyze, flutter test (incl. a new test covering the
add-waypoint path), and a real run on the Pixel_10a emulator: panned the
map and dropped two waypoints, both markers stayed correctly georeferenced.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Constantin Leue
2026-07-27 22:21:35 +02:00
co-authored by Claude Sonnet 5
parent fc7d014fda
commit db6b46140c
5 changed files with 148 additions and 3 deletions
+28
View File
@@ -0,0 +1,28 @@
import 'package:flutter/material.dart';
/// Zentrales Steuerelement zum Setzen von Wegpunkten (HTML-Demonstrator:
/// #centerCluster/#reticleBtn), fixiert in der Bildschirmmitte. Die Karte
/// wird darunter verschoben; ein Tap setzt einen Wegpunkt an der aktuellen
/// Kartenmitte.
class ReticleButton extends StatelessWidget {
const ReticleButton({super.key, required this.onTap});
final VoidCallback onTap;
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: onTap,
child: Container(
width: 55,
height: 55,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Colors.black.withValues(alpha: 0.68),
border: Border.all(color: Colors.white, width: 2),
),
child: const Icon(Icons.add, color: Colors.white, size: 26),
),
);
}
}