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

@@ -77,6 +77,18 @@ final class BackupJob: ObservableObject {
: .failed("Completed with \(result.failedCount) error\(result.failedCount == 1 ? "" : "s")")
}
/// Call after reconciliation proves needBackup == 0 upgrades stale .failed to .completed.
func resolveSuccess() {
if case .failed = status { status = .completed }
}
/// Used when the pending queue is empty at backup start nothing to do.
func allAlreadySafe() {
totalFiles = 0; uploadedFiles = 0; skippedFiles = 0; failedFiles = 0
startDate = Date(); endDate = Date()
status = .completed
}
func fail(error: BackupError) {
endDate = Date()
status = .failed(error.errorDescription ?? error.localizedDescription)