LocalData/Sources/LocalData/Services/SyncHelper.swift
Matt Bruce 1564309a25 Update Services
Summary:
- Sources: Services
- Added symbols: actor EncryptionHelper, actor FileStorageHelper, actor KeychainHelper, func registerKeyMaterialProvider, actor SyncHelper, actor UserDefaultsHelper
- Removed symbols: actor EncryptionHelper, actor FileStorageHelper, actor KeychainHelper, actor SyncHelper, actor UserDefaultsHelper

Stats:
- 6 files changed, 15 insertions(+), 5 deletions(-)
2026-01-18 14:53:26 -06:00

112 lines
3.4 KiB
Swift

import Foundation
#if os(iOS) || os(watchOS)
import WatchConnectivity
#endif
/// Actor that handles WatchConnectivity sync operations.
/// Manages data synchronization between iPhone and Apple Watch.
actor SyncHelper {
public static let shared = SyncHelper()
/// Maximum data size for automatic sync (100KB).
public static let maxAutoSyncSize = 100_000
private init() {}
// MARK: - Public Interface
/// Syncs data to the paired device if appropriate.
/// - Parameters:
/// - data: The data to sync.
/// - keyName: The key name for the application context.
/// - availability: The platform availability setting.
/// - syncPolicy: The sync policy setting.
/// - Throws: `StorageError.dataTooLargeForSync` if data exceeds size limit for automatic sync.
public func syncIfNeeded(
data: Data,
keyName: String,
availability: PlatformAvailability,
syncPolicy: SyncPolicy
) throws {
#if os(iOS) || os(watchOS)
// Only sync for appropriate availability settings
guard availability == .all || availability == .phoneWithWatchSync else {
return
}
switch syncPolicy {
case .never:
return
case .automaticSmall:
guard data.count <= Self.maxAutoSyncSize else {
throw StorageError.dataTooLargeForSync
}
try performSync(data: data, keyName: keyName)
case .manual:
try performSync(data: data, keyName: keyName)
}
#endif
}
/// Manually triggers a sync for the given data.
/// - Parameters:
/// - data: The data to sync.
/// - keyName: The key name for the application context.
/// - Throws: Various errors if sync fails.
public func manualSync(data: Data, keyName: String) throws {
#if os(iOS) || os(watchOS)
try performSync(data: data, keyName: keyName)
#endif
}
/// Checks if sync is available.
/// - Returns: True if WatchConnectivity is supported and active.
public func isSyncAvailable() -> Bool {
#if os(iOS) || os(watchOS)
guard WCSession.isSupported() else { return false }
let session = WCSession.default
guard session.activationState == .activated else { return false }
#if os(iOS)
return session.isPaired && session.isWatchAppInstalled
#else
return true
#endif
#else
return false
#endif
}
/// Gets the current application context.
/// - Returns: The current application context dictionary.
public func currentContext() -> [String: Any] {
#if os(iOS) || os(watchOS)
guard WCSession.isSupported() else { return [:] }
return WCSession.default.applicationContext
#else
return [:]
#endif
}
// MARK: - Private Helpers
#if os(iOS) || os(watchOS)
private func performSync(data: Data, keyName: String) throws {
guard WCSession.isSupported() else { return }
let session = WCSession.default
guard session.activationState == .activated else { return }
#if os(iOS)
guard session.isPaired, session.isWatchAppInstalled else { return }
#endif
try session.updateApplicationContext([keyName: data])
}
#endif
}