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 ability to repeat notifications like on iOS #268

Merged
merged 5 commits into from
Aug 20, 2021
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
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,14 +324,47 @@ 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.
- `isCritical` : If true, the notification sound be played even when the device is locked, muted, or has Do Not Disturb enabled.
- `criticalSoundVolume` : A number between 0 and 1 for volume of critical notification. Default volume will be used if not specified.
- `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.

Choose a reason for hiding this comment

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

Suggest adding year component.

- `day`: Will repeat every selected day in your fireDate.

Choose a reason for hiding this comment

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

Suggest adding dayOfWeek component

- `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.

Choose a reason for hiding this comment

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

Suggest removing nanosecond


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()`
Expand Down
50 changes: 35 additions & 15 deletions ios/RCTConvert+Notification.m
Original file line number Diff line number Diff line change
Expand Up @@ -93,25 +93,32 @@ @implementation RCTConvert (UNNotificationRequest)
+ (UNNotificationRequest *)UNNotificationRequest:(id)json
{
NSDictionary<NSString *, id> *details = [self NSDictionary:json];

BOOL isSilent = [RCTConvert BOOL:details[@"isSilent"]];
BOOL isCritical = [RCTConvert BOOL:details[@"isCritical"]];
float criticalSoundVolume = [RCTConvert float:details[@"criticalSoundVolume"]];
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"]];
if (threadIdentifier){
content.threadIdentifier = threadIdentifier;
}

NSDictionary<NSString *, id> *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) {
if (isCritical) {
Expand All @@ -122,18 +129,31 @@ + (UNNotificationRequest *)UNNotificationRequest:(id)json
}
} else {
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 =

Choose a reason for hiding this comment

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

Suggest addition of NSCalendarUnitYear and NSCalendarUnitWeekday.
Suggest removal of NSCalendarUnitNanosecond.

(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];
Expand Down
6 changes: 5 additions & 1 deletion js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down
12 changes: 12 additions & 0 deletions js/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
repeatsComponent?: {
month?: boolean,

Choose a reason for hiding this comment

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

Suggest addition of year and dayOfWeek. Suggest removal of nanosecond.

day?: boolean,
hour?: boolean,
minute?: boolean,
second?: boolean,
nanosecond?: boolean,
},
/**
* Sets notification to be silent
*/
Expand Down