2015-03-24 12:31:11 +00:00
|
|
|
/**
|
|
|
|
* Copyright (c) 2015-present, Facebook, Inc.
|
|
|
|
* All rights reserved.
|
|
|
|
*
|
|
|
|
* This source code is licensed under the BSD-style license found in the
|
|
|
|
* LICENSE file in the root directory of this source tree. An additional grant
|
|
|
|
* of patent rights can be found in the PATENTS file in the same directory.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#import "RCTPushNotificationManager.h"
|
|
|
|
|
|
|
|
#import "RCTBridge.h"
|
2015-07-14 16:07:24 +00:00
|
|
|
#import "RCTConvert.h"
|
2015-03-24 12:31:11 +00:00
|
|
|
#import "RCTEventDispatcher.h"
|
2015-06-12 18:05:01 +00:00
|
|
|
#import "RCTUtils.h"
|
2015-03-24 12:31:11 +00:00
|
|
|
|
2015-06-03 21:11:20 +00:00
|
|
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
|
|
|
|
|
|
|
#define UIUserNotificationTypeAlert UIRemoteNotificationTypeAlert
|
|
|
|
#define UIUserNotificationTypeBadge UIRemoteNotificationTypeBadge
|
|
|
|
#define UIUserNotificationTypeSound UIRemoteNotificationTypeSound
|
|
|
|
#define UIUserNotificationTypeNone UIRemoteNotificationTypeNone
|
|
|
|
#define UIUserNotificationType UIRemoteNotificationType
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2016-02-09 13:45:23 +00:00
|
|
|
NSString *const RCTLocalNotificationReceived = @"LocalNotificationReceived";
|
2015-03-24 12:31:11 +00:00
|
|
|
NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived";
|
2015-06-03 21:11:20 +00:00
|
|
|
NSString *const RCTRemoteNotificationsRegistered = @"RemoteNotificationsRegistered";
|
2016-06-03 23:14:44 +00:00
|
|
|
NSString *const RCTRegisterUserNotificationSettings = @"RegisterUserNotificationSettings";
|
|
|
|
|
|
|
|
NSString *const RCTErrorUnableToRequestPermissions = @"E_UNABLE_TO_REQUEST_PERMISSIONS";
|
|
|
|
|
|
|
|
@interface RCTPushNotificationManager ()
|
|
|
|
@property (nonatomic, copy) RCTPromiseResolveBlock requestPermissionsResolveBlock;
|
|
|
|
@end
|
2015-03-24 12:31:11 +00:00
|
|
|
|
2015-07-14 16:07:24 +00:00
|
|
|
@implementation RCTConvert (UILocalNotification)
|
|
|
|
|
|
|
|
+ (UILocalNotification *)UILocalNotification:(id)json
|
|
|
|
{
|
2015-11-14 18:25:00 +00:00
|
|
|
NSDictionary<NSString *, id> *details = [self NSDictionary:json];
|
2015-08-17 14:35:34 +00:00
|
|
|
UILocalNotification *notification = [UILocalNotification new];
|
2015-07-14 16:07:24 +00:00
|
|
|
notification.fireDate = [RCTConvert NSDate:details[@"fireDate"]] ?: [NSDate date];
|
|
|
|
notification.alertBody = [RCTConvert NSString:details[@"alertBody"]];
|
2016-02-19 13:18:24 +00:00
|
|
|
notification.alertAction = [RCTConvert NSString:details[@"alertAction"]];
|
2016-01-07 13:01:11 +00:00
|
|
|
notification.soundName = [RCTConvert NSString:details[@"soundName"]] ?: UILocalNotificationDefaultSoundName;
|
2016-02-09 13:45:23 +00:00
|
|
|
notification.userInfo = [RCTConvert NSDictionary:details[@"userInfo"]];
|
2016-02-19 13:18:24 +00:00
|
|
|
notification.category = [RCTConvert NSString:details[@"category"]];
|
2016-04-29 12:36:08 +00:00
|
|
|
if (details[@"applicationIconBadgeNumber"]) {
|
|
|
|
notification.applicationIconBadgeNumber = [RCTConvert NSInteger:details[@"applicationIconBadgeNumber"]];
|
|
|
|
}
|
2015-07-14 16:07:24 +00:00
|
|
|
return notification;
|
|
|
|
}
|
|
|
|
|
|
|
|
@end
|
|
|
|
|
2015-03-24 12:31:11 +00:00
|
|
|
@implementation RCTPushNotificationManager
|
|
|
|
|
2015-04-08 12:42:43 +00:00
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
|
2016-05-27 17:14:12 +00:00
|
|
|
- (void)startObserving
|
2016-05-04 14:06:09 +00:00
|
|
|
{
|
2016-02-09 13:45:23 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(handleLocalNotificationReceived:)
|
|
|
|
name:RCTLocalNotificationReceived
|
|
|
|
object:nil];
|
2015-11-25 11:09:00 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(handleRemoteNotificationReceived:)
|
|
|
|
name:RCTRemoteNotificationReceived
|
|
|
|
object:nil];
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(handleRemoteNotificationsRegistered:)
|
|
|
|
name:RCTRemoteNotificationsRegistered
|
|
|
|
object:nil];
|
2016-06-03 23:14:44 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
|
|
selector:@selector(handleRegisterUserNotificationSettings:)
|
|
|
|
name:RCTRegisterUserNotificationSettings
|
|
|
|
object:nil];
|
2015-11-25 11:09:00 +00:00
|
|
|
}
|
|
|
|
|
2016-05-27 17:14:12 +00:00
|
|
|
- (void)stopObserving
|
|
|
|
{
|
|
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (NSArray<NSString *> *)supportedEvents
|
|
|
|
{
|
|
|
|
return @[@"localNotificationReceived",
|
|
|
|
@"remoteNotificationReceived",
|
|
|
|
@"remoteNotificationsRegistered"];
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Once all JS call sites for popInitialNotification have
|
|
|
|
// been removed we can get rid of this
|
2015-11-25 11:09:00 +00:00
|
|
|
- (NSDictionary<NSString *, id> *)constantsToExport
|
|
|
|
{
|
2016-02-09 13:45:23 +00:00
|
|
|
NSDictionary<NSString *, id> *initialNotification =
|
2016-05-27 17:14:12 +00:00
|
|
|
[self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
|
2015-11-25 11:09:00 +00:00
|
|
|
return @{@"initialNotification": RCTNullIfNil(initialNotification)};
|
2015-04-30 21:09:55 +00:00
|
|
|
}
|
|
|
|
|
2016-01-05 10:42:18 +00:00
|
|
|
+ (void)didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings *)notificationSettings
|
2015-03-24 12:31:11 +00:00
|
|
|
{
|
2016-01-05 10:42:18 +00:00
|
|
|
if ([UIApplication instancesRespondToSelector:@selector(registerForRemoteNotifications)]) {
|
|
|
|
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
2016-06-03 23:14:44 +00:00
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRegisterUserNotificationSettings
|
|
|
|
object:self
|
|
|
|
userInfo:@{@"notificationSettings": notificationSettings}];
|
2015-03-25 00:37:03 +00:00
|
|
|
}
|
2015-03-24 12:31:11 +00:00
|
|
|
}
|
|
|
|
|
2016-01-05 10:42:18 +00:00
|
|
|
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
2015-06-03 21:11:20 +00:00
|
|
|
{
|
|
|
|
NSMutableString *hexString = [NSMutableString string];
|
2015-06-15 14:53:45 +00:00
|
|
|
NSUInteger deviceTokenLength = deviceToken.length;
|
|
|
|
const unsigned char *bytes = deviceToken.bytes;
|
|
|
|
for (NSUInteger i = 0; i < deviceTokenLength; i++) {
|
2015-06-03 21:11:20 +00:00
|
|
|
[hexString appendFormat:@"%02x", bytes[i]];
|
|
|
|
}
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationsRegistered
|
|
|
|
object:self
|
2016-02-09 13:45:23 +00:00
|
|
|
userInfo:@{@"deviceToken" : [hexString copy]}];
|
2015-06-03 21:11:20 +00:00
|
|
|
}
|
|
|
|
|
2016-01-05 10:42:18 +00:00
|
|
|
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
|
2015-03-24 12:31:11 +00:00
|
|
|
{
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
|
|
|
|
object:self
|
|
|
|
userInfo:notification];
|
|
|
|
}
|
|
|
|
|
2016-02-09 13:45:23 +00:00
|
|
|
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification
|
|
|
|
{
|
|
|
|
NSMutableDictionary *details = [NSMutableDictionary new];
|
|
|
|
if (notification.alertBody) {
|
|
|
|
details[@"alertBody"] = notification.alertBody;
|
|
|
|
}
|
|
|
|
if (notification.userInfo) {
|
|
|
|
details[@"userInfo"] = RCTJSONClean(notification.userInfo);
|
|
|
|
}
|
|
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTLocalNotificationReceived
|
|
|
|
object:self
|
|
|
|
userInfo:details];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)handleLocalNotificationReceived:(NSNotification *)notification
|
|
|
|
{
|
2016-05-27 17:14:12 +00:00
|
|
|
[self sendEventWithName:@"localNotificationReceived" body:notification.userInfo];
|
2016-02-09 13:45:23 +00:00
|
|
|
}
|
|
|
|
|
2015-03-24 12:31:11 +00:00
|
|
|
- (void)handleRemoteNotificationReceived:(NSNotification *)notification
|
|
|
|
{
|
2016-05-27 17:14:12 +00:00
|
|
|
[self sendEventWithName:@"remoteNotificationReceived" body:notification.userInfo];
|
2015-03-24 12:31:11 +00:00
|
|
|
}
|
|
|
|
|
2015-06-03 21:11:20 +00:00
|
|
|
- (void)handleRemoteNotificationsRegistered:(NSNotification *)notification
|
|
|
|
{
|
2016-05-27 17:14:12 +00:00
|
|
|
[self sendEventWithName:@"remoteNotificationsRegistered" body:notification.userInfo];
|
2015-06-03 21:11:20 +00:00
|
|
|
}
|
|
|
|
|
2016-06-03 23:14:44 +00:00
|
|
|
- (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
|
|
|
|
{
|
|
|
|
if (self.requestPermissionsResolveBlock == nil) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
UIUserNotificationSettings *notificationSettings = notification.userInfo[@"notificationSettings"];
|
|
|
|
NSDictionary *notificationTypes = @{
|
|
|
|
@"alert": @((notificationSettings.types & UIUserNotificationTypeAlert) > 0),
|
|
|
|
@"sound": @((notificationSettings.types & UIUserNotificationTypeSound) > 0),
|
|
|
|
@"badge": @((notificationSettings.types & UIUserNotificationTypeBadge) > 0),
|
|
|
|
};
|
|
|
|
|
|
|
|
self.requestPermissionsResolveBlock(notificationTypes);
|
|
|
|
self.requestPermissionsResolveBlock = nil;
|
|
|
|
}
|
|
|
|
|
2015-03-24 12:31:11 +00:00
|
|
|
/**
|
|
|
|
* Update the application icon badge number on the home screen
|
|
|
|
*/
|
2015-04-08 15:52:48 +00:00
|
|
|
RCT_EXPORT_METHOD(setApplicationIconBadgeNumber:(NSInteger)number)
|
2015-03-24 12:31:11 +00:00
|
|
|
{
|
2015-09-22 17:43:56 +00:00
|
|
|
RCTSharedApplication().applicationIconBadgeNumber = number;
|
2015-03-24 12:31:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the current application icon badge number on the home screen
|
|
|
|
*/
|
2015-04-08 15:52:48 +00:00
|
|
|
RCT_EXPORT_METHOD(getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback)
|
2015-03-24 12:31:11 +00:00
|
|
|
{
|
2016-02-09 13:45:23 +00:00
|
|
|
callback(@[@(RCTSharedApplication().applicationIconBadgeNumber)]);
|
2015-03-24 12:31:11 +00:00
|
|
|
}
|
|
|
|
|
2016-06-03 23:14:44 +00:00
|
|
|
RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions
|
|
|
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
|
|
rejecter:(RCTPromiseRejectBlock)reject)
|
2015-03-24 12:31:11 +00:00
|
|
|
{
|
2015-09-22 17:43:56 +00:00
|
|
|
if (RCTRunningInAppExtension()) {
|
2016-06-03 23:14:44 +00:00
|
|
|
reject(RCTErrorUnableToRequestPermissions, nil, RCTErrorWithMessage(@"Requesting push notifications is currently unavailable in an app extension"));
|
2015-09-22 17:43:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-06-03 23:14:44 +00:00
|
|
|
if (self.requestPermissionsResolveBlock != nil) {
|
|
|
|
RCTLogError(@"Cannot call requestPermissions twice before the first has returned.");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.requestPermissionsResolveBlock = resolve;
|
|
|
|
|
2015-06-09 22:42:10 +00:00
|
|
|
UIUserNotificationType types = UIUserNotificationTypeNone;
|
2015-06-03 21:11:20 +00:00
|
|
|
if (permissions) {
|
2016-02-09 13:45:23 +00:00
|
|
|
if ([RCTConvert BOOL:permissions[@"alert"]]) {
|
2015-06-03 21:11:20 +00:00
|
|
|
types |= UIUserNotificationTypeAlert;
|
|
|
|
}
|
2016-02-09 13:45:23 +00:00
|
|
|
if ([RCTConvert BOOL:permissions[@"badge"]]) {
|
2015-06-03 21:11:20 +00:00
|
|
|
types |= UIUserNotificationTypeBadge;
|
|
|
|
}
|
2016-02-09 13:45:23 +00:00
|
|
|
if ([RCTConvert BOOL:permissions[@"sound"]]) {
|
2015-06-03 21:11:20 +00:00
|
|
|
types |= UIUserNotificationTypeSound;
|
|
|
|
}
|
2015-04-10 10:10:04 +00:00
|
|
|
} else {
|
2015-06-03 21:11:20 +00:00
|
|
|
types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
|
|
|
|
}
|
2015-04-10 10:10:04 +00:00
|
|
|
|
2015-09-22 17:43:56 +00:00
|
|
|
UIApplication *app = RCTSharedApplication();
|
2015-10-01 01:08:54 +00:00
|
|
|
if ([app respondsToSelector:@selector(registerUserNotificationSettings:)]) {
|
2016-02-09 13:45:23 +00:00
|
|
|
UIUserNotificationSettings *notificationSettings =
|
|
|
|
[UIUserNotificationSettings settingsForTypes:(NSUInteger)types categories:nil];
|
2015-10-01 01:08:54 +00:00
|
|
|
[app registerUserNotificationSettings:notificationSettings];
|
|
|
|
} else {
|
|
|
|
[app registerForRemoteNotificationTypes:(NSUInteger)types];
|
|
|
|
}
|
2015-03-24 12:31:11 +00:00
|
|
|
}
|
|
|
|
|
2015-06-15 19:14:23 +00:00
|
|
|
RCT_EXPORT_METHOD(abandonPermissions)
|
|
|
|
{
|
2015-09-22 17:43:56 +00:00
|
|
|
[RCTSharedApplication() unregisterForRemoteNotifications];
|
2015-06-15 19:14:23 +00:00
|
|
|
}
|
|
|
|
|
2015-04-08 15:52:48 +00:00
|
|
|
RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
|
2015-03-24 12:31:11 +00:00
|
|
|
{
|
2015-09-22 17:43:56 +00:00
|
|
|
if (RCTRunningInAppExtension()) {
|
2016-02-09 13:45:23 +00:00
|
|
|
callback(@[@{@"alert": @NO, @"badge": @NO, @"sound": @NO}]);
|
2015-09-22 17:43:56 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-04-24 15:31:07 +00:00
|
|
|
NSUInteger types = 0;
|
2015-04-10 10:10:04 +00:00
|
|
|
if ([UIApplication instancesRespondToSelector:@selector(currentUserNotificationSettings)]) {
|
2015-09-22 17:43:56 +00:00
|
|
|
types = [RCTSharedApplication() currentUserNotificationSettings].types;
|
2015-04-10 10:10:04 +00:00
|
|
|
} else {
|
|
|
|
|
|
|
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
|
|
|
|
2015-09-22 17:43:56 +00:00
|
|
|
types = [RCTSharedApplication() enabledRemoteNotificationTypes];
|
2015-04-10 10:10:04 +00:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-02-09 13:45:23 +00:00
|
|
|
callback(@[@{
|
|
|
|
@"alert": @((types & UIUserNotificationTypeAlert) > 0),
|
|
|
|
@"badge": @((types & UIUserNotificationTypeBadge) > 0),
|
|
|
|
@"sound": @((types & UIUserNotificationTypeSound) > 0),
|
|
|
|
}]);
|
2015-03-24 12:31:11 +00:00
|
|
|
}
|
|
|
|
|
2015-07-14 16:07:24 +00:00
|
|
|
RCT_EXPORT_METHOD(presentLocalNotification:(UILocalNotification *)notification)
|
|
|
|
{
|
2015-09-22 17:43:56 +00:00
|
|
|
[RCTSharedApplication() presentLocalNotificationNow:notification];
|
2015-07-14 16:07:24 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
RCT_EXPORT_METHOD(scheduleLocalNotification:(UILocalNotification *)notification)
|
|
|
|
{
|
2015-09-22 17:43:56 +00:00
|
|
|
[RCTSharedApplication() scheduleLocalNotification:notification];
|
2015-07-14 16:07:24 +00:00
|
|
|
}
|
|
|
|
|
2015-10-16 17:39:38 +00:00
|
|
|
RCT_EXPORT_METHOD(cancelAllLocalNotifications)
|
|
|
|
{
|
|
|
|
[RCTSharedApplication() cancelAllLocalNotifications];
|
|
|
|
}
|
|
|
|
|
2016-02-09 13:45:23 +00:00
|
|
|
RCT_EXPORT_METHOD(cancelLocalNotifications:(NSDictionary *)userInfo)
|
|
|
|
{
|
|
|
|
for (UILocalNotification *notification in [UIApplication sharedApplication].scheduledLocalNotifications) {
|
|
|
|
__block BOOL matchesAll = YES;
|
|
|
|
NSDictionary *notificationInfo = notification.userInfo;
|
|
|
|
[userInfo enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
|
|
|
|
if (![notificationInfo[key] isEqual:obj]) {
|
|
|
|
matchesAll = NO;
|
|
|
|
*stop = YES;
|
|
|
|
}
|
|
|
|
}];
|
|
|
|
if (matchesAll) {
|
|
|
|
[[UIApplication sharedApplication] cancelLocalNotification:notification];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-05-27 17:14:12 +00:00
|
|
|
RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve
|
|
|
|
reject:(__unused RCTPromiseRejectBlock)reject)
|
|
|
|
{
|
|
|
|
NSDictionary<NSString *, id> *initialNotification =
|
|
|
|
[self.bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
|
|
|
|
resolve(RCTNullIfNil(initialNotification));
|
|
|
|
}
|
|
|
|
|
2015-03-24 12:31:11 +00:00
|
|
|
@end
|