Skip to content

feat: add ParsePush notifications #371

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

Merged
merged 36 commits into from
Jun 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6d7aeab
doc nits
cbaker6 May 30, 2022
14b64f0
remove force unwrap
cbaker6 May 30, 2022
5796ba2
make query codable
cbaker6 May 31, 2022
54aeb2c
make QueryConstraint Codable
cbaker6 Jun 1, 2022
df5daf1
make QueryWhere and QueryConstraint decodable
cbaker6 Jun 5, 2022
aa7f12b
improve ParsePushStatus
cbaker6 Jun 5, 2022
971b170
Add ParsePush
cbaker6 Jun 5, 2022
957ba87
fix test
cbaker6 Jun 5, 2022
8d86982
Improve push payload
cbaker6 Jun 5, 2022
6eeddac
Add channels to push
cbaker6 Jun 5, 2022
e0c4ce1
use query directly.
cbaker6 Jun 5, 2022
b74a502
nits
cbaker6 Jun 5, 2022
abda0d0
Update playground
cbaker6 Jun 5, 2022
9aa3427
fix sending push status
cbaker6 Jun 5, 2022
f687bc6
still a bug decoding ParsePushStatus
cbaker6 Jun 5, 2022
3348756
decode around server encoding bugs
cbaker6 Jun 8, 2022
79c46f2
add ParsePushApplePayloadFCM
cbaker6 Jun 9, 2022
bf5889b
refactor to ParsePushPayloadAny
cbaker6 Jun 9, 2022
5964da2
Fix Query.Order decoder
cbaker6 Jun 9, 2022
39c72f5
update spi file
cbaker6 Jun 9, 2022
b20063d
add new FCM
cbaker6 Jun 11, 2022
cbd7452
add complete FCM legacy support
cbaker6 Jun 11, 2022
8c3961e
doc nits
cbaker6 Jun 11, 2022
fc556c2
add changelog
cbaker6 Jun 11, 2022
063c309
initial tests
cbaker6 Jun 11, 2022
9d070cc
willSet not working
cbaker6 Jun 11, 2022
e06c06a
cover PushStatus
cbaker6 Jun 11, 2022
6ba9857
remove old tests
cbaker6 Jun 11, 2022
55e6a12
additions
cbaker6 Jun 12, 2022
f6d65de
improve signature of ParsePushStatus
cbaker6 Jun 12, 2022
1dd9abe
more PushStatus coverage
cbaker6 Jun 12, 2022
23fb166
add more tests
cbaker6 Jun 12, 2022
6b115a5
add missing files
cbaker6 Jun 12, 2022
b086b04
coverage
cbaker6 Jun 12, 2022
f0469e0
more coverage
cbaker6 Jun 13, 2022
dcfe0bf
nits
cbaker6 Jun 13, 2022
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
2 changes: 1 addition & 1 deletion .spi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ builder:
configs:
- platform: ios
scheme: "ParseSwift (iOS)"
documentation_targets: ["ParseSwift (iOS)"]
- platform: macos-xcodebuild
scheme: "ParseSwift (macOS)"
documentation_targets: ["ParseSwift (iOS)", "ParseSwift (macOS)", "ParseSwift (tvOS)", "ParseSwift (watchOS)"]
- platform: macos-xcodebuild-arm
scheme: "ParseSwift (macOS)"
- platform: tvos
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
* _Contributing to this repo? Add info about your change here to be included in the next release_

__New features__
- Add the ability to send APN and FCM push notifications. Also adds the ability to query _PushStatus ([#371](https://github.com/parse-community/Parse-Swift/pull/371)), thanks to [Corey Baker](https://github.com/cbaker6).
- Add ParseSchema, ParseCLP, and ParseFieldOptions. Should only be used when using the Swift SDK on a secured server ([#370](https://github.com/parse-community/Parse-Swift/pull/370)), thanks to [Corey Baker](https://github.com/cbaker6).

### 4.5.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -251,4 +251,5 @@ gameScoreSchema.purge { result in
}
}

PlaygroundPage.current.finishExecution()
//: [Next](@next)
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
//: [Previous](@previous)

import PlaygroundSupport
import Foundation
import ParseSwift

PlaygroundPage.current.needsIndefiniteExecution = true
initializeParse()

struct Installation: ParseInstallation {
//: These are required by `ParseObject`.
var objectId: String?
var createdAt: Date?
var updatedAt: Date?
var ACL: ParseACL?
var originalData: Data?

//: These are required by `ParseInstallation`.
var installationId: String?
var deviceType: String?
var deviceToken: String?
var badge: Int?
var timeZone: String?
var channels: [String]?
var appName: String?
var appIdentifier: String?
var appVersion: String?
var parseVersion: String?
var localeIdentifier: String?

//: Your custom keys
var customKey: String?

//: Implement your own version of merge
func merge(with object: Self) throws -> Self {
var updated = try mergeParse(with: object)
if updated.shouldRestoreKey(\.customKey,
original: object) {
updated.customKey = object.customKey
}
return updated
}
}

/**
We will begin by creating the payload information we want to
send in the push notification.
*/
let helloAlert = ParsePushAppleAlert(body: "Hello from ParseSwift!")
let applePayload = ParsePushPayloadApple(alert: helloAlert)
.setBadge(1)

/*:
We now crate a query where the `objectId`
is not null or undefined.
*/
let installationQuery = Installation.query(isNotNull(key: "objectId"))

//: Now create a new push notification using the payload and query.
let push = ParsePush(payload: applePayload, query: installationQuery)

//: Creating this property to use later in the playground.
var pushStatusId = ""

//: You can send the push notification whenever you are ready.
push.send { result in
switch result {
case .success(let statusId):
print("The push was created with id: \"\(statusId)\"")
//: Update the stored property with the lastest status id.
pushStatusId = statusId
case .failure(let error):
print("Couldn't create push: \(error)")
}
}

//: You can fetch the status of notificaiton if you know it's id.
push.fetchStatus(pushStatusId) { result in
switch result {
case .success(let pushStatus):
print("The push status is: \"\(pushStatus)\"")
case .failure(let error):
print("Couldn't fetch push status: \(error)")
}
}

/*:
Lets create another Push, this time by incrementing the badge
and using channels instead of a query.
*/
let helloAgainAlert = ParsePushAppleAlert(body: "Hello from ParseSwift again!")
let applePayload2 = ParsePushPayloadApple(alert: helloAgainAlert)
.incrementBadge()

var push2 = ParsePush(payload: applePayload2)
//: Set all channels the notificatioin should be published to.
push2.channels = Set(["newDevices"])

//: You can send the push notification whenever you are ready.
push2.send { result in
switch result {
case .success(let statusId):
print("The push was created with id: \"\(statusId)\"")
//: Update the stored property with the lastest status id.
pushStatusId = statusId
case .failure(let error):
print("Couldn't create push: \(error)")
}
}

/*:
Similar to before, you can fetch the status of notificaiton
if you know the id.
*/
push2.fetchStatus(pushStatusId) { result in
switch result {
case .success(let pushStatus):
print("The push status is: \"\(pushStatus)\"")
case .failure(let error):
print("Couldn't fetch push status: \(error)")
}
}

/*:
You can also send push notifications using Firebase Cloud Messanger.
*/
let helloNotification = ParsePushFirebaseNotification(body: "Hello from ParseSwift using FCM!")
let firebasePayload = ParsePushPayloadFirebase(notification: helloNotification)

let push3 = ParsePush(payload: firebasePayload, query: installationQuery)

//: You can send the push notification whenever you are ready.
push3.send { result in
switch result {
case .success(let statusId):
print("The Firebase push was created with id: \"\(statusId)\"")
//: Update the stored property with the lastest status id.
pushStatusId = statusId
case .failure(let error):
print("Couldn't create push: \(error)")
}
}

/*:
Similar to before, you can fetch the status of notificaiton
if you know the id.
*/
push3.fetchStatus(pushStatusId) { result in
switch result {
case .success(let pushStatus):
print("The Firebase push status is: \"\(pushStatus)\"")
case .failure(let error):
print("Couldn't fetch push status: \(error)")
}
}

/*:
If you have a mixed push environment and are querying
multiple ParsePushStatus's you will can use the any
payload, `ParsePushPayloadAny`.
*/
let query = ParsePushStatus<ParsePushPayloadAny>
.query(isNotNull(key: "objectId"))

/*:
Be sure to add the `.userMasterKey option when doing
anything with `ParsePushStatus` directly.
*/
query.findAll(options: [.useMasterKey]) { result in
switch result {
case .success(let pushStatus):
print("All matching statuses: \"\(pushStatus)\"")
case .failure(let error):
print("Couldn't perform query: \(error)")
}
}

PlaygroundPage.current.finishExecution()
//: [Next](@next)
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,14 @@ currentInstallation?.save { results in
}
}

/*: Update your `ParseInstallation` `customKey` value.
/*: Update your `ParseInstallation` `customKey` and `channels` values.
Performs work on background queue and returns to designated on
designated callbackQueue. If no callbackQueue is specified it
returns to main queue.
*/
var installationToUpdate = Installation.current?.mergeable
installationToUpdate?.customKey = "myCustomInstallationKey2"
installationToUpdate?.channels = ["newDevices"]
installationToUpdate?.save { results in

switch results {
Expand Down
2 changes: 2 additions & 0 deletions ParseSwift.playground/contents.xcplayground
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,7 @@
<page name='17 - SwiftUI - Finding Objects'/>
<page name='18 - SwiftUI - Finding Objects With Custom ViewModel'/>
<page name='19 - SwiftUI - LiveQuery'/>
<page name='20 - Schema'/>
<page name='21 - Push Notifications'/>
</pages>
</playground>
Loading