Skip to content

Commit b0ad866

Browse files
authored
feat(macos): Add in a macOS implementation of NetInfo (react-native-netinfo#312 by @tom-un)
There is currently a known issue where the network type is incorrectly reported at `ethernet`, however, the connection status is currently correct.
1 parent 423fa62 commit b0ad866

28 files changed

+3762
-37
lines changed

.github/workflows/ci.yml

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: CI
2+
3+
on: [push, pull_request]
4+
5+
jobs:
6+
build:
7+
8+
runs-on: macOS-latest
9+
10+
steps:
11+
- uses: actions/checkout@master
12+
- uses: actions/setup-node@v1
13+
with:
14+
node-version: '10.x'
15+
- name: Installing Yarn dependencies
16+
run: yarn install --frozen-lockfile
17+
- name: Run e2e tests
18+
run: yarn test:e2e:macos

CONTRIBUTING.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Currently we use `flow` for typechecking, `eslint` with `prettier` for linting a
1919
* `yarn test:jest`: Run unit tests with `jest`.
2020
* `yarn test:detox:<android|ios>:build:<debug|release>`: Build the `debug` or `release` app for end-to-end tests with `detox` on either `android` or `ios`. You need to run this before running the test command and whenever you make changes to the native code.
2121
* `yarn test:detox:<android|ios>:test:<debug|release>`: Run the `debug` or `release` end-to-end tests with `detox` on either `android` or `ios`.
22+
* `yarn test:e2e:macos`: Run the end-to-end tests for macOS.
2223

2324
## Sending a pull request
2425
When you're sending a pull request:

README.md

+43-26
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11

22
# `@react-native-community/netinfo`
33

4-
[![CircleCI Status](https://img.shields.io/circleci/project/github/react-native-community/react-native-netinfo/master.svg)](https://circleci.com/gh/react-native-community/workflows/react-native-netinfo/tree/master) ![Supports Android, iOS, and Windows](https://img.shields.io/badge/platforms-android%20|%20ios%20|%20windows-lightgrey.svg) ![MIT License](https://img.shields.io/npm/l/@react-native-community/netinfo.svg) [![Lean Core Extracted](https://img.shields.io/badge/Lean%20Core-Extracted-brightgreen.svg)](https://github.com/facebook/react-native/issues/23313)
4+
[![CircleCI Status](https://img.shields.io/circleci/project/github/react-native-community/react-native-netinfo/master.svg)](https://circleci.com/gh/react-native-community/workflows/react-native-netinfo/tree/master) ![Supports Android, iOS, macOS, and Windows](https://img.shields.io/badge/platforms-android%20|%20ios%20|%20macos%20|%20windows-lightgrey.svg) ![MIT License](https://img.shields.io/npm/l/@react-native-community/netinfo.svg) [![Lean Core Extracted](https://img.shields.io/badge/Lean%20Core-Extracted-brightgreen.svg)](https://github.com/facebook/react-native/issues/23313)
55

6-
React Native Network Info API for Android, iOS & Windows. It allows you to get information on:
6+
React Native Network Info API for Android, iOS, macOS & Windows. It allows you to get information on:
77

88
* Connection type
99
* Connection quality
@@ -61,6 +61,10 @@ Linking the package manually is not required anymore with [Autolinking](https://
6161
}
6262
```
6363

64+
- **macOS Platform:**
65+
66+
Autolinking is not yet available on macOS. See the [Manual linking steps for macOS](#manual-linking-macos) below.
67+
6468
#### Using React Native < 0.60
6569

6670
You then need to link the native parts of the library for the platforms you are using. The easiest way to link the library is using the CLI tool by running this command from the root of your project:
@@ -82,6 +86,19 @@ pod 'react-native-netinfo', :path => '../node_modules/@react-native-community/ne
8286

8387
</details>
8488

89+
<details id='manual-linking-macos'>
90+
<summary>Manually link the library on macOS</summary>
91+
92+
1. Open your project `.xcodeproj` on xcode.
93+
94+
2. Right click on the Libraries folder and select `Add files to "yourProjectName"`.
95+
96+
3. Add `RNCNetInfo.xcodeproj` (located at `node_modules/@react-native-community/react-native-netinfo/macos`) to your project Libraries.
97+
98+
4. Go to `Build Phases -> Link Binary with Libraries` and add: `libRNCNetInfo-macOS.a`.
99+
100+
</details>
101+
85102
<details>
86103
<summary>Manually link the library on Android</summary>
87104

@@ -221,7 +238,7 @@ Describes the current state of the network. It is an object with these propertie
221238
| `type` | [`NetInfoStateType`](#netinfostatetype) | The type of the current connection. |
222239
| `isConnected` | `boolean` | If there is an active network connection. Note that this DOES NOT mean that internet is reachable. |
223240
| `isInternetReachable` | `boolean` | If the internet is reachable with the currently active network connection. |
224-
| `isWifiEnabled` | `boolean` | *(Android only)* Whether the device's WiFi is ON or OFF.|
241+
| `isWifiEnabled` | `boolean` | *(Android only)* Whether the device's WiFi is ON or OFF. |
225242
| `details` | | The value depends on the `type` value. See below. |
226243

227244
The `details` value depends on the `type` value.
@@ -234,23 +251,23 @@ The `details` value depends on the `type` value.
234251

235252
`details` has these properties:
236253

237-
| Property | Platform | Type | Description |
238-
| ----------------------- | ----------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
239-
| `isConnectionExpensive` | Android, iOS, Windows, Web | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
240-
| `ssid` | Android, iOS (not tvOS) | `string` | The SSID of the network. May not be present, `null`, or an empty string if it cannot be determined. **On iOS, make sure your app meets at least one of the [following requirements](https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo?language=objc#discussion). On Android, you need to have the `ACCESS_FINE_LOCATION` permission in your `AndroidManifest.xml` and accepted by the user**. |
241-
| `strength` | Android | `number` | An integer number from `0` to `5` for the signal strength. May not be present if the signal strength cannot be determined. |
242-
| `ipAddress` | Android, iOS | `string` | The external IP address. Can be in IPv4 or IPv6 format. May not be present if it cannot be determined. |
243-
| `subnet` | Android, iOS | `string` | The subnet mask in IPv4 format. May not be present if it cannot be determined. |
254+
| Property | Platform | Type | Description |
255+
| ----------------------- | --------------------------------- | --------- | -------------------------------------------------------------------------------------------------------------------------- |
256+
| `isConnectionExpensive` | Android, iOS, macOS, Windows, Web | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
257+
| `ssid` | Android, iOS (not tvOS) | `string` | The SSID of the network. May not be present, `null`, or an empty string if it cannot be determined. **On iOS, make sure your app meets at least one of the [following requirements](https://developer.apple.com/documentation/systemconfiguration/1614126-cncopycurrentnetworkinfo?language=objc#discussion). On Android, you need to have the `ACCESS_FINE_LOCATION` permission in your `AndroidManifest.xml` and accepted by the user**. |
258+
| `strength` | Android | `number` | An integer number from `0` to `5` for the signal strength. May not be present if the signal strength cannot be determined. |
259+
| `ipAddress` | Android, iOS, macOS | `string` | The external IP address. Can be in IPv4 or IPv6 format. May not be present if it cannot be determined. |
260+
| `subnet` | Android, iOS, macOS | `string` | The subnet mask in IPv4 format. May not be present if it cannot be determined. |
244261

245262
##### `type` is `cellular`
246263

247264
`details` has these properties:
248265

249-
| Property | Platform | Type | Description |
250-
| ----------------------- | -------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
251-
| `isConnectionExpensive` | Android, iOS, Windows, Web | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
252-
| `cellularGeneration` | Android, iOS, Windows | [`NetInfoCellularGeneration`](#netinfocellulargeneration) | The generation of the cell network the user is connected to. This can give an indication of speed, but no guarantees. |
253-
| `carrier` | Android, iOS | `string` | The network carrier name. May not be present or may be empty if none can be determined. |
266+
| Property | Platform | Type | Description |
267+
| ----------------------- | --------------------------------- | ------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
268+
| `isConnectionExpensive` | Android, iOS, macOS, Windows, Web | `boolean` | If the network connection is considered "expensive". This could be in either energy or monetary terms. |
269+
| `cellularGeneration` | Android, iOS, Windows | [`NetInfoCellularGeneration`](#netinfocellulargeneration) | The generation of the cell network the user is connected to. This can give an indication of speed, but no guarantees. |
270+
| `carrier` | Android, iOS | `string` | The network carrier name. May not be present or may be empty if none can be determined. |
254271

255272
##### `type` is `bluetooth`, `ethernet`, `wimax`, `vpn`, or `other`
256273

@@ -263,17 +280,17 @@ The `details` value depends on the `type` value.
263280
#### `NetInfoStateType`
264281
Describes the current type of network connection. It is an enum with these possible values:
265282

266-
| Value | Platform | Description |
267-
| ----------- | -------------------------- | ---------------------------------------------------------- |
268-
| `none` | Android, iOS, Windows, Web | No network connection is active |
269-
| `unknown` | Android, iOS, Windows, Web | The network state could not or has yet to be be determined |
270-
| `cellular` | Android, iOS, Windows, Web | Active network over cellular |
271-
| `wifi` | Android, iOS, Windows, Web | Active network over Wifi |
272-
| `bluetooth` | Android, Web | Active network over Bluetooth |
273-
| `ethernet` | Android, Windows, Web | Active network over wired ethernet |
274-
| `wimax` | Android, Web | Active network over WiMax |
275-
| `vpn` | Android | Active network over VPN |
276-
| `other` | Android, iOS, Windows, Web | Active network over another type of network |
283+
| Value | Platform | Description |
284+
| ----------- | --------------------------------- | ---------------------------------------------------------- |
285+
| `none` | Android, iOS, macOS, Windows, Web | No network connection is active |
286+
| `unknown` | Android, iOS, macOS, Windows, Web | The network state could not or has yet to be be determined |
287+
| `cellular` | Android, iOS, Windows, Web | Active network over cellular |
288+
| `wifi` | Android, iOS, macOS, Windows, Web | Active network over Wifi |
289+
| `bluetooth` | Android, Web | Active network over Bluetooth |
290+
| `ethernet` | Android, macOS, Windows, Web | Active network over wired ethernet |
291+
| `wimax` | Android, Web | Active network over WiMax |
292+
| `vpn` | Android | Active network over VPN |
293+
| `other` | Android, iOS, macOS, Windows, Web | Active network over another type of network |
277294

278295
#### `NetInfoCellularGeneration`
279296
Describes the current generation of the `cellular` connection. It is an enum with these possible values:

example/e2e/testCases/HookInitialValue.spec.native.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe('HookInitialValue', () => {
1717
});
1818

1919
it('should have the correct elements to perform the test', async () => {
20-
await expect(element(by.id('results'))).toExist();
20+
await expect(element(by.id('result'))).toExist();
2121
});
2222

2323
it('should show a pass', async () => {

example/index.tsx

+14-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import * as React from 'react';
1212
import {
1313
AppRegistry,
1414
Linking,
15+
Platform,
1516
SafeAreaView,
1617
ScrollView,
1718
StyleSheet,
@@ -127,18 +128,29 @@ class ExampleApp extends React.Component<{}, State> {
127128

128129
componentDidMount() {
129130
Linking.getInitialURL().then(this._handleOpenURLString);
130-
Linking.addEventListener('url', this._handleOpenURL);
131+
if (Platform.OS === 'macos') {
132+
Linking.addEventListener('url', this._handleOpenURLMacOS);
133+
} else {
134+
Linking.addEventListener('url', this._handleOpenURL);
135+
}
131136
}
132137

133138
componentWillUnmount() {
134-
Linking.removeEventListener('url', this._handleOpenURL);
139+
if (Platform.OS === 'macos') {
140+
Linking.removeEventListener('url', this._handleOpenURLMacOS);
141+
} else {
142+
Linking.removeEventListener('url', this._handleOpenURL);
143+
}
135144
}
136145

137146
// Receives commands from the test runner when it opens the app with a given URL
138147
// We use this to decide which test case to show
139148
_handleOpenURL = ({url}: {url: string}) => {
140149
this._handleOpenURLString(url);
141150
};
151+
_handleOpenURLMacOS = (url: any) => {
152+
this._handleOpenURLString(url);
153+
};
142154
_handleOpenURLString = (url: string | null) => {
143155
if (!url) {
144156
return;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import <Cocoa/Cocoa.h>
9+
10+
@class RCTBridge;
11+
12+
@interface AppDelegate : NSObject <NSApplicationDelegate>
13+
14+
@property (nonatomic, readonly) RCTBridge *bridge;
15+
16+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#import "AppDelegate.h"
9+
10+
#import <React/RCTUIKit.h>
11+
#import <React/RCTBridge.h>
12+
#import <React/RCTBundleURLProvider.h>
13+
#import <React/RCTLinkingManager.h>
14+
15+
@interface AppDelegate () <RCTBridgeDelegate>
16+
17+
@end
18+
19+
@implementation AppDelegate
20+
21+
- (void)awakeFromNib {
22+
[super awakeFromNib];
23+
24+
_bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:nil];
25+
}
26+
27+
- (void)applicationWillFinishLaunching:(NSNotification *)__unused aNotification
28+
{
29+
// initialize the url event listeners for Linking module
30+
// this example registers the netinfoexample scheme in Info.plist
31+
[[NSAppleEventManager sharedAppleEventManager] setEventHandler:[RCTLinkingManager class]
32+
andSelector:@selector(getUrlEventHandler:withReplyEvent:)
33+
forEventClass:kInternetEventClass
34+
andEventID:kAEGetURL];
35+
}
36+
37+
#pragma mark - RCTBridgeDelegate Methods
38+
39+
- (NSURL *)sourceURLForBridge:(__unused RCTBridge *)bridge {
40+
return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"example/index" fallbackResource:@"main"]; // .jsbundle;
41+
}
42+
43+
@end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>CFBundleDevelopmentRegion</key>
6+
<string>$(DEVELOPMENT_LANGUAGE)</string>
7+
<key>CFBundleExecutable</key>
8+
<string>$(EXECUTABLE_NAME)</string>
9+
<key>CFBundleIconFile</key>
10+
<string></string>
11+
<key>CFBundleIdentifier</key>
12+
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13+
<key>CFBundleInfoDictionaryVersion</key>
14+
<string>6.0</string>
15+
<key>CFBundleName</key>
16+
<string>$(PRODUCT_NAME)</string>
17+
<key>CFBundlePackageType</key>
18+
<string>APPL</string>
19+
<key>CFBundleShortVersionString</key>
20+
<string>1.0</string>
21+
<key>CFBundleURLTypes</key>
22+
<array>
23+
<dict>
24+
<key>CFBundleTypeRole</key>
25+
<string>Editor</string>
26+
<key>CFBundleURLName</key>
27+
<string>com.reactnativecommunity.netinfo.example</string>
28+
<key>CFBundleURLSchemes</key>
29+
<array>
30+
<string>netinfoexample</string>
31+
</array>
32+
</dict>
33+
</array>
34+
<key>CFBundleVersion</key>
35+
<string>1</string>
36+
<key>LSMinimumSystemVersion</key>
37+
<string>$(MACOSX_DEPLOYMENT_TARGET)</string>
38+
<key>NSAppTransportSecurity</key>
39+
<dict>
40+
<key>NSAllowsArbitraryLoads</key>
41+
<true/>
42+
</dict>
43+
<key>NSHumanReadableCopyright</key>
44+
<string>Copyright © 2020 Facebook. All rights reserved.</string>
45+
<key>NSMainStoryboardFile</key>
46+
<string>Main</string>
47+
<key>NSPrincipalClass</key>
48+
<string>NSApplication</string>
49+
</dict>
50+
</plist>

0 commit comments

Comments
 (0)