nvrsion: Add: Increase sidebar width in Settings panel by ~30% in Sources/NucleicApp/SettingsView.swift; fix iOS app network reconnection delay on app close; update iOS Live Activity Updates to reduce unnecessary push notifications in Sync, Protocol, and Remote modules; adjust iOS notifications to recall “A session is waiting for your approval” push when approval is received on another device; adjust iOS Live Activity Updates to send updates only on transcript changes in Sources/NucleicCore/Sync/SyncHost.swift, Sources/NucleicProtocol/Sync/LiveActivity.swift, ios/NucleicRemote/NucleicRemote/LiveActivityManager.swift, and Tests/NucleicProtocolTests/LiveActivitySnapshotTests.swift.

Nucleic-Promote: 1
Co-authored-by: Nucleic <[email protected]>
This commit is contained in:
2026-07-06 12:59:11 -07:00
co-authored by Nucleic
parent 70842a2cef
commit 69efadb2d6
9 changed files with 277 additions and 12 deletions
@@ -20,6 +20,12 @@ final class NotificationRouter: NSObject {
/// The store notifications act on; set once at app start.
weak var store: RemoteStore?
/// The delivered identifier of the remote wake tickle ("A session is waiting for your
/// approval"). A remote notification's identifier equals its `apns-collapse-id`, so this must
/// match the relay's `APPROVAL_COLLAPSE_ID` (cloud/nucleic-edge/src/apns.ts) for the recall to
/// target the right notification.
static let approvalTickleIdentifier = "approval-pending"
// Category / action identifiers (also referenced from the notification service side).
static let approvalCategory = "NUCLEIC_APPROVAL"
static let approvalActionableCategory = "NUCLEIC_APPROVAL_ACTIONABLE"
@@ -102,6 +108,23 @@ final class NotificationRouter: NSObject {
center.removePendingNotificationRequests(withIdentifiers: [identifier])
}
/// Recall the shared "waiting for your approval" attention notification once nothing is pending
/// anywhere. This is the remote wake tickle (delivered under `approvalTickleIdentifier`) that a
/// prior push left on the lock screen — the counterpart to the per-approval `withdrawApproval`.
/// Arrives two ways: the relay's silent `clear` push (phone was away), or the store's own
/// reconcile when a live socket sees the last approval resolve. Also sweeps any per-approval
/// locals a live socket posted but hasn't individually withdrawn, so the lock screen ends clean.
func withdrawApprovalAttention() {
let center = UNUserNotificationCenter.current()
center.removeDeliveredNotifications(withIdentifiers: [Self.approvalTickleIdentifier])
center.removePendingNotificationRequests(withIdentifiers: [Self.approvalTickleIdentifier])
center.getDeliveredNotifications { delivered in
let stale = delivered.map(\.request.identifier).filter { $0.hasPrefix("approval-") }
guard !stale.isEmpty else { return }
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: stale)
}
}
/// Keep the app-icon badge equal to the NEEDS YOU count (UX_IOS §8).
func updateBadge(_ count: Int) {
UNUserNotificationCenter.current().setBadgeCount(count)