- Update versionCode from 19 to 20 - Update versionName from "1.7.2" to "1.8.0" - Create F-Droid changelog for versionCode 20 (EN + DE) - Update CHANGELOG.md with comprehensive v1.8.0 entry (all 16 features) - Update CHANGELOG.de.md with German v1.8.0 entry - Add commit hashes to all changelog entries for traceability Major feature release: Widgets with interactive checklists, note/checklist sorting, server deletion detection, sync status legend, live sync progress, parallel downloads, checklist UX improvements, and widget text display fix. Complete changelog lists all features with commit references.
35 KiB
Changelog
All notable changes to Simple Notes Sync will be documented in this file.
The format is based on Keep a Changelog.
🌍 Languages: Deutsch · English
[1.8.0] - 2026-02-10
🎉 Major: Widgets, Sorting & Advanced Sync
Complete widget system with interactive checklists, note sorting, and major sync improvements!
🆕 Homescreen Widgets
Full Jetpack Glance Widget Framework (539987f)
- 5 responsive size classes (SMALL, NARROW_MED, NARROW_TALL, WIDE_MED, WIDE_TALL)
- Interactive checklist checkboxes that sync immediately to server
- Material You dynamic colors with configurable background opacity (0-100%)
- Lock widget toggle to prevent accidental edits
- Read-only mode with permanent options bar for locked widgets
- Widget configuration activity with note selection and settings
- Auto-refresh after sync completion
- Tap content to open editor (unlocked) or show options (locked)
- Complete resource cleanup fixes for connection leaks
Widget State Management:
- NoteWidgetState keys for per-instance persistence via DataStore
- Five top-level ActionCallbacks (Toggle Checkbox, Lock, Options, Refresh, Config)
- Type-safe parameter passing with NoteWidgetActionKeys
📊 Note & Checklist Sorting
Note Sorting (96c819b)
- Sort by: Updated (newest/oldest), Created, Title (A-Z/Z-A), Type
- Persistent sort preferences (saved in SharedPreferences)
- Sort dialog in main screen with direction toggle
- Combined sortedNotes StateFlow in MainViewModel
Checklist Sorting (96c819b, 900dad7)
- Sort by: Manual, Alphabetical, Unchecked First, Checked Last
- Visual separator between unchecked/checked items with count display
- Auto-sort on item toggle and reordering
- Drag-only within same group (unchecked/checked)
- Smooth fade/slide animations for item transitions
- Unit tested with 9 test cases for sorting logic validation
🔄 Sync Improvements
Server Deletion Detection (40d7c83, bf7a74e)
- New
DELETED_ON_SERVERsync status for multi-device scenarios - Detects when notes are deleted on other clients
- Zero performance impact (uses existing PROPFIND data)
- Deletion count shown in sync banner: "3 synced · 2 deleted on server"
- Edited deleted notes automatically re-upload to server (status → PENDING)
Sync Status Legend (07607fc)
- Help button (?) in main screen TopAppBar
- Dialog explaining all 5 sync status icons with descriptions
- Only visible when sync is configured
Live Sync Progress UI (df37d2a)
- Real-time phase indicators: PREPARING, UPLOADING, DOWNLOADING, IMPORTING_MARKDOWN
- Upload progress shows x/y counter (known total)
- Download progress shows count (unknown total)
- Single unified SyncProgressBanner (replaces dual system)
- Auto-hide: COMPLETED (2s), ERROR (4s)
- No misleading counters when nothing to sync
- Silent auto-sync stays silent, errors always shown
Parallel Downloads (bdfc0bf)
- Configurable concurrent downloads (default: 3 simultaneous)
- Kotlin coroutines async/awaitAll pattern
- Individual download timeout handling
- Graceful sequential fallback on concurrent errors
- Optimized network utilization for faster sync
✨ UX Improvements
Checklist Enhancements:
- Overflow gradient for long text items (3462f93)
- Auto-expand on focus, collapse to 5 lines when unfocused
- Drag & Drop flicker fix with straddle-target-center detection (538a705)
- Adjacency filter prevents item jumps during fast drag
- Race-condition fix for scroll + move operations
Settings UI Polish:
- Smooth language switching without activity recreate (881c0fd)
- Grid view as default for new installations (6858446)
- Sync settings restructured into clear sections: Triggers & Performance (eaac5a0)
- Changelog link added to About screen (49810ff)
🐛 Bug Fixes
Widget Text Display (d045d4d)
- Fixed text notes showing only 3 lines in widgets
- Changed from paragraph-based to line-based rendering
- LazyColumn now properly scrolls through all content
- Empty lines preserved as 8dp spacers
- Preview limits increased: compact 100→120, full 200→300 chars
🔧 Code Quality
Detekt Cleanup (1da1a63)
- Resolved all 22 Detekt warnings
- Removed 7 unused imports
- Defined constants for 5 magic numbers
- Optimized state reads with derivedStateOf
- Build: 0 Lint errors + 0 Detekt warnings
📚 Documentation
- Complete implementation plans for all 23 v1.8.0 features
- Widget system architecture and state management docs
- Sorting logic unit tests with edge case coverage
- F-Droid changelogs (English + German)
[1.7.2] - 2026-02-04
🐛 Critical Bug Fixes
JSON/Markdown Timestamp Sync
Problem: External editors (Obsidian, Typora, VS Code, custom editors) update Markdown content but don't update YAML updated: timestamp, causing the Android app to skip changes.
Solution:
- Server file modification time (
mtime) is now used as source of truth instead of YAML timestamp - Content changes detected via hash comparison
- Notes marked as
PENDINGafter Markdown import → JSON automatically re-uploaded on next sync - Fixes sorting issues after external edits
SyncStatus on Server Always PENDING
Problem: All JSON files on server contained "syncStatus": "PENDING" even after successful sync, confusing external clients.
Solution:
- Status is now set to
SYNCEDbefore JSON serialization - Server and local copies are now consistent
- External web/Tauri editors can correctly interpret sync state
Deletion Tracker Race Condition
Problem: Batch deletes could lose deletion records due to concurrent file access.
Solution:
- Mutex-based synchronization for deletion tracking
- New
trackDeletionSafe()function prevents race conditions - Guarantees zombie note prevention even with rapid deletes
ISO8601 Timezone Parsing
Problem: Markdown imports failed with timezone offsets like +01:00 or -05:00.
Solution:
- Multi-format ISO8601 parser with fallback chain
- Supports UTC (Z), timezone offsets (+01:00, +0100), and milliseconds
- Compatible with Obsidian, Typora, VS Code timestamps
⚡ Performance Improvements
E-Tag Batch Caching
- E-Tags are now written in single batch operation instead of N individual writes
- Performance gain: ~50-100ms per sync with multiple notes
- Reduced disk I/O operations
Memory Leak Prevention
SafeSardineWrappernow implementsCloseablefor explicit resource cleanup- HTTP connection pool is properly evicted after sync
- Prevents socket exhaustion during frequent syncs
🔧 Technical Details
- IMPL_001:
kotlinx.coroutines.sync.Mutexfor thread-safe deletion tracking - IMPL_002: Pattern-based ISO8601 parser with 8 format variants
- IMPL_003: Connection pool eviction + dispatcher shutdown in
close() - IMPL_004: Batch
SharedPreferences.Editorupdates - IMPL_014: Server
mtimeparameter inNote.fromMarkdown() - IMPL_015:
syncStatusset beforetoJson()call
📚 Documentation
- External Editor Specification for web/Tauri editor developers
- Detailed implementation documentation for all bugfixes
[1.7.1] - 2026-02-02
🐛 Critical Bug Fixes
Android 9 App Crash Fix (#15)
Problem: App crashed on Android 9 (API 28) when using WorkManager Expedited Work for background sync.
Root Cause: When setExpedited() is used in WorkManager, the CoroutineWorker must implement getForegroundInfo() to return a Foreground Service notification. On Android 9-11, WorkManager calls this method, but the default implementation throws IllegalStateException: Not implemented.
Solution: Implemented getForegroundInfo() in SyncWorker to return a proper ForegroundInfo with sync progress notification.
Details:
- Added
ForegroundInfowith sync progress notification for Android 9-11 - Android 10+: Sets
FOREGROUND_SERVICE_TYPE_DATA_SYNCfor proper service typing - Added Foreground Service permissions to AndroidManifest.xml
- Notification shows sync progress with indeterminate progress bar
- Thanks to @roughnecks for the detailed debugging!
VPN Compatibility Fix (#11)
- WiFi socket binding now correctly detects Wireguard VPN interfaces (tun*, wg*, -wg-)
- Traffic routes through VPN tunnel instead of bypassing it directly to WiFi
- Fixes "Connection timeout" when syncing to external servers via VPN
🔧 Technical Changes
- New
SafeSardineWrapperclass ensures proper HTTP connection cleanup - Reduced unnecessary 401 authentication challenges with preemptive auth headers
- Added ProGuard rule to suppress harmless TextInclusionStrategy warnings on older Android versions
- VPN interface detection via
NetworkInterface.getNetworkInterfaces()pattern matching - Foreground Service detection and notification system for background sync tasks
🌍 Localization
- Fixed hardcoded German error messages - now uses string resources for proper localization
- Added German and English strings for sync progress notifications
[1.7.0] - 2026-01-26
🎉 Major: Grid View, WiFi-Only Sync & VPN Support
Pinterest-style grid, WiFi-only sync mode, and proper VPN support!
🎨 Grid Layout
- Pinterest-style staggered grid without gaps
- Consistent 12dp spacing between cards
- Scroll position preserved when returning from settings
- New unified
NoteCardGridwith dynamic preview lines (3 small, 6 large)
📡 Sync Improvements
- WiFi-only sync toggle - Sync only when connected to WiFi
- VPN support - Sync works correctly when VPN is active (traffic routes through VPN)
- Server change detection - All notes reset to PENDING when server URL changes
- Faster server check - Socket timeout reduced from 2s to 1s
- "Sync already running" feedback - Shows snackbar when sync is in progress
🔒 Self-Signed SSL Support
- Documentation added - Guide for using self-signed certificates
- Uses Android's built-in CA trust store
- Works with ownCloud, Nextcloud, Synology, home servers
🔧 Technical
NoteCardGridcomponent with dynamic maxLines- Removed FullLine spans for gapless layout
resetAllSyncStatusToPending()in NotesStorage- VPN detection in
getOrCacheWiFiAddress()
[1.6.1] - 2026-01-20
🧹 Code Quality & Build Improvements
-
detekt: 0 issues - All 29 code quality issues resolved
- Trivial fixes: Unused imports, MaxLineLength
- File rename: DragDropState.kt → DragDropListState.kt
- MagicNumbers → Constants (Dimensions.kt, SyncConstants.kt)
- SwallowedException: Logger.w() added for better error tracking
- LongParameterList: ChecklistEditorCallbacks data class created
- LongMethod: ServerSettingsScreen split into components
- @Suppress annotations for legacy code (WebDavSyncService, SettingsActivity)
-
Zero build warnings - All 21 deprecation warnings eliminated
- File-level @Suppress for deprecated imports
- ProgressDialog, LocalBroadcastManager, AbstractSavedStateViewModelFactory
- onActivityResult, onRequestPermissionsResult
- Gradle Compose config cleaned up (StrongSkipping is now default)
-
ktlint reactivated - Linting re-enabled with Compose-specific rules
- .editorconfig created with Compose formatting rules
- Legacy files excluded: WebDavSyncService.kt, build.gradle.kts
- ignoreFailures=true for gradual migration
-
CI/CD improvements - GitHub Actions lint checks integrated
- detekt + ktlint + Android Lint run before build in pr-build-check.yml
- Ensures code quality on every pull request
🔧 Technical Improvements
-
Constants refactoring - Better code organization
- ui/theme/Dimensions.kt: UI-related constants
- utils/SyncConstants.kt: Sync operation constants
-
Preparation for v2.0.0 - Legacy code marked for removal
- SettingsActivity and MainActivity (replaced by Compose versions)
- All deprecated APIs documented with removal plan
[1.6.0] - 2026-01-19
🎉 Major: Configurable Sync Triggers
Fine-grained control over when your notes sync - choose which triggers fit your workflow best!
⚙️ Sync Trigger System
-
Individual trigger control - Enable/disable each sync trigger separately in settings
-
5 Independent Triggers:
- onSave Sync - Sync immediately after saving a note (5s throttle)
- onResume Sync - Sync when app is opened (60s throttle)
- WiFi-Connect Sync - Sync when WiFi is connected
- Periodic Sync - Background sync every 15/30/60 minutes (configurable)
- Boot Sync - Start background sync after device restart
-
Smart Defaults - Only event-driven triggers active by default (onSave, onResume, WiFi-Connect)
-
Battery Optimized - ~0.2%/day with defaults, up to ~1.0% with periodic sync enabled
-
Offline Mode UI - Grayed-out sync toggles when no server configured
-
Dynamic Settings Subtitle - Shows count of active triggers on main settings screen
🔧 Server Configuration Improvements
- Offline Mode Toggle - Disable all network features with one switch
- Split Protocol & Host - Protocol (http/https) shown as non-editable prefix
- Clickable Settings Cards - Full card clickable for better UX
- Clickable Toggle Rows - Click text/icon to toggle switches (not just the switch itself)
🐛 Bug Fixes
- Fixed: Missing 5th sync trigger (Boot) in main settings screen subtitle count
- Various fixes - UI improvements and stability enhancements
🔧 Technical Improvements
- Reactive offline mode state - StateFlow ensures UI updates correctly
- Separated server config checks -
hasServerConfig()vsisServerConfigured()(offline-aware) - Improved constants - All sync trigger keys and defaults in Constants.kt
- Better code organization - Settings screens refactored for clarity
Looking Ahead
🚀 v1.7.0 will bring server folder checking and additional community features. Feature requests welcome as GitHub Issue.
[1.5.0] - 2026-01-15
🎉 Major: Jetpack Compose UI Redesign
The complete UI has been migrated from XML Views to Jetpack Compose. The app is now more modern, faster, and smoother.
🌍 New Feature: Internationalization (i18n)
- English language support - All 400+ strings translated
- Automatic language detection - Follows system language
- Manual language selection - Switchable in settings
- Per-App Language (Android 13+) - Native language setting via system settings
- locales_config.xml - Complete Android integration
⚙️ Modernized Settings
- 7 categorized settings screens - Clearer and more intuitive
- Compose Navigation - Smooth transitions between screens
- Consistent design - Material Design 3 throughout
✨ UI Improvements
- Selection Mode - Long-press for multi-select instead of swipe-to-delete
- Batch Delete - Delete multiple notes at once
- Silent-Sync Mode - No banner during auto-sync (only for manual sync)
- App Icon in About Screen - High-quality display
- App Icon in Empty State - Instead of emoji when note list is empty
- Splash Screen Update - Uses app foreground icon
- Slide Animations - Smooth animations in NoteEditor
🔧 Technical Improvements
- Jetpack Compose - Complete UI migration
- Compose ViewModel Integration - StateFlow for reactive UI
- Improved Code Quality - Detekt/Lint warnings fixed
- Unused Imports Cleanup - Cleaner codebase
Looking Ahead
🚀 v1.6.0 will bring server folder checking and further technical modernizations. Feature requests welcome as GitHub Issue.
[1.4.1] - 2026-01-11
Fixed
-
🗑️ Deleting older notes (v1.2.0 compatibility)
- Notes from app version v1.2.0 or earlier are now correctly deleted from the server
- Fixes issue with multi-device usage with older notes
-
🔄 Checklist sync backward compatibility
- Checklists now also saved as text fallback in the
contentfield - Older app versions (v1.3.x) display checklists as readable text
- Format: GitHub-style task lists (
[ ] Item/[x] Item) - Recovery mode: If checklist items are lost, they are recovered from content
- Checklists now also saved as text fallback in the
Improved
- 📝 Checklist auto line-wrap
- Long checklist texts now automatically wrap
- No more limit to 3 lines
- Enter key still creates a new item
Looking Ahead
🚀 v1.5.0 will be the next major release. We're collecting ideas and feedback! Feature requests welcome as GitHub Issue.
[1.4.0] - 2026-01-10
🎉 New Feature: Checklists
-
✅ Checklist Notes
- New note type: Checklists with tap-to-toggle items
- Add items via dedicated input field with "+" button
- Drag & drop reordering (long-press to activate)
- Swipe-to-delete items
- Visual distinction: Checked items get strikethrough styling
- Type selector when creating new notes (Text or Checklist)
-
📝 Markdown Integration
- Checklists export as GitHub-style task lists (
- [ ]/- [x]) - Compatible with Obsidian, Notion, and other Markdown editors
- Full round-trip: Edit in Obsidian → Sync back to app
- YAML frontmatter includes
type: checklistfor identification
- Checklists export as GitHub-style task lists (
Fixed
-
<EFBFBD> Markdown Parsing Robustness
- Fixed content extraction after title (was returning empty for some formats)
- Now handles single newline after title (was requiring double newline)
- Protection: Skips import if parsed content is empty but local has content
-
📂 Duplicate Filename Handling
- Notes with identical titles now get unique Markdown filenames
- Format:
title_shortid.md(e.g.,test_71540ca9.md) - Prevents data loss from filename collisions
-
🔔 Notification UX
- No sync notifications when app is in foreground
- User sees changes directly in UI - no redundant notification
- Background syncs still show notifications as expected
Privacy Improvements
- 🔒 WiFi Permissions Removed
- Removed
ACCESS_WIFI_STATEpermission - Removed
CHANGE_WIFI_STATEpermission - WiFi binding now works via IP detection instead of SSID matching
- Cleaned up all SSID-related code from codebase and documentation
- Removed
Technical Improvements
-
📦 New Data Model
NoteTypeenum:TEXT,CHECKLISTChecklistItemdata class with id, text, isChecked, orderNote.ktextended withnoteTypeandchecklistItemsfields
-
🔄 Sync Protocol v1.4.0
- JSON format updated to include checklist fields
- Full backward compatibility with v1.3.x notes
- Robust JSON parsing with manual field extraction
[1.3.2] - 2026-01-10
Changed
- 🧹 Code-Qualität: "Clean Slate" Release
- Alle einfachen Lint-Issues behoben (Phase 1-7 des Cleanup-Plans)
- Unused Imports und Members entfernt
- Magic Numbers durch benannte Konstanten ersetzt
- SwallowedExceptions mit Logger.w() versehen
- MaxLineLength-Verstöße reformatiert
- ConstructorParameterNaming (snake_case → camelCase mit @SerializedName)
- Custom Exceptions: SyncException.kt und ValidationException.kt erstellt
Added
- 📝 F-Droid Privacy Notice
- Datenschutz-Hinweis für die Datei-Logging-Funktion
- Erklärt dass Logs nur lokal gespeichert werden
- Erfüllt F-Droid Opt-in Consent-Anforderungen
Technical Improvements
-
⚡ Neue Konstanten für bessere Wartbarkeit
SYNC_COMPLETED_DELAY_MS,ERROR_DISPLAY_DELAY_MS(MainActivity)CONNECTION_TIMEOUT_MS(SettingsActivity)SOCKET_TIMEOUT_MS,MAX_FILENAME_LENGTH,ETAG_PREVIEW_LENGTH(WebDavSyncService)AUTO_CANCEL_TIMEOUT_MS(NotificationHelper)- RFC 1918 IP-Range Konstanten (UrlValidator)
DAYS_THRESHOLD,TRUNCATE_SUFFIX_LENGTH(Extensions)
-
🔒 @Suppress Annotations für legitime Patterns
- ReturnCount: Frühe Returns für Validierung sind idiomatisch
- LoopWithTooManyJumpStatements: Komplexe Sync-Logik dokumentiert
Notes
- Komplexe Refactorings (LargeClass, LongMethod) für v1.3.3+ geplant
- Deprecation-Warnungen (LocalBroadcastManager, ProgressDialog) bleiben bestehen
[1.3.1] - 2026-01-08
Fixed
- 🔧 Multi-Device JSON Sync (Danke an Thomas aus Bielefeld)
- JSON-Dateien werden jetzt korrekt zwischen Geräten synchronisiert
- Funktioniert auch ohne aktiviertes Markdown
- Hybrid-Optimierung: Server-Timestamp (Primary) + E-Tag (Secondary) Checks
- E-Tag wird nach Upload gecached um Re-Download zu vermeiden
Performance Improvements
-
⚡ JSON Sync Performance-Parität
- JSON-Sync erreicht jetzt gleiche Performance wie Markdown (~2-3 Sekunden)
- Timestamp-basierte Skip-Logik für unveränderte Dateien (~500ms pro Datei gespart)
- E-Tag-Matching als Fallback für Dateien die seit letztem Sync modifiziert wurden
- Beispiel: 24 Dateien von 12-14s auf ~2.7s reduziert (keine Änderungen)
-
⏭️ Skip unveränderte Dateien (Haupt-Performance-Fix!)
- JSON-Dateien: Überspringt alle Notizen, die seit letztem Sync nicht geändert wurden
- Markdown-Dateien: Überspringt unveränderte MD-Dateien basierend auf Server-Timestamp
- Spart ~500ms pro Datei bei Nextcloud (~20 Dateien = 10 Sekunden gespart!)
- Von 21 Sekunden Sync-Zeit auf 2-3 Sekunden reduziert
-
⚡ Session-Caching für WebDAV
- Sardine-Client wird pro Sync-Session wiederverwendet (~600ms gespart)
- WiFi-IP-Adresse wird gecacht statt bei jeder Anfrage neu ermittelt (~300ms gespart)
/notes/Ordner-Existenz wird nur einmal pro Sync geprüft (~500ms gespart)- Gesamt: ~1.4 Sekunden zusätzlich gespart
-
📝 Content-basierte Markdown-Erkennung
- Extern bearbeitete Markdown-Dateien werden auch erkannt wenn YAML-Timestamp nicht aktualisiert wurde
- Löst das Problem: Obsidian/Texteditor-Änderungen wurden nicht importiert
- Hybridansatz: Erst Timestamp-Check (schnell), dann Content-Vergleich (zuverlässig)
Added
- 🔄 Sync-Status-Anzeige (UI)
- Sichtbares Banner "Synchronisiere..." mit ProgressBar während Sync läuft
- Sync-Button und Pull-to-Refresh werden deaktiviert während Sync aktiv
- Verhindert versehentliche Doppel-Syncs durch visuelle Rückmeldung
- Auch in Einstellungen: "Jetzt synchronisieren" Button wird deaktiviert
Fixed
-
🔧 Sync-Mutex verhindert doppelte Syncs
- Keine doppelten Toast-Nachrichten mehr bei schnellem Pull-to-Refresh
- Concurrent Sync-Requests werden korrekt blockiert
-
🐛 Lint-Fehler behoben
View.generateViewId()statt hardcodierte IDs in RadioButtonsapp:tintstattandroid:tintfür AppCompat-Kompatibilität
Added
-
🔍 detekt Code-Analyse
- Statische Code-Analyse mit detekt 1.23.4 integriert
- Pragmatische Konfiguration für Sync-intensive Codebasis
- 91 Issues identifiziert (als Baseline für v1.4.0)
-
🏗️ Debug Build mit separatem Package
- Debug-APK kann parallel zur Release-Version installiert werden
- Package:
dev.dettmer.simplenotes.debug(Debug) vsdev.dettmer.simplenotes(Release) - App-Name zeigt "Simple Notes (Debug)" für einfache Unterscheidung
-
📊 Debug-Logging UI
- Neuer "Debug Log" Button in Einstellungen → Erweitert
- Zeigt letzte Sync-Logs mit Zeitstempeln
- Export-Funktion für Fehlerberichte
Technical
WebDavSyncService: Hybrid-Optimierung für JSON-Downloads (Timestamp PRIMARY, E-Tag SECONDARY)WebDavSyncService: E-Tag refresh nach Upload statt Invalidierung (verhindert Re-Download)- E-Tag Caching:
SharedPreferencesmit Key-Patternetag_json_{noteId} - Skip-Logik:
if (serverModified <= lastSync) skip→ ~1ms pro Datei - Fallback E-Tag:
if (serverETag == cachedETag) skip→ für Dateien modifiziert nach lastSync - PROPFIND nach PUT: Fetch E-Tag nach Upload für korrektes Caching
SyncStateManager: Neuer Singleton mitStateFlow<Boolean>für Sync-StatusMainActivity: Observer aufSyncStateManager.isSyncingfür UI-Updates- Layout:
sync_status_bannermitProgressBar+TextView WebDavSyncService: Skip-Logik für unveränderte JSON/MD Dateien basierend auflastSyncTimestampWebDavSyncService: Neue Session-Cache-Variablen (sessionSardine,sessionWifiAddress,notesDirEnsured)getOrCreateSardine(): Cached Sardine-Client mit automatischer Credentials-KonfigurationgetOrCacheWiFiAddress(): WiFi-Adresse wird nur einmal pro Sync ermitteltclearSessionCache(): Aufräumen am Ende jeder Sync-SessionensureNotesDirectoryExists(): Cached Directory-Check- Content-basierter Import: Vergleicht MD-Content mit lokaler Note wenn Timestamps gleich
- Build-Tooling: detekt aktiviert, ktlint vorbereitet (deaktiviert wegen Parser-Problemen)
- Debug BuildType:
applicationIdSuffix = ".debug",versionNameSuffix = "-debug"
[1.3.0] - 2026-01-07
Added
-
🚀 Multi-Device Sync (Thanks to Thomas from Bielefeld for reporting!)
- Automatic download of new notes from other devices
- Deletion tracking prevents "zombie notes" (deleted notes don't come back)
- Smart cleanup: Re-created notes (newer timestamp) are downloaded
- Works with all devices: v1.2.0, v1.2.1, v1.2.2, and v1.3.0
-
🗑️ Server Deletion via Swipe Gesture
- Swipe left on notes to delete from server (requires confirmation)
- Prevents duplicate notes on other devices
- Works with deletion tracking system
- Material Design confirmation dialog
-
⚡ E-Tag Performance Optimization
- Smart server checking with E-Tag caching (~150ms vs 3000ms for "no changes")
- 20x faster when server has no updates
- E-Tag hybrid approach: E-Tag for JSON (fast), timestamp for Markdown (reliable)
- Battery-friendly with minimal server requests
-
📥 Markdown Auto-Sync Toggle
- NEW: Unified Auto-Sync toggle in Settings (replaces separate Export/Auto-Import toggles)
- When enabled: Notes export to Markdown AND import changes automatically
- When disabled: Manual sync button appears for on-demand synchronization
- Performance: Auto-Sync OFF = 0ms overhead
-
🔘 Manual Markdown Sync Button
- Manual sync button for performance-conscious users
- Shows import/export counts after completion
- Only visible when Auto-Sync is disabled
- On-demand synchronization (~150-200ms only when triggered)
-
⚙️ Server-Restore Modes
- MERGE: Keep local notes + add server notes
- REPLACE: Delete all local + download from server
- OVERWRITE: Update duplicates, keep non-duplicates
- Restore modes now work correctly for WebDAV restore
Technical
- New
DeletionTrackermodel with JSON persistence NotesStorage: Added deletion tracking methodsWebDavSyncService.hasUnsyncedChanges(): Intelligent server checks with E-Tag cachingWebDavSyncService.downloadRemoteNotes(): Deletion-aware downloadsWebDavSyncService.restoreFromServer(): Support for restore modesWebDavSyncService.deleteNoteFromServer(): Server deletion with YAML frontmatter scanningWebDavSyncService.importMarkdownFiles(): Automatic Markdown import during syncWebDavSyncService.manualMarkdownSync(): Manual sync with result countsMainActivity.setupSwipeToDelete(): Two-stage swipe deletion with confirmation- E-Tag caching in SharedPreferences for performance
[1.2.2] - 2026-01-06
Fixed
- Backward Compatibility for v1.2.0 Users (Critical)
- App now reads BOTH old (Root) AND new (
/notes/) folder structures - Users upgrading from v1.2.0 no longer lose their existing notes
- Server-Restore now finds notes from v1.2.0 stored in Root folder
- Automatic deduplication prevents loading the same note twice
- Graceful error handling if Root folder is not accessible
- App now reads BOTH old (Root) AND new (
Technical
WebDavSyncService.downloadRemoteNotes()- Dual-mode download (Root + /notes/)WebDavSyncService.restoreFromServer()- Now uses dual-mode download- Migration happens naturally: new uploads go to
/notes/, old notes stay readable
[1.2.1] - 2026-01-05
Fixed
-
Markdown Initial Export Bugfix
- Existing notes are now exported as Markdown when Desktop Integration is activated
- Previously, only new notes created after activation were exported
- Progress dialog shows export status with current/total counter
- Error handling for network issues during export
- Individual note failures don't abort the entire export
-
Markdown Directory Structure Fix
- Markdown files now correctly land in
/notes-md/folder - Smart URL detection supports both Root-URL and
/notesURL structures - Previously, MD files were incorrectly placed in the root directory
- Markdown import now finds files correctly
- Markdown files now correctly land in
-
JSON URL Normalization
- Simplified server configuration: enter only base URL (e.g.,
http://server:8080/) - App automatically creates
/notes/for JSON files and/notes-md/for Markdown - Smart detection: both
http://server:8080/andhttp://server:8080/notes/work correctly - Backward compatible: existing setups with
/notesin URL continue to work - No migration required for existing users
- Simplified server configuration: enter only base URL (e.g.,
Changed
-
Markdown Directory Creation
notes-md/folder is now created on first sync (regardless of Desktop Integration setting)- Prevents 404 errors when mounting WebDAV folder
- Better user experience: folder is visible before enabling the feature
-
Settings UI Improvements
- Updated example URL from
/webdavto/notesto match app behavior - Example now shows:
http://192.168.0.188:8080/notes
- Updated example URL from
Technical
WebDavSyncService.ensureMarkdownDirectoryExists()- Creates MD folder earlyWebDavSyncService.getMarkdownUrl()- Smart URL detection for both structuresWebDavSyncService.exportAllNotesToMarkdown()- Exports all local notes with progress callbackSettingsActivity.onMarkdownExportToggled()- Triggers initial export with ProgressDialog
1.2.0 - 2026-01-04
Added
-
Local Backup System
- Export all notes as JSON file to any location (Downloads, SD card, cloud folder)
- Import backup with 3 modes: Merge, Replace, or Overwrite duplicates
- Automatic safety backup created before every restore
- Backup validation (format and version check)
-
Markdown Desktop Integration
- Optional Markdown export parallel to JSON sync
.mdfiles synced tonotes-md/folder on WebDAV- YAML frontmatter with
id,created,updated,device - Manual import button to pull Markdown changes from server
- Last-Write-Wins conflict resolution via timestamps
-
Settings UI Extensions
- New "Backup & Restore" section with local + server restore
- New "Desktop Integration" section with Markdown toggle
- Universal restore dialog with radio button mode selection
Changed
- Server Restore Behavior: Users now choose restore mode (Merge/Replace/Overwrite) instead of hard-coded replace-all
Technical
BackupManager.kt- Complete backup/restore logicNote.toMarkdown()/Note.fromMarkdown()- Markdown conversion with YAML frontmatterWebDavSyncService- Extended for dual-format sync (JSON master + Markdown mirror)- ISO8601 timestamp formatting for desktop compatibility
- Filename sanitization for safe Markdown file names
Documentation
- Added WebDAV mount instructions (Windows, macOS, Linux)
- Complete sync architecture documentation
- Desktop integration analysis
1.1.2 - 2025-12-28
Fixed
-
"Job was cancelled" Error
- Fixed coroutine cancellation in sync worker
- Proper error handling for interrupted syncs
-
UI Improvements
- Back arrow instead of X in note editor (better UX)
- Pull-to-refresh for manual sync trigger
- HTTP/HTTPS protocol selection with radio buttons
- Inline error display (no toast spam)
-
Performance & Battery
- Sync only on actual changes (saves battery)
- Auto-save notifications removed
- 24-hour server offline warning instead of instant error
Changed
- Settings grouped into "Auto-Sync" and "Sync Interval" sections
- HTTP only allowed for local networks (RFC 1918 IPs)
- Swipe-to-delete without UI flicker
1.1.1 - 2025-12-27
Fixed
- WiFi Connect Sync
- No error notifications in foreign WiFi networks
- Server reachability check before sync (2s timeout)
- Silent abort when server offline
- Pre-check waits until network is ready
- No errors during network initialization
Changed
- Notifications
- Old sync notifications cleared on app start
- Error notifications auto-dismiss after 30 seconds
UI
- Sync icon only shown when sync is configured
- Swipe-to-delete without flicker
- Scroll to top after saving note
Technical
- Server check with 2-second timeout before sync attempts
- Network readiness check in WiFi connect trigger
- Notification cleanup on MainActivity.onCreate()
1.1.0 - 2025-12-26
Added
-
Configurable Sync Intervals
- User choice: 15, 30, or 60 minutes
- Real-world battery impact displayed (15min: ~0.8%/day, 30min: ~0.4%/day, 60min: ~0.2%/day)
- Radio button selection in settings
- Doze Mode optimization (syncs batched in maintenance windows)
-
About Section
- App version from BuildConfig
- Links to GitHub repository and developer profile
- MIT license information
- Material 3 card design
Changed
- Settings UI redesigned with grouped sections
- Periodic sync updated dynamically when interval changes
- WorkManager uses selected interval for background sync
Removed
- Debug/Logs section from settings (cleaner UI)
Technical
PREF_SYNC_INTERVAL_MINUTESpreference key- NetworkMonitor reads interval from SharedPreferences
ExistingPeriodicWorkPolicy.UPDATEfor live interval changes
1.0.0 - 2025-12-25
Added
- Initial release
- WebDAV synchronization
- Note creation, editing, deletion
- 6 sync triggers:
- Periodic sync (configurable interval)
- App start sync
- WiFi connect sync
- Manual sync (menu button)
- Pull-to-refresh
- Settings "Sync Now" button
- Material 3 design
- Light/Dark theme support
- F-Droid compatible (100% FOSS)