Sync engine / providers:
- LocalAccessor: replace createOutputStream with writeAtomically (temp
sibling + rename/commit) for both JavaFile and SAF backends, so an
interrupted download no longer truncates the destination file.
- SyncEngine: use writeAtomically for DOWNLOAD and propagate downloadFile
failures via getOrThrow (was silently swallowed -> false success + state).
- WebDavProvider (covers Nextcloud/ownCloud): PUT to hidden temp then MOVE
onto destination, so a failed upload can't leave a truncated remote file.
- SftpProvider: upload to temp then rename onto destination.
Build / CI:
- compileSdk 34 -> 35 (was below targetSdk 35).
- Release signing reads keystore from local.properties or env (CI), with a
debug-key fallback so builds still succeed without secrets.
- Disable R8/minify for release (never exercised by CI; keeps signed release
behaving like the debug builds in use today).
- CI: run unit tests on every push/PR, build assembleRelease (signed when
KEYSTORE_BASE64 present), publish APK only on v* tags.
Single source of truth: bump VERSION_NAME/VERSION_CODE in version.properties
to release a new version. BuildConfig.VERSION_NAME exposed to the app.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Supports WebDAV, SFTP, SFTPGo, Nextcloud, ownCloud, Google Drive,
Dropbox, and OneDrive. Credentials encrypted with Android Keystore.
Biometric app-lock, conflict resolution, and auto-sync via WorkManager.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>