diff --git a/android/build.gradle b/android/build.gradle index 344f08a..4cdb5cd 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -13,7 +13,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:3.1.3' + classpath 'com.android.tools.build:gradle:3.1.4' } } @@ -34,7 +34,7 @@ android { defaultConfig { minSdkVersion 16 - targetSdkVersion 22 + targetSdkVersion 27 } lintOptions { @@ -45,5 +45,5 @@ android { dependencies { implementation 'com.facebook.react:react-native:+' - api 'it.near.sdk:nearit:2.9.4' + api 'it.near.sdk:nearit:2.9.5' } diff --git a/android/src/main/java/it/near/sdk/reactnative/rnnearitsdk/RNNearItModule.java b/android/src/main/java/it/near/sdk/reactnative/rnnearitsdk/RNNearItModule.java index da0bacd..678ebac 100644 --- a/android/src/main/java/it/near/sdk/reactnative/rnnearitsdk/RNNearItModule.java +++ b/android/src/main/java/it/near/sdk/reactnative/rnnearitsdk/RNNearItModule.java @@ -175,8 +175,8 @@ private Map getEventContentConstants() { private Map getStatusConstants() { return Collections.unmodifiableMap(new HashMap() { { - put("notified", Recipe.RECEIVED); - put("engaged", Recipe.OPENED); + put("received", Recipe.RECEIVED); + put("opened", Recipe.OPENED); } }); } diff --git a/index.d.ts b/index.d.ts index 8fb7038..0ea9477 100644 --- a/index.d.ts +++ b/index.d.ts @@ -26,8 +26,8 @@ declare module 'react-native-nearit' { } interface NearItStatuses { - notified: string - engaged: string + received: string + opened: string } interface NearItEvent { diff --git a/index.js b/index.js index 3de6786..fea3ce2 100644 --- a/index.js +++ b/index.js @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Mattia Panzeri + * Latest changes by Federico Boschini * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -7,3 +8,4 @@ */ export { NearItManager as default, constants as NearItConstants } from './lib/NearItManager' +export { NearITPermissions } from './lib/permissions' diff --git a/ios/NearITSDK/NearITResources.bundle/Info.plist b/ios/NearITSDK/NearITResources.bundle/Info.plist index 1dfb5bc..e6becc9 100644 Binary files a/ios/NearITSDK/NearITResources.bundle/Info.plist and b/ios/NearITSDK/NearITResources.bundle/Info.plist differ diff --git a/ios/NearITSDK/NearITResources.bundle/NITEnrollDeviceViewController.nib/objects-11.0+.nib b/ios/NearITSDK/NearITResources.bundle/NITEnrollDeviceViewController.nib/objects-11.0+.nib index ffdbaa7..eac8813 100644 Binary files a/ios/NearITSDK/NearITResources.bundle/NITEnrollDeviceViewController.nib/objects-11.0+.nib and b/ios/NearITSDK/NearITResources.bundle/NITEnrollDeviceViewController.nib/objects-11.0+.nib differ diff --git a/ios/NearITSDK/NearITResources.bundle/NITEnrollDeviceViewController.nib/runtime.nib b/ios/NearITSDK/NearITResources.bundle/NITEnrollDeviceViewController.nib/runtime.nib index 4eb44ba..1ec0055 100644 Binary files a/ios/NearITSDK/NearITResources.bundle/NITEnrollDeviceViewController.nib/runtime.nib and b/ios/NearITSDK/NearITResources.bundle/NITEnrollDeviceViewController.nib/runtime.nib differ diff --git a/ios/NearITSDK/NearITResources.bundle/NearITResources b/ios/NearITSDK/NearITResources.bundle/NearITResources index fedd3b6..3340d26 100755 Binary files a/ios/NearITSDK/NearITResources.bundle/NearITResources and b/ios/NearITSDK/NearITResources.bundle/NearITResources differ diff --git a/ios/NearITSDK/NearITResources.bundle/_CodeSignature/CodeResources b/ios/NearITSDK/NearITResources.bundle/_CodeSignature/CodeResources deleted file mode 100644 index 01e975b..0000000 --- a/ios/NearITSDK/NearITResources.bundle/_CodeSignature/CodeResources +++ /dev/null @@ -1,151 +0,0 @@ - - - - - files - - Info.plist - - 6fg7eB2Zd4d17gfTazDKT7zekPo= - - NITEnrollDeviceViewController.nib/objects-11.0+.nib - - 4Ua+f/8DCEau+WDBr/UPbZdQwng= - - NITEnrollDeviceViewController.nib/runtime.nib - - wfaNY31dAu6uL4YSriSyM891l0M= - - - files2 - - NITEnrollDeviceViewController.nib/objects-11.0+.nib - - hash - - 4Ua+f/8DCEau+WDBr/UPbZdQwng= - - hash2 - - iM6xjYjmKP34ThKoQ3hnIxuJ+mgIZc6NyQmLU83lvIQ= - - - NITEnrollDeviceViewController.nib/runtime.nib - - hash - - wfaNY31dAu6uL4YSriSyM891l0M= - - hash2 - - q3jinHfHhofIubzEbPaGEXd36/wxEQZmG8FaPRiptYA= - - - - rules - - ^ - - ^.*\.lproj/ - - optional - - weight - 1000 - - ^.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^Base\.lproj/ - - weight - 1010 - - ^version.plist$ - - - rules2 - - .*\.dSYM($|/) - - weight - 11 - - ^ - - weight - 20 - - ^(.*/)?\.DS_Store$ - - omit - - weight - 2000 - - ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ - - nested - - weight - 10 - - ^.* - - ^.*\.lproj/ - - optional - - weight - 1000 - - ^.*\.lproj/locversion.plist$ - - omit - - weight - 1100 - - ^Base\.lproj/ - - weight - 1010 - - ^Info\.plist$ - - omit - - weight - 20 - - ^PkgInfo$ - - omit - - weight - 20 - - ^[^/]+$ - - nested - - weight - 10 - - ^embedded\.provisionprofile$ - - weight - 20 - - ^version\.plist$ - - weight - 20 - - - - diff --git a/ios/NearITSDK/libNearIT.a b/ios/NearITSDK/libNearIT.a index 4952f0a..a1f50b2 100644 Binary files a/ios/NearITSDK/libNearIT.a and b/ios/NearITSDK/libNearIT.a differ diff --git a/ios/Permissions/RCTConvert+RNNPermissionStatus.h b/ios/Permissions/RCTConvert+RNNPermissionStatus.h new file mode 100644 index 0000000..dcd5f73 --- /dev/null +++ b/ios/Permissions/RCTConvert+RNNPermissionStatus.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#if __has_include() + #import +#elif __has_include("React/RCTConvert.h") + #import "React/RCTConvert.h" +#else + #import "RCTConvert.h" +#endif + +static NSString* RNNStatusNeverAsked = @"never_asked"; +static NSString* RNNStatusDenied = @"denied"; +static NSString* RNNStatusGrantedAlways = @"always"; +static NSString* RNNStatusGrantedWhenInUse = @"when_in_use"; + +typedef NS_ENUM(NSInteger, RNNPermissionType) { + RNNPermissionTypeUnknown, + RNNPermissionTypeLocation, + RNNPermissionTypeNotification +}; + +@interface RCTConvert (RNNPermissionStatus) + +@end \ No newline at end of file diff --git a/ios/Permissions/RCTConvert+RNNPermissionStatus.m b/ios/Permissions/RCTConvert+RNNPermissionStatus.m new file mode 100644 index 0000000..63321f6 --- /dev/null +++ b/ios/Permissions/RCTConvert+RNNPermissionStatus.m @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#import "RCTConvert+RNNPermissionStatus.h" + +@implementation RCTConvert (RNNPermissionStatus) + +RCT_ENUM_CONVERTER(RNNPermissionType, (@{ @"location" : @(RNNPermissionTypeLocation), + @"notification" : @(RNNPermissionTypeNotification) + }), + RNNPermissionTypeUnknown, integerValue) + +@end \ No newline at end of file diff --git a/ios/Permissions/RNNLocationPermission.h b/ios/Permissions/RNNLocationPermission.h new file mode 100644 index 0000000..14efd19 --- /dev/null +++ b/ios/Permissions/RNNLocationPermission.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#import +#import "RCTConvert+RNNPermissionStatus.h" + +@interface RNNLocationPermission : NSObject + ++ (NSString *)getStatus; +- (void)requestWithCompletionHandler:(void (^)(NSString *))completionHandler; + +@end \ No newline at end of file diff --git a/ios/Permissions/RNNLocationPermission.m b/ios/Permissions/RNNLocationPermission.m new file mode 100644 index 0000000..33410fc --- /dev/null +++ b/ios/Permissions/RNNLocationPermission.m @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +#import "RNNLocationPermission.h" +#import "RCTConvert+RNNPermissionStatus.h" +#import + +@interface RNNLocationPermission() +@property (strong, nonatomic) CLLocationManager* locationManager; +@property (copy) void (^completionHandler)(NSString *); +@end + +@implementation RNNLocationPermission + ++ (NSString *)getStatus { + int status = [CLLocationManager authorizationStatus]; + switch (status) { + case kCLAuthorizationStatusAuthorizedAlways: + return RNNStatusGrantedAlways; + case kCLAuthorizationStatusAuthorizedWhenInUse: + return RNNStatusGrantedWhenInUse; + case kCLAuthorizationStatusNotDetermined: + return RNNStatusNeverAsked; + default: + return RNNStatusDenied; + } +} + +- (void)requestWithCompletionHandler:(void (^)(NSString *))completionHandler { + NSString *status = [self.class getStatus]; + if ([status isEqualToString:RNNStatusNeverAsked]) { + self.completionHandler = completionHandler; + + if (self.locationManager == nil) { + self.locationManager = [[CLLocationManager alloc] init]; + self.locationManager.delegate = self; + } + + [self.locationManager requestAlwaysAuthorization]; + } else if ([status isEqualToString:RNNStatusDenied]) { + if (@(UIApplicationOpenSettingsURLString != nil)) { + + NSNotificationCenter * __weak center = [NSNotificationCenter defaultCenter]; + id __block token = [center addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil + queue:nil + usingBlock:^(NSNotification *note) { + [center removeObserver:token]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + completionHandler(RNNLocationPermission.getStatus); + }); + }]; + + NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; + [[UIApplication sharedApplication] openURL:url]; + } else { + NSLog(@"E_OPEN_SETTINGS_ERROR: Can't open app settings"); + completionHandler(status); + } + } else { + completionHandler(status); + } +} + +-(void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { + if (status != kCLAuthorizationStatusNotDetermined) { + if (self.locationManager) { + self.locationManager.delegate = nil; + self.locationManager = nil; + } + + if (self.completionHandler) { + //for some reason, checking permission right away returns denied. need to wait a tiny bit + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + self.completionHandler([RNNLocationPermission getStatus]); + self.completionHandler = nil; + }); + } + } +} + +@end \ No newline at end of file diff --git a/ios/Permissions/RNNNotificationPermission.h b/ios/Permissions/RNNNotificationPermission.h new file mode 100644 index 0000000..64f879c --- /dev/null +++ b/ios/Permissions/RNNNotificationPermission.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#import +#import "RCTConvert+RNNPermissionStatus.h" + +@interface RNNNotificationPermission : NSObject + ++ (NSString *)getStatus; +- (void)requestWithCompletionHandler:(void (^)(NSString*))completionHandler; + +@end \ No newline at end of file diff --git a/ios/Permissions/RNNNotificationPermission.m b/ios/Permissions/RNNNotificationPermission.m new file mode 100644 index 0000000..462b6d8 --- /dev/null +++ b/ios/Permissions/RNNNotificationPermission.m @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#import "RNNNotificationPermission.h" +#import "RCTConvert+RNNPermissionStatus.h" + +static NSString* RNNDidAskForNotification = @"RNNDidAskForNotification"; + +@interface RNNNotificationPermission() +@property (copy) void (^completionHandler)(NSString*); +@end + +@implementation RNNNotificationPermission + ++ (NSString *)getStatus { + BOOL didAskForPermission = [[NSUserDefaults standardUserDefaults] boolForKey:RNNDidAskForNotification]; + BOOL isEnabled = [[[UIApplication sharedApplication] currentUserNotificationSettings] types] != UIUserNotificationTypeNone; + + if (isEnabled) { + return RNNStatusGrantedAlways; + } else { + return didAskForPermission ? RNNStatusDenied : RNNStatusNeverAsked; + } +} + +- (void)requestWithCompletionHandler:(void (^)(NSString*))completionHandler { + NSString *status = [self.class getStatus]; + if ([status isEqualToString:RNNStatusNeverAsked]) { + self.completionHandler = completionHandler; + + [[NSNotificationCenter defaultCenter] addObserver:self + selector:@selector(applicationDidBecomeActive) + name:UIApplicationDidBecomeActiveNotification + object:nil]; + + UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeSound | UIUserNotificationTypeAlert | UIUserNotificationTypeBadge) categories:nil]; + [[UIApplication sharedApplication] registerUserNotificationSettings:settings]; + [[UIApplication sharedApplication] registerForRemoteNotifications]; + + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:RNNDidAskForNotification]; + [[NSUserDefaults standardUserDefaults] synchronize]; + } else if ([status isEqualToString:RNNStatusDenied]) { + if (@(UIApplicationOpenSettingsURLString != nil)) { + + NSNotificationCenter * __weak center = [NSNotificationCenter defaultCenter]; + id __block token = [center addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil + queue:nil + usingBlock:^(NSNotification *note) { + [center removeObserver:token]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + completionHandler(RNNNotificationPermission.getStatus); + }); + }]; + + NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; + [[UIApplication sharedApplication] openURL:url]; + } else { + NSLog(@"E_OPEN_SETTINGS_ERROR: Can't open app settings"); + completionHandler(status); + } + } else { + completionHandler(status); + } +} + +- (void)applicationDidBecomeActive { + [[NSNotificationCenter defaultCenter] removeObserver:self + name:UIApplicationDidBecomeActiveNotification + object:nil]; + + if (self.completionHandler) { + //for some reason, checking permission right away returns denied. need to wait a tiny bit + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + self.completionHandler([self.class getStatus]); + self.completionHandler = nil; + }); + } +} + +@end \ No newline at end of file diff --git a/ios/Permissions/RNNPermissions.h b/ios/Permissions/RNNPermissions.h new file mode 100644 index 0000000..c7ff9ca --- /dev/null +++ b/ios/Permissions/RNNPermissions.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + + #if __has_include() + #import +#elif __has_include("React/RCTBridgeModule.h") + #import "React/RCTBridgeModule.h" +#else + #import "RCTBridgeModule.h" +#endif + +@interface RNNPermissions : NSObject + +@end \ No newline at end of file diff --git a/ios/Permissions/RNNPermissions.m b/ios/Permissions/RNNPermissions.m new file mode 100644 index 0000000..ce8b6a9 --- /dev/null +++ b/ios/Permissions/RNNPermissions.m @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#import "RNNPermissions.h" + +#if __has_include() + #import +#elif __has_include("React/RCTBridge.h") + #import "React/RCTBridge.h" +#else + #import "RCTBridge.h" +#endif + +#if __has_include() + #import +#elif __has_include("React/RCTConvert.h") + #import "React/RCTConvert.h" +#else + #import "RCTConvert.h" +#endif + +#if __has_include() + #import +#elif __has_include("React/RCTEventDispatcher.h") + #import "React/RCTEventDispatcher.h" +#else + #import "RCTEventDispatcher.h" +#endif + +#import "RNNLocationPermission.h" +#import "RNNNotificationPermission.h" + +@interface RNNPermissions() +@property (strong, nonatomic) RNNLocationPermission *locationMgr; +@property (strong, nonatomic) RNNNotificationPermission *notificationMgr; +@end + +@implementation RNNPermissions + +RCT_EXPORT_MODULE(); +@synthesize bridge = _bridge; + ++ (BOOL)requiresMainQueueSetup +{ + return YES; +} + +#pragma mark Initialization + +- (instancetype)init +{ + if (self = [super init]) { + } + + return self; +} + +/** + * run on the main queue. + */ +- (dispatch_queue_t)methodQueue { + return dispatch_get_main_queue(); +} + +// MARK: Open app settings + +RCT_REMAP_METHOD(openSettings, openSettings:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + if (@(UIApplicationOpenSettingsURLString != nil)) { + + NSNotificationCenter * __weak center = [NSNotificationCenter defaultCenter]; + id __block token = [center addObserverForName:UIApplicationDidBecomeActiveNotification + object:nil + queue:nil + usingBlock:^(NSNotification *note) { + [center removeObserver:token]; + resolve(@YES); + }]; + + NSURL *url = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; + [[UIApplication sharedApplication] openURL:url]; + } else { + reject(@"E_OPEN_SETTINGS_ERROR", @"Can't open app settings", nil); + } +} + + +// MARK: Check and request permissions + +RCT_REMAP_METHOD(getPermissionStatus, getPermissionStatus:(RNNPermissionType)type resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + resolve([self getPermissionStatus:type]); +} + +RCT_REMAP_METHOD(requestPermission, permissionType:(RNNPermissionType)type resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) +{ + switch (type) { + case RNNPermissionTypeLocation: + return [self requestLocation:resolve]; + case RNNPermissionTypeNotification: + return [self requestNotification:resolve]; + default: + break; + } +} + +- (NSString *) getPermissionStatus:(RNNPermissionType)permissionType +{ + NSString *status; + switch (permissionType) { + case RNNPermissionTypeLocation: { + status = [RNNLocationPermission getStatus]; + break; + } + case RNNPermissionTypeNotification: { + status = [RNNNotificationPermission getStatus]; + break; + } + default: + break; + } + return status; +} + +- (void) requestLocation:(RCTPromiseResolveBlock)resolve +{ + if (self.locationMgr == nil) { + self.locationMgr = [[RNNLocationPermission alloc] init]; + } + + [self.locationMgr requestWithCompletionHandler:resolve]; +} + +- (void) requestNotification:(RCTPromiseResolveBlock)resolve +{ + if (self.notificationMgr == nil) { + self.notificationMgr = [[RNNNotificationPermission alloc] init]; + } + + [self.notificationMgr requestWithCompletionHandler:resolve]; +} + +@end diff --git a/ios/RNNearIt.m b/ios/RNNearIt.m index 0f70715..912b210 100644 --- a/ios/RNNearIt.m +++ b/ios/RNNearIt.m @@ -1,5 +1,6 @@ /* * Copyright (c) 2017 Mattia Panzeri + * Latest changes by Federico Boschini * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -144,8 +145,8 @@ - (NSDictionary *)constantsToExport @"status": EVENT_STATUS }, @"Statuses": @{ - @"notified": NITRecipeReceived, - @"engaged": NITRecipeOpened + @"received": NITRecipeReceived, + @"opened": NITRecipeOpened }, @"Permissions": @{ @"LocationGranted": PERMISSION_LOCATION_GRANTED, diff --git a/ios/RNNearIt.xcodeproj/project.pbxproj b/ios/RNNearIt.xcodeproj/project.pbxproj index 6d7bd8c..055b901 100644 --- a/ios/RNNearIt.xcodeproj/project.pbxproj +++ b/ios/RNNearIt.xcodeproj/project.pbxproj @@ -9,7 +9,11 @@ /* Begin PBXBuildFile section */ 3008FF0C1F838526006CA738 /* RNNearItBackgroundQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 3008FF0A1F838526006CA738 /* RNNearItBackgroundQueue.m */; }; 303C4C5D1FCC4E5A0060F04B /* RNNotificationsQueue.m in Sources */ = {isa = PBXBuildFile; fileRef = 303C4C5B1FCC4E590060F04B /* RNNotificationsQueue.m */; }; - 3850096C202C576D0076609B /* NearITResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 38500944202B04C00076609B /* NearITResources.bundle */; }; + 3817F1A321382E5C0019F552 /* RNNNotificationPermission.m in Sources */ = {isa = PBXBuildFile; fileRef = 3817F19D21382E5C0019F552 /* RNNNotificationPermission.m */; }; + 3817F1A421382E5C0019F552 /* RCTConvert+RNNPermissionStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 3817F19F21382E5C0019F552 /* RCTConvert+RNNPermissionStatus.m */; }; + 3817F1A521382E5C0019F552 /* RNNLocationPermission.m in Sources */ = {isa = PBXBuildFile; fileRef = 3817F1A021382E5C0019F552 /* RNNLocationPermission.m */; }; + 3817F1A621382E5C0019F552 /* RNNPermissions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3817F1A221382E5C0019F552 /* RNNPermissions.m */; }; + 38D7ED5C2136E8D7008F1212 /* NearITResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 38500944202B04C00076609B /* NearITResources.bundle */; }; 38E31BFE21130F510058EE9D /* libNearIT.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 307D9F851F9F7D7A00BFBA46 /* libNearIT.a */; }; B3E7B58A1CC2AC0600A0062D /* RNNearIt.m in Sources */ = {isa = PBXBuildFile; fileRef = B3E7B5891CC2AC0600A0062D /* RNNearIt.m */; }; /* End PBXBuildFile section */ @@ -34,6 +38,14 @@ 303C4C5B1FCC4E590060F04B /* RNNotificationsQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNotificationsQueue.m; sourceTree = ""; }; 303C4C5C1FCC4E590060F04B /* RNNotificationsQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNotificationsQueue.h; sourceTree = ""; }; 307D9F851F9F7D7A00BFBA46 /* libNearIT.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libNearIT.a; path = NearITSDK/libNearIT.a; sourceTree = ""; }; + 3817F19B21382E5C0019F552 /* RNNNotificationPermission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNNNotificationPermission.h; path = Permissions/RNNNotificationPermission.h; sourceTree = ""; }; + 3817F19C21382E5C0019F552 /* RCTConvert+RNNPermissionStatus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "RCTConvert+RNNPermissionStatus.h"; path = "Permissions/RCTConvert+RNNPermissionStatus.h"; sourceTree = ""; }; + 3817F19D21382E5C0019F552 /* RNNNotificationPermission.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNNNotificationPermission.m; path = Permissions/RNNNotificationPermission.m; sourceTree = ""; }; + 3817F19E21382E5C0019F552 /* RNNLocationPermission.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNNLocationPermission.h; path = Permissions/RNNLocationPermission.h; sourceTree = ""; }; + 3817F19F21382E5C0019F552 /* RCTConvert+RNNPermissionStatus.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "RCTConvert+RNNPermissionStatus.m"; path = "Permissions/RCTConvert+RNNPermissionStatus.m"; sourceTree = ""; }; + 3817F1A021382E5C0019F552 /* RNNLocationPermission.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNNLocationPermission.m; path = Permissions/RNNLocationPermission.m; sourceTree = ""; }; + 3817F1A121382E5C0019F552 /* RNNPermissions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RNNPermissions.h; path = Permissions/RNNPermissions.h; sourceTree = ""; }; + 3817F1A221382E5C0019F552 /* RNNPermissions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RNNPermissions.m; path = Permissions/RNNPermissions.m; sourceTree = ""; }; 38500944202B04C00076609B /* NearITResources.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = NearITResources.bundle; path = NearITSDK/NearITResources.bundle; sourceTree = ""; }; B3E7B5881CC2AC0600A0062D /* RNNearIt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RNNearIt.h; sourceTree = ""; }; B3E7B5891CC2AC0600A0062D /* RNNearIt.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RNNearIt.m; sourceTree = ""; }; @@ -69,6 +81,14 @@ 58B511D21A9E6C8500147676 = { isa = PBXGroup; children = ( + 3817F19C21382E5C0019F552 /* RCTConvert+RNNPermissionStatus.h */, + 3817F19F21382E5C0019F552 /* RCTConvert+RNNPermissionStatus.m */, + 3817F19E21382E5C0019F552 /* RNNLocationPermission.h */, + 3817F1A021382E5C0019F552 /* RNNLocationPermission.m */, + 3817F19B21382E5C0019F552 /* RNNNotificationPermission.h */, + 3817F19D21382E5C0019F552 /* RNNNotificationPermission.m */, + 3817F1A121382E5C0019F552 /* RNNPermissions.h */, + 3817F1A221382E5C0019F552 /* RNNPermissions.m */, 38500944202B04C00076609B /* NearITResources.bundle */, 303C4C5C1FCC4E590060F04B /* RNNotificationsQueue.h */, 303C4C5B1FCC4E590060F04B /* RNNotificationsQueue.m */, @@ -139,7 +159,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3850096C202C576D0076609B /* NearITResources.bundle in Resources */, + 38D7ED5C2136E8D7008F1212 /* NearITResources.bundle in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -150,9 +170,13 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 3817F1A321382E5C0019F552 /* RNNNotificationPermission.m in Sources */, + 3817F1A421382E5C0019F552 /* RCTConvert+RNNPermissionStatus.m in Sources */, + 3817F1A521382E5C0019F552 /* RNNLocationPermission.m in Sources */, 3008FF0C1F838526006CA738 /* RNNearItBackgroundQueue.m in Sources */, B3E7B58A1CC2AC0600A0062D /* RNNearIt.m in Sources */, 303C4C5D1FCC4E5A0060F04B /* RNNotificationsQueue.m in Sources */, + 3817F1A621382E5C0019F552 /* RNNPermissions.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/package.json b/package.json index 6c7a327..bd1b157 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-nearit", - "version": "2.9.0-beta.1", + "version": "2.9.0-beta.2", "author": "Mattia Panzeri ", "contributors": [ "Federico Boschini " @@ -52,10 +52,5 @@ }, "standard": { "parser": "babel-eslint" - }, - "rnpm": { - "commands": { - "postlink": "node node_modules/react-native-nearit/scripts/postlink/run.js" - } } } diff --git a/scripts/postlink/postlink.android.js b/scripts/postlink/postlink.android.js index aceb7ef..e69de29 100644 --- a/scripts/postlink/postlink.android.js +++ b/scripts/postlink/postlink.android.js @@ -1,134 +0,0 @@ -var fs = require('fs') -var path = require('path') -var glob = require('glob') -var emoji = require('../utils').emoji - -module.exports = () => { - console.log(emoji.robot, 'Running Android postlink script') - - // Gradle deps to inject - - var googleServicesGradleDep = `classpath 'com.google.gms:google-services:4.0.1'` - var nearitRequiredCompileSdkVersion = `compileSdkVersion 27` - var nearitRequiredBuildToolsVersion = `buildToolsVersion "27.0.3"` - var rnNearItImport = `import it.near.sdk.reactnative.rnnearitsdk.RNNearItModule;` - var rnNearItOnPostCreateHook = `RNNearItModule.onPostCreate(getApplicationContext(), getIntent());` - var rnNearItOnPostCreateMethod = ` @Override\n protected void onPostCreate(@Nullable Bundle savedInstanceState) {\n super.onPostCreate(savedInstanceState);\n RNNearItModule.onPostCreate(getApplicationContext(), getIntent());\n }` - - // Common build file paths - var ignoreFolders = { ignore: ['node_modules/**', '**/build/**'] } - var mainBuildGradlePath = path.join('android', 'build.gradle') - var appBuildGradlePath = path.join('android', 'app', 'build.gradle') - var mainActivityPath = glob.sync('**/MainActivity.java', ignoreFolders)[0] - - if (!fs.existsSync(mainBuildGradlePath) || !fs.existsSync(appBuildGradlePath)) { - return Promise.reject(new Error(`Couldn't find 'build.gradle' files. You might need to update them manually. \ - Please refer to plugin manual installation section for Android at \ - https://nearit-react-native-sdk.readthedocs.io/en/latest/manual-installation-android/`)) - } - - var mainBuildGradleContents = fs.readFileSync(mainBuildGradlePath, 'utf8') - - // 1. Add google-services dependency definition - var androidToolsGradleLink = mainBuildGradleContents.match(/classpath ["']com\.android\.tools\.build:gradle:.*["']/)[0] - var gmsGradleLinkMatches = mainBuildGradleContents.match(/classpath ["']com\.google\.gms:google-services:.*["']/) - if (gmsGradleLinkMatches && gmsGradleLinkMatches.length > 0) { - if (~mainBuildGradleContents.indexOf(googleServicesGradleDep)) { - console.log(emoji.ok, `"google-services" already added.`) - } else { - console.log(emoji.running, `Updating "google-services" inside build definition`) - var gmsGradleLink = gmsGradleLinkMatches[0] - mainBuildGradleContents = mainBuildGradleContents.replace(gmsGradleLink, googleServicesGradleDep) - fs.writeFileSync(mainBuildGradlePath, mainBuildGradleContents) - } - } else { - console.log(emoji.running, `Adding "google-services" to the build definition`) - mainBuildGradleContents = mainBuildGradleContents.replace(androidToolsGradleLink, - `${androidToolsGradleLink}\n ${googleServicesGradleDep}`) - fs.writeFileSync(mainBuildGradlePath, mainBuildGradleContents) - } - - // 2. Add google maven repository - var jcenterMavenRepository = mainBuildGradleContents.match(/mavenLocal\(\)\n {8}jcenter\(\)/)[0] - var googleMavenRepository = `maven { url "https://maven.google.com" }` - var googleRepository = `google()` - if (~mainBuildGradleContents.indexOf(googleMavenRepository)) { - console.log(emoji.ok, `"google" maven repository already added.`) - } else { - console.log(emoji.running, `Adding "google" maven repository to the build definition`) - mainBuildGradleContents = mainBuildGradleContents.replace(jcenterMavenRepository, - `${jcenterMavenRepository}\n ${googleMavenRepository}`) - fs.writeFileSync(mainBuildGradlePath, mainBuildGradleContents) - } - - if (~mainBuildGradleContents.indexOf(googleRepository)) { - console.log(emoji.ok, `"google()" repository already added.`) - } else { - console.log(emoji.running, `Adding "google()" repository to the build definition`) - mainBuildGradleContents = mainBuildGradleContents.replace(jcenterMavenRepository, - `${googleRepository}\n ${jcenterMavenRepository}\n`) - fs.writeFileSync(mainBuildGradlePath, mainBuildGradleContents) - } - - var appBuildGradleContents = fs.readFileSync(appBuildGradlePath, 'utf8') - - // 3. Add google services plugin to app build definition - var googleServicesPlugin = `apply plugin: 'com.google.gms.google-services'` - if (~appBuildGradleContents.indexOf(googleServicesPlugin)) { - console.log(emoji.ok, `"google-services" plugin already added.`) - } else { - console.log(emoji.running, `Adding "google-services" plugin to the app build definition`) - appBuildGradleContents = `${appBuildGradleContents}\n\n${googleServicesPlugin}` - fs.writeFileSync(appBuildGradlePath, appBuildGradleContents) - } - - // 4. Update compile SDK and Tools versions - var compileSdkVersion = appBuildGradleContents.match(/compileSdkVersion [0-9]{2}/)[0] - if (compileSdkVersion === nearitRequiredCompileSdkVersion) { - console.log(emoji.ok, `"compileSdkVersion" already updated.`) - } else { - console.log(emoji.running, `Updating "compileSdkVersion" in the app build definition`) - appBuildGradleContents = appBuildGradleContents.replace(compileSdkVersion, nearitRequiredCompileSdkVersion) - fs.writeFileSync(appBuildGradlePath, appBuildGradleContents) - } - - var buildToolsVersion = appBuildGradleContents.match(/buildToolsVersion "[0-9]*\.[0-9]*\.[0-9]*"/)[0] - if (buildToolsVersion === nearitRequiredBuildToolsVersion) { - console.log(emoji.ok, `"buildToolsVersion" already updated.`) - } else { - console.log(emoji.running, `Updating "buildToolsVersion" in the app build definition`) - appBuildGradleContents = appBuildGradleContents.replace(buildToolsVersion, nearitRequiredBuildToolsVersion) - fs.writeFileSync(appBuildGradlePath, appBuildGradleContents) - } - - // 5. Add `onPostCreate` passthrough to `MainActivity` - if (mainActivityPath) { - var mainActivityContents = fs.readFileSync(mainActivityPath, 'utf8') - if (~mainActivityContents.indexOf(rnNearItImport)) { - console.log(emoji.ok, `MainActivity.java imports already updated.`) - } else { - console.log(emoji.running, `Updating MainActivity.java imports`) - var reactNativeJavaImport = mainActivityContents.match(/import com\.facebook\.react\.ReactActivity;/)[0] - mainActivityContents = mainActivityContents.replace(reactNativeJavaImport, - `${reactNativeJavaImport}\n\n${rnNearItImport}`) - fs.writeFileSync(mainActivityPath, mainActivityContents) - } - - if (~mainActivityContents.indexOf(rnNearItOnPostCreateHook)) { - console.log(emoji.ok, `MainActivity.java onPostCreateHook already added.`) - } else { - console.log(emoji.running, `Adding onPostCreateHook to MainActivity.java`) - var reactNativeGetComponentMethod = mainActivityContents.match(/getMainComponentName\(\) \{[\s\S]*?\}/)[0] - - mainActivityContents = mainActivityContents.replace(reactNativeGetComponentMethod, - `${reactNativeGetComponentMethod}\n\n\n${rnNearItOnPostCreateMethod}`) - fs.writeFileSync(mainActivityPath, mainActivityContents) - } - } else { - return Promise.reject(new Error(`Couldn't find Android activity entry point. You might need to update it manually. \ - Please refer to plugin configuration section for Android at \ - https://nearit-react-native-sdk.readthedocs.io/en/latest/manual-installation-android/ for more details`)) - } - - return Promise.resolve() -} diff --git a/scripts/postlink/postlink.ios.js b/scripts/postlink/postlink.ios.js index adf1b65..b13ff49 100644 --- a/scripts/postlink/postlink.ios.js +++ b/scripts/postlink/postlink.ios.js @@ -1,201 +1,36 @@ -var fs = require('fs') -var glob = require('glob') -var emoji = require('../utils').emoji - -const packageJson = require('../../../../package.json') - -module.exports = () => { - console.log(emoji.apple, 'Running iOS postlink script') - - var ignoreNodeModules = { ignore: [ 'node_modules/**', '**/build/**' ] } - var appDelegatePaths = glob.sync('**/AppDelegate.+(mm|m)', ignoreNodeModules) - - // Typical location of AppDelegate.m for newer RN versions: $PROJECT_ROOT/ios//AppDelegate.m - // Let's try to find that path by filtering the whole array for any path containing - // If we can't find it there, play dumb and pray it is the first path we find. - var appDelegatePath = findFileByAppName(appDelegatePaths, packageJson ? packageJson.name : null) || appDelegatePaths[0] - - if (!appDelegatePath) { - return Promise.reject(new Error(`Couldn't find AppDelegate. You might need to update it manually \ - Please refer to plugin configuration section for iOS at \ - https://nearit-react-native-sdk.readthedocs.io/en/latest/manual-installation-ios/`)) - } - - var infoPlistPaths = glob.sync('**/Info.plist', { - ignore: [].concat(ignoreNodeModules.ignore, [ '**/*-tvOS/Info.plist', '**/*Tests/Info.plist' ]) - }) - var infoPlistPath = findFileByAppName(infoPlistPaths, packageJson ? packageJson.name : null) || infoPlistPaths[0] - - if (!infoPlistPath) { - return Promise.reject(new Error(`Couldn't find Info.plist file. You might need to update it manually \ - Please refer to plugin configuration section for iOS at \ - https://nearit-react-native-sdk.readthedocs.io/en/latest/manual-installation-ios/`)) - } - - var projectPbxPaths = glob.sync('**/project.pbxproj', ignoreNodeModules) - var projectPbxPath = findFileByAppName(projectPbxPaths, packageJson ? packageJson.name : null) || projectPbxPaths[0] - - if (!projectPbxPaths) { - return Promise.reject(new Error(`Couldn't find project.pbxproj file. You might need to enable Background Modes capability manually \ - Please refer to plugin configuration section for iOS at \ - https://nearit-react-native-sdk.readthedocs.io/en/latest/manual-installation-ios/`)) - } - - var appDelegateContents = fs.readFileSync(appDelegatePath, 'utf8') - var infoPlistContents = fs.readFileSync(infoPlistPath, 'utf8') - var pbxprojFileContents = fs.readFileSync(projectPbxPath, 'utf8') - - // 1. Add the header import statement - var nearItHeaderImportStatement = `#import "RNNearIt.h"` - if (~appDelegateContents.indexOf(nearItHeaderImportStatement)) { - console.log(emoji.ok, `"RNNearIT.h" header already imported.`) - } else { - console.log(emoji.running, `Editing AppDelegate.m to import RNNearIT.h`) - var appDelegateHeaderImportStatement = `#import "AppDelegate.h"` - appDelegateContents = appDelegateContents.replace(appDelegateHeaderImportStatement, - `${appDelegateHeaderImportStatement}\n${nearItHeaderImportStatement}`) - } - - // 2. Add RegisterForRemoteNotification method invocation - var nearItAppDelegateRegisterMethodCall = `[RNNearIt registerForRemoteNotifications];` - if (~appDelegateContents.indexOf(nearItAppDelegateRegisterMethodCall)) { - console.log(emoji.ok, `"[RNNearIt registerForRemoteNotifications];" already added.`) - } else { - console.log(emoji.running, `Editing AppDelegate.m to enable Remote Notification`) - var appDelegateMakeKeyAndVisible = `[self.window makeKeyAndVisible];` - appDelegateContents = appDelegateContents.replace(appDelegateMakeKeyAndVisible, - `${appDelegateMakeKeyAndVisible}\n\n ${nearItAppDelegateRegisterMethodCall}\n`) - } - - // 3. Add didFinishLaunchingWithOptions method invocation - var nearItAppDelegateFinishLaunchingMethodCall = `[RNNearIt application:application didFinishLaunchingWithOptions:launchOptions];` - if (~appDelegateContents.indexOf(nearItAppDelegateFinishLaunchingMethodCall)) { - console.log(emoji.ok, `"[RNNearIt application:application didFinishLaunchingWithOptions:launchOptions];" already added.`) - } else { - console.log(emoji.running, `Editing AppDelegate.m to enable Remote Notification when app is killed`) - appDelegateContents = appDelegateContents.replace(nearItAppDelegateRegisterMethodCall, - `${nearItAppDelegateRegisterMethodCall}\n ${nearItAppDelegateFinishLaunchingMethodCall}\n`) - } - - // AppDelegate.m @end tag - var appDelegateEndTag = `@end` - - // 4. Add Passthrough functions - var nearItPassthroughComment = `// Needed by NearIT plugin -- DO NOT REMOVE THIS COMMENT` - if (~appDelegateContents.indexOf(nearItPassthroughComment)) { - console.log(emoji.ok, `Passthrough functions already added.`) - } else { - console.log(emoji.running, `Editing AppDelegate.m to add Passthrough functions`) - var nearItPassthroughFunctions = getPassthroughFunctionsCalls() - appDelegateContents = appDelegateContents.replace(appDelegateEndTag, - `${nearItPassthroughComment}\n${nearItPassthroughFunctions}\n\n${appDelegateEndTag}`) - } - - // 5. Enable Background Fetch - - // 5.1 Add passthrough function to AppDelegate.m - var nearItBackgroundFetchComment = `// Needed by NearIT plugin -- Enable Background Updates -- DO NOT REMOVE THIS COMMENT` - if (~appDelegateContents.indexOf(nearItBackgroundFetchComment)) { - console.log(emoji.ok, `Background Fetch passthrough function already added.`) - } else { - console.log(emoji.running, `Editing AppDelegate.m to add Background Fetch passthrough function`) - var nearItBkgFetchFunctions = getBackgroundFetchPassthroughFunctionsCalls() - appDelegateContents = appDelegateContents.replace(appDelegateEndTag, - `${nearItBackgroundFetchComment}\n${nearItBkgFetchFunctions}\n\n${appDelegateEndTag}`) - } - - // 5.2 Patch Info.plist - var uiBkgModesPlistEntry = `UIBackgroundModes` - if (~infoPlistContents.indexOf(uiBkgModesPlistEntry)) { - console.log(emoji.ok, `Background Fetch capability already enabled. Info.plist keys are present.`) - } else { - console.log(emoji.running, `Editing Info.plist to add Background Fetch capability entry`) - var plistEndTag = `\n` - var uiBackgroundModesEntries = getBackgroundFetchInfoPlistKeys() - infoPlistContents = infoPlistContents.replace(plistEndTag, - `${uiBackgroundModesEntries}\n${plistEndTag}`) - } - - // 5.3 Patch App Project file - var bkgModesSystemCapability = `com.apple.BackgroundModes` - if (~pbxprojFileContents.indexOf(bkgModesSystemCapability)) { - console.log(emoji.ok, `Background Fetch capability already enabled. Project is already up-to-date.`) - } else { - console.log(emoji.running, `Editing Project.pbxproj file to enable Background Fetch capability`) - var systemCapabilitiesMap = `SystemCapabilities = {` - var backgroundModesSystemCap = getBackgroundModesCapability() - pbxprojFileContents = pbxprojFileContents.replace(systemCapabilitiesMap, - `${systemCapabilitiesMap}${backgroundModesSystemCap}`) - } - - - // Commit changes to files - writePatches() - - // Resolve promise - return Promise.resolve() - - // Internal functions - - // Push notifications functions - function getPassthroughFunctionsCalls () { - return ` -- (void)application:(UIApplication*) application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { - [RNNearIt didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; -} - -- (void)application:(UIApplication*) application didReceiveLocalNotification:(UILocalNotification *)notification { - [RNNearIt didReceiveLocalNotification:notification]; -} - -- (void)application:(UIApplication*) application didReceiveRemoteNotification:(NSDictionary *)userInfo { - [RNNearIt didReceiveRemoteNotification:userInfo]; -}` - } - - // Background fetch functions - function getBackgroundFetchPassthroughFunctionsCalls () { - return ` -- (void)application:(UIApplication *)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { - [RNNearIt application:application performFetchWithCompletionHandler:completionHandler]; -}` - } - - // Background Fetch Info.plist keys - function getBackgroundFetchInfoPlistKeys () { - return ` UIBackgroundModes - - fetch - ` - } - - // Background Modes System Capability - function getBackgroundModesCapability () { - return ` - com.apple.BackgroundModes = { - enabled = 1; - };` - } - - // Commit changes to files - function writePatches () { - fs.writeFileSync(appDelegatePath, appDelegateContents) - fs.writeFileSync(infoPlistPath, infoPlistContents) - fs.writeFileSync(projectPbxPath, pbxprojFileContents) - } - - // Helper that filters an array with AppDelegate.m paths for a path with the app name inside it - // Should cover nearly all cases - function findFileByAppName (array, appName) { - if (array.length === 0 || !appName) return null - - for (var i = 0; i < array.length; i++) { - var path = array[i] - if (path && path.indexOf(appName) !== -1) { - return path - } +const config = require('react-native/local-cli/core/index'); +const PbxFile = require('xcode/lib/pbxFile'); +const path = require('path'); +const xcode = require('xcode'); +const fs = require('fs'); +const createGroupWithMessage = require('react-native/local-cli/link/ios/createGroupWithMessage'); + +function addNearITiOSResources() { + const iOSconfig = config.getProjectConfig().ios; + const nearit_iOSconfig = config.getDependencyConfig('react-native-nearit').ios; + + const project = xcode.project(iOSconfig.pbxprojPath).parseSync(); + + var targets = project.pbxNativeTargetSection(); + + for (uuid in targets) { + var libFiles = project.pbxFrameworksBuildPhaseObj(uuid).files; + var filesCount = libFiles.length; + for (var f = 0; f < filesCount; ++f) { + var fileRef = project.pbxBuildFileSection()[libFiles[f].value].fileRef; + var file = project.pbxFileReferenceSection()[fileRef]; + if (file != null) { + if (file.path == 'libRNNearIt.a') { + createGroupWithMessage(project, 'Resources'); + project.addResourceFile(path.relative(iOSconfig.sourceDir, path.join(nearit_iOSconfig.sourceDir, 'NearITResources.bundle')), {'target' : uuid }, null); + } + } + } } + fs.writeFileSync( + iOSconfig.pbxprojPath, + project.writeSync() + ); +}; - return null - } -} +addNearITiOSResources(); diff --git a/scripts/postlink/run.js b/scripts/postlink/run.js index f8f7517..fdecc2a 100644 --- a/scripts/postlink/run.js +++ b/scripts/postlink/run.js @@ -1,11 +1,11 @@ var postlinks = [ - require('./postlink.ios'), - require('./postlink.android') -] - -// run them sequentially -postlinks - .reduce((p, fn) => p.then(fn), Promise.resolve()) - .catch((err) => { - console.error(err.message) - }) + require('./postlink.ios') + //require('./postlink.android') + ] + + // run them sequentially + postlinks + .reduce((p, fn) => p.then(fn), Promise.resolve()) + .catch((err) => { + console.error(err.message) + }) \ No newline at end of file diff --git a/scripts/utils/index.js b/scripts/utils/index.js deleted file mode 100644 index ef667ff..0000000 --- a/scripts/utils/index.js +++ /dev/null @@ -1,10 +0,0 @@ -module.exports = { - emoji: { - unicorn: "🦄 ", - apple: "🍎 ", - robot: "🤖 ", - pizza: "🍕 ", - ok: "✅ ", - running: "🌀 " - } -} \ No newline at end of file diff --git a/src/NearItManager.js b/src/NearItManager.js index 91a926e..6a57b98 100644 --- a/src/NearItManager.js +++ b/src/NearItManager.js @@ -25,8 +25,8 @@ type NearItEventContent = { } type NearItStatuses = { - notified: string, - engaged: string + received: string, + opened: string } type NearItConstants = { diff --git a/src/permissions.android.js b/src/permissions.android.js new file mode 100644 index 0000000..998e19a --- /dev/null +++ b/src/permissions.android.js @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// @flow +import { AsyncStorage, NativeModules, PermissionsAndroid } from 'react-native' + +type Status = 'always' | 'denied' | 'when_in_use' | 'never_asked' + +const permissionTypes = { + location: PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION +} + +const RESULTS = { + [PermissionsAndroid.RESULTS.GRANTED]: 'always', + [PermissionsAndroid.RESULTS.DENIED]: 'denied', + [PermissionsAndroid.RESULTS.NEVER_ASK_AGAIN]: 'denied' +} + +const STORAGE_KEY = '@RNNAsked:' + +const setDidAskOnce = (permission: string) => + AsyncStorage.setItem(STORAGE_KEY + permission, 'true') + +const getDidAskOnce = (permission: string) => + AsyncStorage.getItem(STORAGE_KEY + permission).then(item => !!item) + +export class NearITPermissions { + static openSettings (): Promise<*> { + return Promise.reject(new Error("'openSettings' is deprecated on android")) + } + + static checkLocation (): Promise { + return PermissionsAndroid.check(permissionTypes['location']).then( + isAuthorized => { + if (isAuthorized) { + return 'always' + } + + return getDidAskOnce('location').then(didAsk => { + if (didAsk) { + return NativeModules.PermissionsAndroid.shouldShowRequestPermissionRationale( + permissionTypes['location'] + ).then(shouldShow => ('denied')) + } + + return 'never_asked' + }) + } + ) + } + + static requestLocation (): Promise { + let rationale + + return PermissionsAndroid.request( + permissionTypes['location'], + rationale + ).then(result => { + // PermissionsAndroid.request() to native module resolves to boolean + // rather than string if running on OS version prior to Android M + if (typeof result === 'boolean') { + return result ? 'always' : 'denied' + } + + return setDidAskOnce('location').then(() => RESULTS[result]) + }) + } + + static checkNotification (): Promise { + return Promise.resolve('always') + } + + static requestNotification (): Promise { + return Promise.resolve('always') + } +} diff --git a/src/permissions.ios.js b/src/permissions.ios.js new file mode 100644 index 0000000..ebaf39c --- /dev/null +++ b/src/permissions.ios.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018 Federico Boschini + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +// @flow +import { NativeModules } from 'react-native' +const PermissionsIOS = NativeModules.RNNPermissions + +type Status = 'always' | 'denied' | 'when_in_use' | 'never_asked' + +export class NearITPermissions { + static openSettings (): Promise<*> { + return PermissionsIOS.openSettings() + } + + static checkLocation (): Promise { + return PermissionsIOS.getPermissionStatus('location') + } + + static requestLocation (): Promise { + return PermissionsIOS.requestPermission('location') + } + + static checkNotification (): Promise { + return PermissionsIOS.getPermissionStatus('notification') + } + + static requestNotification (): Promise { + return PermissionsIOS.requestPermission('notification') + } +}