crossmate

A collaborative crossword app for iOS
Log | Files | Refs | LICENSE

commit 740860632cd6af9d83571899ee8f6774b84f8741
parent b2b5b6719e991d5532878d4936e55960b82c6d39
Author: Michael Camilleri <[email protected]>
Date:   Fri,  8 May 2026 20:37:20 +0900

Instrument notification code path

Diffstat:
MCrossmate/CrossmateApp.swift | 26++++++++++++++++++++++++++
MCrossmate/Services/AppServices.swift | 3+++
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) }