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
@@ -102,6 +102,17 @@ class $MissionsTable extends Missions with TableInfo<$MissionsTable, Mission> {
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const VerificationMeta _terrainProfileJsonMeta =
|
||||
const VerificationMeta('terrainProfileJson');
|
||||
@override
|
||||
late final GeneratedColumn<String> terrainProfileJson =
|
||||
GeneratedColumn<String>(
|
||||
'terrain_profile_json',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [
|
||||
id,
|
||||
@@ -112,6 +123,7 @@ class $MissionsTable extends Missions with TableInfo<$MissionsTable, Mission> {
|
||||
waypointsJson,
|
||||
isDirty,
|
||||
serverId,
|
||||
terrainProfileJson,
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@@ -177,6 +189,15 @@ class $MissionsTable extends Missions with TableInfo<$MissionsTable, Mission> {
|
||||
serverId.isAcceptableOrUnknown(data['server_id']!, _serverIdMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('terrain_profile_json')) {
|
||||
context.handle(
|
||||
_terrainProfileJsonMeta,
|
||||
terrainProfileJson.isAcceptableOrUnknown(
|
||||
data['terrain_profile_json']!,
|
||||
_terrainProfileJsonMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -218,6 +239,10 @@ class $MissionsTable extends Missions with TableInfo<$MissionsTable, Mission> {
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}server_id'],
|
||||
),
|
||||
terrainProfileJson: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}terrain_profile_json'],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -236,6 +261,14 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
final String waypointsJson;
|
||||
final bool isDirty;
|
||||
final String? serverId;
|
||||
|
||||
/// Gecachtes Bodenhoehenprofil (Doku 3.9), an einen routeKeyForTerrain()
|
||||
/// gebunden (siehe TerrainProfile) - null, solange fuer die aktuelle Route
|
||||
/// noch keins abgerufen wurde. Persistiert statt nur im TerrainNotifier
|
||||
/// im Speicher gehalten, damit ein erneutes Oeffnen derselben Mission
|
||||
/// (oder ein Import auf einem anderen Geraet) nicht jedes Mal alle
|
||||
/// AWS-Terrarium-Kacheln neu laden muss.
|
||||
final String? terrainProfileJson;
|
||||
const Mission({
|
||||
required this.id,
|
||||
required this.name,
|
||||
@@ -245,6 +278,7 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
required this.waypointsJson,
|
||||
required this.isDirty,
|
||||
this.serverId,
|
||||
this.terrainProfileJson,
|
||||
});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
@@ -261,6 +295,9 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
if (!nullToAbsent || serverId != null) {
|
||||
map['server_id'] = Variable<String>(serverId);
|
||||
}
|
||||
if (!nullToAbsent || terrainProfileJson != null) {
|
||||
map['terrain_profile_json'] = Variable<String>(terrainProfileJson);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -278,6 +315,9 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
serverId: serverId == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(serverId),
|
||||
terrainProfileJson: terrainProfileJson == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(terrainProfileJson),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -295,6 +335,9 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
waypointsJson: serializer.fromJson<String>(json['waypointsJson']),
|
||||
isDirty: serializer.fromJson<bool>(json['isDirty']),
|
||||
serverId: serializer.fromJson<String?>(json['serverId']),
|
||||
terrainProfileJson: serializer.fromJson<String?>(
|
||||
json['terrainProfileJson'],
|
||||
),
|
||||
);
|
||||
}
|
||||
@override
|
||||
@@ -309,6 +352,7 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
'waypointsJson': serializer.toJson<String>(waypointsJson),
|
||||
'isDirty': serializer.toJson<bool>(isDirty),
|
||||
'serverId': serializer.toJson<String?>(serverId),
|
||||
'terrainProfileJson': serializer.toJson<String?>(terrainProfileJson),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -321,6 +365,7 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
String? waypointsJson,
|
||||
bool? isDirty,
|
||||
Value<String?> serverId = const Value.absent(),
|
||||
Value<String?> terrainProfileJson = const Value.absent(),
|
||||
}) => Mission(
|
||||
id: id ?? this.id,
|
||||
name: name ?? this.name,
|
||||
@@ -330,6 +375,9 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
waypointsJson: waypointsJson ?? this.waypointsJson,
|
||||
isDirty: isDirty ?? this.isDirty,
|
||||
serverId: serverId.present ? serverId.value : this.serverId,
|
||||
terrainProfileJson: terrainProfileJson.present
|
||||
? terrainProfileJson.value
|
||||
: this.terrainProfileJson,
|
||||
);
|
||||
Mission copyWithCompanion(MissionsCompanion data) {
|
||||
return Mission(
|
||||
@@ -343,6 +391,9 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
: this.waypointsJson,
|
||||
isDirty: data.isDirty.present ? data.isDirty.value : this.isDirty,
|
||||
serverId: data.serverId.present ? data.serverId.value : this.serverId,
|
||||
terrainProfileJson: data.terrainProfileJson.present
|
||||
? data.terrainProfileJson.value
|
||||
: this.terrainProfileJson,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -356,7 +407,8 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
..write('updatedAt: $updatedAt, ')
|
||||
..write('waypointsJson: $waypointsJson, ')
|
||||
..write('isDirty: $isDirty, ')
|
||||
..write('serverId: $serverId')
|
||||
..write('serverId: $serverId, ')
|
||||
..write('terrainProfileJson: $terrainProfileJson')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
@@ -371,6 +423,7 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
waypointsJson,
|
||||
isDirty,
|
||||
serverId,
|
||||
terrainProfileJson,
|
||||
);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
@@ -383,7 +436,8 @@ class Mission extends DataClass implements Insertable<Mission> {
|
||||
other.updatedAt == this.updatedAt &&
|
||||
other.waypointsJson == this.waypointsJson &&
|
||||
other.isDirty == this.isDirty &&
|
||||
other.serverId == this.serverId);
|
||||
other.serverId == this.serverId &&
|
||||
other.terrainProfileJson == this.terrainProfileJson);
|
||||
}
|
||||
|
||||
class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
@@ -395,6 +449,7 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
final Value<String> waypointsJson;
|
||||
final Value<bool> isDirty;
|
||||
final Value<String?> serverId;
|
||||
final Value<String?> terrainProfileJson;
|
||||
const MissionsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.name = const Value.absent(),
|
||||
@@ -404,6 +459,7 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
this.waypointsJson = const Value.absent(),
|
||||
this.isDirty = const Value.absent(),
|
||||
this.serverId = const Value.absent(),
|
||||
this.terrainProfileJson = const Value.absent(),
|
||||
});
|
||||
MissionsCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
@@ -414,6 +470,7 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
required String waypointsJson,
|
||||
this.isDirty = const Value.absent(),
|
||||
this.serverId = const Value.absent(),
|
||||
this.terrainProfileJson = const Value.absent(),
|
||||
}) : name = Value(name),
|
||||
waypointsJson = Value(waypointsJson);
|
||||
static Insertable<Mission> custom({
|
||||
@@ -425,6 +482,7 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
Expression<String>? waypointsJson,
|
||||
Expression<bool>? isDirty,
|
||||
Expression<String>? serverId,
|
||||
Expression<String>? terrainProfileJson,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
@@ -435,6 +493,8 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
if (waypointsJson != null) 'waypoints_json': waypointsJson,
|
||||
if (isDirty != null) 'is_dirty': isDirty,
|
||||
if (serverId != null) 'server_id': serverId,
|
||||
if (terrainProfileJson != null)
|
||||
'terrain_profile_json': terrainProfileJson,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -447,6 +507,7 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
Value<String>? waypointsJson,
|
||||
Value<bool>? isDirty,
|
||||
Value<String?>? serverId,
|
||||
Value<String?>? terrainProfileJson,
|
||||
}) {
|
||||
return MissionsCompanion(
|
||||
id: id ?? this.id,
|
||||
@@ -457,6 +518,7 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
waypointsJson: waypointsJson ?? this.waypointsJson,
|
||||
isDirty: isDirty ?? this.isDirty,
|
||||
serverId: serverId ?? this.serverId,
|
||||
terrainProfileJson: terrainProfileJson ?? this.terrainProfileJson,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -487,6 +549,9 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
if (serverId.present) {
|
||||
map['server_id'] = Variable<String>(serverId.value);
|
||||
}
|
||||
if (terrainProfileJson.present) {
|
||||
map['terrain_profile_json'] = Variable<String>(terrainProfileJson.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -500,7 +565,8 @@ class MissionsCompanion extends UpdateCompanion<Mission> {
|
||||
..write('updatedAt: $updatedAt, ')
|
||||
..write('waypointsJson: $waypointsJson, ')
|
||||
..write('isDirty: $isDirty, ')
|
||||
..write('serverId: $serverId')
|
||||
..write('serverId: $serverId, ')
|
||||
..write('terrainProfileJson: $terrainProfileJson')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
@@ -2036,6 +2102,7 @@ typedef $$MissionsTableCreateCompanionBuilder =
|
||||
required String waypointsJson,
|
||||
Value<bool> isDirty,
|
||||
Value<String?> serverId,
|
||||
Value<String?> terrainProfileJson,
|
||||
});
|
||||
typedef $$MissionsTableUpdateCompanionBuilder =
|
||||
MissionsCompanion Function({
|
||||
@@ -2047,6 +2114,7 @@ typedef $$MissionsTableUpdateCompanionBuilder =
|
||||
Value<String> waypointsJson,
|
||||
Value<bool> isDirty,
|
||||
Value<String?> serverId,
|
||||
Value<String?> terrainProfileJson,
|
||||
});
|
||||
|
||||
class $$MissionsTableFilterComposer
|
||||
@@ -2097,6 +2165,11 @@ class $$MissionsTableFilterComposer
|
||||
column: $table.serverId,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get terrainProfileJson => $composableBuilder(
|
||||
column: $table.terrainProfileJson,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$MissionsTableOrderingComposer
|
||||
@@ -2147,6 +2220,11 @@ class $$MissionsTableOrderingComposer
|
||||
column: $table.serverId,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get terrainProfileJson => $composableBuilder(
|
||||
column: $table.terrainProfileJson,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$MissionsTableAnnotationComposer
|
||||
@@ -2183,6 +2261,11 @@ class $$MissionsTableAnnotationComposer
|
||||
|
||||
GeneratedColumn<String> get serverId =>
|
||||
$composableBuilder(column: $table.serverId, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<String> get terrainProfileJson => $composableBuilder(
|
||||
column: $table.terrainProfileJson,
|
||||
builder: (column) => column,
|
||||
);
|
||||
}
|
||||
|
||||
class $$MissionsTableTableManager
|
||||
@@ -2221,6 +2304,7 @@ class $$MissionsTableTableManager
|
||||
Value<String> waypointsJson = const Value.absent(),
|
||||
Value<bool> isDirty = const Value.absent(),
|
||||
Value<String?> serverId = const Value.absent(),
|
||||
Value<String?> terrainProfileJson = const Value.absent(),
|
||||
}) => MissionsCompanion(
|
||||
id: id,
|
||||
name: name,
|
||||
@@ -2230,6 +2314,7 @@ class $$MissionsTableTableManager
|
||||
waypointsJson: waypointsJson,
|
||||
isDirty: isDirty,
|
||||
serverId: serverId,
|
||||
terrainProfileJson: terrainProfileJson,
|
||||
),
|
||||
createCompanionCallback:
|
||||
({
|
||||
@@ -2241,6 +2326,7 @@ class $$MissionsTableTableManager
|
||||
required String waypointsJson,
|
||||
Value<bool> isDirty = const Value.absent(),
|
||||
Value<String?> serverId = const Value.absent(),
|
||||
Value<String?> terrainProfileJson = const Value.absent(),
|
||||
}) => MissionsCompanion.insert(
|
||||
id: id,
|
||||
name: name,
|
||||
@@ -2250,6 +2336,7 @@ class $$MissionsTableTableManager
|
||||
waypointsJson: waypointsJson,
|
||||
isDirty: isDirty,
|
||||
serverId: serverId,
|
||||
terrainProfileJson: terrainProfileJson,
|
||||
),
|
||||
withReferenceMapper: (p0) => p0
|
||||
.map((e) => (e.readTable(table), BaseReferences(db, table, e)))
|
||||
|
||||
Reference in New Issue
Block a user