mirror of
https://github.com/status-im/react-native.git
synced 2025-02-19 12:57:00 +00:00
Summary: This adds workarounds for the code that was preventing React from compiling when linked against an iOS App Extension target. Some iOS APIs are unavailable to App Extensions, and Xcode's static analysis will catch attempts to use methods that have been flagged as unavailable. React currently uses two APIs that are off limits to extensions: `[UIApplication sharedApplication]` and `[UIAlertView initWith ...]`. This commit adds a helper function to `RCTUtils.[hm]` called `RCTRunningInAppExtension()`, which returns `YES` if, at runtime, it can be determined that we're running in an app extension (by checking whether the path to `[NSBundle mainBundle]` has the `"appex"` path extension). It also adds a `RCTSharedApplication()` function, which will return `nil` if running in an App Extension. If running in an App, `RCTSharedApplication()` calls `sharedApplication` by calling `performSelector:` on the `UIApplication` class. This passes the static analysis check, and, in my opinion, obeys the "spirit of th Closes https://github.com/facebook/react-native/pull/1895 Reviewed By: @svcscm Differential Revision: D2224128 Pulled By: @nicklockwood
222 lines
7.0 KiB
Objective-C
222 lines
7.0 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 RCTRemoteNotificationReceived = @"RemoteNotificationReceived";
|
|
NSString *const RCTRemoteNotificationsRegistered = @"RemoteNotificationsRegistered";
|
|
|
|
@implementation RCTConvert (UILocalNotification)
|
|
|
|
+ (UILocalNotification *)UILocalNotification:(id)json
|
|
{
|
|
NSDictionary *details = [self NSDictionary:json];
|
|
UILocalNotification *notification = [UILocalNotification new];
|
|
notification.fireDate = [RCTConvert NSDate:details[@"fireDate"]] ?: [NSDate date];
|
|
notification.alertBody = [RCTConvert NSString:details[@"alertBody"]];
|
|
return notification;
|
|
}
|
|
|
|
@end
|
|
|
|
@implementation RCTPushNotificationManager
|
|
{
|
|
NSDictionary *_initialNotification;
|
|
}
|
|
|
|
RCT_EXPORT_MODULE()
|
|
|
|
@synthesize bridge = _bridge;
|
|
|
|
- (instancetype)init
|
|
{
|
|
if ((self = [super init])) {
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleRemoteNotificationReceived:)
|
|
name:RCTRemoteNotificationReceived
|
|
object:nil];
|
|
[[NSNotificationCenter defaultCenter] addObserver:self
|
|
selector:@selector(handleRemoteNotificationsRegistered:)
|
|
name:RCTRemoteNotificationsRegistered
|
|
object:nil];
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
|
}
|
|
|
|
- (void)setBridge:(RCTBridge *)bridge
|
|
{
|
|
_bridge = bridge;
|
|
_initialNotification = [bridge.launchOptions[UIApplicationLaunchOptionsRemoteNotificationKey] copy];
|
|
}
|
|
|
|
+ (void)application:(__unused UIApplication *)application didRegisterUserNotificationSettings:(__unused UIUserNotificationSettings *)notificationSettings
|
|
{
|
|
if ([application respondsToSelector:@selector(registerForRemoteNotifications)]) {
|
|
[application registerForRemoteNotifications];
|
|
}
|
|
}
|
|
|
|
+ (void)application:(__unused UIApplication *)application 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]];
|
|
}
|
|
NSDictionary *userInfo = @{
|
|
@"deviceToken" : [hexString copy]
|
|
};
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationsRegistered
|
|
object:self
|
|
userInfo:userInfo];
|
|
}
|
|
|
|
+ (void)application:(__unused UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification
|
|
{
|
|
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
|
|
object:self
|
|
userInfo:notification];
|
|
}
|
|
|
|
- (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 ([permissions[@"alert"] boolValue]) {
|
|
types |= UIUserNotificationTypeAlert;
|
|
}
|
|
if ([permissions[@"badge"] boolValue]) {
|
|
types |= UIUserNotificationTypeBadge;
|
|
}
|
|
if ([permissions[@"sound"] boolValue]) {
|
|
types |= UIUserNotificationTypeSound;
|
|
}
|
|
} else {
|
|
types = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound;
|
|
}
|
|
|
|
UIApplication *app = RCTSharedApplication();
|
|
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_8_0
|
|
id notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
|
|
[app registerUserNotificationSettings:notificationSettings];
|
|
[app registerForRemoteNotifications];
|
|
#else
|
|
[app registerForRemoteNotificationTypes:types];
|
|
#endif
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(abandonPermissions)
|
|
{
|
|
[RCTSharedApplication() unregisterForRemoteNotifications];
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
|
|
{
|
|
if (RCTRunningInAppExtension()) {
|
|
NSDictionary *permissions = @{@"alert": @(NO), @"badge": @(NO), @"sound": @(NO)};
|
|
callback(@[permissions]);
|
|
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
|
|
|
|
}
|
|
|
|
NSMutableDictionary *permissions = [NSMutableDictionary new];
|
|
permissions[@"alert"] = @((types & UIUserNotificationTypeAlert) > 0);
|
|
permissions[@"badge"] = @((types & UIUserNotificationTypeBadge) > 0);
|
|
permissions[@"sound"] = @((types & UIUserNotificationTypeSound) > 0);
|
|
|
|
callback(@[permissions]);
|
|
}
|
|
|
|
- (NSDictionary *)constantsToExport
|
|
{
|
|
return @{
|
|
@"initialNotification": RCTNullIfNil(_initialNotification),
|
|
};
|
|
}
|
|
|
|
RCT_EXPORT_METHOD(presentLocalNotification:(UILocalNotification *)notification)
|
|
{
|
|
[RCTSharedApplication() presentLocalNotificationNow:notification];
|
|
}
|
|
|
|
|
|
RCT_EXPORT_METHOD(scheduleLocalNotification:(UILocalNotification *)notification)
|
|
{
|
|
[RCTSharedApplication() scheduleLocalNotification:notification];
|
|
}
|
|
|
|
@end
|