Преглед на файлове

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,6 +56,7 @@ dependencies {
56 56
     implementation project(':react-native-background-timer')
57 57
     implementation project(':react-native-calendar-events')
58 58
     implementation project(':react-native-community-async-storage')
59
+    implementation project(':react-native-community_netinfo')
59 60
     implementation project(':react-native-immersive')
60 61
     implementation project(':react-native-keep-awake')
61 62
     implementation project(':react-native-linear-gradient')

+ 1
- 0
android/sdk/src/main/java/org/jitsi/meet/sdk/ReactInstanceManagerHolder.java Целия файл

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

+ 2
- 0
android/settings.gradle Целия файл

@@ -7,6 +7,8 @@ include ':react-native-calendar-events'
7 7
 project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
8 8
 include ':react-native-community-async-storage'
9 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 12
 include ':react-native-google-signin'
11 13
 project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-google-signin/android')
12 14
 include ':react-native-immersive'

+ 1
- 0
ios/Podfile Целия файл

@@ -47,6 +47,7 @@ target 'JitsiMeet' do
47 47
   pod 'react-native-background-timer', :path => '../node_modules/react-native-background-timer'
48 48
   pod 'react-native-calendar-events', :path => '../node_modules/react-native-calendar-events'
49 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 51
   pod 'react-native-webview', :path => '../node_modules/react-native-webview'
51 52
   pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
52 53
   pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'

+ 7
- 1
ios/Podfile.lock Целия файл

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

+ 5
- 0
package-lock.json Целия файл

@@ -3055,6 +3055,11 @@
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 3063
     "@segment/top-domain": {
3059 3064
       "version": "3.0.0",
3060 3065
       "resolved": "https://registry.npmjs.org/@segment/top-domain/-/top-domain-3.0.0.tgz",

+ 1
- 0
package.json Целия файл

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

+ 21
- 0
react/features/analytics/AnalyticsEvents.js Целия файл

@@ -271,6 +271,27 @@ export function createInviteDialogEvent(
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 296
  * Creates an "offer/answer failure" event.
276 297
  *

+ 10
- 1
react/features/analytics/middleware.js Целия файл

@@ -6,6 +6,7 @@ import {
6 6
     SET_ROOM
7 7
 } from '../base/conference';
8 8
 import { SET_CONFIG } from '../base/config';
9
+import { SET_NETWORK_INFO } from '../base/net-info';
9 10
 import { MiddlewareRegistry } from '../base/redux';
10 11
 import {
11 12
     getLocalAudioTrack,
@@ -16,7 +17,7 @@ import {
16 17
 } from '../base/tracks';
17 18
 
18 19
 import { UPDATE_LOCAL_TRACKS_DURATION } from './actionTypes';
19
-import { createLocalTracksDurationEvent } from './AnalyticsEvents';
20
+import { createLocalTracksDurationEvent, createNetworkInfoEvent } from './AnalyticsEvents';
20 21
 import { initAnalytics, resetAnalytics, sendAnalytics } from './functions';
21 22
 
22 23
 /**
@@ -127,6 +128,14 @@ MiddlewareRegistry.register(store => next => action => {
127 128
         });
128 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 139
     case SET_ROOM: {
131 140
         initAnalytics(store);
132 141
         break;

+ 66
- 0
react/features/base/net-info/NetworkInfoService.native.js Целия файл

@@ -0,0 +1,66 @@
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 Целия файл

@@ -0,0 +1,58 @@
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 Целия файл

@@ -0,0 +1,13 @@
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 Целия файл

@@ -0,0 +1,42 @@
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 Целия файл

@@ -0,0 +1,6 @@
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 Целия файл

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

+ 4
- 0
react/features/base/net-info/index.js Целия файл

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

+ 5
- 0
react/features/base/net-info/logger.js Целия файл

@@ -0,0 +1,5 @@
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 Целия файл

@@ -0,0 +1,64 @@
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 Целия файл

@@ -0,0 +1,30 @@
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 Целия файл

@@ -0,0 +1,39 @@
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…
Отказ
Запис