瀏覽代碼

feat: report analytics for the network connection

Will emit new 'network.info' action with the online/offline status and
extra details for native like the network type and
'isConnectionExpensive' flag.
master
paweldomas 5 年之前
父節點
當前提交
6ae9bbe0c5

+ 1
- 0
android/sdk/build.gradle 查看文件

56
     implementation project(':react-native-background-timer')
56
     implementation project(':react-native-background-timer')
57
     implementation project(':react-native-calendar-events')
57
     implementation project(':react-native-calendar-events')
58
     implementation project(':react-native-community-async-storage')
58
     implementation project(':react-native-community-async-storage')
59
+    implementation project(':react-native-community_netinfo')
59
     implementation project(':react-native-immersive')
60
     implementation project(':react-native-immersive')
60
     implementation project(':react-native-keep-awake')
61
     implementation project(':react-native-keep-awake')
61
     implementation project(':react-native-linear-gradient')
62
     implementation project(':react-native-linear-gradient')

+ 1
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java 查看文件

193
                 new com.oblador.vectoricons.VectorIconsPackage(),
193
                 new com.oblador.vectoricons.VectorIconsPackage(),
194
                 new com.ocetnik.timer.BackgroundTimerPackage(),
194
                 new com.ocetnik.timer.BackgroundTimerPackage(),
195
                 new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
195
                 new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
196
+                new com.reactnativecommunity.netinfo.NetInfoPackage(),
196
                 new com.reactnativecommunity.webview.RNCWebViewPackage(),
197
                 new com.reactnativecommunity.webview.RNCWebViewPackage(),
197
                 new com.rnimmersive.RNImmersivePackage(),
198
                 new com.rnimmersive.RNImmersivePackage(),
198
                 new com.zmxv.RNSound.RNSoundPackage(),
199
                 new com.zmxv.RNSound.RNSoundPackage(),

+ 2
- 0
android/settings.gradle 查看文件

7
 project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
7
 project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
8
 include ':react-native-community-async-storage'
8
 include ':react-native-community-async-storage'
9
 project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
9
 project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
10
+include ':react-native-community_netinfo'
11
+project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
10
 include ':react-native-google-signin'
12
 include ':react-native-google-signin'
11
 project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
13
 project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
12
 include ':react-native-immersive'
14
 include ':react-native-immersive'

+ 1
- 0
ios/Podfile 查看文件

47
   pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'
47
   pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'
48
   pod 'react-native-calendar-events', :path => '../node_modules/react-native-calendar-events'
48
   pod 'react-native-calendar-events', :path => '../node_modules/react-native-calendar-events'
49
   pod 'react-native-keep-awake', :path => '../node_modules/react-native-keep-awake'
49
   pod 'react-native-keep-awake', :path => '../node_modules/react-native-keep-awake'
50
+  pod 'react-native-netinfo', :path => '../node_modules/@react-native-community/netinfo'
50
   pod 'react-native-webview', :path => '../node_modules/react-native-webview'
51
   pod 'react-native-webview', :path => '../node_modules/react-native-webview'
51
   pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
52
   pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
52
   pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
53
   pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'

+ 7
- 1
ios/Podfile.lock 查看文件

139
     - React
139
     - React
140
   - react-native-keep-awake (4.0.0):
140
   - react-native-keep-awake (4.0.0):
141
     - React
141
     - React
142
+  - react-native-netinfo (4.1.5):
143
+    - React
142
   - react-native-webrtc (1.69.2):
144
   - react-native-webrtc (1.69.2):
143
     - React
145
     - React
144
   - react-native-webview (5.8.1):
146
   - react-native-webview (5.8.1):
203
   - react-native-background-timer (from `../node_modules/react-native-background-timer`)
205
   - react-native-background-timer (from `../node_modules/react-native-background-timer`)
204
   - react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
206
   - react-native-calendar-events (from `../node_modules/react-native-calendar-events`)
205
   - react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
207
   - react-native-keep-awake (from `../node_modules/react-native-keep-awake`)
208
+  - react-native-netinfo (from `../node_modules/@react-native-community/netinfo`)
206
   - react-native-webrtc (from `../node_modules/react-native-webrtc`)
209
   - react-native-webrtc (from `../node_modules/react-native-webrtc`)
207
   - react-native-webview (from `../node_modules/react-native-webview`)
210
   - react-native-webview (from `../node_modules/react-native-webview`)
208
   - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
211
   - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
271
     :path: "../node_modules/react-native-calendar-events"
274
     :path: "../node_modules/react-native-calendar-events"
272
   react-native-keep-awake:
275
   react-native-keep-awake:
273
     :path: "../node_modules/react-native-keep-awake"
276
     :path: "../node_modules/react-native-keep-awake"
277
+  react-native-netinfo:
278
+    :path: "../node_modules/@react-native-community/netinfo"
274
   react-native-webrtc:
279
   react-native-webrtc:
275
     :path: "../node_modules/react-native-webrtc"
280
     :path: "../node_modules/react-native-webrtc"
276
   react-native-webview:
281
   react-native-webview:
340
   react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
345
   react-native-background-timer: 0d34748e53a972507c66963490c775321a88f6f2
341
   react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
346
   react-native-calendar-events: 2fe35a9294af05de0ed819d3a1b5dac048d2c010
342
   react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
347
   react-native-keep-awake: eba3137546b10003361b37c761f6c429b59814ae
348
+  react-native-netinfo: 8d8db463bcc5db66a8ac5c48a7d86beb3b92f61a
343
   react-native-webrtc: 1415d2a54b2246dd85ba95eb3e4bf2b66533f951
349
   react-native-webrtc: 1415d2a54b2246dd85ba95eb3e4bf2b66533f951
344
   react-native-webview: a95842e3f351a6d2c8bc8bcc9eab689c7e7e5ad4
350
   react-native-webview: a95842e3f351a6d2c8bc8bcc9eab689c7e7e5ad4
345
   React-RCTActionSheet: b0f1ea83f4bf75fb966eae9bfc47b78c8d3efd90
351
   React-RCTActionSheet: b0f1ea83f4bf75fb966eae9bfc47b78c8d3efd90
359
   RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
365
   RNWatch: 09738b339eceb66e4d80a2371633ca5fb380fa42
360
   yoga: 312528f5bbbba37b4dcea5ef00e8b4033fdd9411
366
   yoga: 312528f5bbbba37b4dcea5ef00e8b4033fdd9411
361
 
367
 
362
-PODFILE CHECKSUM: 6b6e260b4be4e86f9d05c0d7dab40f60118bb355
368
+PODFILE CHECKSUM: 0907bfe60b5b5f11dbdc6b4e65d40a248d000513
363
 
369
 
364
 COCOAPODS: 1.7.2
370
 COCOAPODS: 1.7.2

+ 5
- 0
package-lock.json 查看文件

3055
         }
3055
         }
3056
       }
3056
       }
3057
     },
3057
     },
3058
+    "@react-native-community/netinfo": {
3059
+      "version": "4.1.5",
3060
+      "resolved": "https://registry.npmjs.org/@react-native-community/netinfo/-/netinfo-4.1.5.tgz",
3061
+      "integrity": "sha512-lagdZr9UiVAccNXYfTEj+aUcPCx9ykbMe9puffeIyF3JsRuMmlu3BjHYx1klUHX7wNRmFNC8qVP0puxUt1sZ0A=="
3062
+    },
3058
     "@segment/top-domain": {
3063
     "@segment/top-domain": {
3059
       "version": "3.0.0",
3064
       "version": "3.0.0",
3060
       "resolved": "https://registry.npmjs.org/@segment/top-domain/-/top-domain-3.0.0.tgz",
3065
       "resolved": "https://registry.npmjs.org/@segment/top-domain/-/top-domain-3.0.0.tgz",

+ 1
- 0
package.json 查看文件

35
     "@atlaskit/tooltip": "12.1.13",
35
     "@atlaskit/tooltip": "12.1.13",
36
     "@microsoft/microsoft-graph-client": "1.1.0",
36
     "@microsoft/microsoft-graph-client": "1.1.0",
37
     "@react-native-community/async-storage": "1.3.4",
37
     "@react-native-community/async-storage": "1.3.4",
38
+    "@react-native-community/netinfo": "4.1.5",
38
     "@tensorflow-models/body-pix": "^1.0.1",
39
     "@tensorflow-models/body-pix": "^1.0.1",
39
     "@tensorflow/tfjs": "^1.1.2",
40
     "@tensorflow/tfjs": "^1.1.2",
40
     "@webcomponents/url": "0.7.1",
41
     "@webcomponents/url": "0.7.1",

+ 21
- 0
react/features/analytics/AnalyticsEvents.js 查看文件

271
     };
271
     };
272
 }
272
 }
273
 
273
 
274
+/**
275
+ * Creates an event which reports about the current network information reported by the operating system.
276
+ *
277
+ * @param {boolean} isOnline - Tells whether or not the internet is reachable.
278
+ * @param {string} [networkType] - Network type, see {@code NetworkInfo} type defined by the 'base/net-info' feature.
279
+ * @param {Object} [details] - Extra info, see {@code NetworkInfo} type defined by the 'base/net-info' feature.
280
+ * @returns {Object}
281
+ */
282
+export function createNetworkInfoEvent({ isOnline, networkType, details }) {
283
+    const attributes = { isOnline };
284
+
285
+    // Do no include optional stuff or Amplitude handler will log warnings.
286
+    networkType && (attributes.networkType = networkType);
287
+    details && (attributes.details = details);
288
+
289
+    return {
290
+        action: 'network.info',
291
+        attributes
292
+    };
293
+}
294
+
274
 /**
295
 /**
275
  * Creates an "offer/answer failure" event.
296
  * Creates an "offer/answer failure" event.
276
  *
297
  *

+ 10
- 1
react/features/analytics/middleware.js 查看文件

6
     SET_ROOM
6
     SET_ROOM
7
 } from '../base/conference';
7
 } from '../base/conference';
8
 import { SET_CONFIG } from '../base/config';
8
 import { SET_CONFIG } from '../base/config';
9
+import { SET_NETWORK_INFO } from '../base/net-info';
9
 import { MiddlewareRegistry } from '../base/redux';
10
 import { MiddlewareRegistry } from '../base/redux';
10
 import {
11
 import {
11
     getLocalAudioTrack,
12
     getLocalAudioTrack,
16
 } from '../base/tracks';
17
 } from '../base/tracks';
17
 
18
 
18
 import { UPDATE_LOCAL_TRACKS_DURATION } from './actionTypes';
19
 import { UPDATE_LOCAL_TRACKS_DURATION } from './actionTypes';
19
-import { createLocalTracksDurationEvent } from './AnalyticsEvents';
20
+import { createLocalTracksDurationEvent, createNetworkInfoEvent } from './AnalyticsEvents';
20
 import { initAnalytics, resetAnalytics, sendAnalytics } from './functions';
21
 import { initAnalytics, resetAnalytics, sendAnalytics } from './functions';
21
 
22
 
22
 /**
23
 /**
127
         });
128
         });
128
         break;
129
         break;
129
     }
130
     }
131
+    case SET_NETWORK_INFO:
132
+        sendAnalytics(
133
+            createNetworkInfoEvent({
134
+                isOnline: action.isOnline,
135
+                details: action.details,
136
+                networkType: action.networkType
137
+            }));
138
+        break;
130
     case SET_ROOM: {
139
     case SET_ROOM: {
131
         initAnalytics(store);
140
         initAnalytics(store);
132
         break;
141
         break;

+ 66
- 0
react/features/base/net-info/NetworkInfoService.native.js 查看文件

1
+// @flow
2
+import EventEmitter from 'events';
3
+import NetInfo from '@react-native-community/netinfo';
4
+import type { NetInfoState, NetInfoSubscription } from '@react-native-community/netinfo';
5
+
6
+import { ONLINE_STATE_CHANGED_EVENT } from './events';
7
+
8
+import type { NetworkInfo } from './types';
9
+
10
+/**
11
+ * The network info service implementation for iOS and Android. 'react-native-netinfo' seems to support windows as well,
12
+ * but that has not been tested and is nto used by jitsi-meet.
13
+ */
14
+export default class NetworkInfoService extends EventEmitter {
15
+    /**
16
+     * Stores the native subscription for future cleanup.
17
+     */
18
+    _subscription: NetInfoSubscription;
19
+
20
+    /**
21
+     * Converts library's structure to {@link NetworkInfo} used by jitsi-meet.
22
+     *
23
+     * @param {NetInfoState} netInfoState - The new state given by the native library.
24
+     * @private
25
+     * @returns {NetworkInfo}
26
+     */
27
+    static _convertNetInfoState(netInfoState: NetInfoState): NetworkInfo {
28
+        return {
29
+            isOnline: netInfoState.isInternetReachable,
30
+            details: netInfoState.details,
31
+            networkType: netInfoState.type
32
+        };
33
+    }
34
+
35
+    /**
36
+     * Checks for support.
37
+     *
38
+     * @returns {boolean}
39
+     */
40
+    static isSupported() {
41
+        return Boolean(NetInfo);
42
+    }
43
+
44
+    /**
45
+     * Starts the service.
46
+     *
47
+     * @returns {void}
48
+     */
49
+    start() {
50
+        this._subscription = NetInfo.addEventListener(netInfoState => {
51
+            this.emit(ONLINE_STATE_CHANGED_EVENT, NetworkInfoService._convertNetInfoState(netInfoState));
52
+        });
53
+    }
54
+
55
+    /**
56
+     * Stops the service.
57
+     *
58
+     * @returns {void}
59
+     */
60
+    stop() {
61
+        if (this._subscription) {
62
+            this._subscription();
63
+            this._subscription = undefined;
64
+        }
65
+    }
66
+}

+ 58
- 0
react/features/base/net-info/NetworkInfoService.web.js 查看文件

1
+import EventEmitter from 'events';
2
+
3
+import { ONLINE_STATE_CHANGED_EVENT } from './events';
4
+
5
+/**
6
+ * The network info service implementation for web (Chrome, Firefox and Safari).
7
+ */
8
+export default class NetworkInfoService extends EventEmitter {
9
+
10
+    /**
11
+     * Creates new instance...
12
+     */
13
+    constructor() {
14
+        super();
15
+        this._onlineStateListener = this._handleOnlineStatusChange.bind(this, /* online */ true);
16
+        this._offlineStateListener = this._handleOnlineStatusChange.bind(this, /* offline */ false);
17
+    }
18
+
19
+    /**
20
+     * Callback function to track the online state.
21
+     *
22
+     * @param {boolean} isOnline - Is the browser online or not.
23
+     * @private
24
+     * @returns {void}
25
+     */
26
+    _handleOnlineStatusChange(isOnline) {
27
+        this.emit(ONLINE_STATE_CHANGED_EVENT, { isOnline });
28
+    }
29
+
30
+    /**
31
+     * Checks for support.
32
+     *
33
+     * @returns {boolean}
34
+     */
35
+    static isSupported() {
36
+        return window.addEventListener && typeof navigator.onLine !== 'undefined';
37
+    }
38
+
39
+    /**
40
+     * Starts the service.
41
+     *
42
+     * @returns {void}
43
+     */
44
+    start() {
45
+        window.addEventListener('online', this._onlineStateListener);
46
+        window.addEventListener('offline', this._offlineStateListener);
47
+    }
48
+
49
+    /**
50
+     * Stops the service.
51
+     *
52
+     * @returns {void}
53
+     */
54
+    stop() {
55
+        window.removeEventListener('online', this._onlineStateListener);
56
+        window.removeEventListener('offline', this._offlineStateListener);
57
+    }
58
+}

+ 13
- 0
react/features/base/net-info/actionTypes.js 查看文件

1
+/**
2
+ * The action dispatched when the {@link NetworkInfo} structure is being updated.
3
+ *
4
+ * @type {string}
5
+ */
6
+export const SET_NETWORK_INFO = 'SET_NETWORK_INFO';
7
+
8
+/**
9
+ * Tha action dispatched by 'base/net-info' middleware in order to store the cleanup function for later use.
10
+ * @type {string}
11
+ * @private
12
+ */
13
+export const _STORE_NETWORK_INFO_CLEANUP = 'STORE_NETWORK_INFO_CLEANUP';

+ 42
- 0
react/features/base/net-info/actions.js 查看文件

1
+// @flow
2
+
3
+import { SET_NETWORK_INFO, _STORE_NETWORK_INFO_CLEANUP } from './actionTypes';
4
+
5
+import type { NetworkInfo } from './types';
6
+
7
+/**
8
+ * Up[dates the network info state.
9
+ *
10
+ * @param {NetworkInfo} networkInfo - The new network state to be set.
11
+ * @returns {{
12
+ *     type: SET_NETWORK_INFO,
13
+ *     isOnline: boolean,
14
+ *     networkType: string,
15
+ *     details: Object
16
+ * }}
17
+ */
18
+export function setNetworkInfo({ isOnline, networkType, details }: NetworkInfo): Object {
19
+    return {
20
+        type: SET_NETWORK_INFO,
21
+        isOnline,
22
+        networkType,
23
+        details
24
+    };
25
+}
26
+
27
+/**
28
+ * Stored the cleanup function used to shutdown the {@code NetworkInfoService}.
29
+ *
30
+ * @param {Function} cleanup - The cleanup function to be called on {@code APP_WILL_UNMOUNT}.
31
+ * @returns {{
32
+ *     type: _STORE_NETWORK_INFO_CLEANUP,
33
+ *     cleanup: Function
34
+ * }}
35
+ * @private
36
+ */
37
+export function _storeNetworkInfoCleanup(cleanup: Function): Object {
38
+    return {
39
+        type: _STORE_NETWORK_INFO_CLEANUP,
40
+        cleanup
41
+    };
42
+}

+ 6
- 0
react/features/base/net-info/constants.js 查看文件

1
+/**
2
+ * The name for Redux store key used by the 'base/net-info' feature.
3
+ *
4
+ * @type {string}
5
+ */
6
+export const STORE_NAME = 'features/base/net-info';

+ 1
- 0
react/features/base/net-info/events.js 查看文件

1
+export const ONLINE_STATE_CHANGED_EVENT = 'network-info-online-status-change';

+ 4
- 0
react/features/base/net-info/index.js 查看文件

1
+export * from './actionTypes';
2
+
3
+import './middleware';
4
+import './reducer';

+ 5
- 0
react/features/base/net-info/logger.js 查看文件

1
+// @flow
2
+
3
+import { getLogger } from '../logging/functions';
4
+
5
+export default getLogger('features/base/net-info');

+ 64
- 0
react/features/base/net-info/middleware.js 查看文件

1
+// @flow
2
+
3
+import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../app';
4
+import { MiddlewareRegistry } from '../redux';
5
+
6
+import { _storeNetworkInfoCleanup, setNetworkInfo } from './actions';
7
+import { STORE_NAME } from './constants';
8
+import { ONLINE_STATE_CHANGED_EVENT } from './events';
9
+import logger from './logger';
10
+import NetworkInfoService from './NetworkInfoService';
11
+import type { NetworkInfo } from './types';
12
+
13
+/**
14
+ * Middleware for 'base/net-info' feature.
15
+ *
16
+ * @param {Store} store - The redux store.
17
+ * @returns {Function}
18
+ */
19
+// eslint-disable-next-line no-unused-vars
20
+MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
21
+    const result = next(action);
22
+
23
+    switch (action.type) {
24
+    case APP_WILL_MOUNT:
25
+        if (NetworkInfoService.isSupported()) {
26
+            const networkInfoService = new NetworkInfoService();
27
+            const stop = () => {
28
+                networkInfoService.stop();
29
+                networkInfoService.removeAllListeners();
30
+            };
31
+
32
+            networkInfoService.addListener(
33
+                ONLINE_STATE_CHANGED_EVENT,
34
+                ({ isOnline, networkType, details }: NetworkInfo) => {
35
+                    logger.info('Network changed', JSON.stringify({
36
+                        isOnline,
37
+                        details,
38
+                        networkType
39
+                    }));
40
+                    dispatch(setNetworkInfo({
41
+                        isOnline,
42
+                        networkType,
43
+                        details
44
+                    }));
45
+                });
46
+
47
+            dispatch(_storeNetworkInfoCleanup(stop));
48
+
49
+            networkInfoService.start();
50
+        }
51
+        break;
52
+    case APP_WILL_UNMOUNT: {
53
+        const { _cleanup } = getState()[STORE_NAME];
54
+
55
+        if (_cleanup) {
56
+            _cleanup();
57
+            dispatch(_storeNetworkInfoCleanup(undefined));
58
+        }
59
+    }
60
+        break;
61
+    }
62
+
63
+    return result;
64
+});

+ 30
- 0
react/features/base/net-info/reducer.js 查看文件

1
+// @flow
2
+import { assign, ReducerRegistry } from '../redux';
3
+
4
+import { SET_NETWORK_INFO, _STORE_NETWORK_INFO_CLEANUP } from './actionTypes';
5
+import { STORE_NAME } from './constants';
6
+
7
+const DEFAULT_STATE = {
8
+    isOnline: true
9
+};
10
+
11
+/**
12
+ * The base/net-info feature's reducer.
13
+ */
14
+ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
15
+    switch (action.type) {
16
+    case SET_NETWORK_INFO:
17
+        return assign(state, {
18
+            isOnline: action.isOnline,
19
+            networkType: action.networkType,
20
+            cellularGeneration: action.cellularGeneration,
21
+            details: action.details
22
+        });
23
+    case _STORE_NETWORK_INFO_CLEANUP:
24
+        return assign(state, {
25
+            _cleanup: action.cleanup
26
+        });
27
+    default:
28
+        return state;
29
+    }
30
+});

+ 39
- 0
react/features/base/net-info/types.js 查看文件

1
+// @flow
2
+
3
+import { NetInfoCellularGeneration, NetInfoStateType } from '@react-native-community/netinfo';
4
+
5
+/**
6
+ * Describes the structure which is used by jitsi-meet to store information about the current network type and
7
+ * conditions.
8
+ */
9
+export type NetworkInfo = {
10
+
11
+    /**
12
+     * Tells whether or not the internet is reachable.
13
+     */
14
+    isOnline: boolean,
15
+
16
+    /**
17
+     * The network type. Currently reported only on Android/iOS. Can be one of the constants defined by
18
+     * the 'react-native-netinfo' library.
19
+     */
20
+    networkType: ?NetInfoStateType,
21
+
22
+    /**
23
+     * Any extra info provided by the OS. Should be JSON and is OS specific. Reported only by iOS and Android and
24
+     * the format is whatever comes out of the 'react-native-netinfo' library which is network type dependent.
25
+     */
26
+    details: ?{
27
+
28
+        /**
29
+         * If {@link networkType} is {@link NetInfoStateType.cellular} then it may provide the info about the type of
30
+         * cellular network.
31
+         */
32
+        cellularGeneration: ?NetInfoCellularGeneration;
33
+
34
+        /**
35
+         * Indicates whether or not the connection is expensive.
36
+         */
37
+        isConnectionExpensive: ?boolean;
38
+    }
39
+}

Loading…
取消
儲存