commit 740860632cd6af9d83571899ee8f6774b84f8741
parent b2b5b6719e991d5532878d4936e55960b82c6d39
Author: Michael Camilleri <[email protected]>
Date: Fri, 8 May 2026 20:37:20 +0900
Instrument notification code path
Diffstat:
2 files changed, 29 insertions(+), 0 deletions(-)
diff --git a/Crossmate/CrossmateApp.swift b/Crossmate/CrossmateApp.swift
@@ -34,6 +34,12 @@ struct CrossmateApp: App {
final class AppDelegate: NSObject, UIApplicationDelegate, @preconcurrency UNUserNotificationCenterDelegate, @unchecked Sendable {
var onRemoteNotification: ((String) async -> Void)?
+ /// Reports the outcome of `registerForRemoteNotifications`. Surfaced in
+ /// the diagnostics log so a missing APNs token (e.g. an aps-environment
+ /// mismatch between the entitlements and the TestFlight distribution
+ /// channel) is visible rather than silently degrading sync to the
+ /// CKSyncEngine poll cadence.
+ var onAPNsRegistrationResult: ((String) -> Void)?
func application(
_ application: UIApplication,
@@ -44,6 +50,26 @@ final class AppDelegate: NSObject, UIApplicationDelegate, @preconcurrency UNUser
return true
}
+ func application(
+ _ application: UIApplication,
+ didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
+ ) {
+ let hex = deviceToken.map { String(format: "%02x", $0) }.joined()
+ let prefix = hex.prefix(12)
+ onAPNsRegistrationResult?("APNs registered token=\(prefix)… (\(deviceToken.count) bytes)")
+ }
+
+ func application(
+ _ application: UIApplication,
+ didFailToRegisterForRemoteNotificationsWithError error: Error
+ ) {
+ let nsError = error as NSError
+ onAPNsRegistrationResult?(
+ "APNs registration FAILED — domain=\(nsError.domain) code=\(nsError.code) " +
+ "\(nsError.localizedDescription)"
+ )
+ }
+
/// Foreground notification arrival. If the user is currently viewing the
/// puzzle the ping refers to, hide it entirely (`[]`); otherwise show it
/// as a banner with sound. In both cases the dedup map is updated so a
diff --git a/Crossmate/Services/AppServices.swift b/Crossmate/Services/AppServices.swift
@@ -134,6 +134,9 @@ final class AppServices {
appDelegate.onRemoteNotification = { summary in
await self.handleRemoteNotification(summary: summary)
}
+ appDelegate.onAPNsRegistrationResult = { [syncMonitor] message in
+ syncMonitor.note(message)
+ }
CloudShareAcceptanceBroker.shared.onAcceptShare = { metadata in
await self.enqueueShareAcceptance(metadata)
}