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

feature[iOS]: Add support to live-activity notifications #802

Merged
merged 9 commits into from
Aug 17, 2024
Merged
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
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
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()
dismissal_date := stale_date + 5
timeStamp := time.Now().Unix()
itemId := float64(12345)

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"]
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
Loading