Persist the ground elevation profile with the mission
The Mini-Altitude-Profile terrain data only ever lived in TerrainNotifier's in-memory state (one slot, keyed by route). Every app restart, or every switch away from and back to a mission, forced a full re-fetch of all AWS Terrarium elevation tiles for the route - the noticeably slow load the user reported for some missions was this happening on every visit, not just once. Adds a nullable terrainProfileJson column to the missions table (schema v6->v7) and a saveTerrainProfile() repository method, kept separate from the regular waypoint upsert() so an ordinary autosave never clobbers an already-cached profile. TerrainNotifier persists a profile right after a successful fetch (fire-and-forget) and gains restore(), called from CurrentMissionMetaNotifier whenever a mission is loaded/ started so a previously fetched profile is available immediately - ensureFor() still validates its routeKey before use, so a stale restored profile is never shown for a route that has since changed. Also included in mission export/import (MissionExportData/ ParsedMissionImport) so sharing a mission carries its terrain cache along instead of forcing the recipient to refetch it. Sample-count/resolution stays as-is for now (still fixed 30m spacing, 10-2000 samples) - adapting the sampling density to terrain variance (e.g. coarser sampling over flat ground) is a separate follow-up. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
4e94102861
commit
35351140ae
@@ -1,7 +1,9 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import '../../app_info.dart';
|
||||
import '../../domain/mission/terrain_math.dart';
|
||||
import '../../domain/waypoint/flat_waypoint_list.dart';
|
||||
import '../database/terrain_json_codec.dart';
|
||||
import '../database/waypoint_json_codec.dart';
|
||||
|
||||
/// Missionsdaten fuer den Export - unabhaengig von der Drift-Zeilenklasse,
|
||||
@@ -12,12 +14,18 @@ class MissionExportData {
|
||||
this.placeName,
|
||||
required this.createdAt,
|
||||
required this.waypoints,
|
||||
this.terrainProfile,
|
||||
});
|
||||
|
||||
final String name;
|
||||
final String? placeName;
|
||||
final DateTime createdAt;
|
||||
final List<Waypoint> waypoints;
|
||||
|
||||
/// Gecachtes Bodenhoehenprofil (Doku 3.9), falls fuer die Mission bereits
|
||||
/// eins abgerufen wurde - wird mitexportiert, damit ein Import auf einem
|
||||
/// anderen Geraet nicht erneut alle Kacheln laden muss.
|
||||
final TerrainProfile? terrainProfile;
|
||||
}
|
||||
|
||||
/// Baut die Export-Datei fuer eine Mission (Doku 3.6, analog
|
||||
@@ -33,6 +41,8 @@ String buildMissionExportJson(MissionExportData mission) {
|
||||
'placeName': mission.placeName,
|
||||
'createdAt': mission.createdAt.toUtc().toIso8601String(),
|
||||
'waypoints': [for (final w in mission.waypoints) waypointToJson(w)],
|
||||
if (mission.terrainProfile != null)
|
||||
'terrainProfile': terrainProfileToJson(mission.terrainProfile!),
|
||||
},
|
||||
};
|
||||
return const JsonEncoder.withIndent(' ').convert(map);
|
||||
@@ -51,6 +61,7 @@ class ParsedMissionImport {
|
||||
this.placeName,
|
||||
required this.waypoints,
|
||||
this.versionMismatch,
|
||||
this.terrainProfile,
|
||||
});
|
||||
|
||||
final String name;
|
||||
@@ -61,6 +72,11 @@ class ParsedMissionImport {
|
||||
/// der Hauptversionsnummer unterscheidet - sonst null (analog der
|
||||
/// "Imported from a different app version"-Warnung im HTML-Demonstrator).
|
||||
final String? versionMismatch;
|
||||
|
||||
/// Mitexportiertes Bodenhoehenprofil (Doku 3.9), falls die Datei eins
|
||||
/// enthaelt - null bei Dateien aus einer Version ohne dieses Feld oder
|
||||
/// wenn die Quellmission noch keins hatte.
|
||||
final TerrainProfile? terrainProfile;
|
||||
}
|
||||
|
||||
/// Parst eine importierte Missionsdatei - wirft [FormatException] bei
|
||||
@@ -100,10 +116,16 @@ ParsedMissionImport parseMissionImportJson(String jsonText) {
|
||||
? appVersion
|
||||
: null;
|
||||
|
||||
final terrainProfileRaw = missionData['terrainProfile'];
|
||||
final terrainProfile = terrainProfileRaw is Map<String, dynamic>
|
||||
? terrainProfileFromJson(terrainProfileRaw)
|
||||
: null;
|
||||
|
||||
return ParsedMissionImport(
|
||||
name: name,
|
||||
placeName: placeName,
|
||||
waypoints: waypoints,
|
||||
versionMismatch: mismatch,
|
||||
terrainProfile: terrainProfile,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user