Skip to content

Commit

Permalink
feature(iOS): Add support to live-activity notifications (#802)
Browse files Browse the repository at this point in the history
* [iOS]: support library for live activity notifications

* test to contentState dynamic content

* small lines of documentation for further references

* [iOS]: update Readme file with live-activity support

* support dimissal-date for live activity

* add dismissal-date to README md file

* cleaning code

* fix(iOS): adapt payload naming variables according to latest relase of apns2 related to live activity

* chore(APNS2): update library to newest release to support LiveActivity

---------

Co-authored-by: GonzaloAvilez <[email protected]>
Co-authored-by: Gonzalo Avilez <[email protected]>
  • Loading branch information
3 people authored Aug 17, 2024
1 parent b95fdd6 commit 4f10394
Show file tree
Hide file tree
Showing 6 changed files with 66 additions and 4 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -721,7 +721,12 @@ The Request body must have a notifications array. The following is a parameter t
| mutable_content | bool | enable Notification Service app extension. | - | only iOS(10.0+). |
| name | string | sets the name value on the aps sound dictionary. | - | only iOS |
| volume | float32 | sets the volume value on the aps sound dictionary. | - | only iOS |
| interruption_level | string | defines the interruption level for the push notification. | - | only iOS(15.0+) |
| interruption_level | string | defines the interruption level for the push notification. | - | only iOS(15.0+) |
| content-state | string array | dynamic and custom content for live-activity notification. | - | only iOS(16.1+) |
| timestamp | int | the UNIX time when sending the remote notification that updates or ends a Live Activity | - | only iOS(16.1+) |
| event | string | describes whether you update or end an ongoing Live Activity | - | only iOS(16.1+) |
| stale-date | int | the date which a Live Activity becomes stale, or out of date | - | only iOS(16.1+) |
| dismissal-date | int | the UNIX time -timestamp- which a Live Activity will end and will be removed | - | only iOS(16.1+) |

### iOS alert payload

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ require (
github.com/prometheus/client_golang v1.19.0
github.com/redis/go-redis/v9 v9.5.3
github.com/rs/zerolog v1.32.0
github.com/sideshow/apns2 v0.23.0
github.com/sideshow/apns2 v0.24.0
github.com/sirupsen/logrus v1.9.3
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,8 @@ github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgY
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sideshow/apns2 v0.23.0 h1:lpkikaZ995GIcKk6AFsYzHyezCrsrfEDvUWcWkEGErY=
github.com/sideshow/apns2 v0.23.0/go.mod h1:7Fceu+sL0XscxrfLSkAoH6UtvKefq3Kq1n4W3ayQZqE=
github.com/sideshow/apns2 v0.24.0 h1:syofL4rd8ZeqUVySgYyBSYr/oLMU/HzJi++r3FIp6Z4=
github.com/sideshow/apns2 v0.24.0/go.mod h1:7Fceu+sL0XscxrfLSkAoH6UtvKefq3Kq1n4W3ayQZqE=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
Expand Down
8 changes: 8 additions & 0 deletions notify/notification.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,14 @@ type PushNotification struct {

// ref: https://github.com/sideshow/apns2/blob/54928d6193dfe300b6b88dad72b7e2ae138d4f0a/payload/builder.go#L7-L24
InterruptionLevel string `json:"interruption_level,omitempty"`

// live-activity support
// ref: https://developer.apple.com/documentation/activitykit/updating-and-ending-your-live-activity-with-activitykit-push-notifications

Check failure on line 120 in notify/notification.go

View workflow job for this annotation

GitHub Actions / lint

the line is 137 characters long, which exceeds the maximum of 120 characters. (lll)
ContentState D `json:"content-state,omitempty"`
StaleDate int64 `json:"stale-date,omitempty"`
DismissalDate int64 `json:"dismissal-date"`
Event string `json:"event,omitempty"`
Timestamp int64 `json:"timestamp,omitempty"`
}

// Bytes for queue message
Expand Down
20 changes: 20 additions & 0 deletions notify/notification_apns.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,26 @@ func iosAlertDictionary(notificationPayload *payload.Payload, req *PushNotificat
notificationPayload.AlertSummaryArgCount(req.Alert.SummaryArgCount)
}

if len(req.ContentState) > 0 {
notificationPayload.SetContentState(req.ContentState)
}

if req.StaleDate > 0 {
notificationPayload.SetStaleDate(req.StaleDate)
}

if req.DismissalDate > 0 {
notificationPayload.SetDismissalDate(req.DismissalDate)
}

if len(req.Event) > 0 {
notificationPayload.SetEvent(payload.ELiveActivityEvent(req.Event))
}

if req.Timestamp > 0 {
notificationPayload.SetTimestamp(req.Timestamp)
}

return notificationPayload
}

Expand Down
29 changes: 29 additions & 0 deletions notify/notification_apns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,11 @@ func TestMessageAndTitle(t *testing.T) {

func TestIOSAlertNotificationStructure(t *testing.T) {
var dat map[string]interface{}
unix := time.Now().Unix()
stale_date := time.Now().Unix()

Check failure on line 517 in notify/notification_apns_test.go

View workflow job for this annotation

GitHub Actions / lint

ST1003: should not use underscores in Go names; var stale_date should be staleDate (stylecheck)
dismissal_date := stale_date + 5

Check failure on line 518 in notify/notification_apns_test.go

View workflow job for this annotation

GitHub Actions / lint

ST1003: should not use underscores in Go names; var dismissal_date should be dismissalDate (stylecheck)
timeStamp := time.Now().Unix()
itemId := float64(12345)

Check failure on line 520 in notify/notification_apns_test.go

View workflow job for this annotation

GitHub Actions / lint

ST1003: var itemId should be itemID (stylecheck)

req := &PushNotification{
Message: "Welcome",
Expand All @@ -529,6 +534,14 @@ func TestIOSAlertNotificationStructure(t *testing.T) {
TitleLocKey: testMessage,
},
InterruptionLevel: testMessage,
StaleDate: stale_date,
DismissalDate: dismissal_date,
Event: testMessage,
Timestamp: timeStamp,
ContentState: D{
"item_id": itemId,
"item_name": testMessage,
},
}

notification := GetIOSNotification(req)
Expand All @@ -550,10 +563,16 @@ func TestIOSAlertNotificationStructure(t *testing.T) {
subtitle, _ := jsonparser.GetString(data, "aps", "alert", "subtitle")
titleLocKey, _ := jsonparser.GetString(data, "aps", "alert", "title-loc-key")
interruptionLevel, _ := jsonparser.GetString(data, "aps", "interruption-level")
staleDate, _ := jsonparser.GetInt(data, "aps", "stale-date")
event, _ := jsonparser.GetString(data, "aps", "event")
timestamp, _ := jsonparser.GetInt(data, "aps", "timestamp")
aps := dat["aps"].(map[string]interface{})
alert := aps["alert"].(map[string]interface{})
titleLocArgs := alert["title-loc-args"].([]interface{})
locArgs := alert["loc-args"].([]interface{})
contentState := aps["content-state"].(map[string]interface{})
contentStateItemId := contentState["item_id"]

Check failure on line 574 in notify/notification_apns_test.go

View workflow job for this annotation

GitHub Actions / lint

ST1003: var contentStateItemId should be contentStateItemID (stylecheck)
contentStateItemName := contentState["item_name"]

assert.Equal(t, testMessage, action)
assert.Equal(t, testMessage, actionLocKey)
Expand All @@ -564,6 +583,16 @@ func TestIOSAlertNotificationStructure(t *testing.T) {
assert.Equal(t, testMessage, subtitle)
assert.Equal(t, testMessage, titleLocKey)
assert.Equal(t, testMessage, interruptionLevel)
assert.Equal(t, testMessage, event)
assert.Equal(t, unix, staleDate)
assert.Equal(t, unix, timestamp)

// dynamic contentState content
assert.Equal(t, contentStateItemId, itemId)
assert.Equal(t, contentStateItemName, testMessage)
assert.Contains(t, contentState, "item_id")
assert.Contains(t, contentState, "item_name")

assert.Contains(t, titleLocArgs, "a")
assert.Contains(t, titleLocArgs, "b")
assert.Contains(t, locArgs, "a")
Expand Down

0 comments on commit 4f10394

Please sign in to comment.