Update Helpers, Services

Summary:
- Sources: Helpers, Services
- Added symbols: func updateFromSync

Stats:
- 2 files changed, 26 insertions(+), 23 deletions(-)
This commit is contained in:
Matt Bruce 2026-01-15 11:15:35 -06:00
parent 0d9bd3735f
commit 8eb03183b7
2 changed files with 26 additions and 23 deletions

View File

@ -1,7 +1,5 @@
import Foundation import Foundation
#if os(iOS) || os(watchOS)
import WatchConnectivity import WatchConnectivity
#endif
/// Actor that handles WatchConnectivity sync operations. /// Actor that handles WatchConnectivity sync operations.
/// Manages data synchronization between iPhone and Apple Watch. /// Manages data synchronization between iPhone and Apple Watch.
@ -35,7 +33,6 @@ actor SyncHelper {
availability: PlatformAvailability, availability: PlatformAvailability,
syncPolicy: SyncPolicy syncPolicy: SyncPolicy
) throws { ) throws {
#if os(iOS) || os(watchOS)
// Only sync for appropriate availability settings // Only sync for appropriate availability settings
guard availability == .all || availability == .phoneWithWatchSync else { guard availability == .all || availability == .phoneWithWatchSync else {
return return
@ -54,7 +51,6 @@ actor SyncHelper {
case .manual: case .manual:
try performSync(data: data, keyName: keyName) try performSync(data: data, keyName: keyName)
} }
#endif
} }
/// Manually triggers a sync for the given data. /// Manually triggers a sync for the given data.
@ -63,15 +59,12 @@ actor SyncHelper {
/// - keyName: The key name for the application context. /// - keyName: The key name for the application context.
/// - Throws: Various errors if sync fails. /// - Throws: Various errors if sync fails.
public func manualSync(data: Data, keyName: String) throws { public func manualSync(data: Data, keyName: String) throws {
#if os(iOS) || os(watchOS)
try performSync(data: data, keyName: keyName) try performSync(data: data, keyName: keyName)
#endif
} }
/// Checks if sync is available. /// Checks if sync is available.
/// - Returns: True if WatchConnectivity is supported and active. /// - Returns: True if WatchConnectivity is supported and active.
public func isSyncAvailable() -> Bool { public func isSyncAvailable() -> Bool {
#if os(iOS) || os(watchOS)
guard WCSession.isSupported() else { return false } guard WCSession.isSupported() else { return false }
let session = WCSession.default let session = WCSession.default
@ -82,25 +75,17 @@ actor SyncHelper {
#else #else
return true return true
#endif #endif
#else
return false
#endif
} }
/// Gets the current application context. /// Gets the current application context.
/// - Returns: The current application context dictionary. /// - Returns: The current application context dictionary.
public func currentContext() -> [String: Any] { public func currentContext() -> [String: Any] {
#if os(iOS) || os(watchOS)
guard WCSession.isSupported() else { return [:] } guard WCSession.isSupported() else { return [:] }
return WCSession.default.applicationContext return WCSession.default.applicationContext
#else
return [:]
#endif
} }
// MARK: - Private Helpers // MARK: - Private Helpers
#if os(iOS) || os(watchOS)
private func performSync(data: Data, keyName: String) throws { private func performSync(data: Data, keyName: String) throws {
guard WCSession.isSupported() else { return } guard WCSession.isSupported() else { return }
@ -129,16 +114,20 @@ actor SyncHelper {
fileprivate func handleReceivedContext(_ context: [String: Any]) async { fileprivate func handleReceivedContext(_ context: [String: Any]) async {
Logger.info(">>> [SYNC] Received application context with \(context.count) keys") Logger.info(">>> [SYNC] Received application context with \(context.count) keys")
for (key, value) in context { for (key, value) in context {
guard let data = value as? Data else { continue } guard let data = value as? Data else {
continue
}
Logger.debug(">>> [SYNC] Processing received data for key: \(key)") Logger.debug(">>> [SYNC] Processing received data for key: \(key)")
// Future implementation: Route this back to StorageRouter to update local storage
// For now, we just log it as a skeleton implementation do {
try await StorageRouter.shared.updateFromSync(keyName: key, data: data)
} catch {
Logger.error("Failed to update storage from sync for key: \(key)", error: error)
}
} }
} }
#endif
} }
#if os(iOS) || os(watchOS)
/// A private proxy class to handle WCSessionDelegate callbacks and route them to the SyncHelper actor. /// A private proxy class to handle WCSessionDelegate callbacks and route them to the SyncHelper actor.
private final class SessionDelegateProxy: NSObject, WCSessionDelegate { private final class SessionDelegateProxy: NSObject, WCSessionDelegate {
static let shared = SessionDelegateProxy() static let shared = SessionDelegateProxy()
@ -164,4 +153,3 @@ private final class SessionDelegateProxy: NSObject, WCSessionDelegate {
} }
#endif #endif
} }
#endif

View File

@ -1,8 +1,6 @@
import Foundation import Foundation
#if os(iOS) || os(watchOS)
import WatchConnectivity import WatchConnectivity
#endif
/// The main storage router that coordinates all storage operations. /// The main storage router that coordinates all storage operations.
/// Uses specialized helper actors for each storage domain. /// Uses specialized helper actors for each storage domain.
@ -427,6 +425,23 @@ public actor StorageRouter: StorageProviding {
) )
} }
// MARK: - Internal Sync Handling
/// Internal method to update storage from received sync data.
/// This is called by SyncHelper when the paired device sends new context.
func updateFromSync(keyName: String, data: Data) async throws {
// Find the registered entry for this key
guard let entry = registeredEntries.first(where: { $0.descriptor.name == keyName }) else {
Logger.debug("Received sync data for unregistered or uncatalogued key: \(keyName)")
return
}
// The data received is already 'secured' (encrypted if necessary) by the sender.
// We can store it directly in our local domain.
try await store(data, for: entry)
Logger.info("Successfully updated local storage from sync for key: \(keyName)")
}
// MARK: - Resolution Helpers // MARK: - Resolution Helpers
private func resolveService(_ service: String?) throws -> String { private func resolveService(_ service: String?) throws -> String {