Live Activity Session Retention
Nucleic-Session: F2CCC9F2-A7BA-4A94-ADAA-5414F168045E Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
@@ -130,17 +130,22 @@ final class LiveActivityManager {
|
|||||||
push(state, hostName: hostName)
|
push(state, hostName: hostName)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Nothing is running or waiting. If the glance was showing active work, flash a brief "Done"
|
/// Nothing is running or waiting. If the glance was showing active work, replace it with a "Done"
|
||||||
/// summary of the just-completed sessions and then dismiss (UX_IOS §5.3 — a run should read as
|
/// summary of the just-completed sessions and hold it on the lock screen until the user opens the
|
||||||
/// *finished*, not just vanish). If nothing was on screen, there's nothing to close.
|
/// app and sees them (UX_IOS §5.3 — a finished run should read as *done* and stay put, not vanish
|
||||||
|
/// after a few seconds unseen). Foreground, the user is already on the in-app session list, so
|
||||||
|
/// there's nothing to hold — dismiss. If nothing was on screen, there's nothing to close.
|
||||||
private func finishWithDoneGlance(hostName: String, live: [WireSessionSummary]) {
|
private func finishWithDoneGlance(hostName: String, live: [WireSessionSummary]) {
|
||||||
// Already flashing "Done" and scheduled to dismiss — let that run rather than restart it.
|
// Already holding the "Done" summary — leave it up until the app foregrounds, don't rebuild it.
|
||||||
guard dismissTask == nil else { return }
|
guard !showingDoneGlance else { return }
|
||||||
// Nothing tracked on screen: only reach into ActivityKit if an untracked orphan is lingering.
|
// Nothing tracked on screen: only reach into ActivityKit if an untracked orphan is lingering.
|
||||||
guard activity != nil else {
|
guard activity != nil else {
|
||||||
if !Activity<NucleicSessionAttributes>.activities.isEmpty { end() }
|
if !Activity<NucleicSessionAttributes>.activities.isEmpty { end() }
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
// Foreground: the user is already looking at the in-app session list (the glance isn't even
|
||||||
|
// visible over the app), so there's nothing to hold for later — just dismiss.
|
||||||
|
guard !foreground else { end(); return }
|
||||||
// The sessions that just finished — completed conversational turns and finished runs. These
|
// The sessions that just finished — completed conversational turns and finished runs. These
|
||||||
// are exactly the ones the active-work filter above drops, surfaced now as `.done` rows.
|
// are exactly the ones the active-work filter above drops, surfaced now as `.done` rows.
|
||||||
let done = live
|
let done = live
|
||||||
@@ -151,18 +156,16 @@ final class LiveActivityManager {
|
|||||||
.sorted(by: StatusStyle.attentionThenRecency)
|
.sorted(by: StatusStyle.attentionThenRecency)
|
||||||
.prefix(Self.maxLines)
|
.prefix(Self.maxLines)
|
||||||
.map(Self.line(for:))
|
.map(Self.line(for:))
|
||||||
// Nothing to celebrate (e.g. the work was discarded/deleted) → just dismiss.
|
// Nothing to show (e.g. the work was discarded/deleted) → just dismiss.
|
||||||
guard !done.isEmpty else { end(); return }
|
guard !done.isEmpty else { end(); return }
|
||||||
|
|
||||||
let state = NucleicSessionAttributes.ContentState(
|
let state = NucleicSessionAttributes.ContentState(
|
||||||
runningCount: 0, needsYouCount: 0, approvalCount: 0,
|
runningCount: 0, needsYouCount: 0, approvalCount: 0,
|
||||||
filesChanged: 0, linesAdded: 0, linesRemoved: 0, lines: Array(done))
|
filesChanged: 0, linesAdded: 0, linesRemoved: 0, lines: Array(done))
|
||||||
push(state, hostName: hostName)
|
push(state, hostName: hostName)
|
||||||
dismissTask = Task { [weak self] in
|
// Hold it: the Activity stays alive showing "Done". No scheduled dismissal — `foreground`
|
||||||
try? await Task.sleep(for: Self.doneLinger)
|
// flipping true (the app coming forward) is what ends it.
|
||||||
guard !Task.isCancelled else { return }
|
showingDoneGlance = true
|
||||||
self?.end()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Apply `state` to the Activity — coalesced through one serial task so the newest state always
|
/// Apply `state` to the Activity — coalesced through one serial task so the newest state always
|
||||||
|
|||||||
Reference in New Issue
Block a user