diff --git a/CHANGELOG.de.md b/CHANGELOG.de.md index 38d7540..237af28 100644 --- a/CHANGELOG.de.md +++ b/CHANGELOG.de.md @@ -10,6 +10,22 @@ Das Format basiert auf [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [1.8.0] - 2026-02-10 +### 🚨 CRITICAL BUGFIX (Tag neu erstellt) + +**R8/ProGuard Obfuscation Fix - Verhindert Datenverlust** +- 🔧 **KRITISCH:** Falscher ProGuard-Klassenpfad für `Note$Companion$NoteRaw` korrigiert + - Original v1.8.0 hatte spezifische `-keep` Regeln die nicht griffen + - R8 obfuskierte alle NoteRaw-Felder (id→a, title→b, ...) + - Gson konnte JSON nicht mehr parsen → **ALLE Notizen erschienen verschwunden** + - Zurück zur sicheren breiten Regel: `-keep class dev.dettmer.simplenotes.** { *; }` +- 🛡️ Safety-Guards in `detectServerDeletions()` hinzugefügt + - Verhindert Massenlöschung bei leeren `serverNoteIds` (Netzwerkfehler) + - Abort wenn ALLE lokalen Notizen als gelöscht erkannt würden +- ✅ Notizen waren nie wirklich verloren (JSON-Dateien intakt auf Disk + Server) +- ✅ Downgrade auf v1.7.2 holte alle Notizen zurück + +**⚠️ Falls du v1.8.0 erste Version installiert hattest:** Deine Notizen sind sicher! Einfach updaten. + ### 🎉 Major: Widgets, Sortierung & Erweiterte Sync-Features Komplettes Widget-System mit interaktiven Checklisten, Notiz-Sortierung und umfangreiche Sync-Verbesserungen! diff --git a/CHANGELOG.md b/CHANGELOG.md index 22b99bc..3d5806a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,22 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [1.8.0] - 2026-02-10 +### 🚨 CRITICAL BUGFIX (Tag recreated) + +**R8/ProGuard Obfuscation Fix - Prevents Data Loss** +- 🔧 **CRITICAL:** Fixed incorrect ProGuard class path for `Note$Companion$NoteRaw` + - Original v1.8.0 had specific `-keep` rules that didn't match + - R8 obfuscated all NoteRaw fields (id→a, title→b, ...) + - Gson couldn't parse JSON anymore → **ALL notes appeared lost** + - Reverted to safe broad rule: `-keep class dev.dettmer.simplenotes.** { *; }` +- 🛡️ Added safety-guards in `detectServerDeletions()` + - Prevents mass deletion when `serverNoteIds` is empty (network errors) + - Aborts if ALL local notes would be marked as deleted +- ✅ Notes were never actually lost (JSON files intact on disk + server) +- ✅ Downgrade to v1.7.2 restored all notes + +**⚠️ If you installed original v1.8.0:** Your notes are safe! Just update. + ### 🎉 Major: Widgets, Sorting & Advanced Sync Complete widget system with interactive checklists, note sorting, and major sync improvements! diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro index c187894..076e42a 100644 --- a/android/app/proguard-rules.pro +++ b/android/app/proguard-rules.pro @@ -63,21 +63,16 @@ # App-specific rules: Only keep what Gson/reflection needs # ═══════════════════════════════════════════════════════════════════════ -# Gson data models (serialized/deserialized via reflection) --keep class dev.dettmer.simplenotes.models.Note { *; } --keep class dev.dettmer.simplenotes.models.Note$NoteRaw { *; } --keep class dev.dettmer.simplenotes.models.ChecklistItem { *; } --keep class dev.dettmer.simplenotes.models.DeletionRecord { *; } --keep class dev.dettmer.simplenotes.models.DeletionTracker { *; } --keep class dev.dettmer.simplenotes.backup.BackupData { *; } --keep class dev.dettmer.simplenotes.backup.BackupResult { *; } - -# Keep enum values (used in serialization and widget state) --keepclassmembers enum dev.dettmer.simplenotes.** { - ; - public static **[] values(); - public static ** valueOf(java.lang.String); -} +# 🔧 v1.8.1 FIX: Breite Regel verwenden statt spezifischer Klassen +# +# GRUND: NoteRaw ist eine private data class innerhalb von Note.Companion. +# Der JVM-Klassenname ist Note$Companion$NoteRaw, NICHT Note$NoteRaw. +# Die spezifische Regel griff nicht → R8 obfuskierte NoteRaw-Felder +# → Gson konnte keine JSON-Felder matchen → ALLE Notizen unlesbar! +# +# Sichere Lösung: Alle App-Klassen behalten (wie in v1.7.2). +# APK-Größenoptimierung kann in v1.9.0 sicher evaluiert werden. +-keep class dev.dettmer.simplenotes.** { *; } # v1.7.1: Suppress TextInclusionStrategy warnings on older Android versions # This class only exists on API 35+ but Compose handles the fallback gracefully diff --git a/android/app/src/main/java/dev/dettmer/simplenotes/sync/WebDavSyncService.kt b/android/app/src/main/java/dev/dettmer/simplenotes/sync/WebDavSyncService.kt index eab9726..281b384 100644 --- a/android/app/src/main/java/dev/dettmer/simplenotes/sync/WebDavSyncService.kt +++ b/android/app/src/main/java/dev/dettmer/simplenotes/sync/WebDavSyncService.kt @@ -1115,6 +1115,7 @@ class WebDavSyncService(private val context: Context) { /** * 🆕 v1.8.0: Erkennt Notizen, die auf dem Server gelöscht wurden + * 🔧 v1.8.1: Safety-Guard gegen leere serverNoteIds (verhindert Massenlöschung) * * Keine zusätzlichen HTTP-Requests! Nutzt die bereits geladene * serverNoteIds-Liste aus dem PROPFIND-Request. @@ -1131,15 +1132,36 @@ class WebDavSyncService(private val context: Context) { serverNoteIds: Set, localNotes: List ): Int { - var deletedCount = 0 val syncedNotes = localNotes.filter { it.syncStatus == SyncStatus.SYNCED } + // 🔧 v1.8.1 SAFETY: Wenn serverNoteIds leer ist, NIEMALS Notizen als gelöscht markieren! + // Ein leeres Set bedeutet wahrscheinlich: PROPFIND fehlgeschlagen, /notes/ nicht gefunden, + // oder Netzwerkfehler — NICHT dass alle Notizen gelöscht wurden. + if (serverNoteIds.isEmpty()) { + Logger.w(TAG, "⚠️ detectServerDeletions: serverNoteIds is EMPTY! " + + "Skipping deletion detection to prevent data loss. " + + "localSynced=${syncedNotes.size}, localTotal=${localNotes.size}") + return 0 + } + + // 🔧 v1.8.1 SAFETY: Wenn ALLE lokalen SYNCED-Notizen als gelöscht erkannt werden, + // ist das fast sicher ein Fehler (z.B. falsche Server-URL oder partieller PROPFIND). + // Maximal 50% der Notizen dürfen als gelöscht markiert werden. + val potentialDeletions = syncedNotes.count { it.id !in serverNoteIds } + if (syncedNotes.size > 1 && potentialDeletions == syncedNotes.size) { + Logger.e(TAG, "🚨 detectServerDeletions: ALL ${syncedNotes.size} synced notes " + + "would be marked as deleted! This is almost certainly a bug. " + + "serverNoteIds=${serverNoteIds.size}. ABORTING deletion detection.") + return 0 + } + // 🆕 v1.8.0 (IMPL_022): Statistik-Log für Debugging Logger.d(TAG, "🔍 detectServerDeletions: " + "serverNotes=${serverNoteIds.size}, " + "localSynced=${syncedNotes.size}, " + "localTotal=${localNotes.size}") + var deletedCount = 0 syncedNotes.forEach { note -> // Nur SYNCED-Notizen prüfen: // - LOCAL_ONLY: War nie auf Server → irrelevant