@wniu/react-native-local-network-permission 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +20 -0
- package/LocalNetworkPermission.podspec +22 -0
- package/README.md +147 -0
- package/ios/LocalNetworkPermission.h +5 -0
- package/ios/LocalNetworkPermission.mm +129 -0
- package/lib/module/LocalNetworkPermission.android.js +10 -0
- package/lib/module/LocalNetworkPermission.android.js.map +1 -0
- package/lib/module/LocalNetworkPermission.ios.js +18 -0
- package/lib/module/LocalNetworkPermission.ios.js.map +1 -0
- package/lib/module/LocalNetworkPermission.js +10 -0
- package/lib/module/LocalNetworkPermission.js.map +1 -0
- package/lib/module/NativeLocalNetworkPermission.js +13 -0
- package/lib/module/NativeLocalNetworkPermission.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/LocalNetworkPermission.android.d.ts +6 -0
- package/lib/typescript/src/LocalNetworkPermission.android.d.ts.map +1 -0
- package/lib/typescript/src/LocalNetworkPermission.d.ts +6 -0
- package/lib/typescript/src/LocalNetworkPermission.d.ts.map +1 -0
- package/lib/typescript/src/LocalNetworkPermission.ios.d.ts +12 -0
- package/lib/typescript/src/LocalNetworkPermission.ios.d.ts.map +1 -0
- package/lib/typescript/src/NativeLocalNetworkPermission.d.ts +20 -0
- package/lib/typescript/src/NativeLocalNetworkPermission.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +2 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/package.json +160 -0
- package/src/LocalNetworkPermission.android.ts +7 -0
- package/src/LocalNetworkPermission.ios.ts +15 -0
- package/src/LocalNetworkPermission.ts +7 -0
- package/src/NativeLocalNetworkPermission.ts +22 -0
- package/src/index.tsx +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zephyr
|
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
6
|
+
in the Software without restriction, including without limitation the rights
|
|
7
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
8
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
9
|
+
furnished to do so, subject to the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be included in all
|
|
12
|
+
copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
15
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
16
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
17
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
18
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
19
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
20
|
+
SOFTWARE.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
package = JSON.parse(File.read(File.join(__dir__, "package.json")))
|
|
4
|
+
|
|
5
|
+
Pod::Spec.new do |s|
|
|
6
|
+
s.name = "LocalNetworkPermission"
|
|
7
|
+
s.version = package["version"]
|
|
8
|
+
s.summary = package["description"]
|
|
9
|
+
s.homepage = package["homepage"]
|
|
10
|
+
s.license = package["license"]
|
|
11
|
+
s.authors = package["author"]
|
|
12
|
+
|
|
13
|
+
s.platforms = { :ios => min_ios_version_supported }
|
|
14
|
+
s.source = { :git => "https://github.com/voyageh/react-native-local-network-permission.git", :tag => "#{s.version}" }
|
|
15
|
+
|
|
16
|
+
s.source_files = "ios/**/*.{h,m,mm,swift,cpp}"
|
|
17
|
+
s.private_header_files = "ios/**/*.h"
|
|
18
|
+
|
|
19
|
+
s.frameworks = "Network"
|
|
20
|
+
|
|
21
|
+
install_modules_dependencies(s)
|
|
22
|
+
end
|
package/README.md
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# react-native-local-network-permission
|
|
2
|
+
|
|
3
|
+
A React Native library for handling **iOS Local Network permission**, built on TurboModule architecture.
|
|
4
|
+
|
|
5
|
+
> **This is a React Native library, not an Expo-only module.** It works in bare React Native projects and can also be used in Expo projects via prebuild (`npx expo prebuild`).
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install react-native-local-network-permission
|
|
11
|
+
# or
|
|
12
|
+
yarn add react-native-local-network-permission
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### iOS Setup
|
|
16
|
+
|
|
17
|
+
```sh
|
|
18
|
+
cd ios && pod install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
#### Required Info.plist Configuration
|
|
22
|
+
|
|
23
|
+
You **must** add the following keys to your `ios/<YourApp>/Info.plist`:
|
|
24
|
+
|
|
25
|
+
```xml
|
|
26
|
+
<key>NSLocalNetworkUsageDescription</key>
|
|
27
|
+
<string>This app needs access to the local network to discover nearby devices.</string>
|
|
28
|
+
|
|
29
|
+
<key>NSBonjourServices</key>
|
|
30
|
+
<array>
|
|
31
|
+
<string>_lnp_check._tcp</string>
|
|
32
|
+
</array>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
- **`NSLocalNetworkUsageDescription`**: The message shown to the user in the permission dialog. Customize this to explain why your app needs local network access.
|
|
36
|
+
- **`NSBonjourServices`**: Must include `_lnp_check._tcp` — this is the Bonjour service type used internally by this library to detect permission status.
|
|
37
|
+
|
|
38
|
+
> If your app also browses for other Bonjour services, add those to the array as well.
|
|
39
|
+
|
|
40
|
+
### Expo Setup
|
|
41
|
+
|
|
42
|
+
This library is **not** an Expo Module — it uses React Native TurboModule architecture. To use it in an Expo managed project:
|
|
43
|
+
|
|
44
|
+
1. Install the library as above.
|
|
45
|
+
2. Run `npx expo prebuild` to generate native projects.
|
|
46
|
+
3. Add the Info.plist keys manually, or create a [config plugin](https://docs.expo.dev/guides/config-plugins/) to automate it.
|
|
47
|
+
|
|
48
|
+
The library is fully compatible with Expo projects that use prebuild (Continuous Native Generation).
|
|
49
|
+
|
|
50
|
+
## Usage
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
import {
|
|
54
|
+
requestPermission,
|
|
55
|
+
isAvailable,
|
|
56
|
+
} from 'react-native-local-network-permission';
|
|
57
|
+
|
|
58
|
+
// Request / check permission (may show system dialog on first call)
|
|
59
|
+
const { status, granted, canAskAgain } = await requestPermission();
|
|
60
|
+
|
|
61
|
+
// Check if local network permission is available on this platform
|
|
62
|
+
const available = await isAvailable(); // true on iOS 14+, false on Android
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## API Reference
|
|
66
|
+
|
|
67
|
+
### `requestPermission()`
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
requestPermission(): Promise<LocalNetworkPermissionResponse>
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Requests local network permission. On iOS, this triggers a detection mechanism that:
|
|
74
|
+
- Shows the system permission dialog if the user has not yet made a choice.
|
|
75
|
+
- Returns the current status without a dialog if already granted or denied.
|
|
76
|
+
|
|
77
|
+
On Android, always returns `{ status: 'granted', granted: true, canAskAgain: false }` since Android does not restrict local network access.
|
|
78
|
+
|
|
79
|
+
#### Why only one method instead of separate "get" and "request"?
|
|
80
|
+
|
|
81
|
+
Apple provides **no API to silently query** local network permission status. Any detection attempt is itself a local network operation that may trigger the system dialog. Providing separate `getPermission()` and `requestPermission()` methods would be misleading — they would do exactly the same thing.
|
|
82
|
+
|
|
83
|
+
### `isAvailable()`
|
|
84
|
+
|
|
85
|
+
```ts
|
|
86
|
+
isAvailable(): Promise<boolean>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Returns `true` on iOS 14+, `false` on Android and older iOS versions.
|
|
90
|
+
|
|
91
|
+
### Types
|
|
92
|
+
|
|
93
|
+
```ts
|
|
94
|
+
type PermissionStatus = 'granted' | 'denied';
|
|
95
|
+
|
|
96
|
+
type LocalNetworkPermissionResponse = {
|
|
97
|
+
status: PermissionStatus;
|
|
98
|
+
granted: boolean; // true when status === 'granted'
|
|
99
|
+
canAskAgain: boolean; // false — iOS only shows the dialog once
|
|
100
|
+
};
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## How It Works
|
|
104
|
+
|
|
105
|
+
### The iOS Local Network Permission Challenge
|
|
106
|
+
|
|
107
|
+
Unlike Camera, Location, or Microphone permissions, **Apple does not provide any public API** to directly query or request local network permission. There is no equivalent of `AVCaptureDevice.authorizationStatus` for local network access. This is true across all iOS versions including iOS 18.
|
|
108
|
+
|
|
109
|
+
### Detection Mechanism
|
|
110
|
+
|
|
111
|
+
This library uses the widely-adopted **NWBrowser/NWListener self-discovery technique**:
|
|
112
|
+
|
|
113
|
+
1. A Bonjour `NWListener` is started on the device, advertising a custom service (`_lnp_check._tcp`).
|
|
114
|
+
2. A `NWBrowser` is started to search for that same service.
|
|
115
|
+
3. **If permission is granted:** The browser discovers the listener -> returns `"granted"`.
|
|
116
|
+
4. **If permission is denied:** The browser receives a DNS policy error -> returns `"denied"`.
|
|
117
|
+
5. **If permission is undetermined:** The system shows the permission dialog, then the result is determined.
|
|
118
|
+
|
|
119
|
+
### Limitations
|
|
120
|
+
|
|
121
|
+
- **No silent query**: `requestPermission()` may trigger the system dialog on first call. This is an iOS platform limitation, not a library design choice.
|
|
122
|
+
- **One-time dialog**: iOS shows the local network permission dialog only once. After the user makes a choice, they must go to **Settings > Privacy & Security > Local Network** to change it.
|
|
123
|
+
- **`canAskAgain` is always `false`**: Since we cannot determine whether the dialog has been shown before, and it can only be shown once, this field is always `false`.
|
|
124
|
+
- **iOS 14+ only**: Local network permission was introduced in iOS 14. On older versions, the library returns `"granted"` (unrestricted access).
|
|
125
|
+
- **Android**: Local network access is not restricted on Android. `requestPermission()` returns granted, and `isAvailable()` returns `false`.
|
|
126
|
+
|
|
127
|
+
## Platform Support
|
|
128
|
+
|
|
129
|
+
| Platform | Supported | Notes |
|
|
130
|
+
|----------|-----------|-------|
|
|
131
|
+
| iOS 14+ | Yes | Full support via NWBrowser/NWListener |
|
|
132
|
+
| iOS < 14 | Partial | Always returns granted (no restriction) |
|
|
133
|
+
| Android | N/A | Returns granted; `isAvailable()` returns false |
|
|
134
|
+
|
|
135
|
+
## Contributing
|
|
136
|
+
|
|
137
|
+
- [Development workflow](CONTRIBUTING.md#development-workflow)
|
|
138
|
+
- [Sending a pull request](CONTRIBUTING.md#sending-a-pull-request)
|
|
139
|
+
- [Code of conduct](CODE_OF_CONDUCT.md)
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
Made with [create-react-native-library](https://github.com/callstack/react-native-builder-bob)
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
#import "LocalNetworkPermission.h"
|
|
2
|
+
#import <Network/Network.h>
|
|
3
|
+
|
|
4
|
+
static NSString *const kServiceType = @"_preflight_check._tcp";
|
|
5
|
+
|
|
6
|
+
@implementation LocalNetworkPermission
|
|
7
|
+
|
|
8
|
+
- (void)requestPermission:(RCTPromiseResolveBlock)resolve
|
|
9
|
+
reject:(RCTPromiseRejectBlock)reject
|
|
10
|
+
{
|
|
11
|
+
if (@available(iOS 14.0, *)) {
|
|
12
|
+
[self checkWithResolve:resolve];
|
|
13
|
+
} else {
|
|
14
|
+
resolve(@(YES));
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
- (void)checkWithResolve:(RCTPromiseResolveBlock)resolve API_AVAILABLE(ios(14.0))
|
|
19
|
+
{
|
|
20
|
+
__block nw_listener_t listener = nil;
|
|
21
|
+
__block nw_browser_t browser = nil;
|
|
22
|
+
__block BOOL didResolve = NO;
|
|
23
|
+
|
|
24
|
+
void (^finish)(BOOL) = ^(BOOL granted) {
|
|
25
|
+
if (didResolve) return;
|
|
26
|
+
didResolve = YES;
|
|
27
|
+
|
|
28
|
+
if (listener) {
|
|
29
|
+
nw_listener_set_state_changed_handler(listener, NULL);
|
|
30
|
+
nw_listener_set_new_connection_handler(listener, NULL);
|
|
31
|
+
nw_listener_cancel(listener);
|
|
32
|
+
listener = nil;
|
|
33
|
+
}
|
|
34
|
+
if (browser) {
|
|
35
|
+
nw_browser_set_state_changed_handler(browser, NULL);
|
|
36
|
+
nw_browser_set_browse_results_changed_handler(browser, NULL);
|
|
37
|
+
nw_browser_cancel(browser);
|
|
38
|
+
browser = nil;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
resolve(@(granted));
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
// --- Listener ---
|
|
45
|
+
nw_parameters_t listenerParams = nw_parameters_create_secure_tcp(
|
|
46
|
+
NW_PARAMETERS_DISABLE_PROTOCOL,
|
|
47
|
+
NW_PARAMETERS_DEFAULT_CONFIGURATION
|
|
48
|
+
);
|
|
49
|
+
|
|
50
|
+
listener = nw_listener_create(listenerParams);
|
|
51
|
+
if (!listener) {
|
|
52
|
+
finish(NO);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
NSString *serviceName = [[NSUUID UUID] UUIDString];
|
|
57
|
+
nw_advertise_descriptor_t ad = nw_advertise_descriptor_create_bonjour_service(
|
|
58
|
+
serviceName.UTF8String, kServiceType.UTF8String, NULL
|
|
59
|
+
);
|
|
60
|
+
nw_listener_set_advertise_descriptor(listener, ad);
|
|
61
|
+
nw_listener_set_new_connection_handler(listener, ^(nw_connection_t connection) {});
|
|
62
|
+
|
|
63
|
+
nw_listener_set_state_changed_handler(listener, ^(nw_listener_state_t state, nw_error_t error) {
|
|
64
|
+
switch (state) {
|
|
65
|
+
case nw_listener_state_ready:
|
|
66
|
+
break;
|
|
67
|
+
case nw_listener_state_failed:
|
|
68
|
+
case nw_listener_state_waiting:
|
|
69
|
+
finish(NO);
|
|
70
|
+
break;
|
|
71
|
+
default:
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
nw_listener_set_queue(listener, dispatch_get_main_queue());
|
|
77
|
+
nw_listener_start(listener);
|
|
78
|
+
|
|
79
|
+
// --- Browser ---
|
|
80
|
+
nw_browse_descriptor_t desc = nw_browse_descriptor_create_bonjour_service(
|
|
81
|
+
kServiceType.UTF8String, NULL
|
|
82
|
+
);
|
|
83
|
+
nw_parameters_t browserParams = nw_parameters_create();
|
|
84
|
+
nw_parameters_set_include_peer_to_peer(browserParams, true);
|
|
85
|
+
|
|
86
|
+
browser = nw_browser_create(desc, browserParams);
|
|
87
|
+
|
|
88
|
+
nw_browser_set_state_changed_handler(browser, ^(nw_browser_state_t state, nw_error_t error) {
|
|
89
|
+
switch (state) {
|
|
90
|
+
case nw_browser_state_ready:
|
|
91
|
+
break;
|
|
92
|
+
case nw_browser_state_waiting:
|
|
93
|
+
case nw_browser_state_failed:
|
|
94
|
+
finish(NO);
|
|
95
|
+
break;
|
|
96
|
+
default:
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
nw_browser_set_browse_results_changed_handler(browser, ^(
|
|
102
|
+
nw_browse_result_t oldResult,
|
|
103
|
+
nw_browse_result_t newResult,
|
|
104
|
+
bool batchComplete
|
|
105
|
+
) {
|
|
106
|
+
nw_browse_result_change_t changes = nw_browse_result_get_changes(oldResult, newResult);
|
|
107
|
+
if (changes & nw_browse_result_change_result_added) {
|
|
108
|
+
finish(YES);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
nw_browser_set_queue(browser, dispatch_get_main_queue());
|
|
113
|
+
nw_browser_start(browser);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#pragma mark - TurboModule
|
|
117
|
+
|
|
118
|
+
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
119
|
+
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
120
|
+
{
|
|
121
|
+
return std::make_shared<facebook::react::NativeLocalNetworkPermissionSpecJSI>(params);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
+ (NSString *)moduleName
|
|
125
|
+
{
|
|
126
|
+
return @"LocalNetworkPermission";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
@end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["requestPermission"],"sourceRoot":"../../src","sources":["LocalNetworkPermission.android.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA,OAAO,eAAeA,iBAAiBA,CAAA,EAAqB;EAC1D,OAAO,IAAI;AACb","ignoreList":[]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import NativeModule from "./NativeLocalNetworkPermission.js";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Request / check local network permission on iOS.
|
|
7
|
+
*
|
|
8
|
+
* On iOS 14+, this triggers the NWBrowser/NWListener detection mechanism:
|
|
9
|
+
* - If the user has not yet made a choice, the system permission dialog will appear.
|
|
10
|
+
* - If permission has already been granted or denied, the current status is returned
|
|
11
|
+
* without showing a dialog.
|
|
12
|
+
*
|
|
13
|
+
* @returns `true` if granted, `false` if denied.
|
|
14
|
+
*/
|
|
15
|
+
export async function requestPermission() {
|
|
16
|
+
return NativeModule.requestPermission();
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=LocalNetworkPermission.ios.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["NativeModule","requestPermission"],"sourceRoot":"../../src","sources":["LocalNetworkPermission.ios.ts"],"mappings":";;AAAA,OAAOA,YAAY,MAAM,mCAAgC;;AAEzD;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,eAAeC,iBAAiBA,CAAA,EAAqB;EAC1D,OAAOD,YAAY,CAACC,iBAAiB,CAAC,CAAC;AACzC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["requestPermission"],"sourceRoot":"../../src","sources":["LocalNetworkPermission.ts"],"mappings":";;AAAA;AACA;AACA;AACA;AACA,OAAO,eAAeA,iBAAiBA,CAAA,EAAqB;EAC1D,OAAO,IAAI;AACb","ignoreList":[]}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
import { TurboModuleRegistry } from 'react-native';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Native module spec for codegen.
|
|
7
|
+
*
|
|
8
|
+
* The return type uses inline object shapes because TurboModule codegen
|
|
9
|
+
* does not support importing custom TypeScript types.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
export default TurboModuleRegistry.getEnforcing('LocalNetworkPermission');
|
|
13
|
+
//# sourceMappingURL=NativeLocalNetworkPermission.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativeLocalNetworkPermission.ts"],"mappings":";;AAAA,SAASA,mBAAmB,QAA0B,cAAc;;AAEpE;AACA;AACA;AACA;AACA;AACA;;AAYA,eAAeA,mBAAmB,CAACC,YAAY,CAC7C,wBACF,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["requestPermission"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,iBAAiB,QAAQ,0BAA0B","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"module"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalNetworkPermission.android.d.ts","sourceRoot":"","sources":["../../../src/LocalNetworkPermission.android.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE1D"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalNetworkPermission.d.ts","sourceRoot":"","sources":["../../../src/LocalNetworkPermission.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE1D"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request / check local network permission on iOS.
|
|
3
|
+
*
|
|
4
|
+
* On iOS 14+, this triggers the NWBrowser/NWListener detection mechanism:
|
|
5
|
+
* - If the user has not yet made a choice, the system permission dialog will appear.
|
|
6
|
+
* - If permission has already been granted or denied, the current status is returned
|
|
7
|
+
* without showing a dialog.
|
|
8
|
+
*
|
|
9
|
+
* @returns `true` if granted, `false` if denied.
|
|
10
|
+
*/
|
|
11
|
+
export declare function requestPermission(): Promise<boolean>;
|
|
12
|
+
//# sourceMappingURL=LocalNetworkPermission.ios.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LocalNetworkPermission.ios.d.ts","sourceRoot":"","sources":["../../../src/LocalNetworkPermission.ios.ts"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AACH,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAE1D"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type TurboModule } from 'react-native';
|
|
2
|
+
/**
|
|
3
|
+
* Native module spec for codegen.
|
|
4
|
+
*
|
|
5
|
+
* The return type uses inline object shapes because TurboModule codegen
|
|
6
|
+
* does not support importing custom TypeScript types.
|
|
7
|
+
*/
|
|
8
|
+
export interface Spec extends TurboModule {
|
|
9
|
+
/**
|
|
10
|
+
* Request (or check) local network permission.
|
|
11
|
+
* On iOS this uses the NWBrowser/NWListener trick and may trigger the
|
|
12
|
+
* system permission dialog if the user has not yet made a choice.
|
|
13
|
+
*
|
|
14
|
+
* Resolves with `true` if granted, `false` if denied.
|
|
15
|
+
*/
|
|
16
|
+
requestPermission(): Promise<boolean>;
|
|
17
|
+
}
|
|
18
|
+
declare const _default: Spec;
|
|
19
|
+
export default _default;
|
|
20
|
+
//# sourceMappingURL=NativeLocalNetworkPermission.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NativeLocalNetworkPermission.d.ts","sourceRoot":"","sources":["../../../src/NativeLocalNetworkPermission.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAErE;;;;;GAKG;AACH,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC;;;;;;OAMG;IACH,iBAAiB,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CACvC;;AAED,wBAEE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@wniu/react-native-local-network-permission",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Handles iOS local network permission requests.",
|
|
5
|
+
"main": "./lib/module/index.js",
|
|
6
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"source": "./src/index.tsx",
|
|
10
|
+
"types": "./lib/typescript/src/index.d.ts",
|
|
11
|
+
"default": "./lib/module/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./package.json": "./package.json"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"src",
|
|
17
|
+
"lib",
|
|
18
|
+
"ios",
|
|
19
|
+
"*.podspec",
|
|
20
|
+
"!ios/build",
|
|
21
|
+
"!**/__tests__",
|
|
22
|
+
"!**/__fixtures__",
|
|
23
|
+
"!**/__mocks__",
|
|
24
|
+
"!**/.*"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"example": "yarn workspace react-native-local-network-permission-example",
|
|
28
|
+
"clean": "del-cli lib",
|
|
29
|
+
"prepare": "bob build",
|
|
30
|
+
"typecheck": "tsc",
|
|
31
|
+
"lint": "eslint \"**/*.{js,ts,tsx}\"",
|
|
32
|
+
"test": "jest",
|
|
33
|
+
"release": "release-it --only-version"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"react-native",
|
|
37
|
+
"ios",
|
|
38
|
+
"android"
|
|
39
|
+
],
|
|
40
|
+
"repository": {
|
|
41
|
+
"type": "git",
|
|
42
|
+
"url": "git+https://github.com/voyageh/react-native-local-network-permission.git"
|
|
43
|
+
},
|
|
44
|
+
"author": "zephyr <zephyr.d@qq.com> (https://github.com/voyageh)",
|
|
45
|
+
"license": "MIT",
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/voyageh/react-native-local-network-permission/issues"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://github.com/voyageh/react-native-local-network-permission#readme",
|
|
50
|
+
"publishConfig": {
|
|
51
|
+
"registry": "https://registry.npmjs.org/"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@commitlint/config-conventional": "^20.5.0",
|
|
55
|
+
"@eslint/compat": "^2.0.3",
|
|
56
|
+
"@eslint/eslintrc": "^3.3.5",
|
|
57
|
+
"@eslint/js": "^10.0.1",
|
|
58
|
+
"@jest/globals": "^30.0.0",
|
|
59
|
+
"@react-native/babel-preset": "0.85.0",
|
|
60
|
+
"@react-native/eslint-config": "0.85.0",
|
|
61
|
+
"@react-native/jest-preset": "0.85.0",
|
|
62
|
+
"@release-it/conventional-changelog": "^10.0.6",
|
|
63
|
+
"@types/react": "^19.2.0",
|
|
64
|
+
"commitlint": "^20.5.0",
|
|
65
|
+
"del-cli": "^7.0.0",
|
|
66
|
+
"eslint": "^9.39.4",
|
|
67
|
+
"eslint-config-prettier": "^10.1.8",
|
|
68
|
+
"eslint-plugin-ft-flow": "^3.0.11",
|
|
69
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
70
|
+
"jest": "^30.3.0",
|
|
71
|
+
"lefthook": "^2.1.4",
|
|
72
|
+
"prettier": "^3.8.1",
|
|
73
|
+
"react": "19.2.0",
|
|
74
|
+
"react-native": "0.83.4",
|
|
75
|
+
"react-native-builder-bob": "^0.41.0",
|
|
76
|
+
"release-it": "^19.2.4",
|
|
77
|
+
"turbo": "^2.8.21",
|
|
78
|
+
"typescript": "^6.0.2"
|
|
79
|
+
},
|
|
80
|
+
"peerDependencies": {
|
|
81
|
+
"react": "*",
|
|
82
|
+
"react-native": "*"
|
|
83
|
+
},
|
|
84
|
+
"workspaces": [
|
|
85
|
+
"example"
|
|
86
|
+
],
|
|
87
|
+
"packageManager": "yarn@4.11.0",
|
|
88
|
+
"react-native-builder-bob": {
|
|
89
|
+
"source": "src",
|
|
90
|
+
"output": "lib",
|
|
91
|
+
"targets": [
|
|
92
|
+
[
|
|
93
|
+
"module",
|
|
94
|
+
{
|
|
95
|
+
"esm": true
|
|
96
|
+
}
|
|
97
|
+
],
|
|
98
|
+
[
|
|
99
|
+
"typescript",
|
|
100
|
+
{
|
|
101
|
+
"project": "tsconfig.build.json"
|
|
102
|
+
}
|
|
103
|
+
]
|
|
104
|
+
]
|
|
105
|
+
},
|
|
106
|
+
"codegenConfig": {
|
|
107
|
+
"name": "LocalNetworkPermissionSpec",
|
|
108
|
+
"type": "modules",
|
|
109
|
+
"jsSrcsDir": "src"
|
|
110
|
+
},
|
|
111
|
+
"prettier": {
|
|
112
|
+
"quoteProps": "consistent",
|
|
113
|
+
"singleQuote": true,
|
|
114
|
+
"tabWidth": 2,
|
|
115
|
+
"trailingComma": "es5",
|
|
116
|
+
"useTabs": false
|
|
117
|
+
},
|
|
118
|
+
"jest": {
|
|
119
|
+
"preset": "@react-native/jest-preset",
|
|
120
|
+
"modulePathIgnorePatterns": [
|
|
121
|
+
"<rootDir>/example/node_modules",
|
|
122
|
+
"<rootDir>/lib/"
|
|
123
|
+
]
|
|
124
|
+
},
|
|
125
|
+
"commitlint": {
|
|
126
|
+
"extends": [
|
|
127
|
+
"@commitlint/config-conventional"
|
|
128
|
+
]
|
|
129
|
+
},
|
|
130
|
+
"release-it": {
|
|
131
|
+
"git": {
|
|
132
|
+
"commitMessage": "chore: release ${version}",
|
|
133
|
+
"tagName": "v${version}"
|
|
134
|
+
},
|
|
135
|
+
"npm": {
|
|
136
|
+
"publish": true
|
|
137
|
+
},
|
|
138
|
+
"github": {
|
|
139
|
+
"release": true
|
|
140
|
+
},
|
|
141
|
+
"plugins": {
|
|
142
|
+
"@release-it/conventional-changelog": {
|
|
143
|
+
"preset": {
|
|
144
|
+
"name": "angular"
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
},
|
|
149
|
+
"create-react-native-library": {
|
|
150
|
+
"type": "turbo-module",
|
|
151
|
+
"languages": "kotlin-objc",
|
|
152
|
+
"tools": [
|
|
153
|
+
"eslint",
|
|
154
|
+
"jest",
|
|
155
|
+
"lefthook",
|
|
156
|
+
"release-it"
|
|
157
|
+
],
|
|
158
|
+
"version": "0.62.0"
|
|
159
|
+
}
|
|
160
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import NativeModule from './NativeLocalNetworkPermission';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Request / check local network permission on iOS.
|
|
5
|
+
*
|
|
6
|
+
* On iOS 14+, this triggers the NWBrowser/NWListener detection mechanism:
|
|
7
|
+
* - If the user has not yet made a choice, the system permission dialog will appear.
|
|
8
|
+
* - If permission has already been granted or denied, the current status is returned
|
|
9
|
+
* without showing a dialog.
|
|
10
|
+
*
|
|
11
|
+
* @returns `true` if granted, `false` if denied.
|
|
12
|
+
*/
|
|
13
|
+
export async function requestPermission(): Promise<boolean> {
|
|
14
|
+
return NativeModule.requestPermission();
|
|
15
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TurboModuleRegistry, type TurboModule } from 'react-native';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Native module spec for codegen.
|
|
5
|
+
*
|
|
6
|
+
* The return type uses inline object shapes because TurboModule codegen
|
|
7
|
+
* does not support importing custom TypeScript types.
|
|
8
|
+
*/
|
|
9
|
+
export interface Spec extends TurboModule {
|
|
10
|
+
/**
|
|
11
|
+
* Request (or check) local network permission.
|
|
12
|
+
* On iOS this uses the NWBrowser/NWListener trick and may trigger the
|
|
13
|
+
* system permission dialog if the user has not yet made a choice.
|
|
14
|
+
*
|
|
15
|
+
* Resolves with `true` if granted, `false` if denied.
|
|
16
|
+
*/
|
|
17
|
+
requestPermission(): Promise<boolean>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default TurboModuleRegistry.getEnforcing<Spec>(
|
|
21
|
+
'LocalNetworkPermission'
|
|
22
|
+
);
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { requestPermission } from './LocalNetworkPermission';
|