diff --git a/v3/pkg/services/notifications/notifications_darwin.go b/v3/pkg/services/notifications/notifications_darwin.go index 626f52524..a84d6f024 100644 --- a/v3/pkg/services/notifications/notifications_darwin.go +++ b/v3/pkg/services/notifications/notifications_darwin.go @@ -31,7 +31,7 @@ func (ns *Service) ServiceName() string { // ServiceStartup is called when the service is loaded. func (ns *Service) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } return nil } @@ -48,7 +48,7 @@ func CheckBundleIdentifier() bool { // RequestUserNotificationAuthorization requests permission for notifications. func (ns *Service) RequestUserNotificationAuthorization() (bool, error) { if !CheckBundleIdentifier() { - return false, fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return false, fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } result := C.requestUserNotificationAuthorization(nil) return result == true, nil @@ -57,26 +57,35 @@ func (ns *Service) RequestUserNotificationAuthorization() (bool, error) { // CheckNotificationAuthorization checks current notification permission status. func (ns *Service) CheckNotificationAuthorization() (bool, error) { if !CheckBundleIdentifier() { - return false, fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return false, fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } return bool(C.checkNotificationAuthorization()), nil } // SendNotification sends a basic notification with a unique identifier, title, subtitle, and body. -func (ns *Service) SendNotification(identifier, title, subtitle, body string) error { +func (ns *Service) SendNotification(options NotificationOptions) error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } - cIdentifier := C.CString(identifier) - cTitle := C.CString(title) - cSubtitle := C.CString(subtitle) - cBody := C.CString(body) + cIdentifier := C.CString(options.ID) + cTitle := C.CString(options.Title) + cSubtitle := C.CString(options.Subtitle) + cBody := C.CString(options.Body) defer C.free(unsafe.Pointer(cIdentifier)) defer C.free(unsafe.Pointer(cTitle)) defer C.free(unsafe.Pointer(cSubtitle)) defer C.free(unsafe.Pointer(cBody)) - C.sendNotification(cIdentifier, cTitle, cSubtitle, cBody, nil) + var cDataJSON *C.char + if options.Data != nil { + jsonData, err := json.Marshal(options.Data) + if err == nil { + cDataJSON = C.CString(string(jsonData)) + defer C.free(unsafe.Pointer(cDataJSON)) + } + } + + C.sendNotification(cIdentifier, cTitle, cSubtitle, cBody, cDataJSON, nil) return nil } @@ -85,7 +94,7 @@ func (ns *Service) SendNotification(identifier, title, subtitle, body string) er // If a NotificationCategory is not registered a basic notification will be sent. func (ns *Service) SendNotificationWithActions(options NotificationOptions) error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } cIdentifier := C.CString(options.ID) cTitle := C.CString(options.Title) @@ -115,7 +124,7 @@ func (ns *Service) SendNotificationWithActions(options NotificationOptions) erro // Registering a category with the same name as a previously registered NotificationCategory will override it. func (ns *Service) RegisterNotificationCategory(category NotificationCategory) error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } cCategoryID := C.CString(category.ID) defer C.free(unsafe.Pointer(cCategoryID)) @@ -140,10 +149,10 @@ func (ns *Service) RegisterNotificationCategory(category NotificationCategory) e return nil } -// RemoveNotificationCategory removes a previously registered NotificationCategory. +// RemoveNotificationCategory remove a previously registered NotificationCategory. func (ns *Service) RemoveNotificationCategory(categoryId string) error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } cCategoryID := C.CString(categoryId) defer C.free(unsafe.Pointer(cCategoryID)) @@ -155,7 +164,7 @@ func (ns *Service) RemoveNotificationCategory(categoryId string) error { // RemoveAllPendingNotifications removes all pending notifications. func (ns *Service) RemoveAllPendingNotifications() error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } C.removeAllPendingNotifications() return nil @@ -164,7 +173,7 @@ func (ns *Service) RemoveAllPendingNotifications() error { // RemovePendingNotification removes a pending notification matching the unique identifier. func (ns *Service) RemovePendingNotification(identifier string) error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } cIdentifier := C.CString(identifier) defer C.free(unsafe.Pointer(cIdentifier)) @@ -175,7 +184,7 @@ func (ns *Service) RemovePendingNotification(identifier string) error { // RemoveAllDeliveredNotifications removes all delivered notifications. func (ns *Service) RemoveAllDeliveredNotifications() error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } C.removeAllDeliveredNotifications() return nil @@ -184,7 +193,7 @@ func (ns *Service) RemoveAllDeliveredNotifications() error { // RemoveDeliveredNotification removes a delivered notification matching the unique identifier. func (ns *Service) RemoveDeliveredNotification(identifier string) error { if !CheckBundleIdentifier() { - return fmt.Errorf("Notifications require a bundled application with a unique bundle identifier") + return fmt.Errorf("notifications require a bundled application with a unique bundle identifier") } cIdentifier := C.CString(identifier) defer C.free(unsafe.Pointer(cIdentifier)) diff --git a/v3/pkg/services/notifications/notifications_darwin.h b/v3/pkg/services/notifications/notifications_darwin.h index 74ac28553..21a210289 100644 --- a/v3/pkg/services/notifications/notifications_darwin.h +++ b/v3/pkg/services/notifications/notifications_darwin.h @@ -8,7 +8,7 @@ bool checkBundleIdentifier(void); bool requestUserNotificationAuthorization(void *completion); bool checkNotificationAuthorization(void); -void sendNotification(const char *identifier, const char *title, const char *subtitle, const char *body, void *completion); +void sendNotification(const char *identifier, const char *title, const char *subtitle, const char *body, const char *data_json, void *completion); void sendNotificationWithActions(const char *identifier, const char *title, const char *subtitle, const char *body, const char *categoryId, const char *actions_json, void *completion); void registerNotificationCategory(const char *categoryId, const char *actions_json, bool hasReplyField, const char *replyPlaceholder, const char *replyButtonTitle); void removeNotificationCategory(const char *categoryId); diff --git a/v3/pkg/services/notifications/notifications_darwin.m b/v3/pkg/services/notifications/notifications_darwin.m index 0028211ec..3c3fe4978 100644 --- a/v3/pkg/services/notifications/notifications_darwin.m +++ b/v3/pkg/services/notifications/notifications_darwin.m @@ -118,7 +118,7 @@ bool checkNotificationAuthorization(void) { return isAuthorized; } -void sendNotification(const char *identifier, const char *title, const char *subtitle, const char *body, void *completion) { +void sendNotification(const char *identifier, const char *title, const char *subtitle, const char *body, const char *data_json, void *completion) { ensureDelegateInitialized(); NSString *nsIdentifier = [NSString stringWithUTF8String:identifier]; @@ -126,6 +126,17 @@ void sendNotification(const char *identifier, const char *title, const char *sub NSString *nsSubtitle = [NSString stringWithUTF8String:subtitle]; NSString *nsBody = [NSString stringWithUTF8String:body]; + NSMutableDictionary *customData = [NSMutableDictionary dictionary]; + if (data_json) { + NSString *dataJsonStr = [NSString stringWithUTF8String:data_json]; + NSData *jsonData = [dataJsonStr dataUsingEncoding:NSUTF8StringEncoding]; + NSError *error = nil; + NSDictionary *parsedData = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; + if (!error && parsedData) { + [customData addEntriesFromDictionary:parsedData]; + } + } + UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter]; UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init]; @@ -134,6 +145,11 @@ void sendNotification(const char *identifier, const char *title, const char *sub content.body = nsBody; content.sound = [UNNotificationSound defaultSound]; + // Add custom data if available + if (customData.count > 0) { + content.userInfo = customData; + } + UNTimeIntervalNotificationTrigger *trigger = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:1 repeats:NO]; UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:nsIdentifier content:content trigger:trigger];