Log mission name on send, log mission/drone-profile changes, auto-send on mission switch
Include the mission name in the "Mission sent"/"Mission upload failed" System Messages (was just the waypoint count before). Add MissionMeta.switchSeq, bumped only by an actual mission switch (startNew/startNewFromPlace/loadMission) - not by the id a brand-new mission gets from its first autosave, and not by restoreLastSession() on app start. FlyScreen compares it to detect a genuine switch and reacts two ways: logs "Mission changed to ..." and automatically re-uploads the new route to the flight controller, reusing the same send path as the manual send button (same _sending guard, same success/failure snackbar and log entry). Mission-change and drone-profile-change logging intentionally live in FlyScreen's ref.listen callbacks, not in mission_meta_provider.dart / active_drone_profile_provider.dart themselves - those providers have no notion of the app mode (Plan vs Fly, tracked separately by AppModeCubit), and logging there would record a change regardless of mode. Since FlyScreen only exists while Fly mode is active, scoping the listeners there means switching missions or drone profiles from Plan mode produces no System Messages entries, and only a mission switch (not a drone profile switch) triggers the automatic re-upload, matching what was asked for. Also splits systemMessageLogProvider (the plain message list + log(), no telemetry dependency) from the new systemMessageAutoLogProvider (the Connected/lost/battery/failsafe/connection-type auto-detection, which does watch telemetryProvider) - discovered while wiring the mission-change logging that logging a plain message from Plan-mode code was forcing the entire telemetry/transport stack to spin up as a side effect, which broke an unrelated Plan-mode test (UdpTransport threw on a double-disconnect during teardown). Keeping the two concerns apart means calling log() for a one-off message never has that side effect. Verified end to end on the Pixel_10a emulator: switching to an empty mission while in Fly mode correctly showed "No waypoints to send" and logged "Mission changed to ..." automatically, without touching the send button. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
b09d00ab9f
commit
b68c16d8e6
@@ -8,6 +8,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
import '../../../app_mode/app_mode_cubit.dart';
|
||||
import '../../../domain/mission/drone_profile.dart';
|
||||
import '../../../domain/mission/mission_stats.dart';
|
||||
import '../../../domain/mission/mission_warnings.dart';
|
||||
import '../../../domain/mission/route_geometry.dart';
|
||||
@@ -21,6 +22,7 @@ import '../../providers/active_drone_profile_provider.dart';
|
||||
import '../../providers/current_mission_provider.dart';
|
||||
import '../../providers/follow_drone_provider.dart';
|
||||
import '../../providers/map_controller_provider.dart';
|
||||
import '../../providers/mission_meta_provider.dart';
|
||||
import '../../providers/system_message_log_provider.dart';
|
||||
import '../../providers/telemetry_provider.dart';
|
||||
import '../../providers/terrain_provider.dart';
|
||||
@@ -137,9 +139,15 @@ class _FlyScreenState extends ConsumerState<FlyScreen> {
|
||||
/// den trivialen Fall (keine Wegpunkte), um nicht unnoetig einen
|
||||
/// Verbindungsversuch auszuloesen. Protokolliert Erfolg/Fehlschlag
|
||||
/// zusaetzlich im System-Messages-Log (Doku: "wenn ... Wegpunkte
|
||||
/// übertragen werden").
|
||||
/// übertragen werden") inklusive Missionsname. Wird sowohl vom Sende-
|
||||
/// Knopf als auch automatisch bei einem Missionswechsel aufgerufen (siehe
|
||||
/// den ref.listen(currentMissionMetaProvider, ...) unten) - der
|
||||
/// _sending-Schutz verhindert dabei ein doppeltes Senden, falls beides
|
||||
/// ueberlappt.
|
||||
Future<void> _onSendTap() async {
|
||||
if (_sending) return;
|
||||
final waypoints = ref.read(currentMissionProvider);
|
||||
final missionName = ref.read(currentMissionMetaProvider).name;
|
||||
final messenger = ScaffoldMessenger.of(context);
|
||||
if (waypoints.isEmpty) {
|
||||
messenger.showSnackBar(const SnackBar(content: Text('No waypoints to send')));
|
||||
@@ -155,10 +163,11 @@ class _FlyScreenState extends ConsumerState<FlyScreen> {
|
||||
);
|
||||
await service.syncAndUpload(FlatWaypointList(waypoints));
|
||||
messenger.showSnackBar(const SnackBar(content: Text('Mission sent')));
|
||||
log.log('Mission sent (${waypoints.length} waypoints)');
|
||||
log.log('Mission sent: "$missionName" (${waypoints.length} waypoints)');
|
||||
} catch (e) {
|
||||
messenger.showSnackBar(SnackBar(content: Text('Send failed: $e')));
|
||||
log.log('Mission upload failed: $e', severity: SystemMessageSeverity.critical);
|
||||
log.log('Mission upload failed: "$missionName": $e',
|
||||
severity: SystemMessageSeverity.critical);
|
||||
} finally {
|
||||
if (mounted) setState(() => _sending = false);
|
||||
}
|
||||
@@ -170,16 +179,15 @@ class _FlyScreenState extends ConsumerState<FlyScreen> {
|
||||
final droneProfile = ref.watch(activeDroneProfileProvider);
|
||||
final telemetry = ref.watch(telemetryProvider).value;
|
||||
final followDrone = ref.watch(followDroneProvider);
|
||||
// Beobachtet das System-Messages-Log dauerhaft ab dem ersten Eintritt in
|
||||
// den Fly-Modus (Doku: "log von kritischen ereignissen mit time stamp",
|
||||
// erweitert um Verbindungs-/Uebertragungsereignisse) - haelt
|
||||
// system_message_log_provider.dart's Notifier am Leben, solange dieser
|
||||
// Screen existiert, siehe dessen Klassendoku. Der Rueckgabewert selbst
|
||||
// wird hier nicht mehr gebraucht (der Warnungs-Knopf, der ihn frueher
|
||||
// fuer forceShowWarningsButton auswertete, ist im Fly-Modus durch den
|
||||
// Sende-Knopf ersetzt, siehe onSendTap oben) - System Messages bleiben
|
||||
// ueber die Drohnen-Status-Pille erreichbar.
|
||||
ref.watch(systemMessageLogProvider);
|
||||
// Beobachtet die automatische Ereigniserkennung (Connected/Lost/
|
||||
// Batterie/Failsafe/Verbindungstyp, Doku: "log von kritischen
|
||||
// ereignissen mit time stamp", erweitert um Verbindungsereignisse) fuer
|
||||
// die Dauer des Fly-Modus - siehe systemMessageAutoLogProvider-Doku,
|
||||
// warum das bewusst NICHT systemMessageLogProvider selbst ist (der
|
||||
// bliebe sonst auch im Plan-Modus dauerhaft an telemetryProvider
|
||||
// gekoppelt). Der Rueckgabewert wird hier nicht gebraucht, nur der
|
||||
// Beobachtungs-Seiteneffekt.
|
||||
ref.watch(systemMessageAutoLogProvider);
|
||||
|
||||
// Solange der ueber den GPS-Knopf in der Kopfleiste (FlyMapControls)
|
||||
// aktivierte Folgemodus aktiv ist, jede neue Telemetrie-Position
|
||||
@@ -193,6 +201,35 @@ class _FlyScreenState extends ConsumerState<FlyScreen> {
|
||||
}
|
||||
});
|
||||
|
||||
// Ein Missionswechsel waehrend des Fly-Modus (z.B. ueber die Mission-
|
||||
// Pille in der Fusszeile, die auch dort erreichbar bleibt) wird geloggt
|
||||
// und laedt die neue Route automatisch auf den Flightcontroller (Doku:
|
||||
// "Wechsel der Mission ... nur im fly modus loggen", "automatisch die
|
||||
// Wegpunktliste übertragen, wenn die Mission gewechselt wird im fly
|
||||
// modus") - beides sitzt bewusst hier statt in
|
||||
// mission_meta_provider.dart, das den App-Modus (AppModeCubit,
|
||||
// flutter_bloc) nicht kennt; dieser ref.listen existiert dagegen nur,
|
||||
// waehrend FlyScreen gemountet ist. switchSeq statt eines simplen
|
||||
// id-Vergleichs, weil der erste Autosave einer neuen Mission ebenfalls
|
||||
// deren id setzt, ohne dass die Mission dabei "gewechselt" wurde (siehe
|
||||
// MissionMeta-Doku).
|
||||
ref.listen<MissionMeta>(currentMissionMetaProvider, (previous, next) {
|
||||
if (previous != null && next.switchSeq != previous.switchSeq) {
|
||||
ref.read(systemMessageLogProvider.notifier).log('Mission changed to "${next.name}"');
|
||||
_onSendTap();
|
||||
}
|
||||
});
|
||||
|
||||
// Drohnenprofilwechsel waehrend des Fly-Modus (Doku: "Wechsel ... des
|
||||
// Drohnenprofils ... nur im fly modus loggen") - anders als beim
|
||||
// Missionswechsel bewusst OHNE automatischen Neuversand (Doku sieht das
|
||||
// explizit nur fuer den Missionswechsel vor).
|
||||
ref.listen<DroneProfile>(activeDroneProfileProvider, (previous, next) {
|
||||
if (previous != null && previous.id != next.id) {
|
||||
ref.read(systemMessageLogProvider.notifier).log('Drone profile changed to "${next.name}"');
|
||||
}
|
||||
});
|
||||
|
||||
final routeGeometry = buildRouteGeometry(
|
||||
waypoints,
|
||||
minTurnRadius: droneProfile.minTurnRadius,
|
||||
|
||||
Reference in New Issue
Block a user