@@ -146,12 +146,17 @@ final class SyncCoordinator {
146146 changeTracker. markDirty ( . tag, id: tag. id. uuidString)
147147 }
148148
149+ let sshProfiles = SSHProfileStorage . shared. loadProfiles ( )
150+ for profile in sshProfiles {
151+ changeTracker. markDirty ( . sshProfile, id: profile. id. uuidString)
152+ }
153+
149154 // Mark all settings categories as dirty
150155 for category in [ " general " , " appearance " , " editor " , " dataGrid " , " history " , " tabs " , " keyboard " , " ai " ] {
151156 changeTracker. markDirty ( . settings, id: category)
152157 }
153158
154- Self . logger. info ( " Marked all local data dirty: \( connections. count) connections, \( groups. count) groups, \( tags. count) tags, 8 settings categories " )
159+ Self . logger. info ( " Marked all local data dirty: \( connections. count) connections, \( groups. count) groups, \( tags. count) tags, \( sshProfiles . count ) SSH profiles, 8 settings categories" )
155160 }
156161
157162 /// Called when user disables sync in settings
@@ -254,6 +259,11 @@ final class SyncCoordinator {
254259 collectDirtyTags ( into: & recordsToSave, deletions: & recordIDsToDelete, zoneID: zoneID)
255260 }
256261
262+ // Collect dirty SSH profiles
263+ if settings. syncSSHProfiles {
264+ collectDirtySSHProfiles ( into: & recordsToSave, deletions: & recordIDsToDelete, zoneID: zoneID)
265+ }
266+
257267 // Collect unsynced query history
258268 if settings. syncQueryHistory {
259269 let limit = settings. historySyncLimit. limit ?? Int . max
@@ -301,6 +311,9 @@ final class SyncCoordinator {
301311 changeTracker. clearAllDirty ( . group)
302312 changeTracker. clearAllDirty ( . tag)
303313 }
314+ if settings. syncSSHProfiles {
315+ changeTracker. clearAllDirty ( . sshProfile)
316+ }
304317 if settings. syncSettings {
305318 changeTracker. clearAllDirty ( . settings)
306319 }
@@ -322,6 +335,11 @@ final class SyncCoordinator {
322335 metadataStorage. removeTombstone ( type: . tag, id: tombstone. id)
323336 }
324337 }
338+ if settings. syncSSHProfiles {
339+ for tombstone in metadataStorage. tombstones ( for: . sshProfile) {
340+ metadataStorage. removeTombstone ( type: . sshProfile, id: tombstone. id)
341+ }
342+ }
325343 if settings. syncSettings {
326344 for tombstone in metadataStorage. tombstones ( for: . settings) {
327345 metadataStorage. removeTombstone ( type: . settings, id: tombstone. id)
@@ -416,6 +434,8 @@ final class SyncCoordinator {
416434 case SyncRecordType . tag. rawValue where settings. syncGroupsAndTags:
417435 applyRemoteTag ( record)
418436 groupsOrTagsChanged = true
437+ case SyncRecordType . sshProfile. rawValue where settings. syncSSHProfiles:
438+ applyRemoteSSHProfile ( record)
419439 case SyncRecordType . settings. rawValue where settings. syncSettings:
420440 applyRemoteSettings ( record)
421441 case SyncRecordType . queryHistory. rawValue where settings. syncQueryHistory:
@@ -494,6 +514,18 @@ final class SyncCoordinator {
494514 TagStorage . shared. saveTags ( tags)
495515 }
496516
517+ private func applyRemoteSSHProfile( _ record: CKRecord ) {
518+ guard let remoteProfile = SyncRecordMapper . toSSHProfile ( record) else { return }
519+
520+ var profiles = SSHProfileStorage . shared. loadProfiles ( )
521+ if let index = profiles. firstIndex ( where: { $0. id == remoteProfile. id } ) {
522+ profiles [ index] = remoteProfile
523+ } else {
524+ profiles. append ( remoteProfile)
525+ }
526+ SSHProfileStorage . shared. saveProfilesWithoutSync ( profiles)
527+ }
528+
497529 private func applyRemoteSettings( _ record: CKRecord ) {
498530 guard let category = SyncRecordMapper . settingsCategory ( from: record) ,
499531 let data = SyncRecordMapper . settingsData ( from: record)
@@ -561,6 +593,15 @@ final class SyncCoordinator {
561593 TagStorage . shared. saveTags ( tags)
562594 }
563595 }
596+
597+ if recordName. hasPrefix ( " SSHProfile_ " ) {
598+ let uuidString = String ( recordName. dropFirst ( " SSHProfile_ " . count) )
599+ if let uuid = UUID ( uuidString: uuidString) {
600+ var profiles = SSHProfileStorage . shared. loadProfiles ( )
601+ profiles. removeAll { $0. id == uuid }
602+ SSHProfileStorage . shared. saveProfilesWithoutSync ( profiles)
603+ }
604+ }
564605 }
565606
566607 // MARK: - Observers
@@ -654,6 +695,7 @@ final class SyncCoordinator {
654695 case SyncRecordType . tag. rawValue: syncRecordType = . tag
655696 case SyncRecordType . settings. rawValue: syncRecordType = . settings
656697 case SyncRecordType . queryHistory. rawValue: syncRecordType = . queryHistory
698+ case SyncRecordType . sshProfile. rawValue: syncRecordType = . sshProfile
657699 default : continue
658700 }
659701
@@ -786,4 +828,26 @@ final class SyncCoordinator {
786828 )
787829 }
788830 }
831+
832+ private func collectDirtySSHProfiles(
833+ into records: inout [ CKRecord ] ,
834+ deletions: inout [ CKRecord . ID ] ,
835+ zoneID: CKRecordZone . ID
836+ ) {
837+ let dirtyProfileIds = changeTracker. dirtyRecords ( for: . sshProfile)
838+ if !dirtyProfileIds. isEmpty {
839+ let profiles = SSHProfileStorage . shared. loadProfiles ( )
840+ for id in dirtyProfileIds {
841+ if let profile = profiles. first ( where: { $0. id. uuidString == id } ) {
842+ records. append ( SyncRecordMapper . toCKRecord ( profile, in: zoneID) )
843+ }
844+ }
845+ }
846+
847+ for tombstone in metadataStorage. tombstones ( for: . sshProfile) {
848+ deletions. append (
849+ SyncRecordMapper . recordID ( type: . sshProfile, id: tombstone. id, in: zoneID)
850+ )
851+ }
852+ }
789853}
0 commit comments