Commit 10730bed authored by yogevbd's avatar yogevbd

Refactor, split code, upgrade react

parent cbfbeb77
......@@ -42,8 +42,8 @@ static NSDictionary *RCTFormatUNNotification(UNNotification *notification)
+ (UIMutableUserNotificationAction *)UIMutableUserNotificationAction:(id)json;
@end
@interface RCTConvert (UIMutableUserNotificationCategory)
+ (UIMutableUserNotificationCategory *)UIMutableUserNotificationCategory:(id)json;
@interface RCTConvert (UNMutableUserNotificationCategory)
+ (UNNotificationCategory *)UNMutableUserNotificationCategory:(id)json;
@end
@interface RCTConvert (UILocalNotification)
......
......@@ -10,53 +10,55 @@ RCT_ENUM_CONVERTER(UIUserNotificationActivationMode, (@{
}), UIUserNotificationActivationModeForeground, integerValue)
@end
@implementation RCTConvert (UIUserNotificationActionContext)
RCT_ENUM_CONVERTER(UIUserNotificationActionContext, (@{
@"default": @(UIUserNotificationActionContextDefault),
@"minimal": @(UIUserNotificationActionContextMinimal)
}), UIUserNotificationActionContextDefault, integerValue)
@end
//@implementation RCTConvert (UIUserNotificationActionContext)
//RCT_ENUM_CONVERTER(UIUserNotificationActionContext, (@{
// @"default": @(UIUserNotificationActionContextDefault),
// @"minimal": @(UIUserNotificationActionContextMinimal)
// }), UIUserNotificationActionContextDefault, integerValue)
//@end
@implementation RCTConvert (UNNotificationActionOptions)
+ (UNNotificationActionOptions)UNUserNotificationActionOptions:(id)json {
UNNotificationActionOptions options = UNNotificationActionOptionNone;
if ([json[@"activationMode"] isEqualToString:@"foreground"]) {
options = options | UNNotificationActionOptionForeground;
}
if ([RCTConvert BOOL:json[@"authenticationRequired"]]) {
options = options | UNNotificationActionOptionAuthenticationRequired;
}
if ([RCTConvert BOOL:json[@"destructive"]]) {
options = options | UNNotificationActionOptionDestructive;
}
return options;
}
@implementation RCTConvert (UIUserNotificationActionBehavior)
/* iOS 9 only */
RCT_ENUM_CONVERTER(UIUserNotificationActionBehavior, (@{
@"default": @(UIUserNotificationActionBehaviorDefault),
@"textInput": @(UIUserNotificationActionBehaviorTextInput)
}), UIUserNotificationActionBehaviorDefault, integerValue)
@end
@implementation RCTConvert (UIMutableUserNotificationAction)
+ (UIMutableUserNotificationAction *)UIMutableUserNotificationAction:(id)json
@implementation RCTConvert (UNMutableUserNotificationAction)
+ (UNNotificationAction *)UNMutableUserNotificationAction:(id)json
{
NSDictionary<NSString *, id> *details = [self NSDictionary:json];
UIMutableUserNotificationAction* action =[UIMutableUserNotificationAction new];
action.activationMode = [RCTConvert UIUserNotificationActivationMode:details[@"activationMode"]];
action.behavior = [RCTConvert UIUserNotificationActionBehavior:details[@"behavior"]];
action.authenticationRequired = [RCTConvert BOOL:details[@"authenticationRequired"]];
action.destructive = [RCTConvert BOOL:details[@"destructive"]];
action.title = [RCTConvert NSString:details[@"title"]];
action.identifier = [RCTConvert NSString:details[@"identifier"]];
UNNotificationAction* action = [UNNotificationAction actionWithIdentifier:details[@"identifier"] title:details[@"title"] options:[RCTConvert UNUserNotificationActionOptions:details]];
// action.behavior = [RCTConvert UIUserNotificationActionBehavior:details[@"behavior"]];
return action;
}
@end
@implementation RCTConvert (UIMutableUserNotificationCategory)
+ (UIMutableUserNotificationCategory *)UIMutableUserNotificationCategory:(id)json
@implementation RCTConvert (UNMutableUserNotificationCategory)
+ (UNNotificationCategory *)UNMutableUserNotificationCategory:(id)json
{
NSDictionary<NSString *, id> *details = [self NSDictionary:json];
UIMutableUserNotificationCategory* category = [UIMutableUserNotificationCategory new];
category.identifier = details[@"identifier"];
// category actions
NSMutableArray* actions = [NSMutableArray new];
for (NSDictionary* actionJson in [RCTConvert NSArray:details[@"actions"]]) {
[actions addObject:[RCTConvert UIMutableUserNotificationAction:actionJson]];
[actions addObject:[RCTConvert UNMutableUserNotificationAction:actionJson]];
}
[category setActions:actions forContext:[RCTConvert UIUserNotificationActionContext:details[@"context"]]];
UNNotificationCategory* category = [UNNotificationCategory categoryWithIdentifier:details[@"identifier"] actions:actions intentIdentifiers:@[] options:UNNotificationCategoryOptionNone];
return category;
}
......
......@@ -27,6 +27,11 @@ RCT_EXPORT_MODULE();
return YES;
}
- (void)setBridge:(RCTBridge *)bridge {
_bridge = bridge;
[RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification = [_bridge.launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
}
#pragma mark - JS interface
RCT_EXPORT_METHOD(requestPermissionsWithCategories:(NSArray *)json) {
......
......@@ -2,8 +2,11 @@
#import "RNNotifications.h"
#import "RNNotificationsBridgeQueue.h"
#import "RCTConvert+Notifications.h"
#import "RNPushKit.h"
@implementation RNCommandsHandler
@implementation RNCommandsHandler {
RNPushKit* _pushKit;
}
- (instancetype)init {
self = [super init];
......@@ -15,30 +18,39 @@
}
- (void)onJavaScriptLoaded {
[RNNotificationsBridgeQueue sharedInstance].jsIsReady = YES;
// [RNNotificationsBridgeQueue sharedInstance].jsIsReady = YES;
}
- (void)requestPermissionsWithCategories:(NSArray *)json {
NSMutableSet* categories = nil;
NSMutableSet<UNNotificationCategory *>* categories = nil;
if ([json count] > 0) {
categories = [NSMutableSet new];
for (NSDictionary* categoryJson in json) {
[categories addObject:[RCTConvert UIMutableUserNotificationCategory:categoryJson]];
[categories addObject:[RCTConvert UNMutableUserNotificationCategory:categoryJson]];
}
}
[[RNNotifications sharedInstance] requestPermissionsWithCategories:categories];
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:categories];
UNAuthorizationOptions authOptions = (UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
[UNUserNotificationCenter.currentNotificationCenter requestAuthorizationWithOptions:authOptions completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (error) {
} else {
if (granted) {
[UNUserNotificationCenter.currentNotificationCenter getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
if (settings.authorizationStatus == UNAuthorizationStatusAuthorized) {
[[UIApplication sharedApplication] registerForRemoteNotifications];
}
}];
} else {
}
}
}];
}
- (void)getInitialNotification:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
NSDictionary * notification = nil;
notification = [RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification ?
[RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification :
[RNNotificationsBridgeQueue sharedInstance].openedLocalNotification;
[RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification = nil;
[RNNotificationsBridgeQueue sharedInstance].openedLocalNotification = nil;
resolve(notification);
resolve([RNNotificationsBridgeQueue sharedInstance].openedRemoteNotification);
}
- (void)completionHandler:(NSString *)completionKey {
......@@ -50,7 +62,7 @@
}
- (void)registerPushKit {
[[RNNotifications sharedInstance] registerPushKit];
_pushKit = [[RNPushKit alloc] initWithPushKitEventListener:[RNPushKitEventListener new]];
}
- (void)getBadgesCount:(RCTResponseSenderBlock)callback {
......
#import <Foundation/Foundation.h>
@import UserNotifications;
#import "RNNotificationEventHandler.h"
@interface RNNotificationCenterListener : NSObject <UNUserNotificationCenterDelegate>
- (instancetype)initWithNotificationEventHandler:(RNNotificationEventHandler *)notificationEventHandler;
@end
#import "RNNotificationCenterListener.h"
@implementation RNNotificationCenterListener {
RNNotificationEventHandler* _notificationEventHandler;
}
- (instancetype)initWithNotificationEventHandler:(RNNotificationEventHandler *)notificationEventHandler {
self = [super init];
_notificationEventHandler = notificationEventHandler;
[[UNUserNotificationCenter currentNotificationCenter] setDelegate:self];
return self;
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
[_notificationEventHandler didReceiveForegroundPayload:notification.request.content.userInfo];
}
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler {
if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
[_notificationEventHandler didOpenNotificationPayload:response.notification.request.content.userInfo];
} else if ([response.actionIdentifier isEqualToString:UNNotificationDismissActionIdentifier]) {
} else {
NSString* responseText = [response isKindOfClass:[UNTextInputNotificationResponse class]] ? ((UNTextInputNotificationResponse *)response).userText : nil;
[_notificationEventHandler handleActionWithIdentifier:response.actionIdentifier forPayload:response.notification.request.content.userInfo withResponse:responseText completionHandler:completionHandler];
}
}
@end
#import <Foundation/Foundation.h>
@import UserNotifications;
@interface RNNotificationEventHandler : NSObject
- (void)didReceiveForegroundPayload:(NSDictionary *)payload;
- (void)didOpenNotificationPayload:(NSDictionary *)payload;
- (void)handleActionWithIdentifier:(NSString *)identifier forPayload:(NSDictionary *)payload withResponse:(NSString *)response completionHandler:(void (^)())completionHandler;
@end
#import "RNNotificationEventHandler.h"
#import "RNNotificationsBridgeQueue.h"
#import "RNEventEmitter.h"
@implementation RNNotificationEventHandler
- (void)didReceiveForegroundPayload:(NSDictionary *)payload {
// if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) {
[RNEventEmitter sendEvent:NotificationReceivedForeground body:payload];
// }
}
- (void)didOpenNotificationPayload:(NSDictionary *)payload {
// if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) {
[RNEventEmitter sendEvent:NotificationOpened body:payload];
// }
}
- (void)handleActionWithIdentifier:(NSString *)identifier forPayload:(NSDictionary *)payload withResponse:(NSString *)response completionHandler:(void (^)())completionHandler {
[self emitNotificationActionForIdentifier:identifier response:response userInfo:payload completionHandler:completionHandler];
}
- (void)emitNotificationActionForIdentifier:(NSString *)identifier response:(NSString *)response userInfo:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {
NSString* completionKey = [NSString stringWithFormat:@"%@.%@", identifier, [NSString stringWithFormat:@"%ldd", (long)[[NSDate date] timeIntervalSince1970]]];
NSMutableDictionary* info = [[NSMutableDictionary alloc] initWithDictionary:@{ @"identifier": identifier, @"completionKey": completionKey }];
if (response != NULL) {
info[@"text"] = response;
}
// add notification custom data
if (userInfo != NULL) {
info[@"notification"] = userInfo;
}
// Emit event to the queue (in order to store the completion handler). if JS thread is ready, post it also to the notification center (to the bridge).
[[RNNotificationsBridgeQueue sharedInstance] postAction:info withCompletionKey:completionKey andCompletionHandler:completionHandler];
// if ([RNNotificationsBridgeQueue sharedInstance].jsIsReady == YES) {
[RNEventEmitter sendEvent:NotificationActionReceived body:userInfo];
// }
}
@end
@import UIKit;
#import <React/RCTBridgeModule.h>
#import <PushKit/PushKit.h>
@import UserNotifications;
@interface RNNotifications : NSObject <RCTBridgeModule>
@interface RNNotifications : NSObject
+ (instancetype)sharedInstance;
- (void)requestPermissionsWithCategories:(NSMutableSet *)categories;
- (void)registerPushKit;
- (void)initialize;
- (void)didRegisterForRemoteNotificationsWithDeviceToken:(id)deviceToken;
- (void)didFailToRegisterForRemoteNotificationsWithError:(NSError *)error;
- (void)didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type;
//- (void)didReceiveRemoteNotification:(NSDictionary *)notification;
- (void)handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler;
- (void)handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler;
- (void)didReceiveForegroundNotification:(UNNotification *)notification;
- (void)didReceiveNotificationResponse:(UNNotificationResponse *)response;
//- (void)setBadgeForNotification:(NSDictionary *)notification;
@end
This diff is collapsed.
......@@ -2,9 +2,7 @@
@interface RNNotificationsBridgeQueue : NSObject
@property BOOL jsIsReady;
@property NSDictionary* openedRemoteNotification;
@property NSDictionary* openedLocalNotification;
+ (nonnull instancetype)sharedInstance;
......@@ -16,4 +14,4 @@
- (void)completeAction:(NSString *)completionKey;
@end
\ No newline at end of file
@end
......@@ -21,7 +21,6 @@ NSMutableDictionary* actionCompletionHandlers;
actionsQueue = [NSMutableArray new];
notificationsQueue = [NSMutableArray new];
actionCompletionHandlers = [NSMutableDictionary new];
self.jsIsReady = NO;
return self;
}
......@@ -92,4 +91,4 @@ NSMutableDictionary* actionCompletionHandlers;
}
}
@end
\ No newline at end of file
@end
#import <Foundation/Foundation.h>
@interface RNNotificationsStore : NSObject
@end
#import "RNNotificationsStore.h"
@implementation RNNotificationsStore {
NSMutableDictionary* actionCompletionHandlers;
}
- (instancetype)init {
actionCompletionHandlers = [NSMutableDictionary new];
return self;
}
@end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
//
// RNNotificationsTests.m
// RNNotificationsTests
//
// Created by Yogev Ben David on 06/07/2019.
// Copyright © 2019 Facebook. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface RNNotificationsTests : XCTestCase
@end
@implementation RNNotificationsTests
- (void)setUp {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
@end
#import <UIKit/UIKit.h>
#import "RNPushKitEventListener.h"
@import PushKit;
@interface RNPushKit : NSObject
- (instancetype)initWithPushKitEventListener:(RNPushKitEventListener *)pushKitEventListener;
@end
#import "RNPushKit.h"
@implementation RNPushKit {
RNPushKitEventListener* _pushKitEventListener;
}
- (instancetype)initWithPushKitEventListener:(RNPushKitEventListener *)pushKitEventListener {
self = [super init];
_pushKitEventListener = pushKitEventListener;
PKPushRegistry* pushKitRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
pushKitRegistry.delegate = pushKitEventListener;
pushKitRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
return self;
}
@end
#import <Foundation/Foundation.h>
#import "RNNotificationEventHandler.h"
@interface RNPushKitEventHandler : RNNotificationEventHandler
- (void)registeredWithToken:(NSString *)token;
@end
#import "RNPushKitEventHandler.h"
#import "RNEventEmitter.h"
@implementation RNPushKitEventHandler
- (void)registeredWithToken:(NSString *)token {
[RNEventEmitter sendEvent:PushKitRegistered body:@{@"pushKitToken": token}];
}
@end
#import <Foundation/Foundation.h>
@import PushKit;
#import "RNPushKitEventHandler.h"
@interface RNPushKitEventListener : NSObject <PKPushRegistryDelegate>
- (instancetype)initWithPushKitEventHandler:(RNPushKitEventHandler *)pushKitEventHandler;
@end
#import "RNPushKitEventListener.h"
#import "RNEventEmitter.h"
#import "RNUtils.h"
@implementation RNPushKitEventListener {
PKPushRegistry* _pushRegistry;
RNPushKitEventHandler* _pushKitEventHandler;
}
- (instancetype)initWithPushKitEventHandler:(RNPushKitEventHandler *)pushKitEventHandler {
self = [super init];
_pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
_pushKitEventHandler = pushKitEventHandler;
return self;
}
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type {
[_pushKitEventHandler registeredWithToken:[RNUtils deviceTokenToString:credentials.token]];
}
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type {
[_pushKitEventHandler didOpenNotificationPayload:payload.dictionaryPayload];
}
@end
#import <Foundation/Foundation.h>
@interface RNUtils : NSObject
+ (NSString *)deviceTokenToString:(NSData *)deviceToken;
@end
#import "RNUtils.h"
@implementation RNUtils
+ (NSString *)deviceTokenToString:(NSData *)deviceToken {
NSMutableString *result = [NSMutableString string];
NSUInteger deviceTokenLength = deviceToken.length;
const unsigned char *bytes = deviceToken.bytes;
for (NSUInteger i = 0; i < deviceTokenLength; i++) {
[result appendFormat:@"%02x", bytes[i]];
}
return [result copy];
}
@end
module.exports = function (api) {
api && api.cache(false);
return {
presets: [
"module:metro-react-native-babel-preset"
],
plugins: [
"@babel/plugin-proposal-export-namespace-from",
"@babel/plugin-proposal-export-default-from"
]
};
}
const Utils = require('./Utils');
const { elementByLabel, elementById, sleep } = Utils;
describe('BottomTabs', () => {
beforeEach(async () => {
await device.relaunchApp();
// await elementById(TestIDs.BOTTOM_TABS_BTN).tap();
// await expect(elementByLabel('First Tab')).toBeVisible();
});
it('switch to tab by index', async () => {
// await elementById(TestIDs.SWITCH_TAB_BY_INDEX_BTN).tap();
await expect(elementByLabel('First Tab')).toBeNotVisible();
await expect(elementByLabel('Second Tab')).toBeVisible();
});
});
{
"setupTestFrameworkScriptFile" : "./init.js",
"testEnvironment": "node",
"bail": true,
"verbose": true
}
const detox = require('detox');
const config = require('../package.json').detox;
const exec = require('shell-utils').exec;
const adapter = require('detox/runners/jest/adapter');
jest.setTimeout(300000);
jasmine.getEnv().addReporter(adapter);
beforeAll(async () => {
await detox.init(config, {launchApp: false});
disableAndroidEmulatorAnimations();
});
afterAll(async () => {
await adapter.afterAll();
await detox.cleanup();
});
beforeEach(async () => {
await adapter.beforeEach();
});
function disableAndroidEmulatorAnimations() {
if (device.getPlatform() === 'android') {
const deviceId = device._deviceId;
exec.execAsync(`adb -s ${deviceId} shell settings put global window_animation_scale 0.0`);
exec.execAsync(`adb -s ${deviceId} shell settings put global transition_animation_scale 0.0`);
exec.execAsync(`adb -s ${deviceId} shell settings put global animator_duration_scale 0.0`);
}
}
......@@ -6,41 +6,41 @@
import {
AppRegistry,
StyleSheet,
Text,
View
View,
Text
} from 'react-native';
import React, {Component} from 'react';
import NotificationsIOS, { NotificationAction, NotificationCategory } from 'react-native-notifications';
let upvoteAction = new NotificationAction({
activationMode: "background",
activationMode: 'background',
title: String.fromCodePoint(0x1F44D),
identifier: "UPVOTE_ACTION"
identifier: 'UPVOTE_ACTION'
}, (action, completed) => {
NotificationsIOS.log("ACTION RECEIVED");
NotificationsIOS.log('ACTION RECEIVED');
NotificationsIOS.log(JSON.stringify(action));
completed();
});
let replyAction = new NotificationAction({
activationMode: "background",
title: "Reply",
behavior: "textInput",
activationMode: 'background',
title: 'Reply',
behavior: 'textInput',
authenticationRequired: true,
identifier: "REPLY_ACTION"
identifier: 'REPLY_ACTION'
}, (action, completed) => {
console.log("ACTION RECEIVED");
console.log('ACTION RECEIVED');
console.log(action);
completed();
});
let cat = new NotificationCategory({
identifier: "SOME_CATEGORY",
identifier: 'SOME_CATEGORY',
actions: [upvoteAction, replyAction],
context: "default"
context: 'default'
});
class NotificationsExampleApp extends Component {
......@@ -61,26 +61,26 @@ class NotificationsExampleApp extends Component {
}
onPushRegistered(deviceToken) {
console.log("Device Token Received: " + deviceToken);
console.log('Device Token Received: ' + deviceToken);
}
onPushKitRegistered(deviceToken) {
console.log("PushKit Token Received: " + deviceToken);
console.log('PushKit Token Received: ' + deviceToken);
}
onNotificationReceivedForeground(notification) {
console.log("Notification Received Foreground: " + JSON.stringify(notification));
console.log('Notification Received Foreground: ' + JSON.stringify(notification));
}
onNotificationReceivedBackground(notification) {
NotificationsIOS.log("Notification Received Background: " + JSON.stringify(notification));
NotificationsIOS.log('Notification Received Background: ' + JSON.stringify(notification));
let localNotification = NotificationsIOS.localNotification({
alertBody: "Received background notificiation!",
alertTitle: "Local Notification Title",
alertAction: "Click here to open",
soundName: "chime.aiff",
category: "SOME_CATEGORY",
alertBody: 'Received background notificiation!',
alertTitle: 'Local Notification Title',
alertAction: 'Click here to open',
soundName: 'chime.aiff',
category: 'SOME_CATEGORY',
userInfo: notification.getData()
});
......@@ -88,13 +88,13 @@ class NotificationsExampleApp extends Component {
// add the following line to the notification payload:
// fireDate: new Date(Date.now() + (10 * 1000)).toISOString()
// NotificationsIOS.backgroundTimeRemaining(time => NotificationsIOS.log("remaining background time: " + time));
// NotificationsIOS.backgroundTimeRemaining(time => NotificationsIOS.log('remaining background time: ' + time));
// NotificationsIOS.cancelLocalNotification(localNotification);
}
onNotificationOpened(notification) {
console.log("Notification Opened: " + JSON.stringify(notification));
console.log('Notification Opened: ' + JSON.stringify(notification));
}
render() {
......
......@@ -28,6 +28,41 @@
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
50E49F4022D1F06C007160C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = EDEBC6D6214B3E7000DD5AC8;
remoteInfo = jsi;
};
50E49F4222D1F06C007160C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = EDEBC73B214B45A300DD5AC8;
remoteInfo = jsiexecutor;
};
50E49F4422D1F06C007160C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = ED296FB6214C9A0900B7C4FE;
remoteInfo = "jsi-tvOS";
};
50E49F4622D1F06C007160C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = ED296FEE214C9CF800B7C4FE;
remoteInfo = "jsiexecutor-tvOS";
};
50E49F4A22D1F06C007160C1 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = D85498C21D97B31100DEEE06 /* RNNotifications.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 508CE7C822D12B2600357815;
remoteInfo = RNNotificationsTests;
};
50F1F05F22CE3A6100FD5829 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
......@@ -70,20 +105,6 @@
remoteGlobalIDString = 3D3CD9321DE5FBEE00167DC4;
remoteInfo = "cxxreact-tvOS";
};
50F1F06B22CE3A6100FD5829 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D3CD90B1DE5FBD600167DC4;
remoteInfo = jschelpers;
};
50F1F06D22CE3A6100FD5829 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 3D3CD9181DE5FBD800167DC4;
remoteInfo = "jschelpers-tvOS";
};
50F1F06F22CE3A6100FD5829 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
......@@ -126,20 +147,6 @@
remoteGlobalIDString = 3D383D621EBD27B9005632C8;
remoteInfo = "double-conversion-tvOS";
};
50F1F07B22CE3A6100FD5829 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 9936F3131F5F2E4B0010BF04;
remoteInfo = privatedata;
};
50F1F07D22CE3A6100FD5829 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 146833FF1AC3E56700842450 /* React.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 9936F32F1F5F2E5B0010BF04;
remoteInfo = "privatedata-tvOS";
};
50F1F08922CE3AA000FD5829 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 50F1F08522CE3A9F00FD5829 /* RCTActionSheet.xcodeproj */;
......@@ -358,16 +365,16 @@
50F1F06622CE3A6100FD5829 /* libyoga.a */,
50F1F06822CE3A6100FD5829 /* libcxxreact.a */,
50F1F06A22CE3A6100FD5829 /* libcxxreact.a */,
50F1F06C22CE3A6100FD5829 /* libjschelpers.a */,
50F1F06E22CE3A6100FD5829 /* libjschelpers.a */,
50F1F07022CE3A6100FD5829 /* libjsinspector.a */,
50F1F07222CE3A6100FD5829 /* libjsinspector-tvOS.a */,
50F1F07422CE3A6100FD5829 /* libthird-party.a */,
50F1F07622CE3A6100FD5829 /* libthird-party.a */,
50F1F07822CE3A6100FD5829 /* libdouble-conversion.a */,
50F1F07A22CE3A6100FD5829 /* libdouble-conversion.a */,
50F1F07C22CE3A6100FD5829 /* libprivatedata.a */,
50F1F07E22CE3A6100FD5829 /* libprivatedata-tvOS.a */,
50E49F4122D1F06C007160C1 /* libjsi.a */,
50E49F4322D1F06C007160C1 /* libjsiexecutor.a */,
50E49F4522D1F06C007160C1 /* libjsi-tvOS.a */,
50E49F4722D1F06C007160C1 /* libjsiexecutor-tvOS.a */,
);
name = Products;
sourceTree = "<group>";
......@@ -503,6 +510,7 @@
isa = PBXGroup;
children = (
D85498D11D97B31100DEEE06 /* libRNNotifications.a */,
50E49F4B22D1F06C007160C1 /* RNNotificationsTests.xctest */,
);
name = Products;
sourceTree = "<group>";
......@@ -602,6 +610,41 @@
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
50E49F4122D1F06C007160C1 /* libjsi.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libjsi.a;
remoteRef = 50E49F4022D1F06C007160C1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50E49F4322D1F06C007160C1 /* libjsiexecutor.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libjsiexecutor.a;
remoteRef = 50E49F4222D1F06C007160C1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50E49F4522D1F06C007160C1 /* libjsi-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libjsi-tvOS.a";
remoteRef = 50E49F4422D1F06C007160C1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50E49F4722D1F06C007160C1 /* libjsiexecutor-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libjsiexecutor-tvOS.a";
remoteRef = 50E49F4622D1F06C007160C1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50E49F4B22D1F06C007160C1 /* RNNotificationsTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = RNNotificationsTests.xctest;
remoteRef = 50E49F4A22D1F06C007160C1 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50F1F06022CE3A6100FD5829 /* libReact.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
......@@ -644,20 +687,6 @@
remoteRef = 50F1F06922CE3A6100FD5829 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50F1F06C22CE3A6100FD5829 /* libjschelpers.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libjschelpers.a;
remoteRef = 50F1F06B22CE3A6100FD5829 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50F1F06E22CE3A6100FD5829 /* libjschelpers.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libjschelpers.a;
remoteRef = 50F1F06D22CE3A6100FD5829 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50F1F07022CE3A6100FD5829 /* libjsinspector.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
......@@ -700,20 +729,6 @@
remoteRef = 50F1F07922CE3A6100FD5829 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50F1F07C22CE3A6100FD5829 /* libprivatedata.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = libprivatedata.a;
remoteRef = 50F1F07B22CE3A6100FD5829 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50F1F07E22CE3A6100FD5829 /* libprivatedata-tvOS.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "libprivatedata-tvOS.a";
remoteRef = 50F1F07D22CE3A6100FD5829 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
50F1F08A22CE3AA000FD5829 /* libRCTActionSheet.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
......
......@@ -12,7 +12,7 @@
{
NSURL *jsCodeLocation;
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
moduleName:@"NotificationsExampleApp"
......@@ -25,21 +25,12 @@
rootViewController.view = rootView;
self.window.rootViewController = rootViewController;
[self.window makeKeyAndVisible];
[[RNNotifications sharedInstance] initialize];
return YES;
}
// PushKit API Example
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type
{
[[RNNotifications sharedInstance] didUpdatePushCredentials:credentials forType:type];
}
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type
{
// [[RNNotifications sharedInstance] didReceiveRemoteNotification:payload.dictionaryPayload];
}
// Required to register for notifications
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
......@@ -51,28 +42,4 @@
[[RNNotifications sharedInstance] didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
}
// Required for the notification event.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)notification {
// [[RNNotifications sharedInstance] didReceiveRemoteNotification:notification];
}
// Required for the localNotification event.
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
{
// [[RNNotifications sharedInstance] didReceiveLocalNotification:notification];
}
// Required for the notification actions.
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler
{
[[RNNotifications sharedInstance] handleActionWithIdentifier:identifier forLocalNotification:notification withResponseInfo:responseInfo completionHandler:completionHandler];
}
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo withResponseInfo:(NSDictionary *)responseInfo completionHandler:(void (^)())completionHandler
{
[[RNNotifications sharedInstance] handleActionWithIdentifier:identifier forRemoteNotification:userInfo withResponseInfo:responseInfo completionHandler:completionHandler];
}
@end
require('./example/index');
\ No newline at end of file
module.exports = {
projectRoot: `${__dirname}/example`,
watchFolders: [
__dirname
]
__dirname,
],
transformer: {
getTransformOptions: async () => ({
transform: {
experimentalImportSupport: false,
inlineRequires: false,
},
})
}
};
......@@ -19,10 +19,12 @@
"actionable-notifications",
"interactive-notifications"
],
"main": "lib/src/index",
"scripts": {
"pretest": "./node_modules/.bin/eslint *.js test",
"test": "./node_modules/.bin/mocha --compilers js:babel-register --reporter spec \"test/*.spec.js\"",
"start": "node ./scripts/start"
"start": "node ./scripts/start",
"test-e2e-ios": "node ./scripts/test-e2e --ios"
},
"nativePackage": true,
"dependencies": {
......@@ -34,9 +36,13 @@
"react-native": ">=0.25.1"
},
"devDependencies": {
"@types/react": "16.x.x",
"@types/react-native": "0.57.7",
"@types/react-test-renderer": "16.x.x",
"@babel/plugin-proposal-export-default-from": "7.2.0",
"@babel/plugin-proposal-export-namespace-from": "7.2.0",
"typescript": "3.2.2",
"babel-eslint": "9.0.0",
"babel-preset-react-native": "^1.9.0",
"babel-register": "^6.7.2",
"chai": "^3.5.0",
"chokidar-cli": "^1.2.0",
"eslint": "6.0.1",
......@@ -45,8 +51,11 @@
"sinon": "^1.17.3",
"sinon-chai": "^2.8.0",
"shell-utils": "1.x.x",
"react-native": "0.57.7",
"react": "16.8.6"
"react-native": "0.60.0",
"react": "16.8.6",
"detox": "12.x.x",
"jest": "24.8.0",
"metro-react-native-babel-preset": "0.55.x"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
......@@ -59,9 +68,59 @@
"bugs": {
"url": "https://github.com/wix/react-native-notifications/issues"
},
"babel": {
"presets": [
"react-native"
"detox": {
"test-runner": "jest",
"specs": "",
"configurations": {
"ios.none": {
"binaryPath": "playground/ios/DerivedData/playground/Build/Products/Debug-iphonesimulator/playground.app",
"type": "ios.none",
"name": "iPhone X",
"session": {
"server": "ws://localhost:8099",
"sessionId": "playground"
}
},
"ios.sim.debug": {
"binaryPath": "example/ios/DerivedData/NotificationsExampleApp/Build/Products/Debug-iphonesimulator/NotificationsExampleApp.app",
"build": "RCT_NO_LAUNCH_PACKAGER=true xcodebuild build -scheme NotificationsExampleApp -project example/ios/NotificationsExampleApp.xcodeproj -sdk iphonesimulator -configuration Debug -derivedDataPath example/ios/DerivedData/NotificationsExampleApp ONLY_ACTIVE_ARCH=YES -quiet -UseModernBuildSystem=NO",
"type": "ios.simulator",
"name": "iPhone X"
},
"ios.sim.release": {
"binaryPath": "playground/ios/DerivedData/playground/Build/Products/Release-iphonesimulator/playground.app",
"build": "RCT_NO_LAUNCH_PACKAGER=true xcodebuild build -scheme playground_release -project playground/ios/playground.xcodeproj -sdk iphonesimulator -configuration Release -derivedDataPath playground/ios/DerivedData/playground ONLY_ACTIVE_ARCH=YES -quiet -UseModernBuildSystem=NO",
"type": "ios.simulator",
"name": "iPhone X"
}
}
},
"jest": {
"preset": "react-native",
"transform": {
"^.+\\.js$": "<rootDir>/node_modules/react-native/jest/preprocessor.js"
},
"roots": [
"<rootDir>/node_modules/"
],
"collectCoverageFrom": [
"lib/dist/**/*.js",
"integration/**/*.js",
"!lib/dist/index.js",
"!lib/dist/Navigation.js",
"!lib/dist/adapters/**/*",
"!lib/dist/interfaces/**/*",
"!lib/dist/**/*.test.*",
"!integration/**/*.test.*",
"!integration/*.test.*"
],
"resetMocks": true,
"resetModules": true,
"coverageReporters": [
"json",
"lcov",
"text",
"html"
]
}
}
const exec = require('shell-utils').exec;
module.exports = {
elementByLabel: (label) => {
return element(by.text(label));
},
elementById: (id) => {
return element(by.id(id));
},
tapBackIos: () => {
try {
return element(by.traits(['button']).and(by.label('Back'))).atIndex(0).tap();
} catch (err) {
return element(by.type('_UIModernBarButton').and(by.label('Back'))).tap();
}
},
sleep: ms => new Promise(res => setTimeout(res, ms))
};
const _ = require('lodash');
const exec = require('shell-utils').exec;
const android = _.includes(process.argv, '--android');
const release = _.includes(process.argv, '--release');
const skipBuild = _.includes(process.argv, '--skipBuild');
const headless = _.includes(process.argv, '--headless');
const multi = _.includes(process.argv, '--multi');
run();
function run() {
const prefix = android ? `android.emu` : `ios.sim`;
const suffix = release ? `release` : `debug`;
const configuration = `${prefix}.${suffix}`;
const headless$ = android ? headless ? `--headless` : `` : ``;
const workers = multi ? 3 : 1;
if (!skipBuild) {
exec.execSync(`detox build --configuration ${configuration}`);
}
exec.execSync(`detox test --loglevel verbose --configuration ${configuration} ${headless$} ${!android ? `-w ${workers}` : ``}`); //-f "ScreenStyle.test.js" --loglevel trace
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment