diff --git a/NucleicRemote/NucleicRemote/Models/RemoteStore.swift b/NucleicRemote/NucleicRemote/Models/RemoteStore.swift index 6decb92..2cda3d5 100644 --- a/NucleicRemote/NucleicRemote/Models/RemoteStore.swift +++ b/NucleicRemote/NucleicRemote/Models/RemoteStore.swift @@ -76,6 +76,19 @@ final class RemoteStore: ObservableObject { private var openSessionHostID: String? @Published private(set) var openEvents: [AgentEvent] = [] @Published private(set) var openApprovals: [ApprovalRequest] = [] + + /// The open session is blocked on an approval whose details haven't arrived yet — the state + /// right after opening from a Live Activity or notification while the channel is still + /// (re)connecting. The summary says `.awaitingApproval`, but `openApprovals` (which is filled + /// from the live snapshot) is empty because there's no live channel yet. Drives a lightweight + /// "loading approval" placeholder so a tap from the lock screen lands on the request-in-progress + /// instead of a blank transcript; it flips off the instant the real card arrives (sub-second, + /// thanks to the fast foreground reconnect). Never shown once live — then the snapshot is truth. + var openApprovalLoading: Bool { + guard !connectivity.isLive, openApprovals.isEmpty, let id = openSessionID, + let summary = sessions.first(where: { $0.sessionID == id }) else { return false } + return summary.status == .awaitingApproval || summary.pendingApprovalCount > 0 + } /// Whether the compact (iPhone) Sessions tab currently has a session detail pushed. Distinct /// from `openSessionID`, which is the *data* subscription and is only torn down on the detail's /// `onDisappear` — and SwiftUI fires that at the *end* of the pop transition, so keying the