| 1 | import Foundation |
| 2 | |
| 3 | #if os(iOS) |
| 4 | import UIKit |
| 5 | #else |
| 6 | import AppKit |
| 7 | #endif |
| 8 | |
| 9 | /// Registering this device with Apple, and then with Calls, so that a |
| 10 | /// knock can reach it when the app is closed. |
| 11 | /// |
| 12 | /// The local half — KnockWatch — only reaches an app that is running. |
| 13 | /// This is the other half, and it is the only one that can help the |
| 14 | /// person whose Mac is asleep or whose phone is in a pocket with Calls |
| 15 | /// not open. |
| 16 | /// |
| 17 | /// Everything here is best effort and nothing is ever shown to anyone. A |
| 18 | /// device that could not register is a device that will not be told |
| 19 | /// about a knock, which is exactly where every device was before this |
| 20 | /// existed. It is never a reason to fail a join, and never a sheet. |
| 21 | @MainActor public enum RemoteKnocks { |
| 22 | /// The platform name the server stores alongside the token. The two |
| 23 | /// apps have different bundle identifiers and therefore different APNs |
| 24 | /// topics, so a token is useless without it. |
| 25 | public static var platform: String { |
| 26 | #if os(iOS) |
| 27 | return "ios" |
| 28 | #else |
| 29 | return "macos" |
| 30 | #endif |
| 31 | } |
| 32 | |
| 33 | /// Asks Apple for a device token. The answer arrives at the app |
| 34 | /// delegate, asynchronously and possibly never — without the push |
| 35 | /// entitlement, or on a build Apple will not issue one for, the |
| 36 | /// failure callback is what comes back instead. |
| 37 | public static func register() { |
| 38 | #if os(iOS) |
| 39 | UIApplication.shared.registerForRemoteNotifications() |
| 40 | #else |
| 41 | NSApplication.shared.registerForRemoteNotifications() |
| 42 | #endif |
| 43 | } |
| 44 | |
| 45 | /// Apple's token is opaque bytes; the server stores it as lower-case |
| 46 | /// hex, which is the form every APNs provider uses and the form the |
| 47 | /// registration endpoint validates. |
| 48 | public static func hex(_ token: Data) -> String { |
| 49 | token.map { String(format: "%02x", $0) }.joined() |
| 50 | } |
| 51 | } |
| 52 | |