Add observers for local notifications
Summary: This commit adds the delegate hooks so that local notifications get passed onto the JS and adds a new event listener type for local notifications. Also add functions to clear local notifications Closes https://github.com/facebook/react-native/pull/2084 Reviewed By: svcscm Differential Revision: D2908096 Pulled By: nicklockwood fb-gh-sync-id: 759d299ea35abea177e72934076297d666d3ea20 shipit-source-id: 759d299ea35abea177e72934076297d666d3ea20
This commit is contained in:
parent
c6366e4dd8
commit
758d9e8304
|
@ -21,6 +21,7 @@ var _initialNotification = RCTPushNotificationManager &&
|
||||||
|
|
||||||
var DEVICE_NOTIF_EVENT = 'remoteNotificationReceived';
|
var DEVICE_NOTIF_EVENT = 'remoteNotificationReceived';
|
||||||
var NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered';
|
var NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered';
|
||||||
|
var DEVICE_LOCAL_NOTIF_EVENT = 'localNotificationReceived';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle push notifications for your app, including permission handling and
|
* Handle push notifications for your app, including permission handling and
|
||||||
|
@ -59,6 +60,11 @@ var NOTIF_REGISTER_EVENT = 'remoteNotificationsRegistered';
|
||||||
* {
|
* {
|
||||||
* [RCTPushNotificationManager didReceiveRemoteNotification:notification];
|
* [RCTPushNotificationManager didReceiveRemoteNotification:notification];
|
||||||
* }
|
* }
|
||||||
|
* // Required for the localNotification event.
|
||||||
|
* - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
|
||||||
|
* {
|
||||||
|
* [RCTPushNotificationManager didReceiveLocalNotification:notification];
|
||||||
|
* }
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class PushNotificationIOS {
|
class PushNotificationIOS {
|
||||||
|
@ -74,7 +80,6 @@ class PushNotificationIOS {
|
||||||
*
|
*
|
||||||
* - `alertBody` : The message displayed in the notification alert.
|
* - `alertBody` : The message displayed in the notification alert.
|
||||||
* - `soundName` : The sound played when the notification is fired (optional).
|
* - `soundName` : The sound played when the notification is fired (optional).
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static presentLocalNotification(details: Object) {
|
static presentLocalNotification(details: Object) {
|
||||||
RCTPushNotificationManager.presentLocalNotification(details);
|
RCTPushNotificationManager.presentLocalNotification(details);
|
||||||
|
@ -88,7 +93,7 @@ class PushNotificationIOS {
|
||||||
* - `fireDate` : The date and time when the system should deliver the notification.
|
* - `fireDate` : The date and time when the system should deliver the notification.
|
||||||
* - `alertBody` : The message displayed in the notification alert.
|
* - `alertBody` : The message displayed in the notification alert.
|
||||||
* - `soundName` : The sound played when the notification is fired (optional).
|
* - `soundName` : The sound played when the notification is fired (optional).
|
||||||
*
|
* - `userInfo` : An optional object containing additional notification data.
|
||||||
*/
|
*/
|
||||||
static scheduleLocalNotification(details: Object) {
|
static scheduleLocalNotification(details: Object) {
|
||||||
RCTPushNotificationManager.scheduleLocalNotification(details);
|
RCTPushNotificationManager.scheduleLocalNotification(details);
|
||||||
|
@ -115,6 +120,17 @@ class PushNotificationIOS {
|
||||||
RCTPushNotificationManager.getApplicationIconBadgeNumber(callback);
|
RCTPushNotificationManager.getApplicationIconBadgeNumber(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel local notifications.
|
||||||
|
*
|
||||||
|
* Optionally restricts the set of canceled notifications to those
|
||||||
|
* notifications whose `userInfo` fields match the corresponding fields
|
||||||
|
* in the `userInfo` argument.
|
||||||
|
*/
|
||||||
|
static cancelLocalNotifications(userInfo: Object) {
|
||||||
|
RCTPushNotificationManager.cancelLocalNotifications(userInfo);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Attaches a listener to remote notification events while the app is running
|
* Attaches a listener to remote notification events while the app is running
|
||||||
* in the foreground or the background.
|
* in the foreground or the background.
|
||||||
|
@ -128,8 +144,8 @@ class PushNotificationIOS {
|
||||||
*/
|
*/
|
||||||
static addEventListener(type: string, handler: Function) {
|
static addEventListener(type: string, handler: Function) {
|
||||||
invariant(
|
invariant(
|
||||||
type === 'notification' || type === 'register',
|
type === 'notification' || type === 'register' || type === 'localNotification',
|
||||||
'PushNotificationIOS only supports `notification` and `register` events'
|
'PushNotificationIOS only supports `notification`, `register` and `localNotification` events'
|
||||||
);
|
);
|
||||||
var listener;
|
var listener;
|
||||||
if (type === 'notification') {
|
if (type === 'notification') {
|
||||||
|
@ -139,6 +155,13 @@ class PushNotificationIOS {
|
||||||
handler(new PushNotificationIOS(notifData));
|
handler(new PushNotificationIOS(notifData));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
} else if (type === 'localNotification') {
|
||||||
|
listener = RCTDeviceEventEmitter.addListener(
|
||||||
|
DEVICE_LOCAL_NOTIF_EVENT,
|
||||||
|
(notifData) => {
|
||||||
|
handler(new PushNotificationIOS(notifData));
|
||||||
|
}
|
||||||
|
);
|
||||||
} else if (type === 'register') {
|
} else if (type === 'register') {
|
||||||
listener = RCTDeviceEventEmitter.addListener(
|
listener = RCTDeviceEventEmitter.addListener(
|
||||||
NOTIF_REGISTER_EVENT,
|
NOTIF_REGISTER_EVENT,
|
||||||
|
@ -220,8 +243,8 @@ class PushNotificationIOS {
|
||||||
*/
|
*/
|
||||||
static removeEventListener(type: string, handler: Function) {
|
static removeEventListener(type: string, handler: Function) {
|
||||||
invariant(
|
invariant(
|
||||||
type === 'notification' || type === 'register',
|
type === 'notification' || type === 'register' || type === 'localNotification',
|
||||||
'PushNotificationIOS only supports `notification` and `register` events'
|
'PushNotificationIOS only supports `notification`, `register` and `localNotification` events'
|
||||||
);
|
);
|
||||||
var listener = _notifHandlers.get(handler);
|
var listener = _notifHandlers.get(handler);
|
||||||
if (!listener) {
|
if (!listener) {
|
||||||
|
|
|
@ -16,5 +16,6 @@
|
||||||
+ (void)didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings;
|
+ (void)didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings;
|
||||||
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
|
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;
|
||||||
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification;
|
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification;
|
||||||
|
+ (void)didReceiveLocalNotification:(UILocalNotification *)notification;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
NSString *const RCTLocalNotificationReceived = @"LocalNotificationReceived";
|
||||||
NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived";
|
NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived";
|
||||||
NSString *const RCTRemoteNotificationsRegistered = @"RemoteNotificationsRegistered";
|
NSString *const RCTRemoteNotificationsRegistered = @"RemoteNotificationsRegistered";
|
||||||
|
|
||||||
|
@ -36,6 +37,7 @@ NSString *const RCTRemoteNotificationsRegistered = @"RemoteNotificationsRegister
|
||||||
notification.fireDate = [RCTConvert NSDate:details[@"fireDate"]] ?: [NSDate date];
|
notification.fireDate = [RCTConvert NSDate:details[@"fireDate"]] ?: [NSDate date];
|
||||||
notification.alertBody = [RCTConvert NSString:details[@"alertBody"]];
|
notification.alertBody = [RCTConvert NSString:details[@"alertBody"]];
|
||||||
notification.soundName = [RCTConvert NSString:details[@"soundName"]] ?: UILocalNotificationDefaultSoundName;
|
notification.soundName = [RCTConvert NSString:details[@"soundName"]] ?: UILocalNotificationDefaultSoundName;
|
||||||
|
notification.userInfo = [RCTConvert NSDictionary:details[@"userInfo"]];
|
||||||
return notification;
|
return notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +58,10 @@ RCT_EXPORT_MODULE()
|
||||||
{
|
{
|
||||||
_bridge = bridge;
|
_bridge = bridge;
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
|
selector:@selector(handleLocalNotificationReceived:)
|
||||||
|
name:RCTLocalNotificationReceived
|
||||||
|
object:nil];
|
||||||
[[NSNotificationCenter defaultCenter] addObserver:self
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
||||||
selector:@selector(handleRemoteNotificationReceived:)
|
selector:@selector(handleRemoteNotificationReceived:)
|
||||||
name:RCTRemoteNotificationReceived
|
name:RCTRemoteNotificationReceived
|
||||||
|
@ -68,7 +74,8 @@ RCT_EXPORT_MODULE()
|
||||||
|
|
||||||
- (NSDictionary<NSString *, id> *)constantsToExport
|
- (NSDictionary<NSString *, id> *)constantsToExport
|
||||||
{
|
{
|
||||||
NSDictionary<NSString *, id> *initialNotification = [_bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
|
NSDictionary<NSString *, id> *initialNotification =
|
||||||
|
[_bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
|
||||||
return @{@"initialNotification": RCTNullIfNil(initialNotification)};
|
return @{@"initialNotification": RCTNullIfNil(initialNotification)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,12 +94,9 @@ RCT_EXPORT_MODULE()
|
||||||
for (NSUInteger i = 0; i < deviceTokenLength; i++) {
|
for (NSUInteger i = 0; i < deviceTokenLength; i++) {
|
||||||
[hexString appendFormat:@"%02x", bytes[i]];
|
[hexString appendFormat:@"%02x", bytes[i]];
|
||||||
}
|
}
|
||||||
NSDictionary<NSString *, id> *userInfo = @{
|
|
||||||
@"deviceToken" : [hexString copy]
|
|
||||||
};
|
|
||||||
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationsRegistered
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationsRegistered
|
||||||
object:self
|
object:self
|
||||||
userInfo:userInfo];
|
userInfo:@{@"deviceToken" : [hexString copy]}];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
|
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
|
||||||
|
@ -102,6 +106,26 @@ RCT_EXPORT_MODULE()
|
||||||
userInfo:notification];
|
userInfo:notification];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+ (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
|
||||||
|
{
|
||||||
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"localNotificationReceived"
|
||||||
|
body:notification.userInfo];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)handleRemoteNotificationReceived:(NSNotification *)notification
|
- (void)handleRemoteNotificationReceived:(NSNotification *)notification
|
||||||
{
|
{
|
||||||
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationReceived"
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationReceived"
|
||||||
|
@ -127,9 +151,7 @@ RCT_EXPORT_METHOD(setApplicationIconBadgeNumber:(NSInteger)number)
|
||||||
*/
|
*/
|
||||||
RCT_EXPORT_METHOD(getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback)
|
RCT_EXPORT_METHOD(getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback)
|
||||||
{
|
{
|
||||||
callback(@[
|
callback(@[@(RCTSharedApplication().applicationIconBadgeNumber)]);
|
||||||
@(RCTSharedApplication().applicationIconBadgeNumber)
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions)
|
RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions)
|
||||||
|
@ -140,13 +162,13 @@ RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions)
|
||||||
|
|
||||||
UIUserNotificationType types = UIUserNotificationTypeNone;
|
UIUserNotificationType types = UIUserNotificationTypeNone;
|
||||||
if (permissions) {
|
if (permissions) {
|
||||||
if ([permissions[@"alert"] boolValue]) {
|
if ([RCTConvert BOOL:permissions[@"alert"]]) {
|
||||||
types |= UIUserNotificationTypeAlert;
|
types |= UIUserNotificationTypeAlert;
|
||||||
}
|
}
|
||||||
if ([permissions[@"badge"] boolValue]) {
|
if ([RCTConvert BOOL:permissions[@"badge"]]) {
|
||||||
types |= UIUserNotificationTypeBadge;
|
types |= UIUserNotificationTypeBadge;
|
||||||
}
|
}
|
||||||
if ([permissions[@"sound"] boolValue]) {
|
if ([RCTConvert BOOL:permissions[@"sound"]]) {
|
||||||
types |= UIUserNotificationTypeSound;
|
types |= UIUserNotificationTypeSound;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,7 +177,8 @@ RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions)
|
||||||
|
|
||||||
UIApplication *app = RCTSharedApplication();
|
UIApplication *app = RCTSharedApplication();
|
||||||
if ([app respondsToSelector:@selector(registerUserNotificationSettings:)]) {
|
if ([app respondsToSelector:@selector(registerUserNotificationSettings:)]) {
|
||||||
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:(NSUInteger)types categories:nil];
|
UIUserNotificationSettings *notificationSettings =
|
||||||
|
[UIUserNotificationSettings settingsForTypes:(NSUInteger)types categories:nil];
|
||||||
[app registerUserNotificationSettings:notificationSettings];
|
[app registerUserNotificationSettings:notificationSettings];
|
||||||
[app registerForRemoteNotifications];
|
[app registerForRemoteNotifications];
|
||||||
} else {
|
} else {
|
||||||
|
@ -171,8 +194,7 @@ RCT_EXPORT_METHOD(abandonPermissions)
|
||||||
RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
|
RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
|
||||||
{
|
{
|
||||||
if (RCTRunningInAppExtension()) {
|
if (RCTRunningInAppExtension()) {
|
||||||
NSDictionary<NSString *, NSNumber *> *permissions = @{@"alert": @NO, @"badge": @NO, @"sound": @NO};
|
callback(@[@{@"alert": @NO, @"badge": @NO, @"sound": @NO}]);
|
||||||
callback(@[permissions]);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,12 +211,11 @@ RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NSMutableDictionary<NSString *, NSNumber *> *permissions = [NSMutableDictionary new];
|
callback(@[@{
|
||||||
permissions[@"alert"] = @((types & UIUserNotificationTypeAlert) > 0);
|
@"alert": @((types & UIUserNotificationTypeAlert) > 0),
|
||||||
permissions[@"badge"] = @((types & UIUserNotificationTypeBadge) > 0);
|
@"badge": @((types & UIUserNotificationTypeBadge) > 0),
|
||||||
permissions[@"sound"] = @((types & UIUserNotificationTypeSound) > 0);
|
@"sound": @((types & UIUserNotificationTypeSound) > 0),
|
||||||
|
}]);
|
||||||
callback(@[permissions]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RCT_EXPORT_METHOD(presentLocalNotification:(UILocalNotification *)notification)
|
RCT_EXPORT_METHOD(presentLocalNotification:(UILocalNotification *)notification)
|
||||||
|
@ -212,4 +233,21 @@ RCT_EXPORT_METHOD(cancelAllLocalNotifications)
|
||||||
[RCTSharedApplication() cancelAllLocalNotifications];
|
[RCTSharedApplication() cancelAllLocalNotifications];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -23,7 +23,7 @@ RCT_EXTERN NSString *__nullable RCTJSONStringify(id __nullable jsonObject, NSErr
|
||||||
RCT_EXTERN id __nullable RCTJSONParse(NSString *__nullable jsonString, NSError **error);
|
RCT_EXTERN id __nullable RCTJSONParse(NSString *__nullable jsonString, NSError **error);
|
||||||
RCT_EXTERN id __nullable RCTJSONParseMutable(NSString *__nullable jsonString, NSError **error);
|
RCT_EXTERN id __nullable RCTJSONParseMutable(NSString *__nullable jsonString, NSError **error);
|
||||||
|
|
||||||
// Santize a JSON string by stripping invalid objects and/or NaN values
|
// Sanitize a JSON object by stripping invalid types and/or NaN values
|
||||||
RCT_EXTERN id RCTJSONClean(id object);
|
RCT_EXTERN id RCTJSONClean(id object);
|
||||||
|
|
||||||
// Get MD5 hash of a string
|
// Get MD5 hash of a string
|
||||||
|
|
Loading…
Reference in New Issue