Files
noo/lib/models/sync_status.dart
T
ayushyaandClaude Sonnet 5 faaec5365f
Build APK / build (push) Successful in 7m33s
Add device sync: mirror folders/files locally, background WorkManager engine
- New native sync engine (SyncEngine/SyncWorker/ConflictResolveWorker,
  WorkManager-based) that mirrors selected Nextcloud folders or files to
  app-private local storage, periodically and on-demand ("Sync now"),
  with never-auto-resolved conflict notifications.
- Single files (not just folders) can now be marked "Sync to device".
- Live sync status (syncing/synced/conflicts) pushes from native to Dart
  over a new EventChannel; the persistent header chip/panel now reflects
  device-sync status instead of the WebDAV-refresh loading state, with a
  cloud_off/cloud_sync/cloud_done/cloud_alert icon set and an expandable
  conflicts list with in-app "Keep local"/"Use server" resolution.
  Per-item cloud_done/sync badges show on Files tiles.
- Share/Download short-circuit to the local copy for already-synced
  files instead of a fresh network fetch.
- Settings gained a Device Sync section (per-folder list, "Sync
  everything", Wi-Fi-only toggle, manual "Sync now").
- Fixed two release-only bugs found via on-device testing: Android's
  HttpURLConnection silently rejects the PROPFIND method (switched to
  OkHttp), and R8 was stripping WorkManager's reflection-instantiated
  internals (broadened proguard-rules.pro to keep androidx.work.**
  wholesale rather than chasing individual classes).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-19 00:52:56 -04:00

39 lines
1.2 KiB
Dart

/// A pending device-sync conflict (a file changed both locally and on the
/// server since the last sync) - mirrors `SyncStatusBus.Conflict` on the
/// native side exactly, see `SyncEngine.kt`/`server.md`'s "Device sync"
/// section.
class SyncConflictInfo {
final String accountId;
final String fileId;
final String remotePath;
final String relPath;
final String name;
const SyncConflictInfo({
required this.accountId,
required this.fileId,
required this.remotePath,
required this.relPath,
required this.name,
});
factory SyncConflictInfo.fromMap(Map<dynamic, dynamic> map) {
return SyncConflictInfo(
accountId: map['accountId'] as String? ?? '',
fileId: map['fileId'] as String? ?? '',
remotePath: map['remotePath'] as String? ?? '',
relPath: map['relPath'] as String? ?? '',
name: map['name'] as String? ?? '',
);
}
}
/// A single item's device-sync status, used to badge its tile in the
/// Files view.
enum SyncItemStatus { none, syncing, synced, conflict }
/// The persistent header chip/panel's overall status (account-wide, not
/// scoped to whatever folder is currently browsed) - see
/// `ServerProvider.syncHeaderStatus`.
enum SyncHeaderStatus { off, syncing, done, alert }