From 8738e6d9743ba0e8bd8efefdbb6b35441b3f59bf Mon Sep 17 00:00:00 2001 From: Guillaume Hivert Date: Thu, 11 Mar 2021 22:19:55 +0100 Subject: [PATCH 1/4] :bug: Add repeats component to addNotificationRequest --- ios/RCTConvert+Notification.m | 52 +++++++++++++++++++++++++---------- js/index.js | 6 +++- js/types.js | 12 ++++++++ 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/ios/RCTConvert+Notification.m b/ios/RCTConvert+Notification.m index 434ef80a4..2247329cb 100644 --- a/ios/RCTConvert+Notification.m +++ b/ios/RCTConvert+Notification.m @@ -93,16 +93,15 @@ @implementation RCTConvert (UNNotificationRequest) + (UNNotificationRequest *)UNNotificationRequest:(id)json { NSDictionary *details = [self NSDictionary:json]; - + BOOL isSilent = [RCTConvert BOOL:details[@"isSilent"]]; NSString* identifier = [RCTConvert NSString:details[@"id"]]; - - + UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init]; - content.title= [RCTConvert NSString:details[@"title"]]; - content.subtitle= [RCTConvert NSString:details[@"subtitle"]]; - content.body =[RCTConvert NSString:details[@"body"]]; - content.badge = [RCTConvert NSNumber:details[@"badge"]]; + content.title = [RCTConvert NSString:details[@"title"]]; + content.subtitle = [RCTConvert NSString:details[@"subtitle"]]; + content.body = [RCTConvert NSString:details[@"body"]]; + content.badge = [RCTConvert NSNumber:details[@"badge"]]; content.categoryIdentifier = [RCTConvert NSString:details[@"category"]]; NSString* threadIdentifier = [RCTConvert NSString:details[@"threadId"]]; @@ -110,20 +109,43 @@ + (UNNotificationRequest *)UNNotificationRequest:(id)json content.threadIdentifier = threadIdentifier; } + NSDictionary *userDateComps = [RCTConvert NSDictionary:details[@"repeatsComponent"]]; + BOOL month = [RCTConvert BOOL:userDateComps[@"month"]]; + BOOL day = [RCTConvert BOOL:userDateComps[@"day"]]; + BOOL hour = [RCTConvert BOOL:userDateComps[@"hour"]]; + BOOL minute = [RCTConvert BOOL:userDateComps[@"minute"]]; + BOOL second = [RCTConvert BOOL:userDateComps[@"second"]]; + BOOL nanosecond = [RCTConvert BOOL:userDateComps[@"nanosecond"]]; + content.userInfo = [RCTConvert NSDictionary:details[@"userInfo"]]; if (!isSilent) { - content.sound = [RCTConvert NSString:details[@"sound"]] ? [UNNotificationSound soundNamed:[RCTConvert NSString:details[@"sound"]]] : [UNNotificationSound defaultSound]; + content.sound = [RCTConvert NSString:details[@"sound"]] + ? [UNNotificationSound soundNamed:[RCTConvert NSString:details[@"sound"]]] + : [UNNotificationSound defaultSound]; } NSDate* fireDate = [RCTConvert NSDate:details[@"fireDate"]]; BOOL repeats = [RCTConvert BOOL:details[@"repeats"]]; - NSDateComponents *triggerDate = fireDate ? [[NSCalendar currentCalendar] - components:NSCalendarUnitYear + - NSCalendarUnitMonth + NSCalendarUnitDay + - NSCalendarUnitHour + NSCalendarUnitMinute + - NSCalendarUnitSecond + NSCalendarUnitTimeZone - fromDate:fireDate] : nil; - + NSCalendarUnit defaultDateComponents = + NSCalendarUnitYear | + NSCalendarUnitMonth | + NSCalendarUnitDay | + NSCalendarUnitHour | + NSCalendarUnitMinute | + NSCalendarUnitSecond; + NSCalendarUnit repeatDateComponents = + (month ? NSCalendarUnitMonth : 0) | + (day ? NSCalendarUnitDay : 0) | + (hour ? NSCalendarUnitHour : 0) | + (minute ? NSCalendarUnitMinute : 0) | + (second ? NSCalendarUnitSecond : 0) | + (nanosecond ? NSCalendarUnitNanosecond : 0); + NSDateComponents *triggerDate = fireDate + ? [[NSCalendar currentCalendar] + components:(repeats ? repeatDateComponents : defaultDateComponents) | NSCalendarUnitTimeZone + fromDate:fireDate] + : nil; + UNCalendarNotificationTrigger* trigger = triggerDate ? [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:triggerDate repeats:repeats] : nil; UNNotificationRequest* notification = [UNNotificationRequest requestWithIdentifier:identifier content:content trigger:trigger]; diff --git a/js/index.js b/js/index.js index ad76ed8bb..e13417cf4 100644 --- a/js/index.js +++ b/js/index.js @@ -146,8 +146,12 @@ class PushNotificationIOS { request.fireDate instanceof Date ? {...request, fireDate: request.fireDate.toISOString()} : request; + const finalRequest = { + ...handledRequest, + repeatsComponent: request.repeatsComponent || {}, + }; - RNCPushNotificationIOS.addNotificationRequest(handledRequest); + RNCPushNotificationIOS.addNotificationRequest(finalRequest); } /** diff --git a/js/types.js b/js/types.js index c373e0de8..75a9826d8 100644 --- a/js/types.js +++ b/js/types.js @@ -45,6 +45,18 @@ export type NotificationRequest = {| * Must be used with fireDate. */ repeats?: boolean, + /** + * Define what components should be used in the fireDate during repeats. + * Must be used with repeats and fireDate. + */ + dateRepeatsComponent?: { + month?: boolean, + day?: boolean, + hour?: boolean, + minute?: boolean, + second?: boolean, + nanosecond?: boolean, + }, /** * Sets notification to be silent */ From 85cad5a8f351f7ac19a69c465229522d4e1094b3 Mon Sep 17 00:00:00 2001 From: Guillaume Hivert Date: Thu, 11 Mar 2021 22:26:22 +0100 Subject: [PATCH 2/4] :memo: Write docs for repeating --- README.md | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1ac090d68..314c6e7e7 100644 --- a/README.md +++ b/README.md @@ -312,12 +312,45 @@ request is an object containing: - `body` : The message displayed in the notification alert. - `badge` The number to display as the app's icon badge. Setting the number to 0 removes the icon badge. - `fireDate` : The date and time when the system should deliver the notification. -- `repeats` : Sets notification to repeat daily. Must be used with fireDate. +- `repeats` : Sets notification to repeat. Must be used with fireDate and repeatsComponent. +- `repeatsComponent`: An object indicating which parts of fireDate should be repeated. - `sound` : The sound played when the notification is fired. - `category` : The category of this notification, required for actionable notifications. - `isSilent` : If true, the notification will appear without sound. - `userInfo` : An object containing additional notification data. +request.repeatsComponent is an object containing (each field is optionnal): + +- `month`: Will repeat every selected month in your fireDate. +- `day`: Will repeat every selected day in your fireDate. +- `hour`: Will repeat every selected hour in your fireDate. +- `minute`: Will repeat every selected minute in your fireDate. +- `second`: Will repeat every selected second in your fireDate. +- `nanosecond`: Will repeat every selected nanosecond in your fireDate. + +For example, let’s say you want to have a notification repeating every day at 23:54, starting tomorrow, you will use something like this: + +```javascript +const getCorrectDate = () => { + const date = new Date(); + date.setDate(date.getDate() + 1); + date.setHours(23); + date.setMinutes(54); + return date; +}; + +PushNotificationIOS.addNotificationRequest({ + fireDate: getCorrectDate(), + repeats: true, + repeatsComponent: { + hour: true, + minute: true, + }, +}); +``` + +If you want to repeat every time the clock reach 54 minutes (like 00:54, 01:54, and so on), just switch hour to false. Every field is used to indicate at what time the notification should be repeated, exactly like you could do on iOS. + --- ### `setNotificationCategories()` From 2b9a66b58b9fc542c27070a7d53609e673c9cc3b Mon Sep 17 00:00:00 2001 From: Guillaume Hivert Date: Thu, 11 Mar 2021 22:32:01 +0100 Subject: [PATCH 3/4] :bug: Fix dateRepeatsComponent in types.js --- js/types.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/types.js b/js/types.js index 75a9826d8..4014ae149 100644 --- a/js/types.js +++ b/js/types.js @@ -49,7 +49,7 @@ export type NotificationRequest = {| * Define what components should be used in the fireDate during repeats. * Must be used with repeats and fireDate. */ - dateRepeatsComponent?: { + repeatsComponent?: { month?: boolean, day?: boolean, hour?: boolean, From ed388793657eb59177b1b5910961d7c7c345392e Mon Sep 17 00:00:00 2001 From: Jesse Katsumata Date: Fri, 20 Aug 2021 20:47:07 +0900 Subject: [PATCH 4/4] Apply suggestions from code review --- ios/RCTConvert+Notification.m | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ios/RCTConvert+Notification.m b/ios/RCTConvert+Notification.m index 036da5649..08bfc2e98 100644 --- a/ios/RCTConvert+Notification.m +++ b/ios/RCTConvert+Notification.m @@ -121,9 +121,15 @@ + (UNNotificationRequest *)UNNotificationRequest:(id)json content.userInfo = [RCTConvert NSDictionary:details[@"userInfo"]]; if (!isSilent) { - - ? [UNNotificationSound soundNamed:[RCTConvert NSString:details[@"sound"]]] - : [UNNotificationSound defaultSound]; + if (isCritical) { + if (criticalSoundVolume) { + content.sound = [RCTConvert NSString:details[@"sound"]] ? [UNNotificationSound criticalSoundNamed:[RCTConvert NSString:details[@"sound"]] withAudioVolume:criticalSoundVolume] : [UNNotificationSound defaultCriticalSoundWithAudioVolume:criticalSoundVolume]; + } else { + content.sound = [RCTConvert NSString:details[@"sound"]] ? [UNNotificationSound criticalSoundNamed:[RCTConvert NSString:details[@"sound"]]] : [UNNotificationSound defaultCriticalSound]; + } + } else { + content.sound = [RCTConvert NSString:details[@"sound"]] ? [UNNotificationSound soundNamed:[RCTConvert NSString:details[@"sound"]]] : [UNNotificationSound defaultSound]; + }``` } NSDate* fireDate = [RCTConvert NSDate:details[@"fireDate"]];