@truewatchtech/react-native-mobile 0.3.15 → 0.4.1

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.
Files changed (113) hide show
  1. package/FTMobileReactNativeSDK.podspec +32 -2
  2. package/android/build.gradle +10 -4
  3. package/android/src/main/java/com/ft/sdk/reactnative/FTMobileImpl.java +434 -5
  4. package/android/src/main/java/com/ft/sdk/reactnative/FTRUMImpl.java +12 -0
  5. package/android/src/main/java/com/ft/sdk/reactnative/FTTraceImpl.java +1 -1
  6. package/android/src/newarch/java/com/ft/sdk/reactnative/FTLogModule.java +7 -14
  7. package/android/src/newarch/java/com/ft/sdk/reactnative/FTMobileModule.java +46 -12
  8. package/android/src/newarch/java/com/ft/sdk/reactnative/FTRUMModule.java +12 -13
  9. package/android/src/newarch/java/com/ft/sdk/reactnative/FTTraceModule.java +6 -8
  10. package/android/src/oldarch/java/com/ft/sdk/reactnative/FTMobileModule.java +34 -2
  11. package/android/src/rnpost74/java/com/ft/sdk/reactnative/FTMobilePackage.java +14 -4
  12. package/android/src/rnpre74/java/com/ft/sdk/reactnative/FTMobilePackage.java +0 -2
  13. package/ios/FTMobileReactNative.h +9 -5
  14. package/ios/FTMobileReactNative.mm +619 -0
  15. package/ios/FTReactNativeLog.h +8 -3
  16. package/ios/FTReactNativeLog.mm +79 -0
  17. package/ios/FTReactNativeRUM.h +8 -4
  18. package/ios/{FTReactNativeRUM.m → FTReactNativeRUM.mm} +143 -84
  19. package/ios/FTReactNativeTrace.h +7 -3
  20. package/ios/FTReactNativeTrace.mm +74 -0
  21. package/ios/FtMobileAgent.xcodeproj/project.pbxproj +22 -0
  22. package/lib/commonjs/ft_logger.js +14 -13
  23. package/lib/commonjs/ft_logger.js.map +1 -1
  24. package/lib/commonjs/ft_mobile_agent.js +153 -6
  25. package/lib/commonjs/ft_mobile_agent.js.map +1 -1
  26. package/lib/commonjs/ft_rum.js +55 -21
  27. package/lib/commonjs/ft_rum.js.map +1 -1
  28. package/lib/commonjs/ft_tracing.js +29 -10
  29. package/lib/commonjs/ft_tracing.js.map +1 -1
  30. package/lib/commonjs/index.js +30 -0
  31. package/lib/commonjs/index.js.map +1 -1
  32. package/lib/commonjs/rum/FTRumActionTracking.js +10 -4
  33. package/lib/commonjs/rum/FTRumActionTracking.js.map +1 -1
  34. package/lib/commonjs/rum/FTRumErrorTracking.js +4 -4
  35. package/lib/commonjs/rum/FTRumErrorTracking.js.map +1 -1
  36. package/lib/commonjs/specs/NativeFTMobileReactNative.js +10 -0
  37. package/lib/commonjs/specs/NativeFTMobileReactNative.js.map +1 -0
  38. package/lib/commonjs/specs/NativeFTReactNativeLog.js +10 -0
  39. package/lib/commonjs/specs/NativeFTReactNativeLog.js.map +1 -0
  40. package/lib/commonjs/specs/NativeFTReactNativeRUM.js +10 -0
  41. package/lib/commonjs/specs/NativeFTReactNativeRUM.js.map +1 -0
  42. package/lib/commonjs/specs/NativeFTReactNativeTrace.js +10 -0
  43. package/lib/commonjs/specs/NativeFTReactNativeTrace.js.map +1 -0
  44. package/lib/commonjs/version.js +1 -1
  45. package/lib/commonjs/version.js.map +1 -1
  46. package/lib/module/ft_logger.js +14 -12
  47. package/lib/module/ft_logger.js.map +1 -1
  48. package/lib/module/ft_mobile_agent.js +159 -5
  49. package/lib/module/ft_mobile_agent.js.map +1 -1
  50. package/lib/module/ft_rum.js +54 -16
  51. package/lib/module/ft_rum.js.map +1 -1
  52. package/lib/module/ft_tracing.js +29 -9
  53. package/lib/module/ft_tracing.js.map +1 -1
  54. package/lib/module/index.js +3 -3
  55. package/lib/module/index.js.map +1 -1
  56. package/lib/module/rum/FTRumActionTracking.js +10 -4
  57. package/lib/module/rum/FTRumActionTracking.js.map +1 -1
  58. package/lib/module/rum/FTRumErrorTracking.js +4 -4
  59. package/lib/module/rum/FTRumErrorTracking.js.map +1 -1
  60. package/lib/module/specs/NativeFTMobileReactNative.js +5 -0
  61. package/lib/module/specs/NativeFTMobileReactNative.js.map +1 -0
  62. package/lib/module/specs/NativeFTReactNativeLog.js +5 -0
  63. package/lib/module/specs/NativeFTReactNativeLog.js.map +1 -0
  64. package/lib/module/specs/NativeFTReactNativeRUM.js +5 -0
  65. package/lib/module/specs/NativeFTReactNativeRUM.js.map +1 -0
  66. package/lib/module/specs/NativeFTReactNativeTrace.js +5 -0
  67. package/lib/module/specs/NativeFTReactNativeTrace.js.map +1 -0
  68. package/lib/module/version.js +1 -1
  69. package/lib/module/version.js.map +1 -1
  70. package/lib/typescript/ft_logger.d.ts +6 -6
  71. package/lib/typescript/ft_mobile_agent.d.ts +165 -14
  72. package/lib/typescript/ft_rum.d.ts +32 -8
  73. package/lib/typescript/ft_tracing.d.ts +6 -6
  74. package/lib/typescript/index.d.ts +3 -3
  75. package/lib/typescript/specs/NativeFTMobileReactNative.d.ts +75 -0
  76. package/lib/typescript/specs/NativeFTReactNativeLog.d.ts +23 -0
  77. package/lib/typescript/specs/NativeFTReactNativeRUM.d.ts +89 -0
  78. package/lib/typescript/specs/NativeFTReactNativeTrace.d.ts +24 -0
  79. package/lib/typescript/version.d.ts +1 -1
  80. package/package.json +29 -96
  81. package/scripts/replace-react-require.js +37 -38
  82. package/src/ft_logger.tsx +71 -40
  83. package/src/ft_mobile_agent.tsx +374 -92
  84. package/src/ft_rum.tsx +227 -123
  85. package/src/ft_tracing.tsx +58 -38
  86. package/src/index.tsx +58 -16
  87. package/src/rum/FTRumActionTracking.tsx +212 -204
  88. package/src/rum/FTRumErrorTracking.tsx +70 -71
  89. package/src/specs/NativeFTMobileReactNative.ts +83 -0
  90. package/src/specs/NativeFTReactNativeLog.ts +29 -0
  91. package/src/specs/NativeFTReactNativeRUM.ts +104 -0
  92. package/src/specs/NativeFTReactNativeTrace.ts +26 -0
  93. package/src/version.ts +1 -1
  94. package/LICENSE +0 -201
  95. package/android/.project +0 -17
  96. package/android/.settings/org.eclipse.buildship.core.prefs +0 -13
  97. package/android/gradlew +0 -185
  98. package/android/local.properties +0 -8
  99. package/android/src/main/java/com/ft/sdk/InnerClassProxy.java +0 -8
  100. package/ios/.idea/.name +0 -1
  101. package/ios/.idea/ios.iml +0 -2
  102. package/ios/.idea/modules.xml +0 -8
  103. package/ios/.idea/vcs.xml +0 -6
  104. package/ios/.idea/xcode.xml +0 -4
  105. package/ios/FTMobileReactNative.m +0 -183
  106. package/ios/FTReactNativeLog.m +0 -60
  107. package/ios/FTReactNativeTrace.m +0 -58
  108. package/ios/FtMobileAgent.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -4
  109. package/ios/FtMobileAgent.xcodeproj/project.xcworkspace/xcuserdata/Brandon.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  110. package/ios/FtMobileAgent.xcodeproj/project.xcworkspace/xcuserdata/Brandon.xcuserdatad/xcschemes/xcschememanagement.plist +0 -5
  111. package/ios/FtMobileAgent.xcodeproj/xcuserdata/Brandon.xcuserdatad/xcschemes/FtMobileAgent.xcscheme +0 -56
  112. package/ios/FtMobileAgent.xcodeproj/xcuserdata/Brandon.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  113. package/ios/RCTVersion.h +0 -8
@@ -1,6 +1,7 @@
1
1
  require "json"
2
2
 
3
3
  package = JSON.parse(File.read(File.join(__dir__, "package.json")))
4
+ folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
4
5
 
5
6
  Pod::Spec.new do |s|
6
7
  s.name = "FTMobileReactNativeSDK"
@@ -11,12 +12,41 @@ Pod::Spec.new do |s|
11
12
  s.authors = package["author"]
12
13
 
13
14
  s.platforms = { :ios => "10.0" }
14
- s.source = { :git => "https://github.com/TrueWatchTech/datakit-react-native.git", :tag => "#{s.version}" }
15
+ s.source = { :git => "https://github.com/GuanceCloud/datakit-react-native.git", :tag => "#{s.version}" }
15
16
 
16
17
 
17
18
  s.source_files = "ios/**/*.{h,m,mm,swift}"
18
19
 
19
20
 
20
21
  s.dependency "React-Core"
21
- s.dependency 'FTMobileSDK', '1.5.18'
22
+ s.dependency 'FTMobileSDK', '1.6.2'
23
+
24
+ xcconfig = {
25
+ "HEADER_SEARCH_PATHS" => "$(inherited) " +
26
+ "$(PODS_ROOT)/React-RCTFabric/** " +
27
+ "$(PODS_ROOT)/React-FabricComponents/** " +
28
+ "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_RCTFabric.framework/Headers/** " +
29
+ "$(PODS_CONFIGURATION_BUILD_DIR)/React-FabricComponents/React_FabricComponents.framework/Headers/**",
30
+ "USER_HEADER_SEARCH_PATHS" => "$(inherited) " +
31
+ "$(PODS_ROOT)/React-RCTFabric/** " +
32
+ "$(PODS_ROOT)/React-FabricComponents/** " +
33
+ "${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_RCTFabric.framework/Headers/** " +
34
+ "$(PODS_CONFIGURATION_BUILD_DIR)/React-FabricComponents/React_FabricComponents.framework/Headers/**"
35
+ }
36
+
37
+ if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
38
+ s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
39
+
40
+ xcconfig.merge!({
41
+ "DEFINES_MODULE" => "YES",
42
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
43
+ })
44
+ end
45
+
46
+ s.pod_target_xcconfig = xcconfig
47
+
48
+ if respond_to?(:install_modules_dependencies, true)
49
+ install_modules_dependencies(s)
50
+ end
51
+
22
52
  end
@@ -29,8 +29,10 @@ def reactNativeVersion = new groovy.json.JsonSlurper()
29
29
  def (reactNativeMajorVersion, reactNativeMinorVersion) = reactNativeVersion.split("\\.").collect { it.isInteger() ? it.toInteger() : it }
30
30
 
31
31
  def isNewArchitectureEnabled() {
32
- //return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
33
- return false //TODO code not ready, hide this part
32
+ return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
33
+ }
34
+ if (isNewArchitectureEnabled()) {
35
+ apply plugin: 'com.facebook.react'
34
36
  }
35
37
 
36
38
  android {
@@ -54,7 +56,7 @@ android {
54
56
  compileSdkVersion getExtOrIntegerDefault('compileSdkVersion')
55
57
  buildToolsVersion getExtOrDefault('buildToolsVersion')
56
58
  defaultConfig {
57
- minSdkVersion 16
59
+ minSdkVersion 21
58
60
  targetSdkVersion getExtOrIntegerDefault('targetSdkVersion')
59
61
 
60
62
  buildConfigField("boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString())
@@ -177,7 +179,11 @@ repositories {
177
179
  dependencies {
178
180
  // noinspection GradleDynamicVersion
179
181
  implementation 'com.facebook.react:react-native:+'
180
- implementation 'com.truewatch.ft.mobile.sdk.tracker.agent:ft-sdk:1.6.13'
182
+ implementation 'com.truewatch.ft.mobile.sdk.tracker.agent:ft-sdk:1.7.0'
181
183
  implementation 'com.truewatch.ft.mobile.sdk.tracker.agent:ft-native:1.1.2'
184
+
185
+ // implementation files('../example/android/app/libs/ft-sdk-debug.aar')
186
+ // implementation files('../example/android/app/libs/ft-session-replay-debug.aar')
187
+
182
188
  implementation 'com.google.code.gson:gson:2.8.5'
183
189
  }
@@ -2,23 +2,341 @@ package com.ft.sdk.reactnative;
2
2
 
3
3
  import static com.ft.sdk.garble.utils.Constants.FT_LOG_DEFAULT_MEASUREMENT;
4
4
 
5
+ import androidx.annotation.Nullable;
6
+
7
+ import com.facebook.react.bridge.Arguments;
5
8
  import com.facebook.react.bridge.Promise;
9
+ import com.facebook.react.bridge.ReactApplicationContext;
10
+ import com.facebook.react.bridge.ReadableArray;
6
11
  import com.facebook.react.bridge.ReadableMap;
12
+ import com.facebook.react.bridge.ReadableType;
13
+ import com.facebook.react.bridge.WritableArray;
14
+ import com.facebook.react.bridge.WritableMap;
15
+ import com.facebook.react.modules.core.DeviceEventManagerModule;
7
16
  import com.ft.sdk.DBCacheDiscard;
8
17
  import com.ft.sdk.EnvType;
18
+ import com.ft.sdk.FTRemoteConfigManager;
9
19
  import com.ft.sdk.FTSDKConfig;
10
20
  import com.ft.sdk.FTSdk;
11
- import com.ft.sdk.InnerClassProxy;
12
21
  import com.ft.sdk.LineDataModifier;
22
+ import com.ft.sdk.garble.bean.RemoteConfigBean;
13
23
  import com.ft.sdk.garble.bean.UserData;
14
24
  import com.ft.sdk.DataModifier;
15
25
  import com.ft.sdk.reactnative.utils.ReactNativeUtils;
16
26
 
17
27
  import java.util.HashMap;
28
+ import java.util.ArrayList;
29
+ import java.util.List;
18
30
  import java.util.Map;
31
+ import org.json.JSONArray;
32
+ import org.json.JSONException;
33
+ import org.json.JSONObject;
19
34
 
20
35
  public class FTMobileImpl {
21
36
  public static final String NAME = "FTMobileReactNative";
37
+ private static final String REMOTE_CONFIG_EVENT = "ft_remote_config_callback";
38
+ private final ReactApplicationContext reactContext;
39
+ private boolean remoteConfigurationEnabled = false;
40
+ private int remoteConfigMiniUpdateInterval = 12 * 60 * 60;
41
+ @Nullable
42
+ private ReadableArray remoteConfigOverrideRules;
43
+
44
+ public FTMobileImpl(ReactApplicationContext reactContext) {
45
+ this.reactContext = reactContext;
46
+ }
47
+
48
+ private static class RemoteConfigOverrideResult {
49
+ final RemoteConfigBean configBean;
50
+ final List<String> appliedRuleIds;
51
+
52
+ RemoteConfigOverrideResult(RemoteConfigBean configBean, List<String> appliedRuleIds) {
53
+ this.configBean = configBean;
54
+ this.appliedRuleIds = appliedRuleIds;
55
+ }
56
+ }
57
+
58
+ private WritableMap createRemoteConfigPayload(String triggerType,
59
+ boolean success,
60
+ @Nullable String rawJson,
61
+ @Nullable List<String> appliedRuleIds,
62
+ @Nullable String errorCode,
63
+ @Nullable String errorMessage) {
64
+ WritableMap payload = Arguments.createMap();
65
+ payload.putString("triggerType", triggerType);
66
+ payload.putBoolean("success", success);
67
+ payload.putString("platform", "android");
68
+ payload.putDouble("timestamp", System.currentTimeMillis());
69
+ if (rawJson != null) {
70
+ payload.putString("rawJson", rawJson);
71
+ }
72
+ if (appliedRuleIds != null && !appliedRuleIds.isEmpty()) {
73
+ WritableArray ids = Arguments.createArray();
74
+ for (String ruleId : appliedRuleIds) {
75
+ ids.pushString(ruleId);
76
+ }
77
+ payload.putArray("appliedOverrideRuleIds", ids);
78
+ }
79
+ if (errorCode != null) {
80
+ payload.putString("errorCode", errorCode);
81
+ }
82
+ if (errorMessage != null) {
83
+ payload.putString("errorMessage", errorMessage);
84
+ }
85
+ return payload;
86
+ }
87
+
88
+ private void emitRemoteConfigEvent(boolean success, @Nullable String rawJson,
89
+ @Nullable List<String> appliedRuleIds,
90
+ @Nullable String errorCode, @Nullable String errorMessage) {
91
+ if (!reactContext.hasActiveCatalystInstance()) {
92
+ return;
93
+ }
94
+ reactContext
95
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
96
+ .emit(REMOTE_CONFIG_EVENT, createRemoteConfigPayload("auto", success, rawJson, appliedRuleIds, errorCode, errorMessage));
97
+ }
98
+
99
+ private RemoteConfigOverrideResult applyRemoteConfigOverrideRules(RemoteConfigBean configBean,
100
+ @Nullable String jsonConfig) {
101
+ return applyRemoteConfigOverrideRules(configBean, jsonConfig, this.remoteConfigOverrideRules);
102
+ }
103
+
104
+ private RemoteConfigOverrideResult applyRemoteConfigOverrideRules(RemoteConfigBean configBean,
105
+ @Nullable String jsonConfig,
106
+ @Nullable ReadableArray rules) {
107
+ if (configBean == null || jsonConfig == null || rules == null || rules.size() == 0) {
108
+ return new RemoteConfigOverrideResult(configBean, new ArrayList<>());
109
+ }
110
+ List<String> appliedRuleIds = new ArrayList<>();
111
+ try {
112
+ JSONObject jsonObject = new JSONObject(jsonConfig);
113
+ for (int i = 0; i < rules.size(); i++) {
114
+ if (rules.getType(i) != ReadableType.Map) {
115
+ continue;
116
+ }
117
+ ReadableMap rule = rules.getMap(i);
118
+ boolean enabled = !rule.hasKey("enabled") || rule.isNull("enabled") || rule.getBoolean("enabled");
119
+ if (!enabled) {
120
+ continue;
121
+ }
122
+ ReadableMap match = rule.hasKey("match") && !rule.isNull("match") ? rule.getMap("match") : null;
123
+ ReadableMap customKeys = match != null && match.hasKey("customKeys") && !match.isNull("customKeys")
124
+ ? match.getMap("customKeys") : null;
125
+ if (customKeys == null) {
126
+ continue;
127
+ }
128
+ HashMap<String, Object> keyMap = customKeys.toHashMap();
129
+ if (keyMap.isEmpty()) {
130
+ continue;
131
+ }
132
+ boolean matches = true;
133
+ for (Map.Entry<String, Object> entry : keyMap.entrySet()) {
134
+ Object expectedValue = entry.getValue();
135
+ Object actualValue = getJsonValue(jsonObject, entry.getKey());
136
+
137
+ if (!matchesCustomKey(actualValue, expectedValue)) {
138
+ matches = false;
139
+ break;
140
+ }
141
+ }
142
+ if (!matches) {
143
+ continue;
144
+ }
145
+ ReadableMap override = rule.hasKey("override") && !rule.isNull("override") ? rule.getMap("override") : null;
146
+ if (override == null) {
147
+ continue;
148
+ }
149
+
150
+ // Basic configuration properties
151
+ if (override.hasKey("env") && !override.isNull("env")) {
152
+ configBean.setEnv(override.getString("env"));
153
+ }
154
+ if (override.hasKey("serviceName") && !override.isNull("serviceName")) {
155
+ configBean.setServiceName(override.getString("serviceName"));
156
+ }
157
+ if (override.hasKey("autoSync") && !override.isNull("autoSync")) {
158
+ configBean.setAutoSync(override.getBoolean("autoSync"));
159
+ }
160
+ if (override.hasKey("compressIntakeRequests") && !override.isNull("compressIntakeRequests")) {
161
+ configBean.setCompressIntakeRequests(override.getBoolean("compressIntakeRequests"));
162
+ }
163
+ if (override.hasKey("syncPageSize") && !override.isNull("syncPageSize")) {
164
+ configBean.setSyncPageSize(override.getInt("syncPageSize"));
165
+ }
166
+ if (override.hasKey("syncSleepTime") && !override.isNull("syncSleepTime")) {
167
+ configBean.setSyncSleepTime(override.getInt("syncSleepTime"));
168
+ }
169
+
170
+ // Log configuration properties
171
+ if (override.hasKey("logSampleRate") && !override.isNull("logSampleRate")) {
172
+ configBean.setLogSampleRate((float) override.getDouble("logSampleRate"));
173
+ }
174
+ if (override.hasKey("logLevelFilters") && !override.isNull("logLevelFilters")) {
175
+ ReadableArray filtersArray = override.getArray("logLevelFilters");
176
+ String[] filters = new String[filtersArray.size()];
177
+ for (int j = 0; j < filtersArray.size(); j++) {
178
+ filters[j] = filtersArray.getString(j);
179
+ }
180
+ configBean.setLogLevelFilters(filters);
181
+ }
182
+ if (override.hasKey("logEnableCustomLog") && !override.isNull("logEnableCustomLog")) {
183
+ configBean.setLogEnableCustomLog(override.getBoolean("logEnableCustomLog"));
184
+ }
185
+ if (override.hasKey("logEnableConsoleLog") && !override.isNull("logEnableConsoleLog")) {
186
+ configBean.setLogEnableConsoleLog(override.getBoolean("logEnableConsoleLog"));
187
+ }
188
+
189
+ // RUM configuration properties
190
+ if (override.hasKey("rumSampleRate") && !override.isNull("rumSampleRate")) {
191
+ configBean.setRumSampleRate((float) override.getDouble("rumSampleRate"));
192
+ }
193
+ if (override.hasKey("rumSessionOnErrorSampleRate") && !override.isNull("rumSessionOnErrorSampleRate")) {
194
+ configBean.setRumSessionOnErrorSampleRate((float) override.getDouble("rumSessionOnErrorSampleRate"));
195
+ }
196
+ if (override.hasKey("rumEnableTraceUserAction") && !override.isNull("rumEnableTraceUserAction")) {
197
+ configBean.setRumEnableTraceUserAction(override.getBoolean("rumEnableTraceUserAction"));
198
+ }
199
+ if (override.hasKey("rumEnableTraceUserView") && !override.isNull("rumEnableTraceUserView")) {
200
+ configBean.setRumEnableTraceUserView(override.getBoolean("rumEnableTraceUserView"));
201
+ }
202
+ if (override.hasKey("rumEnableTraceUserResource") && !override.isNull("rumEnableTraceUserResource")) {
203
+ configBean.setRumEnableTraceUserResource(override.getBoolean("rumEnableTraceUserResource"));
204
+ }
205
+ if (override.hasKey("rumEnableResourceHostIP") && !override.isNull("rumEnableResourceHostIP")) {
206
+ configBean.setRumEnableResourceHostIP(override.getBoolean("rumEnableResourceHostIP"));
207
+ }
208
+ if (override.hasKey("rumEnableTrackAppUIBlock") && !override.isNull("rumEnableTrackAppUIBlock")) {
209
+ configBean.setRumEnableTrackAppUIBlock(override.getBoolean("rumEnableTrackAppUIBlock"));
210
+ }
211
+ if (override.hasKey("rumBlockDurationMs") && !override.isNull("rumBlockDurationMs")) {
212
+ configBean.setRumBlockDurationMs((long) override.getInt("rumBlockDurationMs"));
213
+ }
214
+ if (override.hasKey("rumEnableTrackAppCrash") && !override.isNull("rumEnableTrackAppCrash")) {
215
+ configBean.setRumEnableTrackAppCrash(override.getBoolean("rumEnableTrackAppCrash"));
216
+ }
217
+ if (override.hasKey("rumEnableTrackAppANR") && !override.isNull("rumEnableTrackAppANR")) {
218
+ configBean.setRumEnableTrackAppANR(override.getBoolean("rumEnableTrackAppANR"));
219
+ }
220
+ if (override.hasKey("rumEnableTraceWebView") && !override.isNull("rumEnableTraceWebView")) {
221
+ configBean.setRumEnableTraceWebView(override.getBoolean("rumEnableTraceWebView"));
222
+ }
223
+ if (override.hasKey("rumAllowWebViewHost") && !override.isNull("rumAllowWebViewHost")) {
224
+ ReadableArray hostsArray = override.getArray("rumAllowWebViewHost");
225
+ String[] hosts = new String[hostsArray.size()];
226
+ for (int j = 0; j < hostsArray.size(); j++) {
227
+ hosts[j] = hostsArray.getString(j);
228
+ }
229
+ configBean.setRumAllowWebViewHost(hosts);
230
+ }
231
+
232
+ // Trace configuration properties
233
+ if (override.hasKey("traceSampleRate") && !override.isNull("traceSampleRate")) {
234
+ configBean.setTraceSampleRate((float) override.getDouble("traceSampleRate"));
235
+ }
236
+ if (override.hasKey("traceEnableAutoTrace") && !override.isNull("traceEnableAutoTrace")) {
237
+ configBean.setTraceEnableAutoTrace(override.getBoolean("traceEnableAutoTrace"));
238
+ }
239
+ if (override.hasKey("traceType") && !override.isNull("traceType")) {
240
+ configBean.setTraceType(override.getString("traceType"));
241
+ }
242
+
243
+ String ruleId = rule.hasKey("id") && !rule.isNull("id") ? rule.getString("id") : null;
244
+ appliedRuleIds.add(ruleId != null ? ruleId : "rule_" + i);
245
+ }
246
+ } catch (JSONException ignored) {
247
+ }
248
+ return new RemoteConfigOverrideResult(configBean, appliedRuleIds);
249
+ }
250
+
251
+ private Object getJsonValue(JSONObject jsonObject, String key) {
252
+ if (!jsonObject.has(key)) {
253
+ return null;
254
+ }
255
+ try {
256
+ Object value = jsonObject.get(key);
257
+ if (value == JSONObject.NULL) {
258
+ return null;
259
+ }
260
+ return value;
261
+ } catch (JSONException e) {
262
+ return null;
263
+ }
264
+ }
265
+
266
+ private boolean isEqualValue(Object actual, Object expected) {
267
+ if (actual == null && expected == null) {
268
+ return true;
269
+ }
270
+ if (actual == null || expected == null) {
271
+ return false;
272
+ }
273
+
274
+ if (actual instanceof String actualString) {
275
+ Object normalizedActual = parseJsonStringIfNeeded(actualString);
276
+ if (normalizedActual != actual) {
277
+ return isEqualValue(normalizedActual, expected);
278
+ }
279
+ }
280
+
281
+ // Handle number comparison
282
+ if (actual instanceof Number && expected instanceof Number) {
283
+ return ((Number) actual).doubleValue() == ((Number) expected).doubleValue();
284
+ }
285
+
286
+ // Handle string comparison
287
+ if (actual instanceof String && expected instanceof String) {
288
+ return actual.equals(expected);
289
+ }
290
+
291
+ // Handle boolean comparison (JSON booleans are represented as Boolean in Java)
292
+ if (actual instanceof Boolean && expected instanceof Boolean) {
293
+ return actual.equals(expected);
294
+ }
295
+
296
+ // Fallback to string comparison
297
+ return actual.toString().equals(expected.toString());
298
+ }
299
+
300
+ private boolean matchesCustomKey(Object actual, Object expected) {
301
+ if (expected instanceof Map<?, ?> expectedMap && expectedMap.containsKey("contains")) {
302
+ return containsValue(actual, expectedMap.get("contains"));
303
+ }
304
+ return isEqualValue(actual, expected);
305
+ }
306
+
307
+ private boolean containsValue(Object actual, Object expectedValue) {
308
+ Object normalizedActual = actual instanceof String actualString
309
+ ? parseJsonStringIfNeeded(actualString)
310
+ : actual;
311
+
312
+ if (normalizedActual instanceof JSONArray actualArray) {
313
+ try {
314
+ for (int i = 0; i < actualArray.length(); i++) {
315
+ if (isEqualValue(actualArray.get(i), expectedValue)) {
316
+ return true;
317
+ }
318
+ }
319
+ } catch (JSONException ignored) {
320
+ return false;
321
+ }
322
+ }
323
+ return isEqualValue(normalizedActual, expectedValue);
324
+ }
325
+
326
+ private Object parseJsonStringIfNeeded(String value) {
327
+ String trimmedValue = value.trim();
328
+ if (trimmedValue.length() < 2) {
329
+ return value;
330
+ }
331
+ try {
332
+ if (trimmedValue.startsWith("[") && trimmedValue.endsWith("]")) {
333
+ return new JSONArray(trimmedValue);
334
+ }
335
+ } catch (JSONException ignored) {
336
+ return value;
337
+ }
338
+ return value;
339
+ }
22
340
 
23
341
  public void sdkConfig(ReadableMap context, Promise promise) {
24
342
  Map<String, Object> map = context.toHashMap();
@@ -37,9 +355,12 @@ public class FTMobileImpl {
37
355
  Boolean enableLimitWithDbSize = (Boolean) map.get("enableLimitWithDbSize");
38
356
  Long dbCacheLimit = ReactNativeUtils.convertToNativeLong(map.get("dbCacheLimit"));
39
357
  Integer dbDiscardStrategy = ReactNativeUtils.convertToNativeInt(map.get("dbDiscardStrategy"));
40
- String sdkPkgInfo = (String)map.get("pkgInfo");
41
358
  Map<String, Object> dataModifier = (Map<String, Object>) map.get("dataModifier");
42
359
  Map<String, Map<String,Object>> lineDataModifier = (Map<String, Map<String,Object>>) map.get("lineDataModifier");
360
+ Boolean remoteConfiguration = (Boolean) map.get("remoteConfiguration");
361
+ Integer remoteConfigMiniUpdateInterval = ReactNativeUtils.convertToNativeInt(map.get("remoteConfigMiniUpdateInterval"));
362
+ this.remoteConfigOverrideRules = context.hasKey("remoteConfigOverrideRules")
363
+ ? context.getArray("remoteConfigOverrideRules") : null;
43
364
 
44
365
  FTSDKConfig sdkConfig = (datakitUrl != null)
45
366
  ? FTSDKConfig.builder(datakitUrl)
@@ -103,9 +424,6 @@ public class FTMobileImpl {
103
424
  sdkConfig.setDbCacheDiscard(dbCacheDiscard);
104
425
  }
105
426
 
106
- if(sdkPkgInfo!=null){
107
- InnerClassProxy.addPkgInfo(sdkConfig,"reactnative",sdkPkgInfo);
108
- }
109
427
  if (dataModifier != null) {
110
428
  sdkConfig.setDataModifier(new DataModifier() {
111
429
  @Override
@@ -127,6 +445,40 @@ public class FTMobileImpl {
127
445
  }
128
446
  }
129
447
  );
448
+ }
449
+ if (remoteConfiguration != null) {
450
+ sdkConfig.setRemoteConfiguration(remoteConfiguration);
451
+ }
452
+ remoteConfigurationEnabled = sdkConfig.isRemoteConfiguration();
453
+ if (remoteConfigMiniUpdateInterval != null) {
454
+ sdkConfig.setRemoteConfigMiniUpdateInterval(remoteConfigMiniUpdateInterval);
455
+ this.remoteConfigMiniUpdateInterval = remoteConfigMiniUpdateInterval;
456
+ } else {
457
+ this.remoteConfigMiniUpdateInterval = sdkConfig.getRemoteConfigMiniUpdateInterval();
458
+ }
459
+ if (remoteConfigurationEnabled) {
460
+ sdkConfig.setRemoteConfigurationCallBack(new FTRemoteConfigManager.FetchResult() {
461
+ private String rawJson;
462
+ private List<String> appliedRuleIds = new ArrayList<>();
463
+
464
+ @Override
465
+ public RemoteConfigBean onConfigSuccessFetched(RemoteConfigBean configBean, String jsonConfig) {
466
+ rawJson = jsonConfig;
467
+ RemoteConfigOverrideResult result = applyRemoteConfigOverrideRules(configBean, jsonConfig);
468
+ appliedRuleIds = result.appliedRuleIds;
469
+ emitRemoteConfigEvent(true, configBean.toJsonString(), appliedRuleIds, null, null);
470
+ return result.configBean;
471
+ }
472
+
473
+ @Override
474
+ public void onResult(boolean success) {
475
+ if (!success) {
476
+ emitRemoteConfigEvent(false, rawJson, appliedRuleIds, "FETCH_FAILED", "Remote config update failed");
477
+ }
478
+ rawJson = null;
479
+ appliedRuleIds = new ArrayList<>();
480
+ }
481
+ });
130
482
  }
131
483
  FTSdk.install(sdkConfig);
132
484
  // LogUtils.d("configCheck","sdkConfig:"+new Gson().toJson(sdkConfig));
@@ -160,6 +512,16 @@ public class FTMobileImpl {
160
512
  promise.resolve(null);
161
513
  }
162
514
 
515
+ public void setDatakitURL(String datakitUrl, Promise promise) {
516
+ FTSdk.setDatakitUrl(datakitUrl);
517
+ promise.resolve(null);
518
+ }
519
+
520
+ public void setDatawayURL(String datawayUrl, String clientToken, Promise promise) {
521
+ FTSdk.setDatawayUrl(datawayUrl, clientToken);
522
+ promise.resolve(null);
523
+ }
524
+
163
525
  public void flushSyncData(Promise promise) {
164
526
  FTSdk.flushSyncData();
165
527
  promise.resolve(null);
@@ -195,4 +557,71 @@ public class FTMobileImpl {
195
557
  FTSdk.clearAllData();
196
558
  promise.resolve(null);
197
559
  }
560
+
561
+ public void updateRemoteConfig(Promise promise) {
562
+ if (!remoteConfigurationEnabled) {
563
+ promise.reject("E_REMOTE_CONFIG_DISABLED", "Remote configuration is not enabled.");
564
+ return;
565
+ }
566
+ FTSdk.updateRemoteConfig(remoteConfigMiniUpdateInterval, new FTRemoteConfigManager.FetchResult() {
567
+ private String rawJson;
568
+ private List<String> appliedRuleIds = new ArrayList<>();
569
+
570
+ @Override
571
+ public RemoteConfigBean onConfigSuccessFetched(RemoteConfigBean configBean, String jsonConfig) {
572
+ rawJson = jsonConfig;
573
+ RemoteConfigOverrideResult result = applyRemoteConfigOverrideRules(configBean, jsonConfig);
574
+ appliedRuleIds = result.appliedRuleIds;
575
+ promise.resolve(createRemoteConfigPayload("manual", true, configBean.toJsonString(), appliedRuleIds, null, null));
576
+ return result.configBean;
577
+ }
578
+
579
+ @Override
580
+ public void onResult(boolean success) {
581
+ if (!success) {
582
+ promise.reject("E_REMOTE_CONFIG_UPDATE_FAILED", "Remote config update failed");
583
+ } else if (rawJson == null) {
584
+ promise.resolve(createRemoteConfigPayload("manual", true, null, appliedRuleIds, null, null));
585
+ }
586
+ }
587
+ });
588
+ }
589
+
590
+ public void updateRemoteConfigWithMiniUpdateInterval(int interval, @Nullable ReadableArray rules, Promise promise) {
591
+ if (!remoteConfigurationEnabled) {
592
+ promise.reject("E_REMOTE_CONFIG_DISABLED", "Remote configuration is not enabled.");
593
+ return;
594
+ }
595
+ FTSdk.updateRemoteConfig(interval, new FTRemoteConfigManager.FetchResult() {
596
+ private String rawJson;
597
+ private List<String> appliedRuleIds = new ArrayList<>();
598
+
599
+ @Override
600
+ public RemoteConfigBean onConfigSuccessFetched(RemoteConfigBean configBean, String jsonConfig) {
601
+ rawJson = jsonConfig;
602
+ ReadableArray rulesToApply = rules != null && rules.size() > 0 ? rules : remoteConfigOverrideRules;
603
+ RemoteConfigOverrideResult result = applyRemoteConfigOverrideRules(configBean, jsonConfig, rulesToApply);
604
+ appliedRuleIds = result.appliedRuleIds;
605
+ promise.resolve(createRemoteConfigPayload("manual", true, configBean.toJsonString(), appliedRuleIds, null, null));
606
+ return result.configBean;
607
+ }
608
+
609
+ @Override
610
+ public void onResult(boolean success) {
611
+ if (!success) {
612
+ promise.reject("E_REMOTE_CONFIG_UPDATE_FAILED", "Remote config update failed");
613
+ } else if (rawJson == null) {
614
+ promise.resolve(createRemoteConfigPayload("manual", true, null, appliedRuleIds, null, null));
615
+ }
616
+ }
617
+ });
618
+ }
619
+
620
+ public void addListener(String eventName) {
621
+ // Required for NativeEventEmitter. No-op because native does not need listener bookkeeping.
622
+ }
623
+
624
+ public void removeListeners(double count) {
625
+ // Required for NativeEventEmitter. No-op because native does not need listener bookkeeping.
626
+ }
198
627
  }
@@ -15,6 +15,7 @@ import com.ft.sdk.garble.bean.NetStatusBean;
15
15
  import com.ft.sdk.garble.bean.ResourceParams;
16
16
  import com.ft.sdk.reactnative.utils.ReactNativeUtils;
17
17
 
18
+ import java.util.ArrayList;
18
19
  import java.util.HashMap;
19
20
  import java.util.Map;
20
21
 
@@ -44,6 +45,8 @@ public class FTRUMImpl {
44
45
  Map<String, Object> globalContext = (Map<String, Object>) map.get("globalContext");
45
46
  Integer rumCacheLimitCount = ReactNativeUtils.convertToNativeInt(map.get("rumCacheLimitCount"));
46
47
  Integer rumDiscardStrategy = ReactNativeUtils.convertToNativeInt(map.get("rumDiscardStrategy"));
48
+ Boolean enableTraceWebView = (Boolean) map.get("enableTraceWebView");
49
+ ArrayList<String> allowWebViewHost = (ArrayList<String>) map.get("allowWebViewHost");
47
50
 
48
51
  FTRUMConfig rumConfig = new FTRUMConfig().setRumAppId(rumAppId);
49
52
  if (sampleRate != null) {
@@ -122,6 +125,15 @@ public class FTRUMImpl {
122
125
  }
123
126
  rumConfig.setRumCacheDiscardStrategy(rumCacheDiscard);
124
127
  }
128
+ if (enableTraceWebView != null) {
129
+ rumConfig.setEnableTraceWebView(enableTraceWebView);
130
+ }
131
+ if (allowWebViewHost != null) {
132
+ String[] allowWebViewHostArr = new String[allowWebViewHost.size()];
133
+ allowWebViewHost.toArray(allowWebViewHostArr);
134
+ rumConfig.setAllowWebViewHost(allowWebViewHostArr);
135
+ }
136
+
125
137
  FTSdk.initRUMWithConfig(rumConfig);
126
138
  //LogUtils.d("configCheck","rumConfig:"+new Gson().toJson(rumConfig));
127
139
  promise.resolve(null);
@@ -1,5 +1,6 @@
1
1
  package com.ft.sdk.reactnative;
2
2
 
3
+ import com.ft.sdk.reactnative.utils.ReactNativeUtils;
3
4
  import com.facebook.react.bridge.Promise;
4
5
  import com.facebook.react.bridge.ReactMethod;
5
6
  import com.facebook.react.bridge.ReadableMap;
@@ -8,7 +9,6 @@ import com.ft.sdk.FTSdk;
8
9
  import com.ft.sdk.FTTraceConfig;
9
10
  import com.ft.sdk.FTTraceManager;
10
11
  import com.ft.sdk.TraceType;
11
- import com.ft.sdk.reactnative.utils.ReactNativeUtils;
12
12
 
13
13
  import java.util.HashMap;
14
14
  import java.util.Map;
@@ -1,35 +1,28 @@
1
1
  package com.ft.sdk.reactnative;
2
2
 
3
- import androidx.annotation.NonNull;
3
+ import androidx.annotation.Nullable;
4
4
 
5
- import com.facebook.react.turbomodule.core.interfaces.TurboModule;
5
+ import com.facebook.react.bridge.Promise;
6
6
  import com.facebook.react.bridge.ReactApplicationContext;
7
- import com.facebook.react.module.annotations.ReactModule;
8
7
  import com.facebook.react.bridge.ReactMethod;
9
- import com.facebook.react.bridge.Promise;
10
8
  import com.facebook.react.bridge.ReadableMap;
11
9
 
12
- @ReactModule(name = FTLogModule.NAME)
13
- public class FTLogModule extends NativeFTLogSpec {
14
- private final FTLogInterface logImpl = new FTLogImpl();
10
+ public class FTLogModule extends NativeFTReactNativeLogSpec {
11
+ private final FTLogImpl logImpl = new FTLogImpl();
15
12
 
16
13
  public FTLogModule(ReactApplicationContext reactContext) {
17
14
  super(reactContext);
18
15
  }
19
16
 
20
- @Override
21
- public String getName() {
22
- return NAME;
23
- }
24
-
25
17
  @ReactMethod
26
18
  public void logConfig(ReadableMap context, Promise promise) {
27
19
  logImpl.logConfig(context, promise);
28
20
  }
29
21
 
30
22
  @ReactMethod
31
- public void logging(String content, int logStatus, ReadableMap map, Promise promise) {
32
- logImpl.logging(content, logStatus, map, promise);
23
+ @Override
24
+ public void logging(String content, double logStatus, @Nullable ReadableMap property, Promise promise) {
25
+ logImpl.logging(content, (int) logStatus, property, promise);
33
26
  }
34
27
 
35
28
  @ReactMethod