From 0d3894a4282c031ec440d784bf7e3a1d29333341 Mon Sep 17 00:00:00 2001 From: Andrew Blakeslee Moore Date: Mon, 6 Jul 2026 13:44:35 -0700 Subject: [PATCH] Launch Activity Logic Nucleic-Session: EBB24271-3AB2-4CBD-A47A-59FC73500371 Co-authored-by: Nucleic --- .../NucleicRemote/Models/RemoteStore.swift | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/NucleicRemote/NucleicRemote/Models/RemoteStore.swift b/NucleicRemote/NucleicRemote/Models/RemoteStore.swift index 4960e4d..aa0093b 100644 --- a/NucleicRemote/NucleicRemote/Models/RemoteStore.swift +++ b/NucleicRemote/NucleicRemote/Models/RemoteStore.swift @@ -1203,6 +1203,12 @@ final class RemoteStore: ObservableObject { /// Host ids that already have the current token (re-sent to a host that (re)connects, and /// re-sent to everyone when the token rotates). private var liveActivitySentTo: Set = [] + /// This device's push-to-start token (iOS 17.2+), shipped to every capable Mac so it can create + /// the Live Activity over APNs when work starts before the app is opened. Device-scoped, so — + /// unlike `liveActivityReg` — it persists across activities and isn't cleared when one ends. + private var pushToStartToken: String? + /// Host ids that already have the current push-to-start token (mirrors `liveActivitySentTo`). + private var pushToStartSentTo: Set = [] private func setupLiveActivityBridge() { LiveActivityManager.shared.onPushToken = { [weak self] token, activityID in @@ -1211,6 +1217,15 @@ final class RemoteStore: ObservableObject { self.liveActivitySentTo.removeAll() // a fresh token must reach every host again self.syncLiveActivityRegistration() } + LiveActivityManager.shared.onPushToStartToken = { [weak self] token in + guard let self, self.pushToStartToken != token else { return } + self.pushToStartToken = token + self.pushToStartSentTo.removeAll() // a fresh token must reach every host again + self.syncPushToStartRegistration() + } + // Start observing the push-to-start token (and adopting any push-started activity) now — it's + // device-scoped and must be captured even before any Activity exists. + LiveActivityManager.shared.beginPushToStartObservation() LiveActivityManager.shared.onActivityEnded = { [weak self] activityID in guard let self else { return } self.liveActivityReg = nil