Release GPS2Audio v2.5.48 TrackDraft backup fix

This commit is contained in:
Perplexity Computer
2026-05-30 22:19:04 +00:00
parent 990b66e24f
commit 2eeb086481
5 changed files with 86 additions and 33 deletions
@@ -15,6 +15,7 @@ import de.waypointaudio.data.TourAudioSettings
import de.waypointaudio.data.TourPlaybackDefaults
import de.waypointaudio.data.TourCover
import de.waypointaudio.data.TourRoute
import de.waypointaudio.data.TrackDraft
import de.waypointaudio.data.Waypoint
import de.waypointaudio.data.WaypointMusicBehavior
import java.io.File
@@ -102,6 +103,8 @@ object BackupImportManager {
val tourRoutesToWrite: Map<String, TourRoute> = emptyMap(),
// v2.5.5 — Tour-Cover, die geschrieben werden sollen (Map endgültiger Tourname → Cover).
val tourCoversToWrite: Map<String, TourCover> = emptyMap(),
// v2.5.48 — Echte TrackDraft-Objekte, die als neue Drafts hinzugefügt werden sollen.
val trackDraftsToAdd: List<TrackDraft> = emptyList(),
val trackMinDistanceMeters: Int?,
val newTourSelection: String?,
val warnings: List<String>,
@@ -514,42 +517,71 @@ object BackupImportManager {
}
// ---- Track-Entwürfe ----
// v2.5.48 FIX: Importiert echte TrackDraft-Objekte aus dem "drafts"-Array.
// Abwärtskompatibilität: Alte Backups schrieben fälschlicherweise die
// gpsTracks-Map unter "tracks" in track_drafts.json. Falls "drafts" fehlt
// aber "tracks" vorhanden ist, wird das alte Format erkannt und toleriert
// (kein Crash, keine Datenverluste an bestehenden Touren/Waypoints).
val tracksToWrite = mutableMapOf<String, List<GpsTrackPoint>>()
val trackDraftsToAdd = mutableListOf<TrackDraft>()
var tracksImported = 0
if (selection.trackDrafts && draftsJson != null) {
val obj = runCatching {
JsonParser.parseString(draftsJson).asJsonObject
}.getOrNull()
val map: Map<String, List<GpsTrackPoint>> = if (obj != null) {
runCatching {
gson.fromJson<Map<String, List<GpsTrackPoint>>>(
obj.get("tracks"),
object : TypeToken<Map<String, List<GpsTrackPoint>>>() {}.type
) ?: emptyMap()
}.getOrDefault(emptyMap())
} else emptyMap()
map.forEach { (origTour, points) ->
val mappedTour = tourRename[origTour]
?: run {
// Tour war nicht im Tour-Import (z. B. wenn nur Drafts importiert werden):
// prüfen, ob Name kollidiert.
if (origTour == Waypoint.DEFAULT_TOUR_NAME) {
origTour
} else if (origTour in resultTours) {
origTour
} else {
resultTours.add(origTour)
origTour
}
if (obj != null) {
// Neues Format (v2.5.48+): "drafts" enthält eine Liste echter TrackDraft-Objekte.
val hasDraftsKey = obj.has("drafts") && !obj.get("drafts").isJsonNull
if (hasDraftsKey) {
// Neues Format: Liste von TrackDraft-Objekten
val importedDrafts: List<TrackDraft> = runCatching {
gson.fromJson<List<TrackDraft>>(
obj.get("drafts"),
object : TypeToken<List<TrackDraft>>() {}.type
) ?: emptyList()
}.getOrDefault(emptyList())
importedDrafts.forEach { draft ->
// Tourname-Mapping anwenden (für den Fall, dass Tour umbenannt wurde).
val origTour = draft.sourceTourName
val mappedTour = tourRename[origTour]
?: run {
if (origTour == Waypoint.DEFAULT_TOUR_NAME ||
origTour in resultTours
) {
origTour
} else {
resultTours.add(origTour)
origTour
}
}
// Neue UUID vergeben, damit importierte Drafts nie mit
// vorhandenen Drafts-IDs kollidieren.
val newDraft = draft.copy(
id = java.util.UUID.randomUUID().toString(),
sourceTourName = mappedTour,
updatedAt = System.currentTimeMillis()
)
trackDraftsToAdd.add(newDraft)
tracksImported++
}
val existingPoints = existingTracks[mappedTour] ?: emptyList()
if (existingPoints.isEmpty()) {
// Bestehenden Track NICHT überschreiben.
tracksToWrite[mappedTour] = points
tracksImported++
} else {
warnings.add("Track-Entwurf für Tour „$mappedTour\" bereits vorhanden nicht überschrieben.")
// Altes (fehlerhaftes) Format: "tracks" enthält gpsTracks-Map.
// Tolerieren ohne Crash, aber nicht in Tracks oder Drafts importieren,
// da der Inhalt GPS-Track-Daten (nicht Draft-Metadaten) sind.
// Hinweis in Warnings ausgeben.
val hasTracksKey = obj.has("tracks") && !obj.get("tracks").isJsonNull
if (hasTracksKey) {
warnings.add(
"Hinweis: track_drafts.json aus älterem Backup-Format erkannt " +
"(enthält GPS-Tracks statt Draft-Objekte). " +
"TrackDraft-Namen/Notizen können nicht wiederhergestellt werden. " +
"Bestehende Touren und Wegpunkte bleiben unverändert."
)
}
// Keine Daten importieren aus altem, fehlerh. Format — kein Crash.
}
}
}
@@ -636,6 +668,8 @@ object BackupImportManager {
musicToWrite = musicToWrite,
tourRoutesToWrite = tourRoutesToWrite,
tourCoversToWrite = tourCoversToWrite,
// v2.5.48 — Echte TrackDraft-Objekte weitergeben.
trackDraftsToAdd = trackDraftsToAdd,
trackMinDistanceMeters = trackMinDistanceMeters,
newTourSelection = newTourSelection,
warnings = warnings,