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 iOS 15 payload additions #185

Merged
merged 7 commits into from
Sep 22, 2021
Merged

Conversation

neilmorton
Copy link
Contributor

  • Adds interruption-level to payload
    interruption-level options:

    • passive
    • active (default if none is passed to apns)
    • time-sensitive
    • critical (requires Apple entitlement)
  • Adds relevance-score to payload

  • Updates readme re iOS 15 features

- Add interruption-level to payload
 interruption-level options:
    - passive
    - active (default if none is passed to apns)
    - time-sensitive
    - critical (requires Apple entitlement)

- Add relevance-score to payload
relevance-score is a number between 0 and 1
The highest score gets featured in the notification summary.
@neilmorton
Copy link
Contributor Author

neilmorton commented Aug 11, 2021

Hi @sideshow, this PR adds support for new iOS 15 payload features interruption-level & relevance-score. Includes new tests & updated readme. Hope it's useful, thanks.

Copy link

@froodian froodian left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for submitting this! I'm just an interested bystander who'll end up using it ;)

payload/builder.go Outdated Show resolved Hide resolved
Note that at the time of writing [Apple docs](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification#2943360) have a typo, showing `time-senstive` as opposed to `time-sensitive`.

Testing has shown that the correct spelling `time-sensitive` does indeed work.
payload/builder.go Outdated Show resolved Hide resolved
Alphabetically order keys in struct as per @Singwai suggestion.
Comment on lines 329 to 369
// InterruptionLevelPassive sets the aps interruption-level to "passive" on the payload.
// This is to indicate the importance and delivery timing of a notification.
// See: https://developer.apple.com/documentation/usernotifications/unnotificationinterruptionlevel/
//
// {"aps":{"interruption-level":passive}}
func (p *Payload) InterruptionLevelPassive() *Payload {
p.aps().InterruptionLevel = "passive"
return p
}

// InterruptionLevelActive sets the aps interruption-level to "active" on the payload.
// This is to indicate the importance and delivery timing of a notification.
// See: https://developer.apple.com/documentation/usernotifications/unnotificationinterruptionlevel/
//
// {"aps":{"interruption-level":active}}
func (p *Payload) InterruptionLevelActive() *Payload {
p.aps().InterruptionLevel = "active"
return p
}

// InterruptionLevelTimeSensitive sets the aps interruption-level to "time-sensitive" on the payload.
// This is to indicate the importance and delivery timing of a notification.
// See: https://developer.apple.com/documentation/usernotifications/unnotificationinterruptionlevel/
//
// {"aps":{"interruption-level":time-sensitive}}
func (p *Payload) InterruptionLevelTimeSensitive() *Payload {
p.aps().InterruptionLevel = "time-sensitive"
return p
}

// InterruptionLevelCritical sets the aps interruption-level to "critical" on the payload.
// This is to indicate the importance and delivery timing of a notification.
// This interruption level requires an approved entitlement from Apple.
// See: https://developer.apple.com/documentation/usernotifications/unnotificationinterruptionlevel/
//
// {"aps":{"interruption-level":critical}}
func (p *Payload) InterruptionLevelCritical() *Payload {
p.aps().InterruptionLevel = "critical"
return p
}

Copy link
Contributor

@chrishaines chrishaines Sep 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to use these four different functions for setting this value rather than a single setter (i.e. InterruptionLevel) and define a custom string type ala EPushType with the values as defined as constants?

Definitely appreciate the initiative in getting this out.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used the four functions as I was following the way that individual functions were provided for badges eg. ZeroBadge etc.

I am happy to swap to a single setter (which was my original thought tbh).

Welcome your thoughts @chrishaines?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure but it seems to be that this is partially due to typing (it allows Badge to specifically take an int as an argument with UnsetBadge being used to set it to nil to remove it from the payload. I'm not sure why there is a separate ZeroBadge function rather than just using Badge(0) 🤷‍♂️ ).

I think that EPushType seems to be the closest precedent to handling an enumerated value in the codebase.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am inclined to swap it out then as you suggest (I have working code for that implementation ready to go).

Before I do though, can I ask, what is the reason for the E prefix in EPushType? Is there some specific naming convention? (I don't do a huge lot in Go).

Copy link
Contributor

@chrishaines chrishaines Sep 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure where that came from either to be honest. Perhaps it's for Enum? That's really a complete guess.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that seems a sensible guess!
Just wondering if I should employ the same E prefix or not!

Copy link
Contributor

@chrishaines chrishaines Sep 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that sounds reasonable. I would go for it.

Copy link
Contributor Author

@neilmorton neilmorton Sep 4, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have swapped out the InterruptionLevel into a single function. Thanks for your input @chrishaines. Please can you give it a once over?

Comment on lines 329 to 369
// InterruptionLevelPassive sets the aps interruption-level to "passive" on the payload.
// This is to indicate the importance and delivery timing of a notification.
// See: https://developer.apple.com/documentation/usernotifications/unnotificationinterruptionlevel/
//
// {"aps":{"interruption-level":passive}}
func (p *Payload) InterruptionLevelPassive() *Payload {
p.aps().InterruptionLevel = "passive"
return p
}

// InterruptionLevelActive sets the aps interruption-level to "active" on the payload.
// This is to indicate the importance and delivery timing of a notification.
// See: https://developer.apple.com/documentation/usernotifications/unnotificationinterruptionlevel/
//
// {"aps":{"interruption-level":active}}
func (p *Payload) InterruptionLevelActive() *Payload {
p.aps().InterruptionLevel = "active"
return p
}

// InterruptionLevelTimeSensitive sets the aps interruption-level to "time-sensitive" on the payload.
// This is to indicate the importance and delivery timing of a notification.
// See: https://developer.apple.com/documentation/usernotifications/unnotificationinterruptionlevel/
//
// {"aps":{"interruption-level":time-sensitive}}
func (p *Payload) InterruptionLevelTimeSensitive() *Payload {
p.aps().InterruptionLevel = "time-sensitive"
return p
}

// InterruptionLevelCritical sets the aps interruption-level to "critical" on the payload.
// This is to indicate the importance and delivery timing of a notification.
// This interruption level requires an approved entitlement from Apple.
// See: https://developer.apple.com/documentation/usernotifications/unnotificationinterruptionlevel/
//
// {"aps":{"interruption-level":critical}}
func (p *Payload) InterruptionLevelCritical() *Payload {
p.aps().InterruptionLevel = "critical"
return p
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure but it seems to be that this is partially due to typing (it allows Badge to specifically take an int as an argument with UnsetBadge being used to set it to nil to remove it from the payload. I'm not sure why there is a separate ZeroBadge function rather than just using Badge(0) 🤷‍♂️ ).

I think that EPushType seems to be the closest precedent to handling an enumerated value in the codebase.

Comment on lines 376 to 379
func (p *Payload) RelevanceScore(b float32) *Payload {
p.aps().RelevanceScore = b
return p
}
Copy link
Contributor

@chrishaines chrishaines Sep 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't appear to allow setting a relevance-score of 0 because it will omitted when building the aps JSON. This will result in Apple using their default of 0.5. I think you can address this by either using the Badge precedent above (preferred) or by changing the type to a pointer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can make a PR for this if you'd like.

Copy link
Contributor Author

@neilmorton neilmorton Sep 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch @chrishaines on relevance-score.

Sure if you have time to do the PR for that, and I will try and get the other swapped out tomorrow or at the weekend.

Thanks.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here ya go!
neilmorton#1

Copy link
Contributor Author

@neilmorton neilmorton Sep 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @chrishaines! I have merged this.

@sideshow
Copy link
Owner

Thank you @neilmorton @chrishaines , this is great

@sideshow sideshow merged commit 9c1d7c6 into sideshow:master Sep 22, 2021
@neilmorton neilmorton deleted the ios-15-additions branch September 22, 2021 15:37
@scapegoat1630
Copy link

need a new git tag

froodian added a commit to braze-inc/apns2 that referenced this pull request Dec 20, 2021
Add iOS 15 payload additions (sideshow#185)
netrebel added a commit to life360/apns2 that referenced this pull request Jul 18, 2023
…0.23.0

* Add iOS 15 payload additions (sideshow#185)

* Add iOS 15 payload additions

- Add interruption-level to payload
 interruption-level options:
    - passive
    - active (default if none is passed to apns)
    - time-sensitive
    - critical (requires Apple entitlement)

- Add relevance-score to payload
relevance-score is a number between 0 and 1
The highest score gets featured in the notification summary.

* Update readme re iOS 15 features

* Fix documentation typo

Note that at the time of writing [Apple docs](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/generating_a_remote_notification#2943360) have a typo, showing `time-senstive` as opposed to `time-sensitive`.

Testing has shown that the correct spelling `time-sensitive` does indeed work.

* Update builder.go

Alphabetically order keys in struct as per @Singwai suggestion.

* Allow relevance-score to be set to zero.

* Updated to single InterruptionLevel function

Co-authored-by: Chris Haines <chris.haines@braze.com>

* Go modules support (sideshow#181)

* Go Modules Support

* Replace Travis with Github Actions (sideshow#190)

* Replace Travis with Github Actions

* Fix context timeout error

* Add Github workflow badge

* Add coverage to actions

* Update jwt library (sideshow#191)

- Resolves sideshow#186
- Resolves sideshow#187
- Resolves sideshow#189

* Use NewReader instead of NewBuffer (sideshow#193)

* Add location push type (sideshow#194)

* Add location push type
* Fix Typo
* Add InvalidPushType reason error code

* Use type switch with assignment syntax (sideshow#196)

* Use POST http constant (sideshow#203)

* Use if type conditional (sideshow#198)

In that case if type is much simpler and look better.

* Simplify FromPemBytes conditional (sideshow#197)

- Simplify logic. strings.HasSuffix can check both for suffix and for equality

* Use NewRequestWithContext instead of nil checking (sideshow#200)

* Use appropriate type cast functions (sideshow#199)

* Use appropriate type cast functions
* avoid fmt usage

* Fix double pointer (sideshow#195)

* Refactor request/response variable names (sideshow#205)

r *Request is more consistent with n *Notification

* Feature/updated http2 transport (sideshow#209)

* Update http2 transport
* Add ReadIdleTimeout for ping frames
* Update defaults for TCP Keepalive

* Revert "CF-153: Updating Log to print issuedAt (#7)"

This reverts commit 69ea756.

* Revert "CF-133: Adding PushTypeLocation (#6)"

This reverts commit 3668879.

* Reverting Using int64 for timestamp (8fac21d)

* Changing module name

* gitignore idea directory

---------

Co-authored-by: Neil Morton <neil@progressconcepts.com>
Co-authored-by: Chris Haines <chris.haines@braze.com>
Co-authored-by: jbendotnet <2698840+jbendotnet@users.noreply.github.com>
Co-authored-by: Adam Jones <adam@digirati.co.nz>
Co-authored-by: Mikhail Faraponov <11322032+moredure@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

7 participants