84 lines
3.4 KiB
Dart
84 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import 'package:latlong2/latlong.dart';
|
|
|
|
import '../providers/current_mission_provider.dart';
|
|
import '../providers/follow_drone_provider.dart';
|
|
import '../providers/map_controller_provider.dart';
|
|
import '../providers/telemetry_provider.dart';
|
|
import 'drone_follow_icon.dart';
|
|
import 'nav_icon_button.dart';
|
|
|
|
/// Kartensteuerung im Fly-Modus (Doku 3.11): Ortssuche/Home entfallen hier
|
|
/// (keine Missionsbearbeitung), stattdessen schaltet der Drohnen-Button den
|
|
/// Kartenfolgemodus um (followDroneProvider) - "Home" (erster Wegpunkt) ist
|
|
/// waehrend des Flugs kein sinnvoller Bezugspunkt mehr, der Fit-Button
|
|
/// (gesamte Route) bleibt dagegen unveraendert wie im Plan-Modus erhalten.
|
|
class FlyMapControls extends ConsumerWidget {
|
|
const FlyMapControls({super.key});
|
|
|
|
/// Zielzoom beim Aktivieren des Folgemodus - deutlich weiter herausgezoomt
|
|
/// als der Standard-Kartenzoom (siehe MissionMap._initialZoom), damit
|
|
/// waehrend des Verfolgens genug Gelaende/Route um die Drohne herum
|
|
/// sichtbar bleibt statt nur ihrer unmittelbaren Umgebung.
|
|
static const _followZoom = 16.0;
|
|
|
|
/// Erster Tap zoomt auf die aktuelle Telemetrieposition und aktiviert den
|
|
/// Folgemodus (FlyScreen haengt sich darauf ein, zieht die Karte bei
|
|
/// jedem neuen Telemetrie-Frame nach und bricht bei manueller
|
|
/// Karteninteraktion selbststaendig wieder ab). Zweiter Tap beendet ihn
|
|
/// wieder, ohne die Kamera zu bewegen.
|
|
void _onDronePressed(BuildContext context, WidgetRef ref) {
|
|
if (ref.read(followDroneProvider)) {
|
|
ref.read(followDroneProvider.notifier).set(false);
|
|
return;
|
|
}
|
|
final frame = ref.read(telemetryProvider).value;
|
|
if (frame == null) {
|
|
ScaffoldMessenger.of(context)
|
|
.showSnackBar(const SnackBar(content: Text('No telemetry yet')));
|
|
return;
|
|
}
|
|
ref.read(mapControllerProvider).move(LatLng(frame.lat, frame.lon), _followZoom);
|
|
ref.read(followDroneProvider.notifier).set(true);
|
|
}
|
|
|
|
/// Beendet den Folgemodus explizit, statt sich auf den Abbruch bei
|
|
/// manueller Karteninteraktion in FlyScreen zu verlassen (FlyScreen._
|
|
/// onMapEvent) - fitMapToWaypoints() bewegt die Kamera ueber denselben
|
|
/// MapController (source == mapController), gilt dort also nicht als
|
|
/// manuelle Geste und wuerde den Folgemodus sonst aktiv lassen. Ohne
|
|
/// diesen Abbruch wuerde der naechste Telemetrie-Frame die Kamera sofort
|
|
/// wieder von der gerade eingestellten Missionsuebersicht weg auf die
|
|
/// Drohne zurueckziehen.
|
|
void _onFitPressed(BuildContext context, WidgetRef ref) {
|
|
final waypoints = ref.read(currentMissionProvider);
|
|
if (waypoints.isEmpty) {
|
|
ScaffoldMessenger.of(context)
|
|
.showSnackBar(const SnackBar(content: Text('No waypoints to fit')));
|
|
return;
|
|
}
|
|
ref.read(followDroneProvider.notifier).set(false);
|
|
fitMapToWaypoints(ref, waypoints);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final following = ref.watch(followDroneProvider);
|
|
return Row(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
NavIconButton(
|
|
iconWidget: DroneFollowIcon(active: following),
|
|
onTap: () => _onDronePressed(context, ref),
|
|
),
|
|
const SizedBox(width: 8),
|
|
NavIconButton(
|
|
icon: Icons.crop_free,
|
|
onTap: () => _onFitPressed(context, ref),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
}
|