Skip to content

Commit d60241f

Browse files
authored
Add semantic safe API for Complication notifications (#150)
# Motivation We want to provide new APIs that are semantically safe when sending Complication notifications to APNs. # Modification The PR adds new types for the Complication notification and a convenience method to send it notifications with the APNSClient. # Result We can now send Complication notifications.
1 parent af59858 commit d60241f

File tree

3 files changed

+174
-0
lines changed

3 files changed

+174
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the APNSwift open source project
4+
//
5+
// Copyright (c) 2022 the APNSwift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of APNSwift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import Logging
16+
import NIOCore
17+
18+
extension APNSClient {
19+
/// Sends a complication notification to APNs.
20+
///
21+
/// - Parameters:
22+
/// - notification: The notification to send.
23+
///
24+
/// - deviceToken: The hexadecimal bytes that identify the user’s device. Your app receives the bytes for this device token
25+
/// when registering for remote notifications.
26+
///
27+
/// - deadline: Point in time by which sending the notification to APNs must complete.
28+
///
29+
/// - logger: The logger to use for sending this notification.
30+
@discardableResult
31+
@inlinable
32+
public func sendComplicationNotification<Payload: Encodable>(
33+
_ notification: APNSComplicationNotification<Payload>,
34+
deviceToken: String,
35+
deadline: NIODeadline,
36+
logger: Logger = _noOpLogger
37+
) async throws -> APNSResponse {
38+
try await self.send(
39+
payload: notification.payload,
40+
deviceToken: deviceToken,
41+
pushType: .complication,
42+
expiration: notification.expiration,
43+
priority: notification.priority,
44+
topic: notification.topic,
45+
deadline: deadline,
46+
logger: logger
47+
)
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the APNSwift open source project
4+
//
5+
// Copyright (c) 2022 the APNSwift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of APNSwift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import struct Foundation.UUID
16+
17+
/// A complication notification.
18+
public struct APNSComplicationNotification<Payload: Encodable> {
19+
/// A canonical UUID that identifies the notification. If there is an error sending the notification,
20+
/// APNs uses this value to identify the notification to your server. The canonical form is 32 lowercase hexadecimal digits,
21+
/// displayed in five groups separated by hyphens in the form 8-4-4-4-12. An example UUID is as follows:
22+
/// `123e4567-e89b-12d3-a456-42665544000`.
23+
///
24+
/// If you omit this, a new UUID is created by APNs and returned in the response.
25+
public var apnsID: UUID?
26+
27+
/// The topic for the notification. In general, the topic is your app’s bundle ID/app ID suffixed with `.complication`.
28+
public var topic: String
29+
30+
/// The date when the notification is no longer valid and can be discarded. If this value is not `none`,
31+
/// APNs stores the notification and tries to deliver it at least once,
32+
/// repeating the attempt as needed if it is unable to deliver the notification the first time.
33+
/// If the value is `immediately`, APNs treats the notification as if it expires immediately
34+
/// and does not store the notification or attempt to redeliver it.
35+
public var expiration: APNSNotificationExpiration
36+
37+
/// The priority of the notification.
38+
public var priority: APNSPriority
39+
40+
/// Your custom payload.
41+
public var payload: Payload
42+
43+
/// Initializes a new ``APNSComplicationNotification``.
44+
///
45+
/// - Parameters:
46+
/// - expiration: The date when the notification is no longer valid and can be discarded.
47+
/// - priority: The priority of the notification.
48+
/// - appID: Your app’s bundle ID/app ID. This will be suffixed with `.complication`.
49+
/// - payload: Your custom payload.
50+
/// - apnsID: A canonical UUID that identifies the notification.
51+
@inlinable
52+
public init(
53+
expiration: APNSNotificationExpiration,
54+
priority: APNSPriority,
55+
appID: String,
56+
payload: Payload,
57+
apnsID: UUID? = nil
58+
) {
59+
self.init(
60+
expiration: expiration,
61+
priority: priority,
62+
topic: appID + ".complication",
63+
payload: payload,
64+
apnsID: apnsID
65+
)
66+
}
67+
68+
/// Initializes a new ``APNSVoIPNotification``.
69+
///
70+
/// - Important: Your dynamic payload will get encoded to the root of the JSON payload that is send to APNs.
71+
/// It is **important** that you do not encode anything with the key `aps`
72+
///
73+
/// - Parameters:
74+
/// - expiration: The date when the notification is no longer valid and can be discarded.
75+
/// - priority: The priority of the notification.
76+
/// - topic: The topic for the notification. In general, the topic is your app’s bundle ID/app ID suffixed with `.complication`.
77+
/// - payload: Your custom payload.
78+
/// - apnsID: A canonical UUID that identifies the notification.
79+
@inlinable
80+
public init(
81+
expiration: APNSNotificationExpiration,
82+
priority: APNSPriority,
83+
topic: String,
84+
payload: Payload,
85+
apnsID: UUID? = nil
86+
) {
87+
self.expiration = expiration
88+
self.priority = priority
89+
self.topic = topic
90+
self.payload = payload
91+
self.apnsID = apnsID
92+
}
93+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// This source file is part of the APNSwift open source project
4+
//
5+
// Copyright (c) 2022 the APNSwift project authors
6+
// Licensed under Apache License v2.0
7+
//
8+
// See LICENSE.txt for license information
9+
// See CONTRIBUTORS.txt for the list of APNSwift project authors
10+
//
11+
// SPDX-License-Identifier: Apache-2.0
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
import APNSwift
16+
import XCTest
17+
18+
final class APNSComplicationNotificationTests: XCTestCase {
19+
func testAppID() {
20+
struct Payload: Encodable {
21+
let foo = "bar"
22+
}
23+
let complicationNotification = APNSComplicationNotification(
24+
expiration: .immediately,
25+
priority: .immediately,
26+
appID: "com.example.app",
27+
payload: Payload()
28+
)
29+
30+
XCTAssertEqual(complicationNotification.topic, "com.example.app.complication")
31+
}
32+
}

0 commit comments

Comments
 (0)