Explorar o código

refactor. started adding request permissions

Yonah Forst %!s(int64=9) %!d(string=hai) anos
pai
achega
c040506d7c

+ 26 - 0
PermissionsAsker.h

@@ -0,0 +1,26 @@
+//
+//  PermissionsAsker.h
+//  ReactNativePermissions
+//
+//  Created by Yonah Forst on 07/07/16.
+//  Copyright © 2016 Yonah Forst. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+#import <UIKit/UIKit.h>
+#import "RCTConvert+RNPermissionsStatus.h"
+
+@interface PermissionsAsker : NSObject
+
++ (instancetype)sharedInstance;
+- (void)location:(NSString *)type;
+- (void)notification:(UIUserNotificationType)types completionHandler:(void (^)(RNPermissionsStatus))completionHandler;
+- (void)bluetooth;
+- (void)camera;
+- (void)microphone;
+- (void)photo;
+- (void)contacts;
+- (void)event;
+- (void)reminder;
+- (void)backgroundRefresh;
+@end

+ 114 - 0
PermissionsAsker.m

@@ -0,0 +1,114 @@
+//
+//  PermissionsAsker.m
+//  ReactNativePermissions
+//
+//  Created by Yonah Forst on 07/07/16.
+//  Copyright © 2016 Yonah Forst. All rights reserved.
+//
+
+#import "PermissionsAsker.h"
+
+#import <AddressBook/AddressBook.h>
+#import <AssetsLibrary/AssetsLibrary.h>
+#import <EventKit/EventKit.h>
+#import <CoreLocation/CoreLocation.h>
+#import <AVFoundation/AVFoundation.h>
+#import <CoreBluetooth/CoreBluetooth.h>
+
+#import "PermissionsChecker.h"
+
+static PermissionsAsker *__sharedInstance;
+
+@interface PermissionsAsker() <CLLocationManagerDelegate, CBPeripheralManagerDelegate>
+@property (strong, nonatomic) CLLocationManager *locationManager;
+@property (strong, nonatomic) CBPeripheralManager *peripheralManager;
+@property (copy) void (^notificationCompletionBlock)(RNPermissionsStatus);
+
+@end
+
+
+@implementation PermissionsAsker
+
++ (instancetype) sharedInstance
+{
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        __sharedInstance = [[PermissionsAsker alloc] init];
+    });
+    return __sharedInstance;
+}
+
+
+- (void)location:(NSString *)type
+{
+    self.locationManager = [[CLLocationManager alloc] init];
+    self.locationManager.delegate = self;
+    if ([type isEqualToString:@"always"]) {
+        [self.locationManager requestAlwaysAuthorization];
+    } else {
+        [self.locationManager requestWhenInUseAuthorization];
+    }
+}
+
+- (void)notification:(UIUserNotificationType)types completionHandler:(void (^)(RNPermissionsStatus))completionHandler
+{
+    BOOL didAskForPermission = [[NSUserDefaults standardUserDefaults] boolForKey:@"DidAskForNotifications"];
+    if (!didAskForPermission) {
+        self.notificationCompletionBlock = completionHandler;
+        
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(applicationDidBecomeActive)
+                                                     name:UIApplicationDidBecomeActiveNotification
+                                                   object:nil];
+        
+        if ([[UIApplication sharedApplication] respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
+            // iOS8+
+            UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
+            [[UIApplication sharedApplication] registerUserNotificationSettings:settings];
+            [[UIApplication sharedApplication] registerForRemoteNotifications];
+        } else {
+            [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationType)types];
+        }
+        
+        [[NSUserDefaults standardUserDefaults] setBool:YES
+                                                forKey:@"DidAskForNotifications"];
+        [[NSUserDefaults standardUserDefaults] synchronize];
+    } else {
+        RNPermissionsStatus status = [PermissionsChecker notification];
+        completionHandler(status);
+    }
+
+}
+
+- (void)applicationDidBecomeActive
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self
+                                                    name:UIApplicationDidBecomeActiveNotification
+                                                  object:nil];
+
+    //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(), ^{
+        RNPermissionsStatus status = [PermissionsChecker notification];
+        self.notificationCompletionBlock(status);
+        self.notificationCompletionBlock = nil;
+    });
+}
+
+- (void)bluetooth
+{
+    self.peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
+    [self.peripheralManager startAdvertising:@{}];
+}
+
+- (void) peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheralManager
+{
+    if (self.peripheralManager) {
+        [self.peripheralManager stopAdvertising];
+        self.peripheralManager = nil;
+    }
+}
+
+
+
+
+@end

+ 10 - 10
PermissionsChecker.h

@@ -11,15 +11,15 @@
 
 + (BOOL)canOpenSettings;
 + (void)openSettings;
-+ (RNPermissionsStatus)locationPermissionStatus;
-+ (RNPermissionsStatus)cameraPermissionStatus;
-+ (RNPermissionsStatus)microphonePermissionStatus;
-+ (RNPermissionsStatus)photoPermissionStatus;
-+ (RNPermissionsStatus)contactsPermissionStatus;
-+ (RNPermissionsStatus)eventPermissionStatus;
-+ (RNPermissionsStatus)reminderPermissionStatus;
-+ (RNPermissionsStatus)bluetoothPermissionStatus;
-+ (RNPermissionsStatus)notificationPermissionStatus;
-+ (RNPermissionsStatus)backgroundRefreshPermissionStatus;
++ (RNPermissionsStatus)location;
++ (RNPermissionsStatus)camera;
++ (RNPermissionsStatus)microphone;
++ (RNPermissionsStatus)photo;
++ (RNPermissionsStatus)contacts;
++ (RNPermissionsStatus)event;
++ (RNPermissionsStatus)reminder;
++ (RNPermissionsStatus)bluetooth;
++ (RNPermissionsStatus)notification;
++ (RNPermissionsStatus)backgroundRefresh;
 
 @end

+ 30 - 29
PermissionsChecker.m

@@ -42,7 +42,7 @@
 }
 
 
-+ (RNPermissionsStatus)locationPermissionStatus
++ (RNPermissionsStatus)location
 {
     int status = [CLLocationManager authorizationStatus];
     switch (status) {
@@ -61,7 +61,7 @@
 
 
 
-+ (RNPermissionsStatus)cameraPermissionStatus
++ (RNPermissionsStatus)camera
 {
     int status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
     switch (status) {
@@ -76,7 +76,7 @@
     }
 }
 
-+ (RNPermissionsStatus)microphonePermissionStatus
++ (RNPermissionsStatus)microphone
 {
     int status = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
     switch (status) {
@@ -91,7 +91,7 @@
     }
 }
 
-+ (RNPermissionsStatus)photoPermissionStatus
++ (RNPermissionsStatus)photo
 {
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0
     int status = [PHPhotoLibrary authorizationStatus];
@@ -121,7 +121,7 @@
 }
 
 
-+ (RNPermissionsStatus)contactsPermissionStatus
++ (RNPermissionsStatus)contacts
 {
 #if __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0
     int status = [CNContactStore authorizationStatusForEntityType:CNEntityTypeContacts];
@@ -151,7 +151,7 @@
 }
 
 
-+ (RNPermissionsStatus)eventPermissionStatus
++ (RNPermissionsStatus)event
 {
     int status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];
     switch (status) {
@@ -166,7 +166,7 @@
     }
 }
 
-+ (RNPermissionsStatus)reminderPermissionStatus
++ (RNPermissionsStatus)reminder
 {
     int status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeReminder];
     switch (status) {
@@ -182,7 +182,7 @@
 }
 
 
-+ (RNPermissionsStatus)bluetoothPermissionStatus
++ (RNPermissionsStatus)bluetooth
 {
     int status = [CBPeripheralManager authorizationStatus];
     switch (status) {
@@ -198,34 +198,35 @@
 }
 
 //problem here is that we can only return Authorized or Undetermined
-+ (RNPermissionsStatus)notificationPermissionStatus
++ (RNPermissionsStatus)notification
 {
-    if ([[UIApplication sharedApplication] respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
-        // iOS8+
-        BOOL isRegistered = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
-        BOOL isEnabled = [[[UIApplication sharedApplication] currentUserNotificationSettings] types] != UIUserNotificationTypeNone;
-        if (isRegistered || isEnabled) {
-            return isEnabled ? RNPermissionsStatusAuthorized : RNPermissionsStatusDenied;
-        }
-        else {
-            return RNPermissionsStatusUndetermined;
+    BOOL didAskForPermission = [[NSUserDefaults standardUserDefaults] boolForKey:@"DidAskForNotifications"];
+
+    if (didAskForPermission) {
+        if ([[UIApplication sharedApplication] respondsToSelector:@selector(isRegisteredForRemoteNotifications)]) {
+            // iOS8+
+            BOOL isRegistered = [[UIApplication sharedApplication] isRegisteredForRemoteNotifications];
+            BOOL isEnabled = [[[UIApplication sharedApplication] currentUserNotificationSettings] types] != UIUserNotificationTypeNone;
+            if (isRegistered || isEnabled) {
+                return isEnabled ? RNPermissionsStatusAuthorized : RNPermissionsStatusDenied;
+            }
+            else {
+                return RNPermissionsStatusDenied;
+            }
+        } else {
+            if ([[UIApplication sharedApplication] enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone) {
+                return RNPermissionsStatusDenied;
+            }
+            else {
+                return RNPermissionsStatusAuthorized;
+            }
         }
     } else {
-#if __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_8_0
-        if ([[UIApplication sharedApplication] enabledRemoteNotificationTypes] == UIRemoteNotificationTypeNone) {
-            return RNPermissionsStatusUndetermined;
-        }
-        else {
-            return RNPermissionsStatusAuthorized;
-        }
-#else
         return RNPermissionsStatusUndetermined;
-#endif
-        
     }
 }
 
-+ (RNPermissionsStatus)backgroundRefreshPermissionStatus
++ (RNPermissionsStatus)backgroundRefresh
 {
     int status = [[UIApplication sharedApplication] backgroundRefreshStatus];
     switch (status) {

+ 11 - 0
ReactNativePermissions.ios.js

@@ -40,6 +40,17 @@ class ReactNativePermissions {
 		}
 	}
 
+	requestPermission(permission, type) {
+		switch (permission) {
+			case 'location':
+				return RNPermissions.requestLocation(type)
+			case 'notification':
+				return RNPermissions.requestNotification(type)
+			case 'bluetooth':
+				return RNPermissions.requestBluetooth();
+		}
+	}
+
 	//recursive funciton to chain a promises for a list of permissions
 	checkMultiplePermissions(permissions) {
 		let i = permissions.length

+ 50 - 8
ReactNativePermissions.m

@@ -17,6 +17,7 @@
 #import "RCTConvert+RNPermissionsStatus.h"
 
 #import "PermissionsChecker.h"
+#import "PermissionsAsker.h"
 
 @interface ReactNativePermissions()
 @end
@@ -39,25 +40,66 @@ RCT_EXPORT_MODULE();
 
 - (NSDictionary *)constantsToExport
 {
-    return @{ @"StatusUndetermined" : @(RNPermissionsStatusUndetermined),
-              @"StatusDenied" : @(RNPermissionsStatusDenied),
-              @"StatusAuthorized" : @(RNPermissionsStatusAuthorized),
-              @"StatusRestricted" : @(RNPermissionsStatusRestricted)};
+    return @{ @"PermissionTypes" : @[
+                      @"location",
+                      @"camera",
+                      @"microphone",
+                      @"photo",
+                      @"contacts",
+                      @"event",
+                      @"reminder",
+                      @"bluetooth",
+                      @"notification",
+                      @"backgroundRefresh",
+                      ]};
 };
 
 
-RCT_REMAP_METHOD(canOpenSettings, canOpenSettings:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
+RCT_REMAP_METHOD(canOpenSettings, canOpenSettings:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
     resolve(@([PermissionsChecker canOpenSettings]));
 }
-RCT_EXPORT_METHOD(openSettings) {
+
+RCT_EXPORT_METHOD(openSettings)
+{
     [PermissionsChecker openSettings];
 }
-RCT_REMAP_METHOD(getPermissionStatus, getPermissionStatus:(NSString *)permission resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) {
-    SEL s = NSSelectorFromString([NSString stringWithFormat:@"%@PermissionStatus", permission]);
+
+RCT_REMAP_METHOD(getPermissionStatus, getPermissionStatus:(NSString *)permission resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+    SEL s = NSSelectorFromString(permission);
     RNPermissionsStatus status = (RNPermissionsStatus)[PermissionsChecker performSelector:s];
     resolve([self stringForStatus:status]);
 }
 
+RCT_EXPORT_METHOD(requestLocation:(NSString *)type)
+{
+    [[PermissionsAsker sharedInstance] location:type];
+}
+
+RCT_REMAP_METHOD(requestNotification, requestNotification:(NSArray *)typeStrings resolve:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject)
+{
+    UIUserNotificationType types;
+    if ([typeStrings containsObject:@"alert"])
+        types = types | UIUserNotificationTypeAlert;
+    
+    if ([typeStrings containsObject:@"badge"])
+        types = types | UIUserNotificationTypeBadge;
+    
+    if ([typeStrings containsObject:@"sound"])
+        types = types | UIUserNotificationTypeSound;
+
+    [[PermissionsAsker sharedInstance] notification:types completionHandler:^(RNPermissionsStatus status) {
+        resolve([self stringForStatus:status]);
+    }];
+}
+
+
+
+RCT_EXPORT_METHOD(requestBluetooth) {
+    [[PermissionsAsker sharedInstance] bluetooth];
+}
+
 - (NSString *)stringForStatus:(RNPermissionsStatus) status{
     switch (status) {
         case RNPermissionsStatusAuthorized:

+ 6 - 0
ReactNativePermissions.xcodeproj/project.pbxproj

@@ -7,6 +7,7 @@
 	objects = {
 
 /* Begin PBXBuildFile section */
+		9D6F44381D2E604500BF17F4 /* PermissionsAsker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D6F44371D2E604500BF17F4 /* PermissionsAsker.m */; };
 		9D8FB2701D2D68C500AAFC55 /* PermissionsChecker.m in Sources */ = {isa = PBXBuildFile; fileRef = 9D8FB26F1D2D68C500AAFC55 /* PermissionsChecker.m */; };
 		9DE8D2821CA3188D009CE8CC /* ReactNativePermissions.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DE8D2811CA3188D009CE8CC /* ReactNativePermissions.m */; };
 		9DE8D28B1CA31E95009CE8CC /* RCTConvert+RNPermissionsStatus.m in Sources */ = {isa = PBXBuildFile; fileRef = 9DE8D28A1CA31E95009CE8CC /* RCTConvert+RNPermissionsStatus.m */; };
@@ -26,6 +27,8 @@
 
 /* Begin PBXFileReference section */
 		9D23B34F1C767B80008B4819 /* libReactNativePermissions.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativePermissions.a; sourceTree = BUILT_PRODUCTS_DIR; };
+		9D6F44361D2E604500BF17F4 /* PermissionsAsker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PermissionsAsker.h; sourceTree = SOURCE_ROOT; };
+		9D6F44371D2E604500BF17F4 /* PermissionsAsker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PermissionsAsker.m; sourceTree = SOURCE_ROOT; };
 		9D8FB26E1D2D68C500AAFC55 /* PermissionsChecker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PermissionsChecker.h; sourceTree = SOURCE_ROOT; };
 		9D8FB26F1D2D68C500AAFC55 /* PermissionsChecker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PermissionsChecker.m; sourceTree = SOURCE_ROOT; };
 		9DE8D2801CA31888009CE8CC /* ReactNativePermissions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativePermissions.h; sourceTree = SOURCE_ROOT; };
@@ -68,6 +71,8 @@
 				9DE8D28A1CA31E95009CE8CC /* RCTConvert+RNPermissionsStatus.m */,
 				9D8FB26E1D2D68C500AAFC55 /* PermissionsChecker.h */,
 				9D8FB26F1D2D68C500AAFC55 /* PermissionsChecker.m */,
+				9D6F44361D2E604500BF17F4 /* PermissionsAsker.h */,
+				9D6F44371D2E604500BF17F4 /* PermissionsAsker.m */,
 				9DE8D2801CA31888009CE8CC /* ReactNativePermissions.h */,
 				9DE8D2811CA3188D009CE8CC /* ReactNativePermissions.m */,
 			);
@@ -133,6 +138,7 @@
 				9DE8D28B1CA31E95009CE8CC /* RCTConvert+RNPermissionsStatus.m in Sources */,
 				9D8FB2701D2D68C500AAFC55 /* PermissionsChecker.m in Sources */,
 				9DE8D2821CA3188D009CE8CC /* ReactNativePermissions.m in Sources */,
+				9D6F44381D2E604500BF17F4 /* PermissionsAsker.m in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};