Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add content-available option to alert #209

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 20 additions & 2 deletions Sources/APNSCore/Alert/APNSAlertNotification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,18 @@ public struct APNSAlertNotification<Payload: Encodable & Sendable>: APNSMessage,
}
}

/// The content available flag, when set to `1`, the notification will wake up your app in the background and trigger `didReceiveRemoteNotification`.
///
/// The highest score gets featured in the notification summary
public var contentAvailable: Int? {
get {
self.aps.contentAvailable
}
set {
self.aps.contentAvailable = newValue
}
}

/// A canonical UUID that identifies the notification. If there is an error sending the notification,
/// APNs uses this value to identify the notification to your server. The canonical form is 32 lowercase hexadecimal digits,
/// displayed in five groups separated by hyphens in the form 8-4-4-4-12. An example UUID is as follows:
Expand Down Expand Up @@ -176,6 +188,7 @@ public struct APNSAlertNotification<Payload: Encodable & Sendable>: APNSMessage,
/// - targetContentID: The identifier of the window brought forward.
/// - interruptionLevel: A string that indicates the importance and delivery timing of a notification.
/// - relevanceScore: The relevance score, a number between `0` and `1`, that the system uses to sort the notifications from your app.
/// - contentAvailable: The content available flag, when set to `1`, the notification will wake up your app in the background and trigger `didReceiveRemoteNotification`.
/// - apnsID: A canonical UUID that identifies the notification.
public init(
alert: APNSAlertNotificationContent,
Expand All @@ -191,6 +204,7 @@ public struct APNSAlertNotification<Payload: Encodable & Sendable>: APNSMessage,
targetContentID: String? = nil,
interruptionLevel: APNSAlertNotificationInterruptionLevel? = nil,
relevanceScore: Double? = nil,
contentAvailable: Int? = nil,
apnsID: UUID? = nil
) {
self.aps = APNSAlertNotificationAPSStorage(
Expand All @@ -202,7 +216,8 @@ public struct APNSAlertNotification<Payload: Encodable & Sendable>: APNSMessage,
mutableContent: mutableContent,
targetContentID: targetContentID,
interruptionLevel: interruptionLevel,
relevanceScore: relevanceScore
relevanceScore: relevanceScore,
contentAvailable: contentAvailable
)
self.apnsID = apnsID
self.expiration = expiration
Expand Down Expand Up @@ -239,6 +254,7 @@ extension APNSAlertNotification where Payload == EmptyPayload {
/// - targetContentID: The identifier of the window brought forward.
/// - interruptionLevel: A string that indicates the importance and delivery timing of a notification.
/// - relevanceScore: The relevance score, a number between `0` and `1`, that the system uses to sort the notifications from your app.
/// - contentAvailable: The content available flag, when set to `1`, the notification will wake up your app in the background and trigger `didReceiveRemoteNotification`.
/// - apnsID: A canonical UUID that identifies the notification.
public init(
alert: APNSAlertNotificationContent,
Expand All @@ -253,6 +269,7 @@ extension APNSAlertNotification where Payload == EmptyPayload {
targetContentID: String? = nil,
interruptionLevel: APNSAlertNotificationInterruptionLevel? = nil,
relevanceScore: Double? = nil,
contentAvailable: Int? = nil,
apnsID: UUID? = nil
) {
self.aps = APNSAlertNotificationAPSStorage(
Expand All @@ -264,7 +281,8 @@ extension APNSAlertNotification where Payload == EmptyPayload {
mutableContent: mutableContent,
targetContentID: targetContentID,
interruptionLevel: interruptionLevel,
relevanceScore: relevanceScore
relevanceScore: relevanceScore,
contentAvailable: contentAvailable
)
self.apnsID = apnsID
self.expiration = expiration
Expand Down
7 changes: 6 additions & 1 deletion Sources/APNSCore/Alert/APNSAlertNotificationAPSStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ struct APNSAlertNotificationAPSStorage: Encodable, Sendable {
case targetContentID = "target-content-id"
case interruptionLevel = "interruption-level"
case relevanceScore = "relevance-score"
case contentAvailable = "content-available"
}

var alert: APNSAlertNotificationContent
Expand All @@ -49,6 +50,8 @@ struct APNSAlertNotificationAPSStorage: Encodable, Sendable {
}
}

var contentAvailable: Int?

init(
alert: APNSAlertNotificationContent,
badge: Int? = nil,
Expand All @@ -58,7 +61,8 @@ struct APNSAlertNotificationAPSStorage: Encodable, Sendable {
mutableContent: Double? = nil,
targetContentID: String? = nil,
interruptionLevel: APNSAlertNotificationInterruptionLevel? = nil,
relevanceScore: Double? = nil
relevanceScore: Double? = nil,
contentAvailable: Int? = nil
) {
if let relevanceScore = relevanceScore {
precondition(relevanceScore >= 0 && relevanceScore <= 1, "The relevance score can only be between 0 and 1")
Expand All @@ -72,5 +76,6 @@ struct APNSAlertNotificationAPSStorage: Encodable, Sendable {
self.targetContentID = targetContentID
self.interruptionLevel = interruptionLevel
self.relevanceScore = relevanceScore
self.contentAvailable = contentAvailable
}
}
6 changes: 4 additions & 2 deletions Tests/APNSTests/Alert/APNSAlertNotificationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,14 @@ final class APNSAlertNotificationTests: XCTestCase {
targetContentID: "targetContentID",
interruptionLevel: .critical,
relevanceScore: 1,
contentAvailable: 1,
apnsID: .init()
)
let encoder = JSONEncoder()
let data = try encoder.encode(notification)

let expectedJSONString = """
{\"payload\":\"payload\",\"aps\":{\"category\":\"category\",\"relevance-score\":1,\"badge\":1,\"target-content-id\":\"targetContentID\",\"sound\":\"default\",\"interruption-level\":\"critical\",\"alert\":{\"body\":\"body\",\"subtitle-loc-key\":\"subtitle-key\",\"title\":\"title\",\"launch-image\":\"launchimage\",\"subtitle-loc-args\":[\"arg1\"]},\"thread-id\":\"threadID\",\"mutable-content\":1}}
{\"payload\":\"payload\",\"aps\":{\"category\":\"category\",\"relevance-score\":1,\"content-available\":1,\"badge\":1,\"target-content-id\":\"targetContentID\",\"sound\":\"default\",\"interruption-level\":\"critical\",\"alert\":{\"body\":\"body\",\"subtitle-loc-key\":\"subtitle-key\",\"title\":\"title\",\"launch-image\":\"launchimage\",\"subtitle-loc-args\":[\"arg1\"]},\"thread-id\":\"threadID\",\"mutable-content\":1}}
"""
let jsonObject1 = try JSONSerialization.jsonObject(with: data) as! NSDictionary
let jsonObject2 = try JSONSerialization.jsonObject(with: expectedJSONString.data(using: .utf8)!) as! NSDictionary
Expand Down Expand Up @@ -125,13 +126,14 @@ final class APNSAlertNotificationTests: XCTestCase {
targetContentID: "targetContentID",
interruptionLevel: .critical,
relevanceScore: 1,
contentAvailable: 1,
apnsID: .init()
)
let encoder = JSONEncoder()
let data = try encoder.encode(notification)

let expectedJSONString = """
{\"payload\":\"payload\",\"aps\":{\"category\":\"category\",\"relevance-score\":1,\"badge\":1,\"target-content-id\":\"targetContentID\",\"sound\":{\"name\":\"file\",\"volume\":1,\"critical\":1},\"interruption-level\":\"critical\",\"alert\":{\"body\":\"body\",\"subtitle-loc-key\":\"subtitle-key\",\"title\":\"title\",\"launch-image\":\"launchimage\",\"subtitle-loc-args\":[\"arg1\"]},\"thread-id\":\"threadID\",\"mutable-content\":1}}
{\"payload\":\"payload\",\"aps\":{\"category\":\"category\",\"relevance-score\":1,\"content-available\":1,\"badge\":1,\"target-content-id\":\"targetContentID\",\"sound\":{\"name\":\"file\",\"volume\":1,\"critical\":1},\"interruption-level\":\"critical\",\"alert\":{\"body\":\"body\",\"subtitle-loc-key\":\"subtitle-key\",\"title\":\"title\",\"launch-image\":\"launchimage\",\"subtitle-loc-args\":[\"arg1\"]},\"thread-id\":\"threadID\",\"mutable-content\":1}}
"""
let jsonObject1 = try JSONSerialization.jsonObject(with: data) as! NSDictionary
let jsonObject2 = try JSONSerialization.jsonObject(with: expectedJSONString.data(using: .utf8)!) as! NSDictionary
Expand Down