From 4c7ccb83a6da8433d85494b09be637b2ed6baa06 Mon Sep 17 00:00:00 2001 From: Arkadiusz Fal Date: Mon, 19 Oct 2026 21:45:45 +0200 Subject: [PATCH] Keep unsent CloudKit changes across Sync Now (#978) refreshSync() discarded the persisted engine state and the pending buffer, and the engine state is where queued saves and deletions live, so tapping Sync Now within the debounce window dropped history, progress and bookmark changes. Carry the old engine's pending changes into the buffer that the new engine adopts, then schedule a send. --- Yattee/Services/CloudKit/CloudKitSyncEngine.swift | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Yattee/Services/CloudKit/CloudKitSyncEngine.swift b/Yattee/Services/CloudKit/CloudKitSyncEngine.swift index 4c5ed6c4..4209c4be 100644 --- a/Yattee/Services/CloudKit/CloudKitSyncEngine.swift +++ b/Yattee/Services/CloudKit/CloudKitSyncEngine.swift @@ -1629,22 +1629,33 @@ final class CloudKitSyncEngine: @unchecked Sendable { LoggingService.shared.logCloudKit("Refreshing sync state (clearing local tokens)...") + // Unsent local changes live in the engine state being discarded below; + // carry them over so a refresh never drops queued saves or deletions. + let unsentChanges = (syncEngine?.state.pendingRecordZoneChanges ?? []) + pendingChangesBuffer + // Clear local sync state so CKSyncEngine fetches everything fresh UserDefaults.standard.removeObject(forKey: syncStateKey) // Tear down existing engine debounceTimer?.invalidate() debounceTimer = nil - pendingChangesBuffer.removeAll() conflictResolvedRecords.removeAll() retryCount.removeAll() syncEngine = nil + pendingChangesBuffer = unsentChanges updatePendingCount() // Reinitialize - with the persisted state cleared above, setup starts - // from nil state serialization (forces full fetch) + // from nil state serialization (forces full fetch). Setup hands the + // carried-over buffer to the new engine. await setupSyncEngine() + if !unsentChanges.isEmpty { + LoggingService.shared.logCloudKit("Refresh sync carried over \(unsentChanges.count) unsent changes") + updatePendingCount() + scheduleDebounceSync() + } + LoggingService.shared.logCloudKit("Refresh sync completed") }