diff --git a/NucleicRemote/NucleicRemote/LiveActivityManager.swift b/NucleicRemote/NucleicRemote/LiveActivityManager.swift index e34e18b..14b2c9b 100644 --- a/NucleicRemote/NucleicRemote/LiveActivityManager.swift +++ b/NucleicRemote/NucleicRemote/LiveActivityManager.swift @@ -189,6 +189,41 @@ final class LiveActivityManager { enqueue(state) } + /// Start the process-lived observers that make push-to-start work: the device's push-to-start + /// token (forwarded to the Macs so they can create the glance over APNs) and adoption of any + /// Activity a Mac push-started while the app was closed. Idempotent — safe to call on every + /// bridge setup; the guards keep a single observer each. + func beginPushToStartObservation() { + guard ActivityAuthorizationInfo().areActivitiesEnabled else { return } + if pushToStartObservation == nil { + pushToStartObservation = Task { [weak self] in + for await data in Activity.pushToStartTokenUpdates { + let hex = data.map { String(format: "%02x", $0) }.joined() + self?.onPushToStartToken?(hex) + } + } + } + if activityAdoptionObservation == nil { + activityAdoptionObservation = Task { [weak self] in + for await activity in Activity.activityUpdates { + self?.adopt(activity) + } + } + } + } + + /// Adopt an Activity we didn't create locally — almost always one a Mac push-started while the + /// app was closed. Taking ownership wires up its update-token stream (`observePushToken`) so the + /// Macs can keep the glance fresh the normal way, and collapses any strays to one. If we already + /// track an Activity, leave it: the local `Activity.request` path and `endStrays` already keep a + /// single glance, and re-adopting would just churn the token observation. + private func adopt(_ activity: Activity) { + guard self.activity == nil else { return } + self.activity = activity + observePushToken(activity) + endStrays(keeping: activity.id) + } + /// Forward the activity's APNS update token (and its rotations) to `RemoteStore`. private func observePushToken(_ activity: Activity) { tokenObservation?.cancel()