feat(sync): WebDAV vault sync
All checks were successful
CI / Windows build (push) Successful in 12m32s

Two-way sync of the vault folder to a user-configured WebDAV server,
so annotations (which travel with the file) sync with the file.

- WebDavSyncService.syncNow: per-file decision — local-only uploads,
  remote-only downloads, and when BOTH sides changed since the last
  sync it keeps the loser as <file>.conflict-<mtime> on both sides
  (last-write-wins by mtime) so no data is ever lost. Creates dirs as
  needed; deletes are conservative.
- The decision logic is pure and unit-tested against a fake WebDAV
  client; the real client is a thin http adapter (no dio dependency).
- Settings: WebDAV URL / user / password / remote folder, Test
  connection, Sync now (with status + last-synced), and an auto-sync
  toggle (default OFF).

Real server round-trips are device/server-validated. Credentials are in
SharedPreferences for now (TODO secure-storage). analyze clean, 432 tests.
This commit is contained in:
2026-06-25 01:35:13 +08:00
parent e939759458
commit 3cabc7e074
12 changed files with 2012 additions and 5 deletions

View File

@@ -49,6 +49,14 @@ dependencies:
# Settings persistence
shared_preferences: ^2.3.0
# WebDAV sync: a minimal client (PROPFIND/GET/PUT/MKCOL) is hand-rolled over
# `package:http` (HttpWebDavClient) — both were already transitive deps. We
# avoid the `webdav_client` package because it drags in `dio`; `http` works on
# Windows and keeps the real adapter thin so the sync algorithm stays testable
# against a fake client.
http: ^1.2.0
xml: ^6.5.0
# Cross-platform file picker
file_picker: ^8.0.0