Fix backup progress state machine: pending queue, resolvedStatus, failure resolution

- BackupEngine: pre-filter assets against ManifestIndex before job.start() so
  totalFiles reflects only pending items (not full gallery). Short-circuit with
  allAlreadySafe() when queue is empty.
- BackupJob: add resolveSuccess() (upgrades stale .failed → .completed after
  reconciliation proves needBackup==0) and allAlreadySafe() for empty-queue case.
- BackupStatusService: expose refreshAndWait(force:) async for pull-to-refresh
  and post-failure reconciliation.
- BackupView: wire resolvedStatus throughout ringContentID, ringMainView,
  ringColor, and actionButton; fix progress label to show pending-queue
  denominator; handle .failed in onChange by reconciling and auto-resolving
  to .completed when counts confirm all photos are safe.

Co-Authored-By: Kutesir <kutesir@provoc.ug>
Co-Authored-By: Sentry <sentry@provoc.ug>
This commit is contained in:
Robin Kutesa
2026-05-17 15:58:54 +03:00
parent 819f2b949e
commit f40cf9ee37
5 changed files with 146 additions and 99 deletions

View File

@@ -60,6 +60,12 @@ final class BackupStatusService: NSObject, ObservableObject {
}
}
/// Awaitable reconciliation used by pull-to-refresh and post-failure resolution.
func refreshAndWait(force: Bool = true) async {
cancelAll()
await performRefresh(force: force)
}
/// Called by BackupEngine after a completed run with newly uploaded entries.
/// Applies an optimistic count update, writes the manifest in background, then reconciles.
func refreshAfterBackup(entries: [ManifestEntry], connection: NASConnection) {