809929e0ed16c11609db47daede2205b61a6ee49
Root cause of the alreadySafe=1 loop: after a backup where all assets are collision-skipped (Object Name Collision), writeManifest() connects to the NAS to write the updated manifest. If that connection fails or times out, the cache is never updated with the 263 new entries, so the next refresh(force:true) reads the old 1-entry cache and computes alreadySafe=1 → needBackup=263 → loop. BackupEngine: after the upload loop, immediately merge all manifestEntries (uploaded + collision-skipped + fileExists-skipped) into baseManifest and call NASManifestCache.shared.update(). This happens before refreshAfterBackup so the local truth is correct regardless of whether the NAS write later succeeds. BackupStatusService.writeManifest: move NASManifestCache.shared.update() to before transfer.writeData(). The local cache is now updated as soon as the merged manifest is computed, decoupling local reconcile correctness from NAS write success. The NAS write remains best-effort and non-blocking. 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%