Live Activity Launch Consistency

Nucleic-Session: 9D2EE9AB-2E44-485B-A196-54D250F9D89B
Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
2026-07-06 20:05:21 -07:00
co-authored by Nucleic
parent 3bbba42895
commit 81a11261c6
@@ -1584,6 +1584,32 @@ final class RemoteStore: ObservableObject {
}
}
/// Tell every capable, live host the current foreground state so it can pick the Live Activity
/// path: defer to the phone's own creation while foreground, or push-to-start the glance while
/// backgrounded (UX_IOS §5.3). De-duped per host against the value already sent; the set is
/// cleared by `setForegroundState` when the value flips, and a host that dropped re-learns it when
/// it returns (via the `didUpdate` re-sync). Gated on the dedicated capability bit — an older host
/// (even one advertising push-to-start) throws on the unknown `setForeground` tag.
private func syncForegroundState() {
foregroundSentTo = foregroundSentTo.filter { connections[$0]?.connectivity.isLive == true }
for (id, conn) in connections {
guard conn.connectivity.isLive, conn.capabilities.canReceiveForegroundState,
!foregroundSentTo.contains(id) else { continue }
conn.send(.setForeground(isForeground))
foregroundSentTo.insert(id)
}
}
/// Record a foreground/background transition and push it to the hosts. No-op when unchanged so an
/// `inactive`↔`active` flutter (or a repeat call) doesn't re-notify; on a real flip it clears the
/// per-host dedup so `syncForegroundState` re-sends to everyone.
private func setForegroundState(_ foreground: Bool) {
guard isForeground != foreground else { return }
isForeground = foreground
foregroundSentTo.removeAll()
syncForegroundState()
}
// MARK: - Demo simulator (offline, interactive)
//
// In demo mode there's no host, so writes can't go over the wire. Instead they mutate the