feat(agent): add opt-in push notifications

This commit is contained in:
2026-10-14 22:03:21 -07:00
parent 80748f764f
commit a1c0264d36
51 changed files with 4815 additions and 121 deletions
@@ -11,6 +11,7 @@ public struct SplitView: View {
@State private var hasPendingQuickQuestionPresentation = false
@State private var isQuickQuestionPresented = false
@State private var columnVisibility: NavigationSplitViewVisibility = .automatic
@State private var notificationSceneID = UUID()
private var keyboardActions: SybilKeyboardActions? {
guard !viewModel.isCheckingSession, viewModel.isAuthenticated else {
@@ -92,8 +93,14 @@ public struct SplitView: View {
SybilMacQuickQuestionController.shared.attach(viewModel)
#endif
await viewModel.bootstrap()
SybilPushNotifications.foregroundFixtureIfRequested()
viewModel.notifications.setScene(notificationSceneID, active: scenePhase == .active)
routePendingNotification()
presentPendingQuickQuestionIfPossible()
}
.onChange(of: viewModel.notifications.pendingRouteID) { _, _ in routePendingNotification() }
.onChange(of: viewModel.notifications.scope) { _, _ in routePendingNotification() }
.onDisappear { viewModel.notifications.setScene(notificationSceneID, active: false) }
.onReceive(quickActionRouter.$quickQuestionPresentationRequest) { request in
guard request > 0 else {
return
@@ -101,6 +108,7 @@ public struct SplitView: View {
queueQuickQuestionPresentation()
}
.onChange(of: viewModel.isCheckingSession) { _, _ in
routePendingNotification()
presentPendingQuickQuestionIfPossible()
}
.onChange(of: viewModel.isAuthenticated) { _, _ in
@@ -110,11 +118,14 @@ public struct SplitView: View {
viewModel.agent.isModalPresented = presented
}
.onChange(of: scenePhase) { _, nextPhase in
viewModel.notifications.setScene(notificationSceneID, active: nextPhase == .active)
switch nextPhase {
case .background:
shouldRefreshOnForeground = true
viewModel.markAppInactiveForNetwork()
case .active:
SybilPushNotifications.foregroundFixtureIfRequested()
routePendingNotification()
#if targetEnvironment(macCatalyst)
SybilMacQuickQuestionController.shared.attach(viewModel)
#endif
@@ -138,6 +149,13 @@ public struct SplitView: View {
}
}
private func routePendingNotification() {
guard scenePhase == .active, viewModel.consumeAgentNotificationRoute() else { return }
hasPendingQuickQuestionPresentation = false
isQuickQuestionPresented = false
columnVisibility = .detailOnly
}
private func splitNavigationLeadingControl(for size: CGSize) -> SybilWorkspaceNavigationLeadingControl {
return size.width < size.height ? .showSidebar : .hidden
}