- Separator component: Visual divider between unchecked and checked items
* Shows count of completed items with denominator styling
* Prevents accidental drag across group boundaries
* Smooth transitions with fade/slide animations
- Sorting logic: Maintains unchecked items first, checked items last
* Stable sort: Relative order within groups is preserved
* Auto-updates on item toggle and reordering
* Validates drag moves to same-group only
- UI improvements: Enhanced LazyColumn animations
* AnimatedVisibility for smooth item transitions
* Added animateItem() for LazyColumn layout changes
* Item elevation during drag state
- Comprehensive test coverage
* 9 unit tests for sorting logic validation
* Edge cases: empty lists, single items, mixed groups
* Verifies order reassignment and group separation
Affected components:
- CheckedItemsSeparator: New UI component for visual separation
- NoteEditorViewModel: sortChecklistItems() method with validation
- NoteEditorScreen: Separator integration & animation setup
- ChecklistSortingTest: Complete test suite with 9 test cases
- Localizations: German & English plurals
- Add SyncProgress.kt: Data class for entire sync lifecycle UI state
- Add SyncPhase enum: IDLE, PREPARING, UPLOADING, DOWNLOADING, IMPORTING_MARKDOWN, COMPLETED, ERROR
- Rewrite SyncStateManager.kt: SyncProgress (StateFlow) is single source of truth
- Remove pre-set phases: CHECKING_SERVER and SAVING cause flickering
- UPLOADING phase only set when actual uploads happen
- DOWNLOADING phase only set when actual downloads happen
- IMPORTING_MARKDOWN phase only set when feature enabled
- Add onProgress callback to uploadLocalNotes() with uploadedCount/totalToUpload
- Add onProgress callback to downloadRemoteNotes() for actual downloads only
- Progress display: x/y for uploads (known total), count for downloads (unknown)
- Add SyncProgressBanner.kt: Unified banner (replaces dual system)
- Update SyncStatusBanner.kt: Kept for legacy compatibility, only COMPLETED/ERROR
- Update MainViewModel.kt: Remove _syncMessage, add syncProgress StateFlow
- Update MainScreen.kt: Use only SyncProgressBanner (unified)
- Update ComposeMainActivity.kt: Auto-hide COMPLETED (2s), ERROR (4s) via lifecycle
- Add strings.xml (DE+EN): sync_phase_* and sync_wifi_only_error
- Banner appears instantly on sync button click (PREPARING phase)
- Silent auto-sync (onResume) completely silent, errors always shown
- No misleading counters when nothing to sync
Closes #IMPL_006
- New SyncStatusLegendDialog.kt showing all 5 sync status icons with descriptions
- Help button (?) in MainScreen TopAppBar (only visible when sync available)
- Localized strings (English + German) for all 5 status explanations
- Material You design with consistent colors matching NoteCard icons
- Dialog shows: Synced, Pending, Conflict, Local only, Deleted on server
IMPL_021_SYNC_STATUS_LEGEND.md
This commit fixes the critical crash on Android 9 (API 28) that occurred when using
WorkManager Expedited Work for background sync operations.
## Root Cause
When setExpedited() is used in WorkManager, the CoroutineWorker must implement
getForegroundInfo() to return a ForegroundInfo object with 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
- Returns ForegroundInfo with sync progress notification
- Android 10+: Sets FOREGROUND_SERVICE_TYPE_DATA_SYNC for proper service typing
- Added required Foreground Service permissions to AndroidManifest.xml
## Technical Changes
- SyncWorker.kt: Added getForegroundInfo() override
- NotificationHelper.kt: Added createSyncProgressNotification() factory method
- strings.xml: Added sync_in_progress UI strings (EN + DE)
- AndroidManifest.xml: Added FOREGROUND_SERVICE permissions
- Version updated to 1.7.1 (versionCode 18)
## Previously Fixed (in this release)
- Kernel-VPN compatibility (Wireguard interface detection)
- HTTP connection lifecycle optimization (SafeSardineWrapper)
- Stability improvements for sync sessions
## Testing
- Tested on Android 9 (API 28) - No crash on second app start
- Tested on Android 15 (API 35) - No regressions
- WiFi-connect sync working correctly
- Expedited work notifications display properly
Fixes#15
Thanks to @roughnecks for detailed bug report and testing!
Fixes:
1. Notification click now opens ComposeMainActivity instead of legacy MainActivity
2. WiFi-Only toggle moved to its own 'Network Restriction' section at top of sync settings
3. Added hint explaining WiFi-Connect trigger is not affected by WiFi-Only setting
UI Changes:
- New section header: 'Network Restriction' / 'Netzwerk-Einschränkung'
- WiFi-Only toggle now clearly separated from sync triggers
- Info card shows when WiFi-Only is enabled explaining the exception
- NEW: Configurable sync triggers (onSave, onResume, WiFi, Periodic, Boot)
- NEW: Offline mode toggle to disable all network features
- Various fixes and UI improvements
- Version bumped to 1.6.0 (code 14)
FEATURES
========
Batch Delete Toast Aggregation:
- New deleteMultipleNotesFromServer() method
- Shows single aggregated toast instead of multiple ("3 notes deleted from server")
- Partial success handling ("3 of 5 notes deleted from server")
- Added string resources: snackbar_notes_deleted_from_server, snackbar_notes_deleted_from_server_partial
Text Editor Cursor Fix:
- Fixed cursor jumping to end after every keystroke when editing notes
- Added initialCursorSet flag to only set cursor position on first load
- Cursor now stays at user's position while editing
- Changed LaunchedEffect(content) to LaunchedEffect(Unit) to prevent repeated resets
DOCUMENTATION REFACTOR
======================
Breaking Change: English is now the default language
- README.md: Now English (was German)
- QUICKSTART.md: Now English (was German)
- CHANGELOG.md: Now English (was mixed EN/DE)
- docs/*.md: All English (was German)
- German versions: Use .de.md suffix (README.de.md, QUICKSTART.de.md, etc.)
Updated for v1.5.0:
- CHANGELOG.md: Fully translated to English with v1.5.0 release notes
- CHANGELOG.de.md: Created German version
- FEATURES.md: Added i18n section, Selection Mode, Jetpack Compose updates
- FEATURES.de.md: Updated with v1.5.0 features
- UPCOMING.md: v1.5.0 marked as released, v1.6.0/v1.7.0 roadmap
- UPCOMING.de.md: Updated German version
All language headers updated:
- English: [Deutsch](*.de.md) · **English**
- German: **Deutsch** · [English](*.md)
F-DROID METADATA
================
Changelogs (F-Droid):
- fastlane/metadata/android/en-US/changelogs/13.txt: Created
- fastlane/metadata/android/de-DE/changelogs/13.txt: Created
Descriptions:
- full_description.txt (EN/DE): Updated with v1.5.0 changes
- Selection Mode instead of Swipe-to-Delete
- i18n support highlighted
- Jetpack Compose UI mentioned
- Silent-Sync Mode added
OTHER FIXES
===========
Code Quality:
- Unused imports removed from multiple files
- maxLineLength fixes
- Detekt config optimized (increased thresholds for v1.5.0)
- AboutScreen: Uses app foreground icon directly
- EmptyState: Shows app icon instead of emoji
- themes.xml: Splash screen uses app foreground icon
- Added comprehensive English (strings.xml) and German (strings-de.xml) localization with 400+ strings
- Created new LanguageSettingsScreen with System Default, English, and German options
- Fixed hardcoded German notification toasts in MainActivity and ComposeMainActivity
- Integrated Language selector in Settings as top-level menu item
- Changed ComposeSettingsActivity from ComponentActivity to AppCompatActivity for AppCompatDelegate compatibility
- Added locales_config.xml for Android 13+ Per-App Language support
- Updated Extensions.kt with i18n-aware timestamp formatting (toReadableTime with context)
- Translated all UI strings including settings, toasts, notifications, and error messages
- Added dynamic language display in SettingsMainScreen showing current language
Fixes:
- Notification permission toast now respects system language setting
- Activity correctly restarts when language is changed
- All string formatting with parameters properly localized
Migration:
- MainViewModel: All toast messages now use getString()
- SettingsViewModel: All toast and dialog messages localized
- NotificationHelper: Notification titles and messages translated
- UrlValidator: Error messages now accept Context parameter for translation
- NoteCard, DeleteConfirmationDialog, SyncStatusBanner: All strings externalized
Testing completed on device with both EN and DE locale switching.
Closes#5