[ReactNative] Open Source PushNotifications and move Badge Number methods and permission into it

This commit is contained in:
Tadeu Zagallo
2015-03-24 05:31:11 -07:00
parent bc921916ed
commit 8ae0eacf17
12 changed files with 626 additions and 198 deletions

View File

@@ -0,0 +1,117 @@
/**
* 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.
*
* @providesModule PushNotificationIOS
* @flow
*/
'use strict';
var NativeModules = require('NativeModules');
var RCTDeviceEventEmitter = require('RCTDeviceEventEmitter');
var RCTPushNotificationManager = require('NativeModules').PushNotificationManager;
var invariant = require('invariant');
var _notifHandlers = {};
var _initialNotification = RCTPushNotificationManager &&
RCTPushNotificationManager.initialNotification;
var DEVICE_NOTIF_EVENT = 'remoteNotificationReceived';
class PushNotificationIOS {
_data: Object;
_alert: string | Object;
_sound: string;
_badgeCount: number;
static setApplicationIconBadgeNumber(number) {
RCTPushNotificationManager.setApplicationIconBadgeNumber(number);
}
static getApplicationIconBadgeNumber(callback) {
RCTPushNotificationManager.getApplicationIconBadgeNumber(callback);
}
static addEventListener(type, handler) {
_notifHandlers[handler] = RCTDeviceEventEmitter.addListener(
DEVICE_NOTIF_EVENT,
(notifData) => {
handler(new PushNotificationIOS(notifData));
}
);
}
static requestPermissions() {
RCTPushNotificationManager.requestPermissions();
}
static checkPermissions(callback) {
invariant(
typeof callback === 'function',
'Must provide a valid callback'
);
RCTPushNotificationManager.checkPermissions(callback);
}
static removeEventListener(type, handler) {
if (!_notifHandlers[handler]) {
return;
}
_notifHandlers[handler].remove();
_notifHandlers[handler] = null;
}
static popInitialNotification() {
var initialNotification = _initialNotification &&
new PushNotificationIOS(_initialNotification);
_initialNotification = null;
return initialNotification;
}
constructor(nativeNotif) {
this._data = {};
// Extract data from Apple's `aps` dict as defined:
// https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/RemoteNotificationsPG/Chapters/ApplePushService.html
Object.keys(nativeNotif).forEach((notifKey) => {
var notifVal = nativeNotif[notifKey];
if (notifKey === 'aps') {
this._alert = notifVal.alert;
this._sound = notifVal.sound;
this._badgeCount = notifVal.badge;
} else {
this._data[notifKey] = notifVal;
}
});
}
getMessage(): ?string | ?Object {
// alias because "alert" is an ambiguous name
return this._alert;
}
getSound(): ?string {
return this._sound;
}
getAlert(): ?string | ?Object {
return this._alert;
}
getBadgeCount(): ?number {
return this._badgeCount;
}
getData(): ?Object {
return this._data;
}
}
module.exports = PushNotificationIOS;

View File

@@ -0,0 +1,256 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
148699CF1ABD045300480536 /* RCTPushNotificationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 148699CE1ABD045300480536 /* RCTPushNotificationManager.m */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
58B511D91A9E6C8500147676 /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
dstPath = "include/$(PRODUCT_NAME)";
dstSubfolderSpec = 16;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
134814201AA4EA6300B7C361 /* libRCTPushNotification.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libRCTPushNotification.a; sourceTree = BUILT_PRODUCTS_DIR; };
148699CD1ABD045300480536 /* RCTPushNotificationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RCTPushNotificationManager.h; sourceTree = "<group>"; };
148699CE1ABD045300480536 /* RCTPushNotificationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RCTPushNotificationManager.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
58B511D81A9E6C8500147676 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
134814211AA4EA7D00B7C361 /* Products */ = {
isa = PBXGroup;
children = (
134814201AA4EA6300B7C361 /* libRCTPushNotification.a */,
);
name = Products;
sourceTree = "<group>";
};
58B511D21A9E6C8500147676 = {
isa = PBXGroup;
children = (
148699CD1ABD045300480536 /* RCTPushNotificationManager.h */,
148699CE1ABD045300480536 /* RCTPushNotificationManager.m */,
134814211AA4EA7D00B7C361 /* Products */,
);
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
58B511DA1A9E6C8500147676 /* RCTPushNotification */ = {
isa = PBXNativeTarget;
buildConfigurationList = 58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTPushNotification" */;
buildPhases = (
58B511D71A9E6C8500147676 /* Sources */,
58B511D81A9E6C8500147676 /* Frameworks */,
58B511D91A9E6C8500147676 /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = RCTPushNotification;
productName = RCTDataManager;
productReference = 134814201AA4EA6300B7C361 /* libRCTPushNotification.a */;
productType = "com.apple.product-type.library.static";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
58B511D31A9E6C8500147676 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0610;
ORGANIZATIONNAME = Facebook;
TargetAttributes = {
58B511DA1A9E6C8500147676 = {
CreatedOnToolsVersion = 6.1.1;
};
};
};
buildConfigurationList = 58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTPushNotification" */;
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 58B511D21A9E6C8500147676;
productRefGroup = 58B511D21A9E6C8500147676;
projectDirPath = "";
projectRoot = "";
targets = (
58B511DA1A9E6C8500147676 /* RCTPushNotification */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
58B511D71A9E6C8500147676 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
148699CF1ABD045300480536 /* RCTPushNotificationManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
58B511ED1A9E6C8500147676 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
58B511EE1A9E6C8500147676 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES;
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.1;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
58B511F01A9E6C8500147676 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../ReactKit/**",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos",
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = RCTPushNotification;
SKIP_INSTALL = YES;
};
name = Debug;
};
58B511F11A9E6C8500147676 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(SRCROOT)/../../ReactKit/**",
);
LIBRARY_SEARCH_PATHS = (
"$(inherited)",
"/Users/nicklockwood/fbobjc-hg/Libraries/FBReactKit/js/react-native-github/ReactKit/build/Debug-iphoneos",
);
OTHER_LDFLAGS = "-ObjC";
PRODUCT_NAME = RCTPushNotification;
SKIP_INSTALL = YES;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
58B511D61A9E6C8500147676 /* Build configuration list for PBXProject "RCTPushNotification" */ = {
isa = XCConfigurationList;
buildConfigurations = (
58B511ED1A9E6C8500147676 /* Debug */,
58B511EE1A9E6C8500147676 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
58B511EF1A9E6C8500147676 /* Build configuration list for PBXNativeTarget "RCTPushNotification" */ = {
isa = XCConfigurationList;
buildConfigurations = (
58B511F01A9E6C8500147676 /* Debug */,
58B511F11A9E6C8500147676 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 58B511D31A9E6C8500147676 /* Project object */;
}

View File

@@ -0,0 +1,22 @@
/**
* 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 <UIKit/UIKit.h>
#import "../../ReactKit/Base/RCTBridgeModule.h"
@interface RCTPushNotificationManager : NSObject <RCTBridgeModule>
- (instancetype)initWithInitialNotification:(NSDictionary *)initialNotification NS_DESIGNATED_INITIALIZER;
+ (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings;
+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification;
+ (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation;
@end

View File

@@ -0,0 +1,156 @@
/**
* 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 "RCTEventDispatcher.h"
NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived";
NSString *const RCTOpenURLNotification = @"RCTOpenURLNotification";
@implementation RCTPushNotificationManager
{
NSDictionary *_initialNotification;
}
@synthesize bridge = _bridge;
- (instancetype)init
{
return [self initWithInitialNotification:nil];
}
- (instancetype)initWithInitialNotification:(NSDictionary *)initialNotification
{
if ((self = [super init])) {
_initialNotification = [initialNotification copy];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleRemoteNotificationReceived:)
name:RCTRemoteNotificationReceived
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleOpenURLNotification:)
name:RCTOpenURLNotification
object:nil];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
+ (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
#ifdef __IPHONE_8_0
[application registerForRemoteNotifications];
#endif
}
+ (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification
{
[[NSNotificationCenter defaultCenter] postNotificationName:RCTRemoteNotificationReceived
object:self
userInfo:notification];
}
+ (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
{
NSDictionary *payload = @{@"url": [url absoluteString]};
[[NSNotificationCenter defaultCenter] postNotificationName:RCTOpenURLNotification
object:self
userInfo:payload];
return YES;
}
- (void)handleRemoteNotificationReceived:(NSNotification *)notification
{
[_bridge.eventDispatcher sendDeviceEventWithName:@"remoteNotificationReceived"
body:[notification userInfo]];
}
- (void)handleOpenURLNotification:(NSNotification *)notification
{
[_bridge.eventDispatcher sendDeviceEventWithName:@"openURL"
body:[notification userInfo]];
}
/**
* Update the application icon badge number on the home screen
*/
+ (void)setApplicationIconBadgeNumber:(NSInteger)number
{
RCT_EXPORT();
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
[self requestPermissions];
});
[UIApplication sharedApplication].applicationIconBadgeNumber = number;
}
/**
* Get the current application icon badge number on the home screen
*/
+ (void)getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback
{
RCT_EXPORT();
callback(@[
@([UIApplication sharedApplication].applicationIconBadgeNumber)
]);
}
+ (void)requestPermissions
{
RCT_EXPORT();
#ifdef __IPHONE_8_0
UIUserNotificationType types = UIUserNotificationTypeSound | UIUserNotificationTypeBadge | UIUserNotificationTypeAlert;
UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
#else
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
#endif
}
+ (void)checkPermissions:(RCTResponseSenderBlock)callback
{
RCT_EXPORT();
NSMutableDictionary *permissions = [[NSMutableDictionary alloc] init];
#ifdef __IPHONE_8_0
UIUserNotificationType types = [[[UIApplication sharedApplication] currentUserNotificationSettings] types];
permissions[@"alert"] = @((BOOL)(types & UIUserNotificationTypeAlert));
permissions[@"badge"] = @((BOOL)(types & UIUserNotificationTypeBadge));
permissions[@"sound"] = @((BOOL)(types & UIUserNotificationTypeSound));
#else
UIRemoteNotificationType types = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
permissions[@"alert"] = @((BOOL)(types & UIRemoteNotificationTypeAlert));
permissions[@"badge"] = @((BOOL)(types & UIRemoteNotificationTypeBadge));
permissions[@"sound"] = @((BOOL)(types & UIRemoteNotificationTypeSound));
#endif
callback(@[permissions]);
}
- (NSDictionary *)constantsToExport
{
return @{
@"initialNotification": _initialNotification ?: [NSNull null]
};
}
@end