nvrsion: Add: Chat: Chat View Refinement to modernize session chat interface by removing vertical space for selectors, Fix: Chat: Remove Face ID Permission Text, Refactor: Chat: Live Activity Content Density to open app directly into waiting sessions when tapped, Refactor: Chat: Live Activity Content Density to refresh live activity info significantly faster, Fix: Chat: Live Activity Content Density to refresh live activity info significantly faster, Fix: Chat: Live Activity Content Density to refresh live activity info significantly faster, Fix: Chat: Network Type Transition Optimization to reduce delay during network type switches, Feature Enhancement Planning: All devices in a mesh group should see and be aware of each other; “pair” reframed into “join”; scanning, Fix: Chat: Session Transcript Sync to show only current frame’s transcript when opening a session on another Mac, Build: Push-update path to stay fresh while locked.
Nucleic-Promote: 1 Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -28,6 +28,14 @@ final class LiveActivityManager {
|
||||
private var pendingState: NucleicSessionAttributes.ContentState?
|
||||
private var updateTask: Task<Void, Never>?
|
||||
|
||||
/// Set by `RemoteStore` to ship the activity's APNS push token to the paired Macs (and to tell
|
||||
/// them it ended). The Macs use the token to keep this glance fresh over APNs while the phone
|
||||
/// is backgrounded and its sync socket is suspended (UX_IOS §5.3).
|
||||
var onPushToken: ((_ token: String, _ activityID: String) -> Void)?
|
||||
var onActivityEnded: ((_ activityID: String) -> Void)?
|
||||
/// Streams the activity's per-activity APNS update token (it can rotate); cancelled on end.
|
||||
private var tokenObservation: Task<Void, Never>?
|
||||
|
||||
/// Reconcile the Activity with the current session set.
|
||||
func sync(hostName: String, sessions: [WireSessionSummary]) {
|
||||
guard ActivityAuthorizationInfo().areActivitiesEnabled else { return }
|
||||
@@ -82,17 +90,34 @@ final class LiveActivityManager {
|
||||
// recovered one still needs the fresh state, so fall through to the update pipeline.
|
||||
if let existing = Activity<NucleicSessionAttributes>.activities.first {
|
||||
activity = existing
|
||||
observePushToken(existing)
|
||||
enqueue(state)
|
||||
} else {
|
||||
activity = try? Activity.request(
|
||||
// `pushType: .token` opts the activity into APNs updates — the Macs push new
|
||||
// content-state to the token so the glance stays fresh while the phone is locked.
|
||||
let started = try? Activity.request(
|
||||
attributes: NucleicSessionAttributes(hostName: hostName),
|
||||
content: ActivityContent(state: state, staleDate: nil))
|
||||
content: ActivityContent(state: state, staleDate: nil),
|
||||
pushType: .token)
|
||||
activity = started
|
||||
if let started { observePushToken(started) }
|
||||
}
|
||||
return
|
||||
}
|
||||
enqueue(state)
|
||||
}
|
||||
|
||||
/// Forward the activity's APNS update token (and its rotations) to `RemoteStore`.
|
||||
private func observePushToken(_ activity: Activity<NucleicSessionAttributes>) {
|
||||
tokenObservation?.cancel()
|
||||
tokenObservation = Task { [weak self] in
|
||||
for await tokenData in activity.pushTokenUpdates {
|
||||
let hex = tokenData.map { String(format: "%02x", $0) }.joined()
|
||||
self?.onPushToken?(hex, activity.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Hand the newest state to the serial drainer (starting it if idle).
|
||||
private func enqueue(_ state: NucleicSessionAttributes.ContentState) {
|
||||
pendingState = state
|
||||
@@ -111,10 +136,13 @@ final class LiveActivityManager {
|
||||
func end() {
|
||||
updateTask?.cancel()
|
||||
updateTask = nil
|
||||
tokenObservation?.cancel()
|
||||
tokenObservation = nil
|
||||
pendingState = nil
|
||||
lastState = nil
|
||||
guard let activity else { return }
|
||||
self.activity = nil
|
||||
onActivityEnded?(activity.id) // let the Macs stop pushing to this token
|
||||
Task {
|
||||
await activity.end(
|
||||
ActivityContent(state: activity.content.state, staleDate: nil),
|
||||
|
||||
Reference in New Issue
Block a user