8d8b6c441874927c01fcc180b9e570c314fde096
BackupEngine: after all retries fail, call fileExists() before recording a failure. If the file is on NAS (uploaded earlier but fileExists silently threw on the pre-check), count it as skipped and add it to manifestEntries — this ensures writeManifest includes every safe asset and prevents alreadySafe from dropping to 1 after the post-backup reconcile. BackupView: remove the immediate refreshAndWait from onChange(.failed). That call raced with refreshAfterBackup's writeManifest, cancelled the manifest- correct refresh, then reconciled against a stale 1-entry NAS manifest. Auto-resolve (.failed → .completed when needBackup == 0) is now owned by the coordinator so it runs after writeManifest finishes. AutoBackupCoordinator: add backupTriggerArmed flag (set by onActive/ handleNASReachable, cleared by handleReconciliationComplete). Post-backup reconciles from refreshAfterBackup are no longer able to re-trigger auto- backup — only an explicit app-open or LAN-join can arm the trigger. Also added auto-resolve: calls engine.resolveSuccess() when job is .failed but needBackup == 0, which fires the .completed green-flash path in BackupView. Co-Authored-By: Kutesir <kutesir@provoc.ug> Co-Authored-By: Sentry <sentry@provoc.ug>
perf: eliminate full rescans with local caches; add queue tracking, notifications, SyncView redesign
perf: eliminate full rescans with local caches; add queue tracking, notifications, SyncView redesign
Description
Privacy-first iOS photo backup to NAS — SMB + SFTP, auto LAN trigger
Languages
Swift
100%