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
+4
View File
@@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SybilAPNSEnvironment</key>
<string>$(SYBIL_APNS_ENVIRONMENT)</string>
<key>UIBackgroundModes</key>
<array><string>remote-notification</string></array>
<!-- macOS-only: keep the global Quick Question shortcut available with no windows. -->
<key>NSSupportsAutomaticTermination</key>
<false/>
+32 -1
View File
@@ -1,6 +1,7 @@
import Sybil
import SwiftUI
import UIKit
import UserNotifications
@main
struct SybilApp: App
@@ -18,11 +19,13 @@ struct SybilApp: App
}
@MainActor
final class SybilAppDelegate: NSObject, UIApplicationDelegate {
final class SybilAppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil
) -> Bool {
UNUserNotificationCenter.current().delegate = self
SybilPushNotifications.launchFixtureIfRequested()
SybilHomeScreenQuickActionHandler.configureQuickActions()
#if targetEnvironment(macCatalyst)
SybilMacQuickQuestionController.shared.start()
@@ -30,6 +33,31 @@ final class SybilAppDelegate: NSObject, UIApplicationDelegate {
return true
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
SybilPushNotifications.didRegister(deviceToken: deviceToken)
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
SybilPushNotifications.didFailToRegister()
}
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
SybilPushNotifications.receiveBackground(userInfo: userInfo) { result in completionHandler(result) }
}
nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification) async -> UNNotificationPresentationOptions {
let event = SybilPushNotifications.Event(userInfo: notification.request.content.userInfo)
return await SybilPushNotifications.presentationOptions(event: event)
}
nonisolated func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async {
if response.actionIdentifier == UNNotificationDefaultActionIdentifier {
let event = SybilPushNotifications.Event(userInfo: response.notification.request.content.userInfo)
await SybilPushNotifications.didRespond(event: event, identifier: response.notification.request.identifier)
}
}
#if targetEnvironment(macCatalyst)
func applicationWillTerminate(_ application: UIApplication) {
SybilMacQuickQuestionController.shared.stop()
@@ -73,6 +101,9 @@ final class SybilSceneDelegate: NSObject, UIWindowSceneDelegate {
if let shortcutItem = connectionOptions.shortcutItem {
_ = SybilHomeScreenQuickActionHandler.handle(shortcutItem)
}
if let response = connectionOptions.notificationResponse, response.actionIdentifier == UNNotificationDefaultActionIdentifier {
SybilPushNotifications.didRespond(userInfo: response.notification.request.content.userInfo, identifier: response.notification.request.identifier)
}
}
#if targetEnvironment(macCatalyst)
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>$(SYBIL_APNS_ENVIRONMENT)</string>
</dict>
</plist>
+12
View File
@@ -5,6 +5,12 @@ targets:
- iOS
- macCatalyst
deploymentTarget: "18.0"
attributes:
SystemCapabilities:
com.apple.Push:
enabled: 1
com.apple.BackgroundModes:
enabled: 1
sources:
- Sources
- Resources
@@ -25,6 +31,9 @@ targets:
PRODUCT_MODULE_NAME: SybilApp
DEVELOPMENT_TEAM: DQQH5H6GBD
CODE_SIGN_STYLE: Automatic
"CODE_SIGN_ENTITLEMENTS[sdk=iphoneos*]": Apps/Sybil/Sybil.entitlements
"CODE_SIGN_ENTITLEMENTS[sdk=iphonesimulator*]": Apps/Sybil/Sybil.entitlements
INFOPLIST_KEY_SybilAPNSEnvironment: "$(SYBIL_APNS_ENVIRONMENT)"
SWIFT_VERSION: 6.0
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD: NO
TARGETED_DEVICE_FAMILY: "1,2,6"
@@ -41,7 +50,10 @@ targets:
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone: UIInterfaceOrientationPortrait
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad: UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight
configs:
Debug:
SYBIL_APNS_ENVIRONMENT: development
Release:
SYBIL_APNS_ENVIRONMENT: production
CODE_SIGN_STYLE: Manual
CODE_SIGN_IDENTITY: Apple Distribution
"CODE_SIGN_IDENTITY[sdk=iphoneos*]": Apple Distribution