From 002d5e24de2353d8d88ae55158d3b9309c6ebf25 Mon Sep 17 00:00:00 2001 From: Geraint White Date: Thu, 19 May 2022 12:30:11 +0100 Subject: [PATCH 1/4] Add support for iOS Local Network permission --- README.md | 2 + example/ios/RNPermissionsExample/Info.plist | 6 ++ example/package.json | 1 + .../LocalNetworkPrivacy.swift | 70 +++++++++++++++++++ .../Permission-LocalNetworkPrivacy.podspec | 20 ++++++ .../RNPermissionHandlerLocalNetworkPrivacy.h | 5 ++ .../RNPermissionHandlerLocalNetworkPrivacy.m | 34 +++++++++ ios/RNPermissionsHelper.h | 3 + ios/RNPermissionsModule.mm | 14 ++++ src/permissions.ios.ts | 1 + 10 files changed, 156 insertions(+) create mode 100644 ios/LocalNetworkPrivacy/LocalNetworkPrivacy.swift create mode 100644 ios/LocalNetworkPrivacy/Permission-LocalNetworkPrivacy.podspec create mode 100644 ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.h create mode 100644 ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m diff --git a/README.md b/README.md index bfa66706..a2d28745 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ _📌  Note that these commands must be re-executed each time you update this "Camera", "Contacts", "FaceID", + "LocalNetworkPrivacy", "LocationAccuracy", "LocationAlways", "LocationWhenInUse", @@ -488,6 +489,7 @@ PERMISSIONS.IOS.CALENDARS; PERMISSIONS.IOS.CAMERA; PERMISSIONS.IOS.CONTACTS; PERMISSIONS.IOS.FACE_ID; +PERMISSIONS.IOS.LOCAL_NETWORK_PRIVACY; PERMISSIONS.IOS.LOCATION_ALWAYS; PERMISSIONS.IOS.LOCATION_WHEN_IN_USE; PERMISSIONS.IOS.MEDIA_LIBRARY; diff --git a/example/ios/RNPermissionsExample/Info.plist b/example/ios/RNPermissionsExample/Info.plist index ce57f966..bc76b70d 100644 --- a/example/ios/RNPermissionsExample/Info.plist +++ b/example/ios/RNPermissionsExample/Info.plist @@ -35,6 +35,10 @@ + NSBonjourServices + + _lnp._tcp. + NSAppleMusicUsageDescription Let me use your media library NSBluetoothAlwaysUsageDescription @@ -49,6 +53,8 @@ Let me use your contacts NSFaceIDUsageDescription Let me use FaceID + NSLocalNetworkUsageDescription + Let me use your local network NSLocationAlwaysAndWhenInUseUsageDescription Let me use your location, even in background NSLocationAlwaysUsageDescription diff --git a/example/package.json b/example/package.json index 45d05143..d3799d1f 100644 --- a/example/package.json +++ b/example/package.json @@ -17,6 +17,7 @@ "Camera", "Contacts", "FaceID", + "LocalNetworkPrivacy", "LocationAccuracy", "LocationAlways", "LocationWhenInUse", diff --git a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.swift b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.swift new file mode 100644 index 00000000..70720681 --- /dev/null +++ b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.swift @@ -0,0 +1,70 @@ +// +// LocalNetworkPrivacy.swift +// CloudVoiceExpress +// +// Created by Geraint White on 29/04/2022. +// + +import Foundation +import UIKit + +@objc public enum OptionalBool: Int { + case none + case yes + case no +} + +@objc open class LocalNetworkPrivacy : NSObject { + let service: NetService + + var completion: ((Bool) -> Void)? + var timer: Timer? + var publishing = false + + static var granted: OptionalBool = OptionalBool.none + + @objc public override init() { + service = .init(domain: "local.", type:"_lnp._tcp.", name: "LocalNetworkPrivacy", port: 1100) + super.init() + } + + @objc public static + func authorizationStatus() -> OptionalBool { + return LocalNetworkPrivacy.granted + } + + @objc public + func checkAccessState(completion: @escaping (Bool) -> Void) { + self.completion = completion + + timer = .scheduledTimer(withTimeInterval: 2, repeats: true, block: { timer in + guard UIApplication.shared.applicationState == .active else { + return + } + + if self.publishing { + LocalNetworkPrivacy.granted = OptionalBool.no + self.timer?.invalidate() + self.completion?(false) + } + else { + self.publishing = true + self.service.delegate = self + self.service.publish() + + } + }) + } + + deinit { + service.stop() + } +} + +extension LocalNetworkPrivacy : NetServiceDelegate { + public func netServiceDidPublish(_ sender: NetService) { + LocalNetworkPrivacy.granted = OptionalBool.yes + timer?.invalidate() + completion?(true) + } +} diff --git a/ios/LocalNetworkPrivacy/Permission-LocalNetworkPrivacy.podspec b/ios/LocalNetworkPrivacy/Permission-LocalNetworkPrivacy.podspec new file mode 100644 index 00000000..70c03590 --- /dev/null +++ b/ios/LocalNetworkPrivacy/Permission-LocalNetworkPrivacy.podspec @@ -0,0 +1,20 @@ +require 'json' +package = JSON.parse(File.read('../../package.json')) + +Pod::Spec.new do |s| + s.name = "Permission-LocalNetworkPrivacy" + s.dependency "RNPermissions" + + s.version = package["version"] + s.license = package["license"] + s.summary = package["description"] + s.authors = package["author"] + s.homepage = package["homepage"] + + s.ios.deployment_target = "10.0" + s.tvos.deployment_target = "11.0" + s.requires_arc = true + + s.source = { :git => package["repository"]["url"], :tag => s.version } + s.source_files = "*.{h,m,swift}" +end diff --git a/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.h b/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.h new file mode 100644 index 00000000..c25281db --- /dev/null +++ b/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.h @@ -0,0 +1,5 @@ +#import "RNPermissions.h" + +@interface RNPermissionHandlerLocalNetworkPrivacy : NSObject + +@end diff --git a/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m b/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m new file mode 100644 index 00000000..2b2f4671 --- /dev/null +++ b/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m @@ -0,0 +1,34 @@ +#import "RNPermissionHandlerLocalNetworkPrivacy.h" +#import "Permission_LocalNetworkPrivacy-Swift.h" + +@implementation RNPermissionHandlerLocalNetworkPrivacy + ++ (NSArray * _Nonnull)usageDescriptionKeys { + return @[@"NSLocalNetworkUsageDescription"]; +} + ++ (NSString * _Nonnull)handlerUniqueId { + return @"ios.permission.LOCAL_NETWORK_PRIVACY"; +} + +- (void)checkWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve + rejecter:(void (__unused ^ _Nonnull)(NSError * _Nonnull))reject { + switch ([LocalNetworkPrivacy authorizationStatus]) { + case OptionalBoolNone: + return resolve(RNPermissionStatusNotDetermined); + case OptionalBoolNo: + return resolve(RNPermissionStatusDenied); + case OptionalBoolYes: + return resolve(RNPermissionStatusAuthorized); + } +} + +- (void)requestWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve + rejecter:(void (^ _Nonnull)(NSError * _Nonnull))reject { + LocalNetworkPrivacy *local = [LocalNetworkPrivacy new]; + [local checkAccessStateWithCompletion:^(BOOL granted) { + [self checkWithResolver:resolve rejecter:reject]; + }]; +} + +@end diff --git a/ios/RNPermissionsHelper.h b/ios/RNPermissionsHelper.h index f45c3dcf..19340823 100644 --- a/ios/RNPermissionsHelper.h +++ b/ios/RNPermissionsHelper.h @@ -53,6 +53,9 @@ typedef NS_ENUM(NSInteger, RNPermission) { #if __has_include("RNPermissionHandlerPhotoLibraryAddOnly.h") RNPermissionPhotoLibraryAddOnly = 17, #endif +#if __has_include("RNPermissionHandlerLocalNetworkPrivacy.h") + RNPermissionLocalNetworkPrivacy = 18, +#endif }; typedef enum { diff --git a/ios/RNPermissionsModule.mm b/ios/RNPermissionsModule.mm index c5faea9b..53d75062 100644 --- a/ios/RNPermissionsModule.mm +++ b/ios/RNPermissionsModule.mm @@ -58,6 +58,9 @@ #if __has_include("RNPermissionHandlerLocationAccuracy.h") #import "RNPermissionHandlerLocationAccuracy.h" #endif +#if __has_include("RNPermissionHandlerLocalNetworkPrivacy.h") +#import "RNPermissionHandlerLocalNetworkPrivacy.h" +#endif @implementation RCTConvert(RNPermission) @@ -113,6 +116,9 @@ @implementation RCTConvert(RNPermission) #if __has_include("RNPermissionHandlerPhotoLibraryAddOnly.h") [RNPermissionHandlerPhotoLibraryAddOnly handlerUniqueId]: @(RNPermissionPhotoLibraryAddOnly), #endif +#if __has_include("RNPermissionHandlerLocalNetworkPrivacy.h") + [RNPermissionHandlerLocalNetworkPrivacy handlerUniqueId]: @(RNPermissionLocalNetworkPrivacy), +#endif }), RNPermissionUnknown, integerValue); @end @@ -195,6 +201,9 @@ - (NSDictionary *)constantsToExport { #if __has_include("RNPermissionHandlerLocationAccuracy.h") [available addObject:[RNPermissionHandlerLocationAccuracy handlerUniqueId]]; #endif +#if __has_include("RNPermissionHandlerLocalNetworkPrivacy.h") + [available addObject:[RNPermissionHandlerLocalNetworkPrivacy handlerUniqueId]]; +#endif #if RCT_DEV if ([available count] == 0) { @@ -310,6 +319,11 @@ - (void)checkUsageDescriptionKeys:(NSArray * _Nonnull)keys { case RNPermissionPhotoLibraryAddOnly: handler = [RNPermissionHandlerPhotoLibraryAddOnly new]; break; +#endif +#if __has_include("RNPermissionHandlerLocalNetworkPrivacy.h") + case RNPermissionLocalNetworkPrivacy: + handler = [RNPermissionHandlerLocalNetworkPrivacy new]; + break; #endif case RNPermissionUnknown: break; // RCTConvert prevents this case diff --git a/src/permissions.ios.ts b/src/permissions.ios.ts index 87e6eb22..264bef72 100644 --- a/src/permissions.ios.ts +++ b/src/permissions.ios.ts @@ -8,6 +8,7 @@ const IOS = Object.freeze({ CAMERA: 'ios.permission.CAMERA', CONTACTS: 'ios.permission.CONTACTS', FACE_ID: 'ios.permission.FACE_ID', + LOCAL_NETWORK_PRIVACY: 'ios.permission.LOCAL_NETWORK_PRIVACY', LOCATION_ALWAYS: 'ios.permission.LOCATION_ALWAYS', LOCATION_WHEN_IN_USE: 'ios.permission.LOCATION_WHEN_IN_USE', MEDIA_LIBRARY: 'ios.permission.MEDIA_LIBRARY', From 399de97a72f645b42bc6f1dfc9e848f3f83a6383 Mon Sep 17 00:00:00 2001 From: Geraint White Date: Fri, 20 May 2022 12:35:51 +0100 Subject: [PATCH 2/4] rewrite LocalNetworkPrivacy in objective c --- ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h | 12 ++++ ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m | 63 +++++++++++++++++ .../LocalNetworkPrivacy.swift | 70 ------------------- .../Permission-LocalNetworkPrivacy.podspec | 2 +- .../RNPermissionHandlerLocalNetworkPrivacy.m | 4 +- 5 files changed, 78 insertions(+), 73 deletions(-) create mode 100644 ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h create mode 100644 ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m delete mode 100644 ios/LocalNetworkPrivacy/LocalNetworkPrivacy.swift diff --git a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h new file mode 100644 index 00000000..5d0922d8 --- /dev/null +++ b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h @@ -0,0 +1,12 @@ +typedef enum { + OptionalBoolNone, + OptionalBoolYes, + OptionalBoolNo, +} OptionalBool; + +@interface LocalNetworkPrivacy : NSObject + ++ (OptionalBool)authorizationStatus; +- (void)checkAccessState:(void (^)(BOOL))completion; + +@end diff --git a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m new file mode 100644 index 00000000..e60ce0f8 --- /dev/null +++ b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m @@ -0,0 +1,63 @@ +#import +#import "LocalNetworkPrivacy.h" + +@interface LocalNetworkPrivacy () + +@property (nonatomic) NSNetService *service; +@property (nonatomic) void (^completion)(BOOL); +@property (nonatomic) NSTimer *timer; +@property (nonatomic) BOOL publishing; +@property (class, nonatomic) OptionalBool granted; + +@end + +@implementation LocalNetworkPrivacy + +static OptionalBool granted = OptionalBoolNone; + +- (instancetype)init { + if (self = [super init]) { + self.service = [[NSNetService alloc] initWithDomain:@"local." type:@"_lnp._tcp." name:@"LocalNetworkPrivacy" port:1100]; + } + return self; +} + +- (void)dealloc { + [self.service stop]; +} + ++ (OptionalBool)authorizationStatus { + return granted; +} + +- (void)checkAccessState:(void (^)(BOOL))completion { + self.completion = completion; + + self.timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) { + if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive) { + return; + } + + if (self.publishing) { + granted = OptionalBoolNo; + [self.timer invalidate]; + self.completion(NO); + } + else { + self.publishing = YES; + self.service.delegate = self; + [self.service publish]; + } + }]; +} + + +#pragma mark - NSNetServiceDelegate + +- (void)netServiceDidPublish:(NSNetService *)sender { + granted = OptionalBoolYes; + [self.timer invalidate]; + self.completion(YES); +} + +@end diff --git a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.swift b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.swift deleted file mode 100644 index 70720681..00000000 --- a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.swift +++ /dev/null @@ -1,70 +0,0 @@ -// -// LocalNetworkPrivacy.swift -// CloudVoiceExpress -// -// Created by Geraint White on 29/04/2022. -// - -import Foundation -import UIKit - -@objc public enum OptionalBool: Int { - case none - case yes - case no -} - -@objc open class LocalNetworkPrivacy : NSObject { - let service: NetService - - var completion: ((Bool) -> Void)? - var timer: Timer? - var publishing = false - - static var granted: OptionalBool = OptionalBool.none - - @objc public override init() { - service = .init(domain: "local.", type:"_lnp._tcp.", name: "LocalNetworkPrivacy", port: 1100) - super.init() - } - - @objc public static - func authorizationStatus() -> OptionalBool { - return LocalNetworkPrivacy.granted - } - - @objc public - func checkAccessState(completion: @escaping (Bool) -> Void) { - self.completion = completion - - timer = .scheduledTimer(withTimeInterval: 2, repeats: true, block: { timer in - guard UIApplication.shared.applicationState == .active else { - return - } - - if self.publishing { - LocalNetworkPrivacy.granted = OptionalBool.no - self.timer?.invalidate() - self.completion?(false) - } - else { - self.publishing = true - self.service.delegate = self - self.service.publish() - - } - }) - } - - deinit { - service.stop() - } -} - -extension LocalNetworkPrivacy : NetServiceDelegate { - public func netServiceDidPublish(_ sender: NetService) { - LocalNetworkPrivacy.granted = OptionalBool.yes - timer?.invalidate() - completion?(true) - } -} diff --git a/ios/LocalNetworkPrivacy/Permission-LocalNetworkPrivacy.podspec b/ios/LocalNetworkPrivacy/Permission-LocalNetworkPrivacy.podspec index 70c03590..52cefb09 100644 --- a/ios/LocalNetworkPrivacy/Permission-LocalNetworkPrivacy.podspec +++ b/ios/LocalNetworkPrivacy/Permission-LocalNetworkPrivacy.podspec @@ -16,5 +16,5 @@ Pod::Spec.new do |s| s.requires_arc = true s.source = { :git => package["repository"]["url"], :tag => s.version } - s.source_files = "*.{h,m,swift}" + s.source_files = "*.{h,m}" end diff --git a/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m b/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m index 2b2f4671..ffc73465 100644 --- a/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m +++ b/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m @@ -1,5 +1,5 @@ #import "RNPermissionHandlerLocalNetworkPrivacy.h" -#import "Permission_LocalNetworkPrivacy-Swift.h" +#import "LocalNetworkPrivacy.h" @implementation RNPermissionHandlerLocalNetworkPrivacy @@ -26,7 +26,7 @@ - (void)checkWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve - (void)requestWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve rejecter:(void (^ _Nonnull)(NSError * _Nonnull))reject { LocalNetworkPrivacy *local = [LocalNetworkPrivacy new]; - [local checkAccessStateWithCompletion:^(BOOL granted) { + [local checkAccessState:^(BOOL granted) { [self checkWithResolver:resolve rejecter:reject]; }]; } From 5bb9e167a99b1ec40c7f84fa05ea71900e436e5e Mon Sep 17 00:00:00 2001 From: Geraint White Date: Fri, 20 May 2022 12:59:40 +0100 Subject: [PATCH 3/4] Add NSBonjourServices to README --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index a2d28745..9cac3c6e 100644 --- a/README.md +++ b/README.md @@ -98,6 +98,8 @@ Then update your `Info.plist` with wanted permissions usage descriptions: YOUR TEXT NSFaceIDUsageDescription YOUR TEXT + NSLocalNetworkUsageDescription + YOUR TEXT NSLocationAlwaysAndWhenInUseUsageDescription YOUR TEXT NSLocationAlwaysUsageDescription @@ -126,6 +128,13 @@ Then update your `Info.plist` with wanted permissions usage descriptions: NSUserTrackingUsageDescription YOUR TEXT + + + NSBonjourServices + + _lnp._tcp. + + From a29dd2a9cd3500631f3e81b57869f0f6502b7ab8 Mon Sep 17 00:00:00 2001 From: Geraint White Date: Thu, 26 May 2022 13:43:01 +0100 Subject: [PATCH 4/4] use isFlaggedAsRequested when checking local network permission --- ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h | 7 ----- ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m | 30 +++++-------------- .../RNPermissionHandlerLocalNetworkPrivacy.m | 15 +++++----- 3 files changed, 14 insertions(+), 38 deletions(-) diff --git a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h index 5d0922d8..3c0a8b24 100644 --- a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h +++ b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.h @@ -1,12 +1,5 @@ -typedef enum { - OptionalBoolNone, - OptionalBoolYes, - OptionalBoolNo, -} OptionalBool; - @interface LocalNetworkPrivacy : NSObject -+ (OptionalBool)authorizationStatus; - (void)checkAccessState:(void (^)(BOOL))completion; @end diff --git a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m index e60ce0f8..9ea9fa95 100644 --- a/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m +++ b/ios/LocalNetworkPrivacy/LocalNetworkPrivacy.m @@ -7,14 +7,11 @@ @interface LocalNetworkPrivacy () @property (nonatomic) void (^completion)(BOOL); @property (nonatomic) NSTimer *timer; @property (nonatomic) BOOL publishing; -@property (class, nonatomic) OptionalBool granted; @end @implementation LocalNetworkPrivacy -static OptionalBool granted = OptionalBoolNone; - - (instancetype)init { if (self = [super init]) { self.service = [[NSNetService alloc] initWithDomain:@"local." type:@"_lnp._tcp." name:@"LocalNetworkPrivacy" port:1100]; @@ -26,28 +23,16 @@ - (void)dealloc { [self.service stop]; } -+ (OptionalBool)authorizationStatus { - return granted; -} - - (void)checkAccessState:(void (^)(BOOL))completion { self.completion = completion; - self.timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) { - if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive) { - return; - } - - if (self.publishing) { - granted = OptionalBoolNo; - [self.timer invalidate]; - self.completion(NO); - } - else { - self.publishing = YES; - self.service.delegate = self; - [self.service publish]; - } + self.publishing = YES; + self.service.delegate = self; + [self.service publish]; + + self.timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:NO block:^(NSTimer * _Nonnull timer) { + [self.timer invalidate]; + self.completion(NO); }]; } @@ -55,7 +40,6 @@ - (void)checkAccessState:(void (^)(BOOL))completion { #pragma mark - NSNetServiceDelegate - (void)netServiceDidPublish:(NSNetService *)sender { - granted = OptionalBoolYes; [self.timer invalidate]; self.completion(YES); } diff --git a/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m b/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m index ffc73465..0e69ab09 100644 --- a/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m +++ b/ios/LocalNetworkPrivacy/RNPermissionHandlerLocalNetworkPrivacy.m @@ -13,21 +13,20 @@ + (NSString * _Nonnull)handlerUniqueId { - (void)checkWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve rejecter:(void (__unused ^ _Nonnull)(NSError * _Nonnull))reject { - switch ([LocalNetworkPrivacy authorizationStatus]) { - case OptionalBoolNone: - return resolve(RNPermissionStatusNotDetermined); - case OptionalBoolNo: - return resolve(RNPermissionStatusDenied); - case OptionalBoolYes: - return resolve(RNPermissionStatusAuthorized); + if (![RNPermissionsHelper isFlaggedAsRequested:[[self class] handlerUniqueId]]) { + return resolve(RNPermissionStatusNotDetermined); } + + [self requestWithResolver:resolve rejecter:reject]; } - (void)requestWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve rejecter:(void (^ _Nonnull)(NSError * _Nonnull))reject { + [RNPermissionsHelper flagAsRequested:[[self class] handlerUniqueId]]; + LocalNetworkPrivacy *local = [LocalNetworkPrivacy new]; [local checkAccessState:^(BOOL granted) { - [self checkWithResolver:resolve rejecter:reject]; + resolve(granted ? RNPermissionStatusAuthorized : RNPermissionStatusDenied); }]; }