1
0
mirror of https://github.com/laurent22/joplin.git synced 2024-12-30 10:36:35 +02:00
joplin/packages/react-native-alarm-notification/ios/RnAlarmNotification.m
Laurent Cozic 138bc8144b Android: Fixes non-working alarms
Also imported react-native-alarm-notificatio into the project
2023-01-20 17:33:19 +00:00

795 lines
34 KiB
Objective-C

#import "RnAlarmNotification.h"
#import <UserNotifications/UserNotifications.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUtils.h>
#import <AudioToolbox/AudioToolbox.h>
#import <AVFoundation/AVFoundation.h>
static NSString *const kLocalNotificationReceived = @"LocalNotificationReceived";
static NSString *const kLocalNotificationDismissed = @"LocalNotificationDismissed";
static AVAudioPlayer *player;
static id _sharedInstance = nil;
@implementation RnAlarmNotification
+(instancetype)sharedInstance {
static dispatch_once_t p;
dispatch_once(&p, ^{
_sharedInstance = [[self alloc] init];
});
return _sharedInstance;
}
API_AVAILABLE(ios(10.0))
static NSDictionary *RCTFormatUNNotification(UNNotification *notification) {
NSMutableDictionary *formattedNotification = [NSMutableDictionary dictionary];
UNNotificationContent *content = notification.request.content;
formattedNotification[@"id"] = notification.request.identifier;
formattedNotification[@"data"] = RCTNullIfNil([content.userInfo objectForKey:@"data"]);
return formattedNotification;
}
static NSDateComponents *parseDate(NSString *dateString) {
NSArray *fire_date = [dateString componentsSeparatedByString:@" "];
NSString *date = fire_date[0];
NSString *time = fire_date[1];
NSArray *splitDate = [date componentsSeparatedByString:@"-"];
NSArray *splitHour = [time componentsSeparatedByString:@":"];
NSString *strNumDay = splitDate[0];
NSString *strNumMonth = splitDate[1];
NSString *strNumYear = splitDate[2];
NSString *strNumHour = splitHour[0];
NSString *strNumMinute = splitHour[1];
NSString *strNumSecond = splitHour[2];
// Configure the trigger for date
NSDateComponents *fireDate = [[NSDateComponents alloc] init];
fireDate.day = [strNumDay intValue];
fireDate.month = [strNumMonth intValue];
fireDate.year = [strNumYear intValue];
fireDate.hour = [strNumHour intValue];
fireDate.minute = [strNumMinute intValue];
fireDate.second = [strNumSecond intValue];
fireDate.timeZone = [NSTimeZone defaultTimeZone];
return fireDate;
}
static NSDateComponents *dateToComponents(NSDate *date) {
NSDateComponents *fireDate = [[NSDateComponents alloc] init];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy"];
NSString *year = [formatter stringFromDate:date];
[formatter setDateFormat:@"MM"];
NSString *month = [formatter stringFromDate:date];
[formatter setDateFormat:@"dd"];
NSString *day = [formatter stringFromDate:date];
[formatter setDateFormat:@"HH"];
NSString *hour = [formatter stringFromDate:date];
[formatter setDateFormat:@"mm"];
NSString *minute = [formatter stringFromDate:date];
[formatter setDateFormat:@"ss"];
NSString *second = [formatter stringFromDate:date];
fireDate.day = [day intValue];
fireDate.month = [month intValue];
fireDate.year = [year intValue];
fireDate.hour = [hour intValue];
fireDate.minute = [minute intValue];
fireDate.second = [second intValue];
fireDate.timeZone = [NSTimeZone defaultTimeZone];
return fireDate;
}
static NSString *stringify(NSDictionary *notification) {
NSError *error;
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:notification options:0 error:&error];
if (! jsonData) {
NSLog(@"Got an error: %@", error);
return @"bad json";
} else {
NSString * jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
return jsonString;
}
}
- (dispatch_queue_t)methodQueue {
return dispatch_get_main_queue();
}
RCT_EXPORT_MODULE(RNAlarmNotification);
+ (void)vibratePhone {
NSLog(@"vibratePhone %@", @"here");
if([[UIDevice currentDevice].model isEqualToString:@"iPhone"]) {
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
} else {
AudioServicesPlayAlertSound(kSystemSoundID_Vibrate);
}
}
+ (void) didReceiveNotification:(UNNotification *)notification API_AVAILABLE(ios(10.0)){
NSLog(@"content: %@", notification.request.content.userInfo);
NSLog(@"alarm id: %@", notification.request.identifier);
NSNumber *vibrate = [notification.request.content.userInfo objectForKey:@"vibrate"];
NSLog(@"vibrate: %@", vibrate);
NSNumber *sound = [notification.request.content.userInfo objectForKey:@"sound"];
if([vibrate isEqualToNumber: [NSNumber numberWithInt: 1]]){
NSLog(@"do vibrate now");
[RnAlarmNotification vibratePhone];
}
if([sound isEqualToNumber: [NSNumber numberWithInt: 1]]){
[RnAlarmNotification playSound:notification];
}
NSString *scheduleType = [notification.request.content.userInfo objectForKey:@"schedule_type"];
if([scheduleType isEqualToString:@"repeat"]){
[RnAlarmNotification repeatAlarm:notification];
}
}
+ (void)didReceiveNotificationResponse:(UNNotificationResponse *)response
API_AVAILABLE(ios(10.0)) {
NSLog(@"show notification");
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
if ([response.notification.request.content.categoryIdentifier isEqualToString:@"CUSTOM_ACTIONS"]) {
if ([response.actionIdentifier isEqualToString:@"SNOOZE_ACTION"]) {
[RnAlarmNotification snoozeAlarm:response.notification];
} else if ([response.actionIdentifier isEqualToString:@"DISMISS_ACTION"]) {
NSLog(@"do dismiss");
[RnAlarmNotification stopSound];
NSMutableDictionary *notification = [NSMutableDictionary dictionary];
notification[@"id"] = response.notification.request.identifier;
[[NSNotificationCenter defaultCenter] postNotificationName:kLocalNotificationDismissed
object:self
userInfo:notification];
}
}
// send notification
[[NSNotificationCenter defaultCenter] postNotificationName:kLocalNotificationReceived
object:self
userInfo:RCTFormatUNNotification(response.notification)];
}
- (void)startObserving {
// receive notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleLocalNotificationReceived:) name:kLocalNotificationReceived
object:nil];
// dismiss notification
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleLocalNotificationDismissed:) name:kLocalNotificationDismissed
object:nil];
}
- (NSArray<NSString *> *)supportedEvents {
return @[@"OnNotificationOpened", @"OnNotificationDismissed"];
}
- (void)handleLocalNotificationReceived:(NSNotification *)notification {
// send to js
[self sendEventWithName:@"OnNotificationOpened" body: stringify(notification.userInfo)];
}
- (void)handleLocalNotificationDismissed:(NSNotification *)notification {
// send to js
[self sendEventWithName:@"OnNotificationDismissed" body: stringify(notification.userInfo)];
}
- (void)stopObserving {
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
+ (void)playSound:(UNNotification *)notification API_AVAILABLE(ios(10.0)){
@try {
NSString *soundName = [notification.request.content.userInfo objectForKey:@"sound_name"];
NSNumber *loopSound = [notification.request.content.userInfo objectForKey:@"loop_sound"];
NSString *volume = [notification.request.content.userInfo objectForKey:@"volume"];
NSLog(@"do play sound now: %@", soundName);
NSLog(@"loop sound: %@", loopSound);
NSLog(@"volume sound: %@", volume);
// AVAudioSession *session = [AVAudioSession sharedInstance];
// [session setCategory:AVAudioSessionCategoryPlayback
// withOptions:AVAudioSessionCategoryOptionMixWithOthers
// error:nil];
// [session setActive:true error:nil];
//[session setMode:AVAudioSessionModeDefault error:nil]; // optional
// NSError *playerError = nil;
// if([RnAlarmNotification checkStringIsNotEmpty:soundName]){
// NSLog(@"soundName: %@", soundName);
//
// NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:soundName];
//
// NSString* soundPathEscaped = [path stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
// NSURL *soundUri = [NSURL URLWithString:soundPathEscaped];
//
// NSLog(@"sound path: %@", soundUri);
//
// if(player){
// [player stop];
// player = nil;
// }
//
// player = [[AVAudioPlayer alloc] initWithContentsOfURL:soundUri
// error:&playerError];
//
// if(playerError) {
// NSLog(@"[AppDelegate] audioPlayerError: %@", playerError);
// } else if (player){
// @synchronized(self){
// player.delegate = (id<AVAudioPlayerDelegate>)self;;
// player.enableRate = YES;
// [player prepareToPlay];
//
// NSLog(@"sound volume: %@", RCTNullIfNil(volume));
// // set volume
// player.volume = [volume floatValue];
//
// NSLog(@"sound loop: %@", loopSound);
// // enable/disable loop
// if ([loopSound isEqualToNumber: [NSNumber numberWithInt: 1]]) {
// player.numberOfLoops = -1;
// } else {
// player.numberOfLoops = 0;
// }
//
// [player play];
// }
// }
// }
} @catch(NSException *exception){
NSLog(@"%@", exception.reason);
}
}
+ (void)stopSound {
@try {
if (player) {
[player stop];
player.currentTime = 0;
}
} @catch(NSException *exception){
NSLog(@"%@", exception.reason);
}
}
+ (void)repeatAlarm:(UNNotification *)notification API_AVAILABLE(ios(10.0)) {
[RnAlarmNotification stopSound];
@try {
if (@available(iOS 10.0, *)) {
UNNotificationContent *contentInfo = notification.request.content;
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = contentInfo.title;
content.body = contentInfo.body;
NSString *scheduleType = [contentInfo.userInfo objectForKey:@"schedule_type"];
NSLog(@"schedule type: %@", scheduleType);
NSNumber *has_button = [contentInfo.userInfo objectForKey:@"has_button"];
// set buttons
if([has_button isEqualToNumber: [NSNumber numberWithInt: 1]]){
content.categoryIdentifier = @"CUSTOM_ACTIONS";
}
// set alarm date
NSString *fire_date = [contentInfo.userInfo objectForKey:@"fire_date"];
NSDateComponents *fireDate = parseDate(fire_date);
NSString *repeat_interval = [contentInfo.userInfo objectForKey:@"repeat_interval"];
NSNumber *interval_value = [contentInfo.userInfo objectForKey:@"interval_value"];
NSLog(@"schedule repeat interval %@", repeat_interval);
if([repeat_interval isEqualToString:@"minutely"]){
fireDate.minute = fireDate.minute + [interval_value intValue];
} else if([repeat_interval isEqualToString:@"hourly"]) {
fireDate.hour = fireDate.hour + [interval_value intValue];
} else if([repeat_interval isEqualToString:@"daily"]) {
fireDate.day = fireDate.day + 1;
} else if([repeat_interval isEqualToString:@"weekly"]) {
fireDate.weekday = fireDate.weekday + 1;
}
NSLog(@"------ next fire date: %@", fireDate);
// date to string
NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDate *dateString = [gregorianCalendar dateFromComponents:fireDate];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"dd-MM-yyyy HH:mm:ss"];
NSString *stringFromDate = [formatter stringFromDate:dateString];
NSLog(@"%@", stringFromDate);
UNCalendarNotificationTrigger* trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:fireDate repeats:NO];
// alarm id
NSString *alarmId = [contentInfo.userInfo objectForKey:@"alarmId"];
NSString *soundName = [contentInfo.userInfo objectForKey:@"sound_name"];
NSNumber *playSound = [contentInfo.userInfo objectForKey:@"sound"];
content.userInfo = @{
@"alarmId": alarmId,
@"sound": playSound,
@"vibrate": [contentInfo.userInfo objectForKey:@"vibrate"],
@"data": [contentInfo.userInfo objectForKey:@"data"],
@"fire_date": stringFromDate,
@"sound_name": soundName,
@"loop_sound": [contentInfo.userInfo objectForKey:@"loop_sound"],
@"volume": [contentInfo.userInfo objectForKey:@"volume"],
@"has_button": [contentInfo.userInfo objectForKey:@"has_button"],
@"schedule_type": [contentInfo.userInfo objectForKey:@"schedule_type"],
@"repeat_interval": [contentInfo.userInfo objectForKey:@"repeat_interval"],
@"interval_value": [contentInfo.userInfo objectForKey:@"interval_value"],
@"snooze_interval": [contentInfo.userInfo objectForKey:@"snooze_interval"]
};
if([playSound isEqualToNumber: [NSNumber numberWithInt: 1]]) {
BOOL notEmpty = [RnAlarmNotification checkStringIsNotEmpty:soundName];
if(notEmpty != YES){
content.sound = UNNotificationSound.defaultSound;
} else {
content.sound = [UNNotificationSound soundNamed:soundName];
}
}
// Create the request object.
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:alarmId content:content trigger:trigger];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"error: %@", error.localizedDescription);
}
}];
NSDictionary *alarm = [NSDictionary dictionaryWithObjectsAndKeys: alarmId, @"id", nil];
NSLog(@"repeat alarm: %@", alarm);
} else {
// Fallback on earlier versions
}
} @catch(NSException *exception){
NSLog(@"error: %@", exception.reason);
}
}
+ (void)snoozeAlarm:(UNNotification *)notification API_AVAILABLE(ios(10.0)) {
NSLog(@"do snooze");
[RnAlarmNotification stopSound];
@try {
if (@available(iOS 10.0, *)) {
UNNotificationContent *contentInfo = notification.request.content;
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = contentInfo.title;
content.body = contentInfo.body;
NSNumber *has_button = [contentInfo.userInfo objectForKey:@"has_button"];
NSNumber *snooze_interval = [contentInfo.userInfo objectForKey:@"snooze_interval"];
// set buttons
if([has_button isEqualToNumber: [NSNumber numberWithInt: 1]]){
content.categoryIdentifier = @"CUSTOM_ACTIONS";
}
// set alarm date
int interval = [snooze_interval intValue];
NSTimeInterval snoozeInterval = interval * 60;
NSDate *now = [NSDate date];
NSDate *newDate = [now dateByAddingTimeInterval:snoozeInterval];
NSLog(@"new fire date after snooze: %@", newDate);
NSDateComponents *newFireDate = dateToComponents(newDate);
UNCalendarNotificationTrigger* trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:newFireDate repeats:NO];
NSString *alarmId = [NSString stringWithFormat: @"%ld", (long) NSDate.date.timeIntervalSince1970];
NSString *soundName = [contentInfo.userInfo objectForKey:@"sound_name"];
NSNumber *playSound = [contentInfo.userInfo objectForKey:@"sound"];
content.userInfo = @{
@"alarmId": alarmId,
@"sound": playSound,
@"vibrate": [contentInfo.userInfo objectForKey:@"vibrate"],
@"data": [contentInfo.userInfo objectForKey:@"data"],
@"fire_date": [contentInfo.userInfo objectForKey:@"fire_date"],
@"sound_name": soundName,
@"loop_sound": [contentInfo.userInfo objectForKey:@"loop_sound"],
@"volume": [contentInfo.userInfo objectForKey:@"volume"],
@"has_button": [contentInfo.userInfo objectForKey:@"has_button"],
@"schedule_type": [contentInfo.userInfo objectForKey:@"schedule_type"],
@"repeat_interval": [contentInfo.userInfo objectForKey:@"repeat_interval"],
@"interval_value": [contentInfo.userInfo objectForKey:@"interval_value"],
@"snooze_interval": [contentInfo.userInfo objectForKey:@"snooze_interval"]
};
if([playSound isEqualToNumber: [NSNumber numberWithInt: 1]]) {
BOOL notEmpty = [RnAlarmNotification checkStringIsNotEmpty:soundName];
if(notEmpty != YES){
NSLog(@"use default sound");
content.sound = UNNotificationSound.defaultSound;
} else {
content.sound = [UNNotificationSound soundNamed:soundName];
}
}
// Create the request object.
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:alarmId content:content trigger:trigger];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"error: %@", error.localizedDescription);
}
}];
NSDictionary *alarm = [NSDictionary dictionaryWithObjectsAndKeys: alarmId, @"id", nil];
NSLog(@"snooze alarm: %@", alarm);
} else {
// Fallback on earlier versions
}
} @catch(NSException *exception){
NSLog(@"error: %@", exception.reason);
}
}
+ (BOOL) checkStringIsNotEmpty:(NSString*)string {
if (string == (id)[NSNull null] || string.length == 0) return NO;
return YES;
}
RCT_EXPORT_METHOD(scheduleAlarm: (NSDictionary *)details resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
@try {
if (@available(iOS 10.0, *)) {
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:details[@"title"] arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:details[@"message"] arguments:nil];
// set buttons
if([details[@"has_button"] isEqualToNumber: [NSNumber numberWithInt: 1]]){
content.categoryIdentifier = @"CUSTOM_ACTIONS";
}
// set alarm date
NSDateComponents *fireDate = parseDate(details[@"fire_date"]);
UNCalendarNotificationTrigger* trigger = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:fireDate repeats:NO];
// alarm id
NSString *alarmId = [NSString stringWithFormat: @"%ld", (long) NSDate.date.timeIntervalSince1970];
NSString *volume = [details[@"volume"] stringValue];
content.userInfo = @{
@"alarmId": alarmId,
@"sound": details[@"play_sound"],
@"vibrate": details[@"vibrate"],
@"data": details[@"data"],
@"fire_date": details[@"fire_date"],
@"sound_name": details[@"sound_name"],
@"loop_sound": details[@"loop_sound"],
@"volume": volume,
@"has_button": details[@"has_button"],
@"schedule_type": details[@"schedule_type"],
@"repeat_interval": details[@"repeat_interval"],
@"interval_value": details[@"interval_value"],
@"snooze_interval": details[@"snooze_interval"]
};
if([details[@"play_sound"] isEqualToNumber: [NSNumber numberWithInt: 1]]) {
BOOL notEmpty = [RnAlarmNotification checkStringIsNotEmpty:details[@"sound_name"]];
if(notEmpty != YES){
content.sound = UNNotificationSound.defaultSound;
} else {
content.sound = [UNNotificationSound soundNamed:details[@"sound_name"]];
}
}
// Create the request object.
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:alarmId content:content trigger:trigger];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {
if (error != nil) {
NSLog(@"error: %@", error.localizedDescription);
reject(@"error", nil, error);
}
}];
NSDictionary *alarm = [NSDictionary dictionaryWithObjectsAndKeys: alarmId, @"id", nil];
resolve(alarm);
} else {
// Fallback on earlier versions
}
} @catch(NSException *exception){
NSLog(@"%@", exception.reason);
NSMutableDictionary * info = [NSMutableDictionary dictionary];
[info setValue:exception.name forKey:@"ExceptionName"];
[info setValue:exception.reason forKey:@"ExceptionReason"];
[info setValue:exception.callStackSymbols forKey:@"ExceptionCallStackSymbols"];
[info setValue:exception.userInfo forKey:@"ExceptionUserInfo"];
NSError *error = [[NSError alloc] initWithDomain:exception.name code:0 userInfo:info];
reject(@"error", nil, error);
}
}
RCT_EXPORT_METHOD(sendNotification: (NSDictionary *)details) {
@try {
NSLog(@"send notification now");
if (@available(iOS 10.0, *)) {
UNMutableNotificationContent* content = [[UNMutableNotificationContent alloc] init];
content.title = [NSString localizedUserNotificationStringForKey:details[@"title"] arguments:nil];
content.body = [NSString localizedUserNotificationStringForKey:details[@"message"] arguments:nil];
// set buttons
if([details[@"has_button"] isEqualToNumber: [NSNumber numberWithInt: 1]]){
content.categoryIdentifier = @"CUSTOM_ACTIONS";
}
// alarm id
NSString *alarmId = [NSString stringWithFormat: @"%ld", (long) NSDate.date.timeIntervalSince1970];
NSString *volume = [details[@"volume"] stringValue];
content.userInfo = @{
@"alarmId": alarmId,
@"sound": details[@"play_sound"],
@"vibrate": details[@"vibrate"],
@"data": details[@"data"],
@"sound_name": details[@"sound_name"],
@"loop_sound": details[@"loop_sound"],
@"volume": volume,
@"schedule_type": @"once"
};
if([details[@"play_sound"] isEqualToNumber: [NSNumber numberWithInt: 1]]) {
BOOL notEmpty = [RnAlarmNotification checkStringIsNotEmpty:details[@"sound_name"]];
if(notEmpty != YES){
content.sound = UNNotificationSound.defaultSound;
} else {
content.sound = [UNNotificationSound soundNamed:details[@"sound_name"]];
}
}
// Create the request object.
UNNotificationRequest* request = [UNNotificationRequest requestWithIdentifier:alarmId content:content trigger:nil];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) { }];
} else {
// Fallback on earlier versions
}
} @catch(NSException *exception){
NSLog(@"error: %@", exception.reason);
}
}
RCT_EXPORT_METHOD(deleteAlarm: (NSInteger *)id){
NSLog(@"delete alarm: %li", (long) id);
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
NSArray *array = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%li", (long)id], nil];
[center removePendingNotificationRequestsWithIdentifiers:array];
} else {
// Fallback on earlier versions
}
}
RCT_EXPORT_METHOD(deleteRepeatingAlarm: (NSInteger *)id){
NSLog(@"delete alarm: %li", (long) id);
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
NSArray *array = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%li", (long)id], nil];
[center removePendingNotificationRequestsWithIdentifiers:array];
} else {
// Fallback on earlier versions
}
}
RCT_EXPORT_METHOD(stopAlarmSound){
NSLog(@"stop alarm sound");
[RnAlarmNotification stopSound];
}
RCT_EXPORT_METHOD(removeFiredNotification: (NSInteger)id){
NSLog(@"remove fired notification: %li", (long) id);
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
NSArray *array = [NSArray arrayWithObjects:[NSString stringWithFormat:@"%li", (long)id], nil];
[center removeDeliveredNotificationsWithIdentifiers:array];
} else {
// Fallback on earlier versions
}
}
RCT_EXPORT_METHOD(removeAllFiredNotifications){
NSLog(@"remove all notifications");
if (@available(iOS 10.0, *)) {
if ([UNUserNotificationCenter class]) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center removeAllDeliveredNotifications];
}
} else {
// Fallback on earlier versions
}
}
API_AVAILABLE(ios(10.0))
static NSDictionary *RCTFormatUNNotificationRequest(UNNotificationRequest *request)
{
NSMutableDictionary *formattedNotification = [NSMutableDictionary dictionary];
UNNotificationContent *content = request.content;
NSDateComponents *fireDate = parseDate(content.userInfo[@"fire_date"]);
formattedNotification[@"id"] = request.identifier;
formattedNotification[@"day"] = [NSString stringWithFormat:@"%li", (long)fireDate.day];
formattedNotification[@"month"] = [NSString stringWithFormat:@"%li", (long)fireDate.month];
formattedNotification[@"year"] = [NSString stringWithFormat:@"%li", (long)fireDate.year];
formattedNotification[@"hour"] = [NSString stringWithFormat:@"%li", (long)fireDate.hour];
formattedNotification[@"minute"] =[NSString stringWithFormat:@"%li", (long)fireDate.minute];
formattedNotification[@"second"] = [NSString stringWithFormat:@"%li", (long)fireDate.second];
return formattedNotification;
}
RCT_EXPORT_METHOD(getScheduledAlarms: (RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject){
NSLog(@"get all notifications");
if (@available(iOS 10.0, *)) {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> * _Nonnull requests) {
NSLog(@"count%lu",(unsigned long)requests.count);
NSMutableArray<NSDictionary *> *formattedNotifications = [NSMutableArray new];
for (UNNotificationRequest *request in requests) {
[formattedNotifications addObject:RCTFormatUNNotificationRequest(request)];
}
resolve(formattedNotifications);
}];
} else {
resolve(nil);
}
}
RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) {
if (RCTRunningInAppExtension()) {
reject(@"E_UNABLE_TO_REQUEST_PERMISSIONS", nil, RCTErrorWithMessage(@"Requesting push notifications is currently unavailable in an app extension"));
return;
}
UIUserNotificationType types = UIUserNotificationTypeNone;
if (permissions) {
if ([RCTConvert BOOL:permissions[@"alert"]]) {
types |= UIUserNotificationTypeAlert;
}
if ([RCTConvert BOOL:permissions[@"badge"]]) {
types |= UIUserNotificationTypeBadge;
}
if ([RCTConvert BOOL:permissions[@"sound"]]) {
types |= UIUserNotificationTypeSound;
}
} else {
types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
}
if (@available(iOS 10.0, *)) {
UNNotificationCategory* generalCategory = [UNNotificationCategory
categoryWithIdentifier:@"GENERAL"
actions:@[]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
UNNotificationAction* snoozeAction = [UNNotificationAction
actionWithIdentifier:@"SNOOZE_ACTION"
title:@"SNOOZE"
options:UNNotificationActionOptionNone];
UNNotificationAction* stopAction = [UNNotificationAction
actionWithIdentifier:@"DISMISS_ACTION"
title:@"DISMISS"
options:UNNotificationActionOptionForeground];
UNNotificationCategory* customCategory = [UNNotificationCategory
categoryWithIdentifier:@"CUSTOM_ACTIONS"
actions:@[snoozeAction, stopAction]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionNone];
UNUserNotificationCenter* center = [UNUserNotificationCenter currentNotificationCenter];
[center setNotificationCategories:[NSSet setWithObjects:generalCategory, customCategory, nil]];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert + UIUserNotificationTypeBadge + UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError *_Nullable error) {
if (error != NULL) {
reject(@"-1", @"Error - Push authorization request failed.", error);
} else {
dispatch_async(dispatch_get_main_queue(), ^(void){
[RCTSharedApplication() registerForRemoteNotifications];
});
[UNUserNotificationCenter.currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
resolve(RCTPromiseResolveValueForUNNotificationSettings(settings));
}];
}
}];
} else {
// Fallback on earlier versions
resolve(nil);
}
}
RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback) {
if (RCTRunningInAppExtension()) {
callback(@[RCTSettingsDictForUNNotificationSettings(NO, NO, NO, NO, NO)]);
return;
}
if (@available(iOS 10.0, *)) {
[UNUserNotificationCenter.currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
callback(@[RCTPromiseResolveValueForUNNotificationSettings(settings)]);
}];
} else {
// Fallback on earlier versions
}
}
API_AVAILABLE(ios(10.0))
static inline NSDictionary *RCTPromiseResolveValueForUNNotificationSettings(UNNotificationSettings* _Nonnull settings) {
return RCTSettingsDictForUNNotificationSettings(settings.alertSetting == UNNotificationSettingEnabled, settings.badgeSetting == UNNotificationSettingEnabled, settings.soundSetting == UNNotificationSettingEnabled, settings.lockScreenSetting == UNNotificationSettingEnabled, settings.notificationCenterSetting == UNNotificationSettingEnabled);
}
static inline NSDictionary *RCTSettingsDictForUNNotificationSettings(BOOL alert, BOOL badge, BOOL sound, BOOL lockScreen, BOOL notificationCenter) {
return @{@"alert": @(alert), @"badge": @(badge), @"sound": @(sound), @"lockScreen": @(lockScreen), @"notificationCenter": @(notificationCenter)};
}
@end