Skip to content

Commit

Permalink
Make PushNotificationManager TurboModule-compatible
Browse files Browse the repository at this point in the history
Summary:
Changelog:
[iOS][Added] - Make PushNotificationManager TurboModule-compatible

Reviewed By: PeteTheHeat

Differential Revision: D18375067

fbshipit-source-id: 256e6a42bf0055253f04df45e67f538f7564a966
  • Loading branch information
RSNara authored and facebook-github-bot committed Nov 8, 2019
1 parent 777e603 commit 861c860
Show file tree
Hide file tree
Showing 8 changed files with 254 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2054,9 +2054,9 @@ namespace facebook {
namespace JS {
namespace NativePushNotificationManagerIOS {
struct SpecRequestPermissionsPermission {
folly::Optional<bool> alert() const;
folly::Optional<bool> badge() const;
folly::Optional<bool> sound() const;
bool alert() const;
bool badge() const;
bool sound() const;

SpecRequestPermissionsPermission(NSDictionary *const v) : _v(v) {}
private:
Expand Down Expand Up @@ -3568,20 +3568,20 @@ inline JS::NativePlatformConstantsIOS::Constants::Builder::Builder(const Input i
inline JS::NativePlatformConstantsIOS::Constants::Builder::Builder(Constants i) : _factory(^{
return i.unsafeRawValue();
}) {}
inline folly::Optional<bool> JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::alert() const
inline bool JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::alert() const
{
id const p = _v[@"alert"];
return RCTBridgingToOptionalBool(p);
return RCTBridgingToBool(p);
}
inline folly::Optional<bool> JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::badge() const
inline bool JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::badge() const
{
id const p = _v[@"badge"];
return RCTBridgingToOptionalBool(p);
return RCTBridgingToBool(p);
}
inline folly::Optional<bool> JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::sound() const
inline bool JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission::sound() const
{
id const p = _v[@"sound"];
return RCTBridgingToOptionalBool(p);
return RCTBridgingToBool(p);
}
inline bool JS::NativePushNotificationManagerIOS::Permissions::alert() const
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ export interface Spec extends TurboModule {
+setApplicationIconBadgeNumber: (num: number) => void;
+getApplicationIconBadgeNumber: (callback: (num: number) => void) => void;
+requestPermissions: (permission: {|
+alert?: ?boolean,
+badge?: ?boolean,
+sound?: ?boolean,
+alert: boolean,
+badge: boolean,
+sound: boolean,
|}) => Promise<Permissions>;
+abandonPermissions: () => void;
+checkPermissions: (callback: (permissions: Permissions) => void) => void;
Expand Down
12 changes: 5 additions & 7 deletions Libraries/PushNotificationIOS/PushNotificationIOS.js
Original file line number Diff line number Diff line change
Expand Up @@ -306,19 +306,17 @@ class PushNotificationIOS {
badge: boolean,
sound: boolean,
}> {
let requestedPermissions = {};
let requestedPermissions = {
alert: true,
badge: true,
sound: true,
};
if (permissions) {
requestedPermissions = {
alert: !!permissions.alert,
badge: !!permissions.badge,
sound: !!permissions.sound,
};
} else {
requestedPermissions = {
alert: true,
badge: true,
sound: true,
};
}
invariant(
NativePushNotificationManagerIOS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@

#import <UserNotifications/UserNotifications.h>

#import <FBReactNativeSpec/FBReactNativeSpec.h>
#import <React/RCTBridge.h>
#import <React/RCTConvert.h>
#import <React/RCTEventDispatcher.h>
#import <React/RCTUtils.h>

#import "RCTPushNotificationPlugins.h"

NSString *const RCTRemoteNotificationReceived = @"RemoteNotificationReceived";

static NSString *const kLocalNotificationReceived = @"LocalNotificationReceived";
Expand All @@ -40,7 +43,7 @@ @implementation RCTConvert (NSCalendarUnit)

@end

@interface RCTPushNotificationManager ()
@interface RCTPushNotificationManager () <NativePushNotificationManagerIOSSpec>
@property (nonatomic, strong) NSMutableDictionary *remoteNotificationCallbacks;
@end

Expand Down Expand Up @@ -73,6 +76,9 @@ + (UILocalNotification *)UILocalNotification:(id)json
@"UIBackgroundFetchResultFailed": @(UIBackgroundFetchResultFailed),
}), UIBackgroundFetchResultNoData, integerValue)

@end
#else
@interface RCTPushNotificationManager () <NativePushNotificationManagerIOS>
@end
#endif //TARGET_OS_TV / TARGET_OS_UIKITFORMAC

Expand Down Expand Up @@ -187,7 +193,7 @@ + (void)didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
NSMutableString *hexString = [NSMutableString string];
NSUInteger deviceTokenLength = deviceToken.length;
const unsigned char *bytes = deviceToken.bytes;
const unsigned char *bytes = reinterpret_cast<const unsigned char *>(deviceToken.bytes);
for (NSUInteger i = 0; i < deviceTokenLength; i++) {
[hexString appendFormat:@"%02x", bytes[i]];
}
Expand Down Expand Up @@ -285,7 +291,8 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
_requestPermissionsResolveBlock = nil;
}

RCT_EXPORT_METHOD(onFinishRemoteNotification:(NSString *)notificationId fetchResult:(UIBackgroundFetchResult)result) {
RCT_EXPORT_METHOD(onFinishRemoteNotification:(NSString *)notificationId fetchResult:(NSString *)fetchResult) {
UIBackgroundFetchResult result = [RCTConvert UIBackgroundFetchResult:fetchResult];
RCTRemoteNotificationCallback completionHandler = self.remoteNotificationCallbacks[notificationId];
if (!completionHandler) {
RCTLogError(@"There is no completion handler with notification id: %@", notificationId);
Expand All @@ -298,7 +305,7 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
/**
* Update the application icon badge number on the home screen
*/
RCT_EXPORT_METHOD(setApplicationIconBadgeNumber:(NSInteger)number)
RCT_EXPORT_METHOD(setApplicationIconBadgeNumber:(double)number)
{
RCTSharedApplication().applicationIconBadgeNumber = number;
}
Expand All @@ -311,9 +318,9 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
callback(@[@(RCTSharedApplication().applicationIconBadgeNumber)]);
}

RCT_EXPORT_METHOD(requestPermissions:(NSDictionary *)permissions
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject)
RCT_EXPORT_METHOD(requestPermissions:(JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission &)permissions
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
if (RCTRunningInAppExtension()) {
reject(kErrorUnableToRequestPermissions, nil, RCTErrorWithMessage(@"Requesting push notifications is currently unavailable in an app extension"));
Expand All @@ -330,18 +337,15 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
_requestPermissionsResolveBlock = resolve;

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;

if (permissions.alert()) {
types |= UIUserNotificationTypeAlert;
}
if (permissions.badge()) {
types |= UIUserNotificationTypeBadge;
}
if (permissions.sound()) {
types |= UIUserNotificationTypeSound;
}

UIUserNotificationSettings *notificationSettings =
Expand Down Expand Up @@ -369,14 +373,46 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification
}]);
}

RCT_EXPORT_METHOD(presentLocalNotification:(UILocalNotification *)notification)
RCT_EXPORT_METHOD(presentLocalNotification:(JS::NativePushNotificationManagerIOS::Notification &)notification)
{
[RCTSharedApplication() presentLocalNotificationNow:notification];
NSMutableDictionary *notificationDict = [NSMutableDictionary new];
notificationDict[@"alertTitle"] = notification.alertTitle();
notificationDict[@"alertBody"] = notification.alertBody();
notificationDict[@"alertAction"] = notification.alertAction();
notificationDict[@"userInfo"] = notification.userInfo();
notificationDict[@"category"] = notification.category();
notificationDict[@"repeatInterval"] = notification.repeatInterval();
if (notification.fireDate()) {
notificationDict[@"fireDate"] = @(*notification.fireDate());
}
if (notification.applicationIconBadgeNumber()) {
notificationDict[@"applicationIconBadgeNumber"] = @(*notification.applicationIconBadgeNumber());
}
if (notification.isSilent()) {
notificationDict[@"isSilent"] = @(*notification.isSilent());
}
[RCTSharedApplication() presentLocalNotificationNow:[RCTConvert UILocalNotification:notificationDict]];
}

RCT_EXPORT_METHOD(scheduleLocalNotification:(UILocalNotification *)notification)
RCT_EXPORT_METHOD(scheduleLocalNotification:(JS::NativePushNotificationManagerIOS::Notification &)notification)
{
[RCTSharedApplication() scheduleLocalNotification:notification];
NSMutableDictionary *notificationDict = [NSMutableDictionary new];
notificationDict[@"alertTitle"] = notification.alertTitle();
notificationDict[@"alertBody"] = notification.alertBody();
notificationDict[@"alertAction"] = notification.alertAction();
notificationDict[@"userInfo"] = notification.userInfo();
notificationDict[@"category"] = notification.category();
notificationDict[@"repeatInterval"] = notification.repeatInterval();
if (notification.fireDate()) {
notificationDict[@"fireDate"] = @(*notification.fireDate());
}
if (notification.applicationIconBadgeNumber()) {
notificationDict[@"applicationIconBadgeNumber"] = @(*notification.applicationIconBadgeNumber());
}
if (notification.isSilent()) {
notificationDict[@"isSilent"] = @(*notification.isSilent());
}
[RCTSharedApplication() scheduleLocalNotification:[RCTConvert UILocalNotification:notificationDict]];
}

RCT_EXPORT_METHOD(cancelAllLocalNotifications)
Expand Down Expand Up @@ -470,11 +506,98 @@ - (void)handleRegisterUserNotificationSettings:(NSNotification *)notification

#else //TARGET_OS_TV / TARGET_OS_UIKITFORMAC

RCT_EXPORT_METHOD(onFinishRemoteNotification:(NSString *)notificationId fetchResult:(NSString *)fetchResult)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(setApplicationIconBadgeNumber:(double)number)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(getApplicationIconBadgeNumber:(RCTResponseSenderBlock)callback)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(requestPermissions:(JS::NativePushNotificationManagerIOS::SpecRequestPermissionsPermission &)permissions
resolve:(RCTPromiseResolveBlock)resolve
reject:(RCTPromiseRejectBlock)reject)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(abandonPermissions)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(checkPermissions:(RCTResponseSenderBlock)callback)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(presentLocalNotification:(JS::NativePushNotificationManagerIOS::Notification &)notification)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(scheduleLocalNotification:(JS::NativePushNotificationManagerIOS::Notification &)notification)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(cancelAllLocalNotifications)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(cancelLocalNotifications:(NSDictionary<NSString *, id> *)userInfo)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(getInitialNotification:(RCTPromiseResolveBlock)resolve
reject:(__unused RCTPromiseRejectBlock)reject)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(getScheduledLocalNotifications:(RCTResponseSenderBlock)callback)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(removeAllDeliveredNotifications)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(removeDeliveredNotifications:(NSArray<NSString *> *)identifiers)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

RCT_EXPORT_METHOD(getDeliveredNotifications:(RCTResponseSenderBlock)callback)
{
RCTLogError(@"Not implemented: %@", NSStringFromSelector(_cmd));
}

- (NSArray<NSString *> *)supportedEvents
{
return @[];
}

#endif //TARGET_OS_TV / TARGET_OS_UIKITFORMAC

- (std::shared_ptr<facebook::react::TurboModule>)getTurboModuleWithJsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
{
return std::make_shared<facebook::react::NativePushNotificationManagerIOSSpecJSI>(self, jsInvoker);
}

@end

Class RCTPushNotificationManagerCls(void) {
return RCTPushNotificationManager.class;
}
40 changes: 40 additions & 0 deletions Libraries/PushNotificationIOS/RCTPushNotificationPlugins.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @generated by an internal plugin build system
*/

#ifdef RN_DISABLE_OSS_PLUGIN_HEADER

// FB Internal: FBRCTPushNotificationPlugins.h is autogenerated by the build system.
#import <React/FBRCTPushNotificationPlugins.h>

#else

// OSS-compatibility layer

#import <Foundation/Foundation.h>

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wreturn-type-c-linkage"

#ifdef __cplusplus
extern "C" {
#endif

// RCTTurboModuleManagerDelegate should call this to resolve module classes.
Class RCTPushNotificationClassProvider(const char *name);

// Lookup functions
Class RCTPushNotificationManagerCls(void) __attribute__((used));

#ifdef __cplusplus
}
#endif

#pragma GCC diagnostic pop

#endif // RN_DISABLE_OSS_PLUGIN_HEADER
Loading

0 comments on commit 861c860

Please sign in to comment.