mirror of
https://github.com/status-im/react-native.git
synced 2025-02-12 09:26:37 +00:00
Summary:In order to use iOS notification actions with local notifications, we need to be able to specify a category string. This PR adds a category property to the `details` object used to create a local notification. I also added support for the `alertAction` property, which is used to control the "slide to {alertAction}" text beneath the notification. Finally, I added the doc for `userInfo` to `presentLocalNotification` (previously was only documented for `scheduleLocalNotification`. **Test plan (required)** I implemented the example from the [react-native-ios-notification-actions README](https://github.com/holmesal/react-native-ios-notification-actions), and created a couple of actions and grouped them under a category with identifier `something_happened`. Prior to the changes in this PR, the shown local notification would not contain any actions. With the changes in this PR, the shown local notification contains the specified actions. Like so: ![demo](https://camo.githubusercontent.com/c4a86 Closes https://github.com/facebook/react-native/pull/5994 Differential Revision: D2953919 Pulled By: nicklockwood fb-gh-sync-id: a05a9ea9ae8c150ff0714e106410e094c2747eca shipit-source-id: a05a9ea9ae8c150ff0714e106410e094c2747eca
256 lines
8.8 KiB
Objective-C
256 lines
8.8 KiB
Objective-C
/**
|
|
* 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"
|
|
#import "RCTConvert.h"
|
|
#import "RCTEventDispatcher.h"
|
|
#import "RCTUtils.h"
|
|
|
|
#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
|
|
|
|
NSString *const RCTLocalNotificationReceived = @"LocalNotificationReceived";
|
|
NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived";
|
|
NSString *const RCTRemoteNotificationsRegistered = @"RemoteNotificationsRegistered";
|
|
|
|
@implementation RCTConvert (UILocalNotification)
|
|
|
|
+ (UILocalNotification *)UILocalNotification:(id)json
|
|
{
|
|
NSDictionary<NSString *, id> *details = [self NSDictionary:json];
|
|
UILocalNotification *notification = [UILocalNotification new];
|
|
notification.fireDate = [RCTConvert NSDate:details[@"fireDate"]] ?: [NSDate date];
|
|
notification.alertBody = [RCTConvert NSString:details[@"alertBody"]];
|
|
notification.alertAction = [RCTConvert NSString:details[@"alertAction"]];
|
|
notification.soundName = [RCTConvert NSString:details[@"soundName"]] ?: UILocalNotificationDefaultSoundName;
|
|
notification.userInfo = [RCTConvert NSDictionary:details[@"userInfo"]];
|
|
notification.category = [RCTConvert NSString:details[@"category"]];
|
|
return notification;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation RCTPushNotificationManager
|
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
@synthesize bridge = _bridge;
|
|
|
|
- (void)dealloc
|
|
{
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
}
|
|
|
|
- (void)setBridge:(RCTBridge *)bridge
|
|
{
|
|
_bridge = bridge;
|
|
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleLocalNotificationReceived:)
|
|
name:RCTLocalNotificationReceived
|
|
object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleRemoteNotificationReceived:)
|
|
name:RCTRemoteNotificationReceived
|
|
object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleRemoteNotificationsRegistered:)
|
|
name:RCTRemoteNotificationsRegistered
|
|
object:nil];
|
|
}
|
|
|
|
- (NSDictionary<NSString *, id> *)constantsToExport
|
|
{
|
|
NSDictionary<NSString *, id> *initialNotification =
|
|
[_bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
|
|
return @{@"initialNotification": RCTNullIfNil(initialNotification)};
|
|
}
|
|
|
|
+ (void)didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings *)notificationSettings
|
|
{
|
|
if ([UIApplication instancesRespondToSelector:@selector(registerForRemoteNotifications)]) {
|
|
[[UIApplication sharedApplication] registerForRemoteNotifications];
|
|
}
|
|
}
|
|
|
|
+ (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
|
|
{
|
|
NSMutableString *hexString = [NSMutableString string];
|
|
NSUInteger deviceTokenLength = deviceToken.length;
|
|
const unsigned char *bytes = deviceToken.bytes;
|
|
for (NSUInteger i = 0; i < deviceTokenLength; i++) {
|
|
[hexString appendFormat:@"%02x", bytes[i]];
|
|
}
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationsRegistered
|
|
object:self
|
|
userInfo:@{@"deviceToken" : [hexString copy]}];
|
|
}
|
|
|
|
+ (void)didReceiveRemoteNotification:(NSDictionary *)notification
|
|
{
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
|
|
object:self
|
|
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
|
|
{
|
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationReceived"
|
|
body:notification.userInfo];
|
|
}
|
|
|
|
- (void)handleRemoteNotificationsRegistered:(NSNotification *)notification
|
|
{
|
|
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationsRegistered"
|
|
body:notification.userInfo];
|
|
}
|
|
|
|
/**
|
|
* Update the application icon badge number on the home screen
|
|
*/
|
|
RCT_EXPORT_METHOD(setApplicationIconBadgeNumber:(NSInteger)number)
|
|
{
|
|
RCTSharedApplication().applicationIconBadgeNumber = number;
|
|
}
|
|
|
|
/**
|
|
* Get the current application icon badge number on the home screen
|
|
*/
|
|
RCT_EXPORT_METHOD(getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback)
|
|
{
|
|
callback(@[@(RCTSharedApplication().applicationIconBadgeNumber)]);
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions)
|
|
{
|
|
if (RCTRunningInAppExtension()) {
|
|
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;
|
|
}
|
|
|
|
UIApplication *app = RCTSharedApplication();
|
|
if ([app respondsToSelector:@selector(registerUserNotificationSettings:)]) {
|
|
UIUserNotificationSettings *notificationSettings =
|
|
[UIUserNotificationSettings settingsForTypes:(NSUInteger)types categories:nil];
|
|
[app registerUserNotificationSettings:notificationSettings];
|
|
[app registerForRemoteNotifications];
|
|
} else {
|
|
[app registerForRemoteNotificationTypes:(NSUInteger)types];
|
|
}
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(abandonPermissions)
|
|
{
|
|
[RCTSharedApplication() unregisterForRemoteNotifications];
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
|
|
{
|
|
if (RCTRunningInAppExtension()) {
|
|
callback(@[@{@"alert": @NO, @"badge": @NO, @"sound": @NO}]);
|
|
return;
|
|
}
|
|
|
|
NSUInteger types = 0;
|
|
if ([UIApplication instancesRespondToSelector:@selector(currentUserNotificationSettings)]) {
|
|
types = [RCTSharedApplication() currentUserNotificationSettings].types;
|
|
} else {
|
|
|
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
|
|
|
|
types = [RCTSharedApplication() enabledRemoteNotificationTypes];
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
callback(@[@{
|
|
@"alert": @((types & UIUserNotificationTypeAlert) > 0),
|
|
@"badge": @((types & UIUserNotificationTypeBadge) > 0),
|
|
@"sound": @((types & UIUserNotificationTypeSound) > 0),
|
|
}]);
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(presentLocalNotification:(UILocalNotification *)notification)
|
|
{
|
|
[RCTSharedApplication() presentLocalNotificationNow:notification];
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(scheduleLocalNotification:(UILocalNotification *)notification)
|
|
{
|
|
[RCTSharedApplication() scheduleLocalNotification:notification];
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(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
|