react-native-permissions icon indicating copy to clipboard operation
react-native-permissions copied to clipboard

Add support for iOS Local Network permission

Open geraintwhite opened this issue 2 years ago • 20 comments

Summary

Fix #509

Test Plan

Tested in my app by calling the following and verifying that the permission prompt is displayed:

Permissions.check(PERMISSIONS.IOS.LOCAL_NETWORK_PRIVACY)
Permissions.request(PERMISSIONS.IOS.LOCAL_NETWORK_PRIVACY)

Compatibility

OS Implemented
iOS
Android

Checklist

  • [x] I have tested this on a device and a simulator (local network privacy not available on simulator)
  • [x] I added the documentation in README.md
  • [ ] I mentioned this change in CHANGELOG.md
  • [x] I updated the typed files (TS and Flow)
  • [x] I added a sample use of the API in the example project (example/App.js)

geraintwhite avatar May 19 '22 11:05 geraintwhite

Thanks a lot for this one! However, is it possible for you to migrate the module to ObjC? There's already too much languages on this repository (ObjC, Java, TypeScript, C#…).

zoontek avatar May 20 '22 08:05 zoontek

Thanks a lot for this one! However, is it possible for you to migrate the module to ObjC? There's already too much languages on this repository (ObjC, Java, TypeScript, C#…).

Converted to objective c and tested it still works d2d598fc5aa0bcfaf0aa2c186db65207f9061a01

geraintwhite avatar May 20 '22 12:05 geraintwhite

It's occurred to me that checking the permission will only return an accurate result after requesting it, as the only way to check it is by requesting it first and storing the result (https://stackoverflow.com/questions/63940427/ios-14-how-to-trigger-local-network-dialog-and-check-user-answer/64242745#64242745).

I can think of three possible solutions:

  • leave it as is so the check result will be inaccurate until it is requested
  • disable Permissions.check for this permission
  • persist the result somewhere other than a class property.

geraintwhite avatar May 26 '22 09:05 geraintwhite

@grit96 The library has a builtin escape hatch for these cases: https://github.com/zoontek/react-native-permissions/blob/37d732e8333f1a653300292e82d08decaf9e3995/ios/RNPermissions.m#L363

Get isFlaggedAsRequested value on check. If it's false, return "NotDetermined". If it's true, you can perform a request to get the status (don't forget to call flagAsRequested on request).

You can have an usage example in the FaceID handler: https://github.com/zoontek/react-native-permissions/blob/2d645ff4f3dfc6db9686bc2fd2877bd049b8043e/ios/FaceID/RNPermissionHandlerFaceID.m

zoontek avatar May 26 '22 10:05 zoontek

@zoontek something like this?

#import "RNPermissionHandlerLocalNetworkPrivacy.h"
#import "LocalNetworkPrivacy.h"

@implementation RNPermissionHandlerLocalNetworkPrivacy

+ (NSArray<NSString *> *_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 {
  if (![RNPermissions isFlaggedAsRequested:[[self class] handlerUniqueId]]) {
    return resolve(RNPermissionStatusNotDetermined);
  }

  LocalNetworkPrivacy *local = [LocalNetworkPrivacy new];
  [local checkAccessState:^(BOOL granted) {
    resolve(granted ? RNPermissionStatusAuthorized : RNPermissionStatusDenied);
  }];
}

- (void)requestWithResolver:(void (^_Nonnull)(RNPermissionStatus))resolve
                   rejecter:(void (^_Nonnull)(NSError *_Nonnull))reject {
  [RNPermissions flagAsRequested:[[self class] handlerUniqueId]];
  [self checkWithResolver:resolve rejecter:reject];
}

@end

geraintwhite avatar May 26 '22 10:05 geraintwhite

@grit96 Exactly. With your current request code:

- (void)requestWithResolver:(void (^ _Nonnull)(RNPermissionStatus))resolve
                   rejecter:(void (^ _Nonnull)(NSError * _Nonnull))reject {
  LocalNetworkPrivacy *local = [LocalNetworkPrivacy new];
  [local checkAccessState:^(BOOL granted) {
      [RNPermissions flagAsRequested:[[self class] handlerUniqueId]];
      [self checkWithResolver:resolve rejecter:reject];
  }];
}

zoontek avatar May 26 '22 10:05 zoontek

I've moved the network request from requestWithResolver into checkWithResolver so it doesn't get called twice.

geraintwhite avatar May 26 '22 10:05 geraintwhite

I recommend the opposite : perform a request in check (for consistency)

zoontek avatar May 26 '22 10:05 zoontek

Hi i used Permissions.check(PERMISSIONS.IOS.LOCAL_NETWORK_PRIVACY) this error generated -> Cannot find name 'Permissions'. Did you mean 'PERMISSIONS'? i need Network privacy permission check and displaying message for accessing application to Local Network please help me tnx a lot @zoontek @grit96

nilrezaee88 avatar May 27 '22 08:05 nilrezaee88

Hello! Thanks for this PR, I've tested this and find out that straight after permission request it immediately returns BLOCKED as a response while user request alert is still on screen and user did not allowed or denied it, so it just do not wait untill user will process with any action

bintoll avatar Jun 02 '22 12:06 bintoll

@bintoll hmm you are correct - it's happening because there is no way to detect when the user presses decline, so we have a timer which automatically returns denied after 2s. There does seem to be an alternative using NWBrowser but I can't find any objc equivalent API (https://stackoverflow.com/a/67758105/2468126).

geraintwhite avatar Jun 15 '22 12:06 geraintwhite

@grit96 Got it, that generally is fine, it will not lead to the best UX for user (in case if we would like to alert user after declining permission and allow him to navigate to device settings), but requesting permission itself works nice. I would recommend to mention this behavior somewhere in readme so the flow would be clear and developers would not create issues regarding this functionality. Thank you again for implementing this!

bintoll avatar Jun 15 '22 12:06 bintoll

after a decline you can re-check (but not re-request!) in order to differentiate perhaps? I have not looked that closely though, if that idea doesn't fit at all, apologies

mikehardy avatar Jun 15 '22 12:06 mikehardy

@mikehardy It seems that it could work, it will be needed to setup an interval to check status consistently until the status will be changed (when user finally will press allow or decline). Will check it al little bit later. But anyway, as long as this flow breaks the common behavior of requesting permissions in this lib, it's better to mention this.

bintoll avatar Jun 15 '22 12:06 bintoll

Why this PR is not merged yet?

nilaydigiwhiz avatar Jul 15 '22 04:07 nilaydigiwhiz

@nilaydigiwhiz https://jacobtomlinson.dev/posts/2022/dont-be-that-open-source-user-dont-be-me/

I do almost free, volunteer work on this library (and others) and have a full time job, that's why.

Also, every time someone say things like "Why is this not done yet?", "My company need this!" (for free, obviously) or else, my motivation doesn't go up, isn't it weird? 😄

Anyway, I'm currently on holidays ☀️ and will probably take some time from it to review it / test it on several devices and simulators / release it (and later, maintain it and reply to issues - just in case you though that being an open source maintainer is just pressing "merge" buttons)

zoontek avatar Jul 15 '22 08:07 zoontek

@zoontek Thanks for your effort and for this great library! Did you have time to review/test this PR? Maybe I can help in someway with this?

vitalyiegorov avatar Sep 08 '22 10:09 vitalyiegorov

@vitalyiegorov Not yet.

FC04FED5-4F72-4651-AB62-6D5786A53B14

Sure, you can try and confirm if it works well.

zoontek avatar Sep 08 '22 10:09 zoontek

I took a check and finally try the @grit96 solution. IMHO this is not enough (and I'm afraid it can't be better) The permission must be requested using the library or it will fails on check (ex: here react native in dev mode will prompt for permission at app start)

Also, this indeed use deprecated APIs so it's not future proof. I'd rather not merge this as it will create confusions and issues.

https://user-images.githubusercontent.com/1902323/189542881-c009ee70-e0c6-49c3-aa16-241dab03e455.MP4

zoontek avatar Sep 11 '22 18:09 zoontek

Any updates here?

Audrey-Ann avatar Oct 30 '23 20:10 Audrey-Ann