@@ -9,6 +9,8 @@ import CloudKit
99import os
1010import RxSwift
1111import RealmSwift
12+ import PVSettings
13+ import Defaults
1214
1315/// Save states syncer for all OS's using CloudKit
1416public class CloudKitSaveStatesSyncer: CloudKitSyncer , SaveStatesSyncing {
@@ -949,6 +951,19 @@ public class CloudKitSaveStatesSyncer: CloudKitSyncer, SaveStatesSyncing {
949951
950952 Task {
951953 defer { self . isLoadAllInFlight. withLock { $0 = false } }
954+
955+ // metadataOnly: use the lightweight metadata sync instead of full
956+ // conflict resolution, artwork caching, and filesystem probes.
957+ if Defaults [ . cloudKitSyncContentType] == . metadataOnly {
958+ let syncLog = CloudSyncManager . syncLog
959+ syncLog. event ( . start, item: " save/loadAll " , status: . skipped, detail: " metadataOnly — using lightweight sync " )
960+ let count = await self . syncMetadataOnly ( )
961+ syncLog. event ( . complete, item: " save/loadAll " , status: . ok, detail: " metadataOnly processed \( count) records " )
962+ await iterationComplete ? ( )
963+ observer ( . completed)
964+ return
965+ }
966+
952967 do {
953968 let syncLog = CloudSyncManager . syncLog
954969 CloudSyncManager . syncLog. event ( . start, item: " save/loadAll " , status: . inProgress)
@@ -1138,16 +1153,24 @@ public class CloudKitSaveStatesSyncer: CloudKitSyncer, SaveStatesSyncing {
11381153
11391154 var targetSaveState : PVSaveState ?
11401155 var needsRomDownload = false
1156+ let isMetadataOnly = Defaults [ . cloudKitSyncContentType] == . metadataOnly
11411157
11421158 // Step 2: Handle existing or create new (async work)
11431159 if let existingSaveState = existingSaveState {
1144- syncLog. event ( . sync, item: " save/ \( existingSaveState. id) " , status: . inProgress, detail: " handling existing " )
1145- await self . refreshLocalDownloadState ( for: existingSaveState)
1146- await self . handleSaveStateConflict ( existingSaveState, cloudRecord: record, preferredCoreID: coreHint. coreID, preferredCoreVersion: coreHint. coreVersion)
1147- targetSaveState = existingSaveState
1148- // If the game isn't downloaded locally, flag for ROM download
1149- if existingSaveState. game? . isDownloaded == false {
1150- needsRomDownload = true
1160+ if isMetadataOnly {
1161+ // metadataOnly: skip conflict resolution and filesystem probes,
1162+ // just ensure cloudRecordID is linked.
1163+ syncLog. event ( . sync, item: " save/ \( existingSaveState. id) " , status: . ok, detail: " metadataOnly — skipping conflict resolution " )
1164+ targetSaveState = existingSaveState
1165+ } else {
1166+ syncLog. event ( . sync, item: " save/ \( existingSaveState. id) " , status: . inProgress, detail: " handling existing " )
1167+ await self . refreshLocalDownloadState ( for: existingSaveState)
1168+ await self . handleSaveStateConflict ( existingSaveState, cloudRecord: record, preferredCoreID: coreHint. coreID, preferredCoreVersion: coreHint. coreVersion)
1169+ targetSaveState = existingSaveState
1170+ // If the game isn't downloaded locally, flag for ROM download
1171+ if existingSaveState. game? . isDownloaded == false {
1172+ needsRomDownload = true
1173+ }
11511174 }
11521175
11531176 // Ensure cloudRecordID is set if it wasn't before
@@ -1167,10 +1190,14 @@ public class CloudKitSaveStatesSyncer: CloudKitSyncer, SaveStatesSyncing {
11671190 }
11681191 } else if let newSaveState = await self . createSaveStateFromCloudRecord ( record, game: frozenGame, originalID: originalSaveStateID, preferredCoreID: coreHint. coreID, preferredCoreVersion: coreHint. coreVersion) {
11691192 syncLog. event ( . download, item: " save/ \( newSaveState. id) " , status: . ok, detail: " created new save state " )
1170- await self . markSaveStateForDownload ( newSaveState, cloudRecord: record)
1193+ if !isMetadataOnly {
1194+ await self . markSaveStateForDownload ( newSaveState, cloudRecord: record)
1195+ }
11711196 targetSaveState = newSaveState
11721197 // New save states from cloud need the ROM downloaded
1173- needsRomDownload = true
1198+ if !isMetadataOnly {
1199+ needsRomDownload = true
1200+ }
11741201 }
11751202 else if frozenGame == nil {
11761203 // Defer processing until ROM metadata lands to avoid losing this record on fresh installs.
@@ -1184,7 +1211,9 @@ public class CloudKitSaveStatesSyncer: CloudKitSyncer, SaveStatesSyncing {
11841211 to: targetSaveState,
11851212 preferredCoreID: coreHint. coreID,
11861213 preferredCoreVersion: coreHint. coreVersion)
1187- if record [ CloudKitSchema . SaveStateFields. imageAsset] as? CKAsset != nil {
1214+ // Skip artwork caching in metadataOnly mode — avoid I/O on every boot
1215+ if !isMetadataOnly,
1216+ record [ CloudKitSchema . SaveStateFields. imageAsset] as? CKAsset != nil {
11881217 await cacheSaveStateArtworkAsset ( from: record, for: targetSaveState)
11891218 }
11901219
0 commit comments