feat(analytics) unify Amplitude handlers across web and mobile

The amplitude-js library gained React Native support so there is no need to keep
separate implementations.
This commit is contained in:
Saúl Ibarra Corretgé 2020-12-10 14:53:55 +01:00 committed by Saúl Ibarra Corretgé
parent 5ecb5717c7
commit 687a6c31ee
16 changed files with 126 additions and 396 deletions

View File

@ -25,10 +25,6 @@ android {
sourceSets {
main {
java {
if (rootProject.ext.libreBuild) {
srcDir "src"
exclude "**/AmplitudeModule.java"
}
exclude "test/"
}
}
@ -52,18 +48,18 @@ dependencies {
implementation 'com.squareup.duktape:duktape-android:1.3.0'
if (!rootProject.ext.libreBuild) {
implementation 'com.amplitude:android-sdk:2.14.1'
implementation(project(":react-native-google-signin")) {
exclude group: 'com.google.android.gms'
exclude group: 'androidx'
}
}
implementation project(':react-native-async-storage')
implementation project(':react-native-background-timer')
implementation project(':react-native-calendar-events')
implementation project(':react-native-community-async-storage')
implementation project(':react-native-community_netinfo')
implementation project(':react-native-default-preference')
implementation project(':react-native-device-info')
implementation project(':react-native-immersive')
implementation project(':react-native-keep-awake')
implementation project(':react-native-linear-gradient')

View File

@ -1,122 +0,0 @@
/*
* Copyright @ 2019-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jitsi.meet.sdk;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.SharedPreferences;
import android.provider.Settings;
import android.text.TextUtils;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.amplitude.api.Amplitude;
import com.facebook.react.module.annotations.ReactModule;
import org.jitsi.meet.sdk.log.JitsiMeetLogger;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Implements the react-native module for the Amplitude integration.
*/
@ReactModule(name = AmplitudeModule.NAME)
class AmplitudeModule
extends ReactContextBaseJavaModule {
public static final String NAME = "Amplitude";
public static final String JITSI_PREFERENCES = "jitsi-preferences";
public static final String AMPLITUDE_DEVICE_ID_KEY = "amplitudeDeviceId";
public AmplitudeModule(ReactApplicationContext reactContext) {
super(reactContext);
}
/**
* Initializes the Amplitude SDK.
*
* @param instanceName The name of the Amplitude instance. Should
* be used only for multi-project logging.
* @param apiKey The API_KEY of the Amplitude project.
*/
@ReactMethod
@SuppressLint("HardwareIds")
public void init(String instanceName, String apiKey) {
Amplitude.getInstance(instanceName).initialize(getCurrentActivity(), apiKey);
// Set the device ID to something consistent.
SharedPreferences sharedPreferences = getReactApplicationContext().getSharedPreferences(JITSI_PREFERENCES, Context.MODE_PRIVATE);
String android_id = sharedPreferences.getString(AMPLITUDE_DEVICE_ID_KEY, "");
if (!TextUtils.isEmpty(android_id)) {
Amplitude.getInstance(instanceName).setDeviceId(android_id);
} else {
String amplitudeId = Amplitude.getInstance(instanceName).getDeviceId();
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString(JITSI_PREFERENCES, amplitudeId).apply();
}
}
/**
* Sets the user ID for an Amplitude instance.
*
* @param instanceName The name of the Amplitude instance.
* @param userId The new value for the user ID.
*/
@ReactMethod
public void setUserId(String instanceName, String userId) {
Amplitude.getInstance(instanceName).setUserId(userId);
}
/**
* Sets the user properties for an Amplitude instance.
*
* @param instanceName The name of the Amplitude instance.
* @param userProps JSON string with user properties to be set.
*/
@ReactMethod
public void setUserProperties(String instanceName, ReadableMap userProps) {
if (userProps != null) {
Amplitude.getInstance(instanceName).setUserProperties(
new JSONObject(userProps.toHashMap()));
}
}
/**
* Log an analytics event.
*
* @param instanceName The name of the Amplitude instance.
* @param eventType The event type.
* @param eventPropsString JSON string with the event properties.
*/
@ReactMethod
public void logEvent(String instanceName, String eventType, String eventPropsString) {
try {
JSONObject eventProps = new JSONObject(eventPropsString);
Amplitude.getInstance(instanceName).logEvent(eventType, eventProps);
} catch (JSONException e) {
JitsiMeetLogger.e(e, "Error logging event");
}
}
@Override
public String getName() {
return NAME;
}
}

View File

@ -91,14 +91,6 @@ class ReactInstanceManagerHolder {
nativeModules.add(new WebRTCModule(reactContext, options));
try {
Class<?> amplitudeModuleClass = Class.forName("org.jitsi.meet.sdk.AmplitudeModule");
Constructor constructor = amplitudeModuleClass.getConstructor(ReactApplicationContext.class);
nativeModules.add((NativeModule)constructor.newInstance(reactContext));
} catch (Exception e) {
// Ignore any error, the module is not compiled when LIBRE_BUILD is enabled.
}
return nativeModules;
}
@ -192,6 +184,7 @@ class ReactInstanceManagerHolder {
new com.facebook.react.shell.MainReactPackage(),
new com.horcrux.svg.SvgPackage(),
new com.kevinresol.react_native_default_preference.RNDefaultPreferencePackage(),
new com.learnium.RNDeviceInfo.RNDeviceInfo(),
new com.ocetnik.timer.BackgroundTimerPackage(),
new com.reactnativecommunity.asyncstorage.AsyncStoragePackage(),
new com.reactnativecommunity.netinfo.NetInfoPackage(),

View File

@ -1,16 +1,18 @@
rootProject.name = 'jitsi-meet'
include ':app', ':sdk'
include ':react-native-async-storage'
project(':react-native-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-async-storage/async-storage/android')
include ':react-native-background-timer'
project(':react-native-background-timer').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-background-timer/android')
include ':react-native-calendar-events'
project(':react-native-calendar-events').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-calendar-events/android')
include ':react-native-community-async-storage'
project(':react-native-community-async-storage').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/async-storage/android')
include ':react-native-community_netinfo'
project(':react-native-community_netinfo').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/netinfo/android')
include ':react-native-default-preference'
project(':react-native-default-preference').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-default-preference/android')
include ':react-native-device-info'
project(':react-native-device-info').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-device-info/android')
include ':react-native-google-signin'
project(':react-native-google-signin').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/google-signin/android')
include ':react-native-immersive'

View File

@ -58,21 +58,21 @@ target 'JitsiMeetSDK' do
pod 'react-native-calendar-events', :path => '../node_modules/react-native-calendar-events'
pod 'react-native-keep-awake', :path => '../node_modules/react-native-keep-awake'
pod 'react-native-netinfo', :path => '../node_modules/@react-native-community/netinfo'
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
pod 'react-native-webview', :path => '../node_modules/react-native-webview'
pod 'react-native-webrtc', :path => '../node_modules/react-native-webrtc'
pod 'BVLinearGradient', :path => '../node_modules/react-native-linear-gradient'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-async-storage/async-storage'
pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
pod 'RNGoogleSignin', :path => '../node_modules/@react-native-community/google-signin'
pod 'RNSound', :path => '../node_modules/react-native-sound'
pod 'RNSVG', :path => '../node_modules/react-native-svg'
pod 'RNWatch', :path => '../node_modules/react-native-watch-connectivity'
pod 'RNDefaultPreference', :path => '../node_modules/react-native-default-preference'
pod 'react-native-splash-screen', :path => '../node_modules/react-native-splash-screen'
# Native pod dependencies
#
pod 'Amplitude-iOS', '~> 4.0.4'
pod 'CocoaLumberjack', '~>3.5.3'
pod 'ObjectiveDropboxOfficial', '~> 3.9.4'

View File

@ -1,5 +1,4 @@
PODS:
- Amplitude-iOS (4.0.4)
- AppAuth (1.2.0):
- AppAuth/Core (= 1.2.0)
- AppAuth/ExternalUserAgent (= 1.2.0)
@ -351,10 +350,12 @@ PODS:
- React-jsi (= 0.61.5-jitsi.2)
- ReactCommon/jscallinvoker (= 0.61.5-jitsi.2)
- ReactCommon/turbomodule/core (= 0.61.5-jitsi.2)
- RNCAsyncStorage (1.3.4):
- RNCAsyncStorage (1.13.2):
- React
- RNDefaultPreference (1.4.2):
- React
- RNDeviceInfo (7.3.1):
- React-Core
- RNGoogleSignin (3.0.1):
- GoogleSignIn (~> 5.0.0)
- React
@ -370,7 +371,6 @@ PODS:
- Yoga (1.14.0)
DEPENDENCIES:
- Amplitude-iOS (~> 4.0.4)
- BVLinearGradient (from `../node_modules/react-native-linear-gradient`)
- CocoaLumberjack (~> 3.5.3)
- DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`)
@ -410,8 +410,9 @@ DEPENDENCIES:
- React-RCTText (from `../node_modules/react-native/Libraries/Text`)
- React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`)
- ReactCommon/turbomodule (from `../node_modules/react-native/ReactCommon`)
- "RNCAsyncStorage (from `../node_modules/@react-native-community/async-storage`)"
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
- RNDefaultPreference (from `../node_modules/react-native-default-preference`)
- RNDeviceInfo (from `../node_modules/react-native-device-info`)
- "RNGoogleSignin (from `../node_modules/@react-native-community/google-signin`)"
- RNSound (from `../node_modules/react-native-sound`)
- RNSVG (from `../node_modules/react-native-svg`)
@ -420,7 +421,6 @@ DEPENDENCIES:
SPEC REPOS:
trunk:
- Amplitude-iOS
- AppAuth
- boost-for-react-native
- CocoaLumberjack
@ -507,9 +507,11 @@ EXTERNAL SOURCES:
ReactCommon:
:path: "../node_modules/react-native/ReactCommon"
RNCAsyncStorage:
:path: "../node_modules/@react-native-community/async-storage"
:path: "../node_modules/@react-native-async-storage/async-storage"
RNDefaultPreference:
:path: "../node_modules/react-native-default-preference"
RNDeviceInfo:
:path: "../node_modules/react-native-device-info"
RNGoogleSignin:
:path: "../node_modules/@react-native-community/google-signin"
RNSound:
@ -522,7 +524,6 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS:
Amplitude-iOS: 2ad4d7270c99186236c1272a3a9425463b1ae1a7
AppAuth: bce82c76043657c99d91e7882e8a9e1a93650cd4
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872
@ -574,14 +575,15 @@ SPEC CHECKSUMS:
React-RCTText: 4f1b99f228278d2a5e9008eced8dc9c974c4a270
React-RCTVibration: c1041024893fdfdb8371e7c720c437751b711676
ReactCommon: 18014e1d98dbeb9141e935cfe35fc93bd511ffb6
RNCAsyncStorage: 8e31405a9f12fbf42c2bb330e4560bfd79c18323
RNCAsyncStorage: bc2f81cc1df90c267ce9ed30bb2dbc93b945a8ee
RNDefaultPreference: 56a405ce61033ac77b95004dccd7ac54c2eb50d1
RNDeviceInfo: 57bb2806fb7bd982a1434e9f0b4e6a6ab1f6702e
RNGoogleSignin: 39336070b35fc4cea6a98cf111e00480317be0ae
RNSound: c980916b596cc15c8dcd2f6ecd3b13c4881dbe20
RNSVG: 069864be08c9fe065a2cf7e63656a34c78653c99
RNWatch: a5320c959c75e72845c07985f3e935e58998f1d3
Yoga: 96b469c5e81ff51b917b92e8c3390642d4ded30c
PODFILE CHECKSUM: e77f7134cda53f089046f29cb1f32b08c00c8a2e
PODFILE CHECKSUM: 5be5132e41831a98362eeed760558227a4df89ae
COCOAPODS: 1.10.0

View File

@ -31,7 +31,6 @@
75635B0B20751D6D00F29C9F /* left.wav in Resources */ = {isa = PBXBuildFile; fileRef = 75635B0920751D6D00F29C9F /* left.wav */; };
87FE6F3321E52437004A5DC7 /* incomingMessage.wav in Resources */ = {isa = PBXBuildFile; fileRef = 87FE6F3221E52437004A5DC7 /* incomingMessage.wav */; };
A4414AE020B37F1A003546E6 /* rejected.wav in Resources */ = {isa = PBXBuildFile; fileRef = A4414ADF20B37F1A003546E6 /* rejected.wav */; };
A480429C21EE335600289B73 /* AmplitudeModule.m in Sources */ = {isa = PBXBuildFile; fileRef = A480429B21EE335600289B73 /* AmplitudeModule.m */; };
A4A934E9212F3ADB001E9388 /* Dropbox.m in Sources */ = {isa = PBXBuildFile; fileRef = A4A934E8212F3ADB001E9388 /* Dropbox.m */; };
C30F88D0CB0F4F5593216D24 /* liveStreamingOff.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */; };
C30F88D2CB0F4F5593216D24 /* liveStreamingOn.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = C30F88D3CB0F4F5593216D24 /* liveStreamingOn.mp3 */; };
@ -94,7 +93,6 @@
98E09B5C73D9036B4ED252FC /* Pods-JitsiMeet.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.debug.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.debug.xcconfig"; sourceTree = "<group>"; };
9C77CA3CC919B081F1A52982 /* Pods-JitsiMeet.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-JitsiMeet.release.xcconfig"; path = "../Pods/Target Support Files/Pods-JitsiMeet/Pods-JitsiMeet.release.xcconfig"; sourceTree = "<group>"; };
A4414ADF20B37F1A003546E6 /* rejected.wav */ = {isa = PBXFileReference; lastKnownFileType = audio.wav; name = rejected.wav; path = ../../sounds/rejected.wav; sourceTree = "<group>"; };
A480429B21EE335600289B73 /* AmplitudeModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AmplitudeModule.m; path = src/analytics/AmplitudeModule.m; sourceTree = SOURCE_ROOT; };
A4A934E8212F3ADB001E9388 /* Dropbox.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = Dropbox.m; sourceTree = "<group>"; };
A4A934EB21349A06001E9388 /* Dropbox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Dropbox.h; sourceTree = "<group>"; };
C30F88D1CB0F4F5593216D24 /* liveStreamingOff.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; name = liveStreamingOff.mp3; path = ../../sounds/liveStreamingOff.mp3; sourceTree = "<group>"; };
@ -190,7 +188,6 @@
0BD906E71EC0C00300C8C18E /* src */ = {
isa = PBXGroup;
children = (
A480429821ECE2D800289B73 /* analytics */,
0BB9AD7C1F60356D001C08DB /* AppInfo.m */,
0BCA495C1EC4B6C600B793EE /* AudioMode.m */,
C69EFA02209A0EFD0027712B /* callkit */,
@ -246,15 +243,6 @@
name = Frameworks;
sourceTree = "<group>";
};
A480429821ECE2D800289B73 /* analytics */ = {
isa = PBXGroup;
children = (
A480429B21EE335600289B73 /* AmplitudeModule.m */,
);
name = analytics;
path = "New Group";
sourceTree = "<group>";
};
A4A934E7212F3AB8001E9388 /* dropbox */ = {
isa = PBXGroup;
children = (
@ -438,18 +426,10 @@
);
inputPaths = (
"${PODS_ROOT}/Target Support Files/Pods-JitsiMeetSDK/Pods-JitsiMeetSDK-resources.sh",
"${PODS_ROOT}/Amplitude-iOS/Amplitude/api.amplitude.com.der",
"${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoCaLimitedRsaCertificationAuthority.der",
"${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoRsaCA.der",
"${PODS_ROOT}/Amplitude-iOS/Amplitude/ComodoRsaDomainValidationCA.der",
"${PODS_ROOT}/GoogleSignIn/Resources/GoogleSignIn.bundle",
);
name = "[CP] Copy Pods Resources";
outputPaths = (
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/api.amplitude.com.der",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoCaLimitedRsaCertificationAuthority.der",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaCA.der",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/ComodoRsaDomainValidationCA.der",
"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/GoogleSignIn.bundle",
);
runOnlyForDeploymentPostprocessing = 0;
@ -479,7 +459,6 @@
DEFC743F21B178FA00E4DD96 /* LocaleDetector.m in Sources */,
0BCA495F1EC4B6C600B793EE /* AudioMode.m in Sources */,
0BCA49611EC4B6C600B793EE /* Proximity.m in Sources */,
A480429C21EE335600289B73 /* AmplitudeModule.m in Sources */,
C69EFA0C209A0F660027712B /* JMCallKitEmitter.swift in Sources */,
DEFE535621FB2E8300011A3A /* ReactUtils.m in Sources */,
C6A34261204EF76800E062DD /* DragGestureController.swift in Sources */,

View File

@ -1,61 +0,0 @@
/*
* Copyright @ 2018-present 8x8, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#import <React/RCTBridgeModule.h>
#import "Amplitude.h"
#import "LogUtils.h"
@interface AmplitudeModule : NSObject<RCTBridgeModule>
@end
@implementation AmplitudeModule
RCT_EXPORT_MODULE(Amplitude)
+ (BOOL)requiresMainQueueSetup {
return NO;
}
RCT_EXPORT_METHOD(init:(NSString*)instanceName API_KEY:(NSString*)apiKey) {
[[Amplitude instanceWithName:instanceName] initializeApiKey:apiKey];
}
RCT_EXPORT_METHOD(setUserId:(NSString*)instanceName userId: (NSString *) userId) {
[[Amplitude instanceWithName:instanceName] setUserId:userId];
}
RCT_EXPORT_METHOD(setUserProperties:(NSString*)instanceName userPropsString:(NSDictionary*)userProps) {
if (userProps != nil) {
[[Amplitude instanceWithName:instanceName] setUserProperties:userProps];
}
}
RCT_EXPORT_METHOD(logEvent:(NSString*)instanceName eventType:(NSString*)eventType eventPropsString:(NSString*)eventPropsString) {
NSError *error;
NSData *eventPropsData = [eventPropsString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *eventProperties = [NSJSONSerialization JSONObjectWithData:eventPropsData
options:NSJSONReadingMutableContainers
error:&error];
if (eventProperties == nil) {
DDLogError(@"[Amplitude] Error parsing event properties: %@", error);
} else {
[[Amplitude instanceWithName:instanceName] logEvent:eventType withEventProperties:eventProperties];
}
}
@end

59
package-lock.json generated
View File

@ -4,11 +4,34 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@amplitude/eslint-config-typescript": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@amplitude/eslint-config-typescript/-/eslint-config-typescript-1.1.0.tgz",
"integrity": "sha512-N8sKkwtFakPD2/cSOrBnM5Wudjp4qeDD69U1cG7dZ6DDczxBhUEqnJDJ0wiYmKMPXqr+bmFOsDdbCcOmb/CLYA=="
},
"@amplitude/types": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@amplitude/types/-/types-1.1.0.tgz",
"integrity": "sha512-aJebJlI1hfRrzsbcRzW1heTDEClhElwEJ4ODyYZbBacKzH29q3OKZCkgNfaEYdxfgLpoDSh/ffHYpl7fWm3SQA==",
"requires": {
"@amplitude/eslint-config-typescript": "^1.1.0"
}
},
"@amplitude/ua-parser-js": {
"version": "0.7.24",
"resolved": "https://registry.npmjs.org/@amplitude/ua-parser-js/-/ua-parser-js-0.7.24.tgz",
"integrity": "sha512-VbQuJymJ20WEw0HtI2np7EdC3NJGUWi8+Xdbc7uk8WfMIF308T0howpzkQ3JFMN7ejnrcSM/OyNGveeE3TP3TA=="
},
"@amplitude/utils": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@amplitude/utils/-/utils-1.1.0.tgz",
"integrity": "sha512-TbKgBZNSRFu5RfYTKpprn/DFlZqr8jnmjXASZyQ/m8XDdbD2VoRqHDmKUwFiruX9OhAb2m9BhjLuaiwRYHCcqQ==",
"requires": {
"@amplitude/eslint-config-typescript": "^1.1.0",
"@amplitude/types": "^1.1.0",
"tslib": "^1.9.3"
}
},
"@atlaskit/analytics-next": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/@atlaskit/analytics-next/-/analytics-next-3.2.1.tgz",
@ -3343,10 +3366,13 @@
"isomorphic-fetch": "^2.2.1"
}
},
"@react-native-community/async-storage": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@react-native-community/async-storage/-/async-storage-1.3.4.tgz",
"integrity": "sha512-fJmzL27x0BEjhmMXPnDPnUNCZK7bph+NBVCfAz9fzHzAamaiOkdUwuL3PvE4Oj4Kw4knP8ocw5VRDGorAidZ2g=="
"@react-native-async-storage/async-storage": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@react-native-async-storage/async-storage/-/async-storage-1.13.2.tgz",
"integrity": "sha512-isTDvUApRJPVWFxV15yrQSOGqarX7cIedq/y4N5yWSnotf68D9qvDEv1I7rCXhkBDi0u4OJt6GA9dksUT0D3wg==",
"requires": {
"deep-assign": "^3.0.0"
}
},
"@react-native-community/cli-debugger-ui": {
"version": "3.0.0",
@ -4922,11 +4948,12 @@
"dev": true
},
"amplitude-js": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/amplitude-js/-/amplitude-js-7.3.1.tgz",
"integrity": "sha512-dsJU9MdtDDAOtKnbHrJuVBgsL5UGxD1P2B7doGdAQ1hxxT/5mFrmJTFzi1tKe+2ir3QtcRa9B0qvH8TMsGw22A==",
"version": "7.3.3",
"resolved": "https://registry.npmjs.org/amplitude-js/-/amplitude-js-7.3.3.tgz",
"integrity": "sha512-krSXUXeHqbQk15ozx0kC3h0K3i7wQ1ycSG08OfZBga2Vfbi3Y30CP6UXLdtJX4AiBB8EkjMePdMgU6kyuIpi/A==",
"requires": {
"@amplitude/ua-parser-js": "0.7.24",
"@amplitude/utils": "^1.0.5",
"blueimp-md5": "^2.10.0",
"query-string": "5"
}
@ -7246,6 +7273,14 @@
"resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz",
"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU="
},
"deep-assign": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/deep-assign/-/deep-assign-3.0.0.tgz",
"integrity": "sha512-YX2i9XjJ7h5q/aQ/IM9PEwEnDqETAIYbggmdDB3HLTlSgo1CxPsj6pvhPG68rq6SVE0+p+6Ywsm5fTYNrYtBWw==",
"requires": {
"is-obj": "^1.0.0"
}
},
"deep-equal": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
@ -10245,6 +10280,11 @@
"kind-of": "^3.0.2"
}
},
"is-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8="
},
"is-path-cwd": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz",
@ -14158,6 +14198,11 @@
"resolved": "https://registry.npmjs.org/react-native-default-preference/-/react-native-default-preference-1.4.2.tgz",
"integrity": "sha512-kNhBLv8s6kO2gJJFEKM7qew7oRvJnygjgG1CU2ZEY6SlG5qsRX8z1Ms7z1Oo/XB7fVfyXrAoZDGhIvy+uiByrg=="
},
"react-native-device-info": {
"version": "7.3.1",
"resolved": "https://registry.npmjs.org/react-native-device-info/-/react-native-device-info-7.3.1.tgz",
"integrity": "sha512-RQP3etbmXsOlcaxHeHNug68nRli02S9iGC7TbaXpkvyyevIuRogfnrI71sWtqmlT91kdpYAOYKmNfRL9LOSKVw=="
},
"react-native-immersive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/react-native-immersive/-/react-native-immersive-2.0.0.tgz",

View File

@ -34,13 +34,13 @@
"@atlaskit/tooltip": "12.1.13",
"@jitsi/js-utils": "1.0.3",
"@microsoft/microsoft-graph-client": "1.1.0",
"@react-native-community/async-storage": "1.3.4",
"@react-native-async-storage/async-storage": "1.13.2",
"@react-native-community/google-signin": "3.0.1",
"@react-native-community/netinfo": "4.1.5",
"@svgr/webpack": "4.3.2",
"@tensorflow-models/body-pix": "2.0.4",
"@tensorflow/tfjs": "1.5.1",
"amplitude-js": "7.3.1",
"amplitude-js": "7.3.3",
"base64-js": "1.3.1",
"bc-css-flags": "3.0.0",
"dropbox": "4.0.9",
@ -75,6 +75,7 @@
"react-native-callstats": "3.61.0",
"react-native-collapsible": "1.5.1",
"react-native-default-preference": "1.4.2",
"react-native-device-info": "7.3.1",
"react-native-immersive": "2.0.0",
"react-native-keep-awake": "4.0.0",
"react-native-linear-gradient": "2.5.6",

View File

@ -1,5 +1,9 @@
import amplitude from 'amplitude-js';
import logger from '../logger';
import AbstractHandler from './AbstractHandler';
import { amplitude, fixDeviceID } from './amplitude';
import { fixDeviceID } from './amplitude';
/**
* Analytics handler for Amplitude.
@ -17,24 +21,39 @@ export default class AmplitudeHandler extends AbstractHandler {
const { amplitudeAPPKey, host, user } = options;
if (!amplitudeAPPKey) {
throw new Error('Failed to initialize Amplitude handler, no APP key');
}
this._enabled = true;
this._host = host; // Only used on React Native.
this._amplitudeOptions = {
host
const onError = e => {
logger.error('Error initializing Amplitude', e);
this._enabled = false;
};
amplitude.getInstance(this._amplitudeOptions).init(amplitudeAPPKey, undefined, { includeReferrer: true });
fixDeviceID(amplitude.getInstance(this._amplitudeOptions));
const amplitudeOptions = {
domain: navigator.product === 'ReactNative' ? host : undefined,
includeReferrer: true,
onError
};
this._getInstance().init(amplitudeAPPKey, undefined, amplitudeOptions);
fixDeviceID(this._getInstance());
if (user) {
amplitude.getInstance(this._amplitudeOptions).setUserId(user);
this._getInstance().setUserId(user);
}
}
/**
* Returns the AmplitudeClient instance.
*
* @returns {AmplitudeClient}
*/
_getInstance() {
const name = navigator.product === 'ReactNative' ? this._host : undefined;
return amplitude.getInstance(name);
}
/**
* Sets the Amplitude user properties.
*
@ -43,8 +62,7 @@ export default class AmplitudeHandler extends AbstractHandler {
*/
setUserProperties(userProps) {
if (this._enabled) {
amplitude.getInstance(this._amplitudeOptions)
.setUserProperties(userProps);
this._getInstance().setUserProperties(userProps);
}
}
@ -61,9 +79,7 @@ export default class AmplitudeHandler extends AbstractHandler {
return;
}
amplitude.getInstance(this._amplitudeOptions).logEvent(
this._extractName(event),
event);
this._getInstance().logEvent(this._extractName(event), event);
}
/**
@ -72,15 +88,10 @@ export default class AmplitudeHandler extends AbstractHandler {
* @returns {Object}
*/
getIdentityProps() {
// TODO: Remove when web and native Aplitude implementations are unified.
if (navigator.product === 'ReactNative') {
return {};
}
return {
sessionId: amplitude.getInstance(this._amplitudeOptions).getSessionId(),
deviceId: amplitude.getInstance(this._amplitudeOptions).options.deviceId,
userId: amplitude.getInstance(this._amplitudeOptions).options.userId
sessionId: this._getInstance().getSessionId(),
deviceId: this._getInstance().options.deviceId,
userId: this._getInstance().options.userId
};
}
}

View File

@ -1,115 +0,0 @@
import { NativeModules } from 'react-native';
const { Amplitude: AmplitudeNative } = NativeModules;
/**
* Wrapper for the Amplitude native module.
*/
class Amplitude {
/**
* Create new Amplitude instance.
*
* @param {string} instanceName - The name of the Amplitude instance. Should
* be used only for multi-project logging.
*/
constructor(instanceName) {
// It might not have been included in the build.
if (!AmplitudeNative) {
throw new Error('Amplitude analytics is not supported');
}
this._instanceName = instanceName;
}
/**
* Initializes the Amplitude SDK.
*
* @param {string} apiKey - The API_KEY of the Amplitude project.
* @returns {void}
*/
init(apiKey) {
AmplitudeNative.init(this._instanceName, apiKey);
}
/**
* Sets an identifier for the current user.
*
* @param {string} userId - The new user id.
* @param {string} opt_userId - Currently not used.
* @param {Object} opt_config - Currently not used.
* @param {Function} opt_callback - Currently not used.
* @returns {void}
*/
setUserId(userId, opt_userId, opt_config, opt_callback) { // eslint-disable-line camelcase, no-unused-vars
AmplitudeNative.setUserId(this._instanceName, userId);
}
/**
* Sets user properties for the current user.
*
* @param {Object} userProperties - The user properties to be set.
* @returns {void}
*/
setUserProperties(userProperties) {
AmplitudeNative.setUserProperties(this._instanceName, userProperties);
}
/**
* Log an event with eventType and eventProperties.
*
* @param {string} eventType - The type of the event.
* @param {Object} eventProperties - The properties of the event.
* @returns {void}
*/
logEvent(eventType, eventProperties) {
// The event properties are converted to JSON string because of known
// performance issue when passing objects trough the RN bridge too
// often (a few times a second).
AmplitudeNative.logEvent(
this._instanceName, eventType, JSON.stringify(eventProperties));
}
}
/**
* Cache of <tt>Amplitude</tt> instances by instanceName.
*/
const instances = {};
/**
* The default (with instanceName - undefined) <tt>Amplitude</tt> instance.
*/
let defaultInstance;
export default {
/**
* Returns a <tt>Amplitude</tt> instance.
*
* @param {Object} options - Optional parameters.
* @param {string} options.host - The host property from the current URL.
* @param {string|undefined} options.instanceName - The name of the
* amplitude instance. Should be used only for multi-project logging.
* @returns {Amplitude}
*/
getInstance(options = {}) {
let instance;
const { host = '', instanceName = '' } = options;
let internalInstanceName = host;
if (instanceName !== '') {
internalInstanceName += `-${instanceName}`;
}
if (internalInstanceName === '') {
instance = defaultInstance = defaultInstance || new Amplitude();
} else {
instance = instances[internalInstanceName]
= instances[internalInstanceName]
|| new Amplitude(internalInstanceName);
}
return instance;
}
};

View File

@ -1,14 +0,0 @@
import amplitude from 'amplitude-js';
export default {
/**
* Returns the AmplitudeClient instance.
*
* @param {Object} options - Optional parameters.
* @property {string} options.instanceName - The name of the AmplitudeClient instance.
* @returns {AmplitudeClient}
*/
getInstance(options = {}) {
return amplitude.getInstance(options.instanceName);
}
};

View File

@ -1,9 +1,23 @@
import DefaultPreference from 'react-native-default-preference';
import DeviceInfo from 'react-native-device-info';
/**
* Custom logic for setting the correct device id.
*
* @param {AmplitudeClient} amplitude - The amplitude instance.
* @returns {void}
*/
export function fixDeviceID(amplitude) { // eslint-disable-line no-unused-vars
export async function fixDeviceID(amplitude) {
await DefaultPreference.setName('jitsi-preferences');
const current = await DefaultPreference.get('amplitudeDeviceId');
if (current) {
amplitude.setDeviceId(current);
} else {
const uid = DeviceInfo.getUniqueId();
amplitude.setDeviceId(uid);
DefaultPreference.set('amplitudeDeviceId', uid);
}
}

View File

@ -1,2 +1 @@
export { default as amplitude } from './Amplitude';
export * from './fixDeviceID';

View File

@ -1,4 +1,4 @@
import AsyncStorage from '@react-native-community/async-storage';
import AsyncStorage from '@react-native-async-storage/async-storage';
/**
* A Web Sorage API implementation used for polyfilling