diff --git a/.gitignore b/.gitignore
index 4033aaa3b..efad193fc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,3 +69,6 @@ android/keystores/debug.keystore
# .idea run configurations
/.run/*
+.yarn/
+examples/default/.yarn/
+examples/default/ios/.xcode.env.local
diff --git a/android/native.gradle b/android/native.gradle
index faa3246cd..d9c7a2f5b 100644
--- a/android/native.gradle
+++ b/android/native.gradle
@@ -1,5 +1,5 @@
project.ext.instabug = [
- version: '15.0.1'
+ version: '15.0.2.7020723-SNAPSHOT'
]
dependencies {
diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java
index d75b4f75b..f6ef387c1 100644
--- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java
+++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugAPMModule.java
@@ -1,6 +1,8 @@
package com.instabug.reactlibrary;
+import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod;
+
import android.os.SystemClock;
import android.util.Log;
@@ -16,17 +18,13 @@
import com.instabug.apm.networking.APMNetworkLogger;
import com.instabug.apm.networkinterception.cp.APMCPNetworkLog;
import com.instabug.reactlibrary.utils.EventEmitterModule;
-import com.instabug.apm.networkinterception.cp.APMCPNetworkLog;
import com.instabug.reactlibrary.utils.MainThreadHandler;
import java.lang.reflect.Method;
-
import java.util.HashMap;
import javax.annotation.Nonnull;
-import static com.instabug.reactlibrary.utils.InstabugUtil.getMethod;
-
public class RNInstabugAPMModule extends EventEmitterModule {
public RNInstabugAPMModule(ReactApplicationContext reactApplicationContext) {
@@ -211,7 +209,6 @@ public void run() {
* Starts an execution trace
*
* @param name string name of the trace.
- *
* @deprecated see {@link #startFlow(String)}
*/
@Deprecated
@@ -242,7 +239,6 @@ public void run() {
* @param id String id of the trace.
* @param key attribute key
* @param value attribute value. Null to remove attribute
- *
* @deprecated see {@link #setFlowAttribute}
*/
@Deprecated
@@ -264,7 +260,6 @@ public void run() {
* Ends a trace
*
* @param id string id of the trace.
- *
* @deprecated see {@link #endFlow}
*/
@Deprecated
@@ -318,73 +313,73 @@ public void run() {
});
}
- /**
- * The `networkLogAndroid` function logs network-related information using APMNetworkLogger in a React
- * Native module.
- *
- * @param requestStartTime The `requestStartTime` parameter in the `networkLogAndroid` method
- * represents the timestamp when the network request started. It is of type `double` and is passed as
- * a parameter to log network-related information.
- * @param requestDuration The `requestDuration` parameter in the `networkLogAndroid` method represents
- * the duration of the network request in milliseconds. It indicates the time taken for the request to
- * complete from the moment it was initiated until the response was received. This parameter helps in
- * measuring the performance of network requests and identifying any potential
- * @param requestHeaders requestHeaders is a string parameter that contains the headers of the network
- * request. It typically includes information such as the content type, authorization token, and any
- * other headers that were sent with the request.
- * @param requestBody The `requestBody` parameter in the `networkLogAndroid` method represents the
- * body of the HTTP request being logged. It contains the data that is sent as part of the request to
- * the server. This could include form data, JSON payload, XML data, or any other content that is
- * being transmitted
- * @param requestBodySize The `requestBodySize` parameter in the `networkLogAndroid` method represents
- * the size of the request body in bytes. It is a double value that indicates the size of the request
- * body being sent in the network request. This parameter is used to log information related to the
- * network request, including details
- * @param requestMethod The `requestMethod` parameter in the `networkLogAndroid` method represents the
- * HTTP method used in the network request, such as GET, POST, PUT, DELETE, etc. It indicates the type
- * of operation that the client is requesting from the server.
- * @param requestUrl The `requestUrl` parameter in the `networkLogAndroid` method represents the URL
- * of the network request being logged. It typically contains the address of the server to which the
- * request is being made, along with any additional path or query parameters required for the request.
- * This URL is essential for identifying the
- * @param requestContentType The `requestContentType` parameter in the `networkLogAndroid` method
- * represents the content type of the request being made. This could be values like
- * "application/json", "application/xml", "text/plain", etc., indicating the format of the data being
- * sent in the request body. It helps in specifying
- * @param responseHeaders The `responseHeaders` parameter in the `networkLogAndroid` method represents
- * the headers of the response received from a network request. These headers typically include
- * information such as content type, content length, server information, and any other metadata
- * related to the response. The `responseHeaders` parameter is expected to
- * @param responseBody The `responseBody` parameter in the `networkLogAndroid` method represents the
- * body of the response received from a network request. It contains the data or content sent back by
- * the server in response to the request made by the client. This could be in various formats such as
- * JSON, XML, HTML
- * @param responseBodySize The `responseBodySize` parameter in the `networkLogAndroid` method
- * represents the size of the response body in bytes. It is a double value that indicates the size of
- * the response body received from the network request. This parameter is used to log information
- * related to the network request and response, including
- * @param statusCode The `statusCode` parameter in the `networkLogAndroid` method represents the HTTP
- * status code of the network request/response. It indicates the status of the HTTP response, such as
- * success (200), redirection (3xx), client errors (4xx), or server errors (5xx). This parameter is
- * @param responseContentType The `responseContentType` parameter in the `networkLogAndroid` method
- * represents the content type of the response received from the network request. It indicates the
- * format of the data in the response, such as JSON, XML, HTML, etc. This information is useful for
- * understanding how to parse and handle the
- * @param errorDomain The `errorDomain` parameter in the `networkLogAndroid` method is used to specify
- * the domain of an error, if any occurred during the network request. If there was no error, this
- * parameter will be `null`.
- * @param w3cAttributes The `w3cAttributes` parameter in the `networkLogAndroid` method is a
- * ReadableMap object that contains additional attributes related to W3C external trace. It may
- * include the following key-value pairs:
- * @param gqlQueryName The `gqlQueryName` parameter in the `networkLogAndroid` method represents the
- * name of the GraphQL query being executed. It is a nullable parameter, meaning it can be null if no
- * GraphQL query name is provided. This parameter is used to log information related to GraphQL
- * queries in the network logging
- * @param serverErrorMessage The `serverErrorMessage` parameter in the `networkLogAndroid` method is
- * used to pass any error message received from the server during network communication. This message
- * can provide additional details about any errors that occurred on the server side, helping in
- * debugging and troubleshooting network-related issues.
- */
+ /**
+ * The `networkLogAndroid` function logs network-related information using APMNetworkLogger in a React
+ * Native module.
+ *
+ * @param requestStartTime The `requestStartTime` parameter in the `networkLogAndroid` method
+ * represents the timestamp when the network request started. It is of type `double` and is passed as
+ * a parameter to log network-related information.
+ * @param requestDuration The `requestDuration` parameter in the `networkLogAndroid` method represents
+ * the duration of the network request in milliseconds. It indicates the time taken for the request to
+ * complete from the moment it was initiated until the response was received. This parameter helps in
+ * measuring the performance of network requests and identifying any potential
+ * @param requestHeaders requestHeaders is a string parameter that contains the headers of the network
+ * request. It typically includes information such as the content type, authorization token, and any
+ * other headers that were sent with the request.
+ * @param requestBody The `requestBody` parameter in the `networkLogAndroid` method represents the
+ * body of the HTTP request being logged. It contains the data that is sent as part of the request to
+ * the server. This could include form data, JSON payload, XML data, or any other content that is
+ * being transmitted
+ * @param requestBodySize The `requestBodySize` parameter in the `networkLogAndroid` method represents
+ * the size of the request body in bytes. It is a double value that indicates the size of the request
+ * body being sent in the network request. This parameter is used to log information related to the
+ * network request, including details
+ * @param requestMethod The `requestMethod` parameter in the `networkLogAndroid` method represents the
+ * HTTP method used in the network request, such as GET, POST, PUT, DELETE, etc. It indicates the type
+ * of operation that the client is requesting from the server.
+ * @param requestUrl The `requestUrl` parameter in the `networkLogAndroid` method represents the URL
+ * of the network request being logged. It typically contains the address of the server to which the
+ * request is being made, along with any additional path or query parameters required for the request.
+ * This URL is essential for identifying the
+ * @param requestContentType The `requestContentType` parameter in the `networkLogAndroid` method
+ * represents the content type of the request being made. This could be values like
+ * "application/json", "application/xml", "text/plain", etc., indicating the format of the data being
+ * sent in the request body. It helps in specifying
+ * @param responseHeaders The `responseHeaders` parameter in the `networkLogAndroid` method represents
+ * the headers of the response received from a network request. These headers typically include
+ * information such as content type, content length, server information, and any other metadata
+ * related to the response. The `responseHeaders` parameter is expected to
+ * @param responseBody The `responseBody` parameter in the `networkLogAndroid` method represents the
+ * body of the response received from a network request. It contains the data or content sent back by
+ * the server in response to the request made by the client. This could be in various formats such as
+ * JSON, XML, HTML
+ * @param responseBodySize The `responseBodySize` parameter in the `networkLogAndroid` method
+ * represents the size of the response body in bytes. It is a double value that indicates the size of
+ * the response body received from the network request. This parameter is used to log information
+ * related to the network request and response, including
+ * @param statusCode The `statusCode` parameter in the `networkLogAndroid` method represents the HTTP
+ * status code of the network request/response. It indicates the status of the HTTP response, such as
+ * success (200), redirection (3xx), client errors (4xx), or server errors (5xx). This parameter is
+ * @param responseContentType The `responseContentType` parameter in the `networkLogAndroid` method
+ * represents the content type of the response received from the network request. It indicates the
+ * format of the data in the response, such as JSON, XML, HTML, etc. This information is useful for
+ * understanding how to parse and handle the
+ * @param errorDomain The `errorDomain` parameter in the `networkLogAndroid` method is used to specify
+ * the domain of an error, if any occurred during the network request. If there was no error, this
+ * parameter will be `null`.
+ * @param w3cAttributes The `w3cAttributes` parameter in the `networkLogAndroid` method is a
+ * ReadableMap object that contains additional attributes related to W3C external trace. It may
+ * include the following key-value pairs:
+ * @param gqlQueryName The `gqlQueryName` parameter in the `networkLogAndroid` method represents the
+ * name of the GraphQL query being executed. It is a nullable parameter, meaning it can be null if no
+ * GraphQL query name is provided. This parameter is used to log information related to GraphQL
+ * queries in the network logging
+ * @param serverErrorMessage The `serverErrorMessage` parameter in the `networkLogAndroid` method is
+ * used to pass any error message received from the server during network communication. This message
+ * can provide additional details about any errors that occurred on the server side, helping in
+ * debugging and troubleshooting network-related issues.
+ */
@ReactMethod
private void networkLogAndroid(final double requestStartTime,
final double requestDuration,
@@ -403,15 +398,15 @@ private void networkLogAndroid(final double requestStartTime,
@Nullable final ReadableMap w3cAttributes,
@Nullable final String gqlQueryName,
@Nullable final String serverErrorMessage
- ) {
+ ) {
try {
APMNetworkLogger networkLogger = new APMNetworkLogger();
final boolean hasError = errorDomain != null && !errorDomain.isEmpty();
final String errorMessage = hasError ? errorDomain : null;
- Boolean isW3cHeaderFound=false;
- Long partialId=null;
- Long networkStartTimeInSeconds=null;
+ Boolean isW3cHeaderFound = false;
+ Long partialId = null;
+ Long networkStartTimeInSeconds = null;
try {
@@ -420,7 +415,7 @@ private void networkLogAndroid(final double requestStartTime,
}
if (!w3cAttributes.isNull("partialId")) {
- partialId =(long) w3cAttributes.getDouble("partialId");
+ partialId = (long) w3cAttributes.getDouble("partialId");
networkStartTimeInSeconds = (long) w3cAttributes.getDouble("networkStartTimeInSeconds");
}
@@ -438,34 +433,54 @@ private void networkLogAndroid(final double requestStartTime,
try {
Method method = getMethod(Class.forName("com.instabug.apm.networking.APMNetworkLogger"), "log", long.class, long.class, String.class, String.class, long.class, String.class, String.class, String.class, String.class, String.class, long.class, int.class, String.class, String.class, String.class, String.class, APMCPNetworkLog.W3CExternalTraceAttributes.class);
if (method != null) {
- method.invoke(
- networkLogger,
- (long) requestStartTime * 1000,
- (long) requestDuration,
- requestHeaders,
- requestBody,
- (long) requestBodySize,
- requestMethod,
- requestUrl,
- requestContentType,
- responseHeaders,
- responseBody,
- (long)responseBodySize,
- (int) statusCode,
- responseContentType,
- errorMessage,
- gqlQueryName,
- serverErrorMessage,
- w3cExternalTraceAttributes
- );
+ method.invoke(
+ networkLogger,
+ (long) requestStartTime * 1000,
+ (long) requestDuration,
+ requestHeaders,
+ requestBody,
+ (long) requestBodySize,
+ requestMethod,
+ requestUrl,
+ requestContentType,
+ responseHeaders,
+ responseBody,
+ (long) responseBodySize,
+ (int) statusCode,
+ responseContentType,
+ errorMessage,
+ gqlQueryName,
+ serverErrorMessage,
+ w3cExternalTraceAttributes
+ );
} else {
Log.e("IB-CP-Bridge", "APMNetworkLogger.log was not found by reflection");
}
} catch (Throwable e) {
e.printStackTrace();
}
- } catch(Throwable e) {
+ } catch (Throwable e) {
e.printStackTrace();
}
}
+
+
+ /**
+ * Enables or disables screen rendering
+ *
+ * @param isEnabled boolean indicating enabled or disabled.
+ */
+ @ReactMethod
+ public void setScreenRenderEnabled(boolean isEnabled) {
+ MainThreadHandler.runOnMainThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ APM.setScreenRenderingEnabled(isEnabled);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
}
diff --git a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java
index 17f48656f..8507993ad 100644
--- a/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java
+++ b/android/src/main/java/com/instabug/reactlibrary/RNInstabugReactnativeModule.java
@@ -26,7 +26,6 @@
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.uimanager.UIManagerModule;
import com.instabug.apm.InternalAPM;
-import com.instabug.apm.configuration.cp.APMFeature;
import com.instabug.library.Feature;
import com.instabug.library.Instabug;
import com.instabug.library.InstabugColorTheme;
@@ -35,12 +34,11 @@
import com.instabug.library.LogLevel;
import com.instabug.library.ReproConfigurations;
import com.instabug.library.core.InstabugCore;
+import com.instabug.library.featuresflags.model.IBGFeatureFlag;
import com.instabug.library.internal.crossplatform.CoreFeature;
import com.instabug.library.internal.crossplatform.CoreFeaturesState;
import com.instabug.library.internal.crossplatform.FeaturesStateListener;
import com.instabug.library.internal.crossplatform.InternalCore;
-import com.instabug.library.featuresflags.model.IBGFeatureFlag;
-import com.instabug.library.internal.crossplatform.InternalCore;
import com.instabug.library.internal.crossplatform.OnFeaturesUpdatedListener;
import com.instabug.library.internal.module.InstabugLocale;
import com.instabug.library.invocation.InstabugInvocationEvent;
@@ -48,11 +46,9 @@
import com.instabug.library.model.NetworkLog;
import com.instabug.library.model.Report;
import com.instabug.library.ui.onboarding.WelcomeMessage;
-import com.instabug.library.util.InstabugSDKLogger;
import com.instabug.reactlibrary.utils.ArrayUtil;
import com.instabug.reactlibrary.utils.EventEmitterModule;
import com.instabug.reactlibrary.utils.MainThreadHandler;
-
import com.instabug.reactlibrary.utils.RNTouchedViewExtractor;
import org.json.JSONException;
@@ -115,6 +111,7 @@ public void removeListeners(Integer count) {
/**
* Enables or disables Instabug functionality.
+ *
* @param isEnabled A boolean to enable/disable Instabug.
*/
@ReactMethod
@@ -1175,7 +1172,7 @@ public void invoke(@NonNull CoreFeaturesState featuresState) {
params.putBoolean("isW3ExternalTraceIDEnabled", featuresState.isW3CExternalTraceIdEnabled());
params.putBoolean("isW3ExternalGeneratedHeaderEnabled", featuresState.isAttachingGeneratedHeaderEnabled());
params.putBoolean("isW3CaughtHeaderEnabled", featuresState.isAttachingCapturedHeaderEnabled());
- params.putInt("networkBodyLimit",featuresState.getNetworkLogCharLimit());
+ params.putInt("networkBodyLimit", featuresState.getNetworkLogCharLimit());
sendEvent(Constants.IBG_ON_FEATURE_FLAGS_UPDATE_RECEIVED_CALLBACK, params);
}
@@ -1259,7 +1256,7 @@ public void run() {
* Map between the exported JS constant and the arg key in {@link ArgsRegistry}.
* The constant name and the arg key should match to be able to resolve the
* constant with its actual value from the {@link ArgsRegistry} maps.
- *
+ *
* This is a workaround, because RN cannot resolve enums in the constants map.
*/
@Override
@@ -1290,23 +1287,25 @@ public void invoke() {
}
});
}
+
/**
- * Enables or disables capturing network body.
- * @param isEnabled A boolean to enable/disable capturing network body.
- */
- @ReactMethod
- public void setNetworkLogBodyEnabled(final boolean isEnabled) {
- MainThreadHandler.runOnMainThread(new Runnable() {
- @Override
- public void run() {
- try {
- Instabug.setNetworkLogBodyEnabled(isEnabled);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- });
- }
+ * Enables or disables capturing network body.
+ *
+ * @param isEnabled A boolean to enable/disable capturing network body.
+ */
+ @ReactMethod
+ public void setNetworkLogBodyEnabled(final boolean isEnabled) {
+ MainThreadHandler.runOnMainThread(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ Instabug.setNetworkLogBodyEnabled(isEnabled);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
/**
* Sets the auto mask screenshots types.
diff --git a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java
index 85ca1384d..63445978f 100644
--- a/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java
+++ b/android/src/test/java/com/instabug/reactlibrary/RNInstabugAPMModuleTest.java
@@ -205,5 +205,13 @@ public void testSetFlowAttribute() {
APM.endUITrace();
}
+ @Test
+ public void given$setScreenRenderEnabled_whenQuery_thenShouldCallNativeApiWithEnabled() {
+ apmModule.setScreenRenderEnabled(true);
+ // then
+ verify(APM.class, times(1));
+ APM.setScreenRenderingEnabled(true);
+ }
+
}
diff --git a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj
index fb1253b31..9424acb7e 100644
--- a/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj
+++ b/examples/default/ios/InstabugExample.xcodeproj/project.pbxproj
@@ -22,7 +22,6 @@
CC3DF8932A1DFC9A003E9914 /* InstabugSurveysTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3DF88B2A1DFC99003E9914 /* InstabugSurveysTests.m */; };
CC3DF8942A1DFC9A003E9914 /* InstabugAPMTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3DF88C2A1DFC99003E9914 /* InstabugAPMTests.m */; };
CC3DF8952A1DFC9A003E9914 /* IBGConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = CC3DF88D2A1DFC9A003E9914 /* IBGConstants.m */; };
- CC487A9C2C71FCFC0021F680 /* Instabug.plist in Resources */ = {isa = PBXBuildFile; fileRef = CC487A9B2C71FCFC0021F680 /* Instabug.plist */; };
CCF1E4092B022CF20024802D /* RNInstabugTests.m in Sources */ = {isa = PBXBuildFile; fileRef = CCF1E4082B022CF20024802D /* RNInstabugTests.m */; };
CD36F4707EA1F435D2CC7A15 /* libPods-InstabugExample-InstabugTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 3AF7A6E02D40E0CEEA833CC4 /* libPods-InstabugExample-InstabugTests.a */; };
F7BF47401EF3A435254C97BB /* libPods-InstabugExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BAED0D0441A708AE2390E153 /* libPods-InstabugExample.a */; };
@@ -57,7 +56,7 @@
BE3328762BDACE030078249A /* IBGCrashReporting+CP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "IBGCrashReporting+CP.h"; sourceTree = ""; };
C3C8C24386310A3120006604 /* CrashReportingExampleModule.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CrashReportingExampleModule.m; sourceTree = ""; };
C3C8C784EADC037C5A752B94 /* CrashReportingExampleModule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CrashReportingExampleModule.h; sourceTree = ""; };
- C4E7796400B3B360DD0B6E73 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; name = PrivacyInfo.xcprivacy; path = InstabugExample/PrivacyInfo.xcprivacy; sourceTree = ""; };
+ C4E7796400B3B360DD0B6E73 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xml; name = PrivacyInfo.xcprivacy; path = InstabugExample/PrivacyInfo.xcprivacy; sourceTree = ""; };
CC3DF8852A1DFC99003E9914 /* InstabugCrashReportingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstabugCrashReportingTests.m; sourceTree = ""; };
CC3DF8862A1DFC99003E9914 /* InstabugBugReportingTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstabugBugReportingTests.m; sourceTree = ""; };
CC3DF8872A1DFC99003E9914 /* InstabugSampleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstabugSampleTests.m; sourceTree = ""; };
@@ -67,7 +66,6 @@
CC3DF88B2A1DFC99003E9914 /* InstabugSurveysTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstabugSurveysTests.m; sourceTree = ""; };
CC3DF88C2A1DFC99003E9914 /* InstabugAPMTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstabugAPMTests.m; sourceTree = ""; };
CC3DF88D2A1DFC9A003E9914 /* IBGConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IBGConstants.m; sourceTree = ""; };
- CC487A9B2C71FCFC0021F680 /* Instabug.plist */ = {isa = PBXFileReference; lastKnownFileType = file.bplist; name = Instabug.plist; path = InstabugExample/Instabug.plist; sourceTree = ""; };
CCF1E4082B022CF20024802D /* RNInstabugTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RNInstabugTests.m; sourceTree = ""; };
DBCB1B1D023646D84146C91E /* Pods-InstabugExample-InstabugTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-InstabugExample-InstabugTests.release.xcconfig"; path = "Target Support Files/Pods-InstabugExample-InstabugTests/Pods-InstabugExample-InstabugTests.release.xcconfig"; sourceTree = ""; };
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
@@ -124,7 +122,6 @@
13B07FAE1A68108700A75B9A /* InstabugExample */ = {
isa = PBXGroup;
children = (
- CC487A9B2C71FCFC0021F680 /* Instabug.plist */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
13B07FB01A68108700A75B9A /* AppDelegate.mm */,
13B07FB51A68108700A75B9A /* Images.xcassets */,
@@ -302,7 +299,6 @@
buildActionMask = 2147483647;
files = (
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */,
- CC487A9C2C71FCFC0021F680 /* Instabug.plist in Resources */,
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */,
AF8A18C6FA80B2BFE6006C9E /* PrivacyInfo.xcprivacy in Resources */,
);
diff --git a/examples/default/ios/InstabugExample/Instabug.plist b/examples/default/ios/InstabugExample/Instabug.plist
deleted file mode 100644
index 24d035f42..000000000
Binary files a/examples/default/ios/InstabugExample/Instabug.plist and /dev/null differ
diff --git a/examples/default/ios/InstabugTests/InstabugAPMTests.m b/examples/default/ios/InstabugTests/InstabugAPMTests.m
index 949393adb..cac456550 100644
--- a/examples/default/ios/InstabugTests/InstabugAPMTests.m
+++ b/examples/default/ios/InstabugTests/InstabugAPMTests.m
@@ -177,6 +177,22 @@ - (void) testEndUITrace {
OCMVerify([mock endUITrace]);
}
+- (void) testSetScreenRenderEnabled {
+ id mock = OCMClassMock([IBGAPM class]);
+ BOOL isEnabled = YES;
+ [self.instabugBridge setScreenRenderEnabled:isEnabled];
+
+ OCMVerify([mock setScreenRenderingEnabled:YES]);
+}
+
+- (void) testSetScreenRenderDisabled {
+ id mock = OCMClassMock([IBGAPM class]);
+ BOOL isEnabled = NO;
+
+ [self.instabugBridge setScreenRenderEnabled:isEnabled];
+
+ OCMVerify([mock setScreenRenderingEnabled:NO]);
+}
@end
diff --git a/examples/default/ios/Podfile b/examples/default/ios/Podfile
index e1dda08e3..0d3e454c6 100644
--- a/examples/default/ios/Podfile
+++ b/examples/default/ios/Podfile
@@ -15,7 +15,7 @@ target 'InstabugExample' do
config = use_native_modules!
rn_maps_path = '../node_modules/react-native-maps'
pod 'react-native-google-maps', :path => rn_maps_path
-
+ pod 'Instabug', :podspec => 'https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.26/Instabug.podspec'
# Flags change depending on the env values.
flags = get_default_flags()
diff --git a/examples/default/ios/Podfile.lock b/examples/default/ios/Podfile.lock
index 0d7d7a1ff..eab18a2da 100644
--- a/examples/default/ios/Podfile.lock
+++ b/examples/default/ios/Podfile.lock
@@ -31,7 +31,7 @@ PODS:
- hermes-engine (0.75.4):
- hermes-engine/Pre-built (= 0.75.4)
- hermes-engine/Pre-built (0.75.4)
- - Instabug (15.1.1)
+ - Instabug (15.1.26)
- instabug-reactnative-ndk (0.1.0):
- DoubleConversion
- glog
@@ -1626,7 +1626,7 @@ PODS:
- ReactCommon/turbomodule/core
- Yoga
- RNInstabug (15.0.1):
- - Instabug (= 15.1.1)
+ - Instabug (= 15.1.26)
- React-Core
- RNReanimated (3.16.1):
- DoubleConversion
@@ -1770,6 +1770,7 @@ DEPENDENCIES:
- fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`)
- glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`)
- hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`)
+ - Instabug (from `https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.26/Instabug.podspec`)
- instabug-reactnative-ndk (from `../node_modules/instabug-reactnative-ndk`)
- OCMock
- RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`)
@@ -1850,7 +1851,6 @@ SPEC REPOS:
trunk:
- Google-Maps-iOS-Utils
- GoogleMaps
- - Instabug
- OCMock
- SocketRocket
@@ -1868,6 +1868,8 @@ EXTERNAL SOURCES:
hermes-engine:
:podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec"
:tag: hermes-2024-08-15-RNv0.75.1-4b3bf912cc0f705b51b71ce1a5b8bd79b93a451b
+ Instabug:
+ :podspec: https://ios-releases.instabug.com/custom/faeture-screen_rendering-release/15.1.26/Instabug.podspec
instabug-reactnative-ndk:
:path: "../node_modules/instabug-reactnative-ndk"
RCT-Folly:
@@ -2022,7 +2024,7 @@ SPEC CHECKSUMS:
Google-Maps-iOS-Utils: f77eab4c4326d7e6a277f8e23a0232402731913a
GoogleMaps: 032f676450ba0779bd8ce16840690915f84e57ac
hermes-engine: ea92f60f37dba025e293cbe4b4a548fd26b610a0
- Instabug: 3e7af445c14d7823fcdecba223f09b5f7c0c6ce1
+ Instabug: c47bd604b5212496da79b19b368eb5de73833d69
instabug-reactnative-ndk: d765ac289d56e8896398d02760d9abf2562fc641
OCMock: 589f2c84dacb1f5aaf6e4cec1f292551fe748e74
RCT-Folly: 4464f4d875961fce86008d45f4ecf6cef6de0740
@@ -2090,14 +2092,14 @@ SPEC CHECKSUMS:
ReactCommon: 6a952e50c2a4b694731d7682aaa6c79bc156e4ad
RNCClipboard: 2821ac938ef46f736a8de0c8814845dde2dcbdfb
RNGestureHandler: 511250b190a284388f9dd0d2e56c1df76f14cfb8
- RNInstabug: f17d4e6c679fbc921f2692c223a1c21395589cc5
+ RNInstabug: 35bf420d77731598fae13c33ceecf0343fd8dd99
RNReanimated: f42a5044d121d68e91680caacb0293f4274228eb
RNScreens: c7ceced6a8384cb9be5e7a5e88e9e714401fd958
RNSVG: 8b1a777d54096b8c2a0fd38fc9d5a454332bbb4d
RNVectorIcons: 6382277afab3c54658e9d555ee0faa7a37827136
SocketRocket: abac6f5de4d4d62d24e11868d7a2f427e0ef940d
- Yoga: 055f92ad73f8c8600a93f0e25ac0b2344c3b07e6
+ Yoga: aa3df615739504eebb91925fc9c58b4922ea9a08
-PODFILE CHECKSUM: 837b933596e1616ff02cc206bb17dee4f611fdbc
+PODFILE CHECKSUM: 4e2ae668f4fb59c72dfd359d3d9c86ec6d4967e5
-COCOAPODS: 1.14.0
+COCOAPODS: 1.15.2
diff --git a/examples/default/src/App.tsx b/examples/default/src/App.tsx
index ceef8bc19..703932594 100644
--- a/examples/default/src/App.tsx
+++ b/examples/default/src/App.tsx
@@ -3,8 +3,8 @@ import { ActivityIndicator, StyleSheet } from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { NavigationContainer, useNavigationContainerRef } from '@react-navigation/native';
-import type { SessionMetadata } from 'instabug-reactnative';
import Instabug, {
+ APM,
CrashReporting,
InvocationEvent,
LaunchType,
@@ -12,6 +12,7 @@ import Instabug, {
NetworkInterceptionMode,
NetworkLogger,
ReproStepsMode,
+ type SessionMetadata,
SessionReplay,
} from 'instabug-reactnative';
import { NativeBaseProvider } from 'native-base';
@@ -42,35 +43,41 @@ export const App: React.FC = () => {
const [isInstabugInitialized, setIsInstabugInitialized] = useState(false);
- const initializeInstabug = async () => {
- try {
- SessionReplay.setSyncCallback((data) => shouldSyncSession(data));
-
- await Instabug.init({
- token: 'deb1910a7342814af4e4c9210c786f35',
- invocationEvents: [InvocationEvent.floatingButton],
- debugLogsLevel: LogLevel.verbose,
- networkInterceptionMode: NetworkInterceptionMode.javascript,
+ const initializeInstabug = () => {
+ // Synchronous setup
+ SessionReplay.setSyncCallback((data) => shouldSyncSession(data));
+
+ // Start async initialization but don't block rendering
+ Instabug.init({
+ token: 'deb1910a7342814af4e4c9210c786f35',
+ invocationEvents: [InvocationEvent.floatingButton],
+ debugLogsLevel: LogLevel.verbose,
+ networkInterceptionMode: NetworkInterceptionMode.javascript,
+ })
+ .then(() => {
+ // Post-initialization setup
+ NetworkLogger.setNetworkDataObfuscationHandler(async (networkData) => {
+ networkData.url = `${networkData.url}/JS/Obfuscated`;
+ return networkData;
+ });
+ APM.setScreenRenderEnabled(true);
+ setIsInstabugInitialized(true);
+ })
+ .catch((error) => {
+ console.error('Instabug initialization failed:', error);
+ setIsInstabugInitialized(true); // Proceed even if initialization fails
});
- CrashReporting.setNDKCrashesEnabled(true);
- Instabug.setReproStepsConfig({ all: ReproStepsMode.enabled });
+ // Synchronous configuration that doesn't depend on init completion
+ CrashReporting.setNDKCrashesEnabled(true);
+ Instabug.setReproStepsConfig({ all: ReproStepsMode.enabled });
- setIsInstabugInitialized(true); // Set to true after initialization
- } catch (error) {
- console.error('Instabug initialization failed:', error);
- setIsInstabugInitialized(true); // Proceed even if initialization fails
- }
+ // Set initialized immediately to show UI - initialization continues in background
+ setIsInstabugInitialized(true);
};
useEffect(() => {
- initializeInstabug().then(() => {
- NetworkLogger.setNetworkDataObfuscationHandler(async (networkData) => {
- networkData.url = `${networkData.url}/JS/Obfuscated`;
- return networkData;
- });
- // NetworkLogger.setRequestFilterExpression('false');
- });
+ initializeInstabug();
});
useEffect(() => {
diff --git a/examples/default/src/navigation/HomeStack.tsx b/examples/default/src/navigation/HomeStack.tsx
index 090aa6587..0eafe75cb 100644
--- a/examples/default/src/navigation/HomeStack.tsx
+++ b/examples/default/src/navigation/HomeStack.tsx
@@ -22,7 +22,8 @@ import {
import { GoogleMapsScreen } from '../screens/user-steps/GoogleMapsScreen';
import { LargeImageListScreen } from '../screens/user-steps/LargeImageListScreen';
import { APMScreen } from '../screens/apm/APMScreen';
-import { TracesScreen } from '../screens/apm/TracesScreen';
+import { ExecutionTraceScreen } from '../screens/apm/ExecutionTraceScreen';
+import { CustomUITraceScreen } from '../screens/apm/CustomUITraceScreen';
import { NetworkScreen } from '../screens/apm/NetworkScreen';
import { FlowsScreen } from '../screens/apm/FlowsScreen';
import { SessionReplayScreen } from '../screens/SessionReplayScreen';
@@ -31,6 +32,7 @@ import { HttpScreen } from '../screens/apm/HttpScreen';
import { WebViewsScreen } from '../screens/apm/webViews/WebViewsScreen';
import { FullWebViewsScreen } from '../screens/apm/webViews/FullWebViewsScreen';
import { PartialWebViewsScreen } from '../screens/apm/webViews/PartialWebViewsScreen';
+import ScreenRender from '../screens/apm/ScreenRender';
export type HomeStackParamList = {
Home: undefined;
@@ -43,7 +45,7 @@ export type HomeStackParamList = {
BasicComponents: undefined;
ScrollView: undefined;
FlatList: undefined;
- ComplexViews: undefined;
+ ComplexViews: { initialDepth?: number; initialBreadth?: number } | undefined;
SectionList: undefined;
Gestures: undefined;
GoogleMapsScreen: undefined;
@@ -57,10 +59,12 @@ export type HomeStackParamList = {
APM: undefined;
NetworkTraces: undefined;
ExecutionTraces: undefined;
+ CustomUITraces: undefined;
AppFlows: undefined;
WebViews: undefined;
FullWebViews: undefined;
PartialWebViews: undefined;
+ ScreenRender: undefined;
};
const HomeStack = createNativeStackNavigator();
@@ -140,7 +144,8 @@ export const HomeStackNavigator: React.FC = () => {
-
+
+
{
component={PartialWebViewsScreen}
options={{ title: 'PartialWebViews' }}
/>
+
);
};
diff --git a/examples/default/src/screens/apm/APMScreen.tsx b/examples/default/src/screens/apm/APMScreen.tsx
index 3652a95c5..7f647924d 100644
--- a/examples/default/src/screens/apm/APMScreen.tsx
+++ b/examples/default/src/screens/apm/APMScreen.tsx
@@ -34,10 +34,12 @@ export const APMScreen: React.FC APM.endAppLaunch()} />
navigation.navigate('NetworkTraces')} />
- navigation.navigate('ExecutionTraces')} />
+ navigation.navigate('ExecutionTraces')} />
+ navigation.navigate('CustomUITraces')} />
navigation.navigate('AppFlows')} />
navigation.navigate('WebViews')} />
navigation.navigate('ComplexViews')} />
+ navigation.navigate('ScreenRender')} />
);
};
diff --git a/examples/default/src/screens/apm/CustomUITraceScreen.tsx b/examples/default/src/screens/apm/CustomUITraceScreen.tsx
new file mode 100644
index 000000000..f03b13334
--- /dev/null
+++ b/examples/default/src/screens/apm/CustomUITraceScreen.tsx
@@ -0,0 +1,58 @@
+import React, { useState } from 'react';
+import { APM } from 'instabug-reactnative';
+import { ScrollView } from 'react-native';
+import { Section } from '../../components/Section';
+import { Screen } from '../../components/Screen';
+import { VStack } from 'native-base';
+import { InputField } from '../../components/InputField';
+import { CustomButton } from '../../components/CustomButton';
+import BackgroundTimer from 'react-native-background-timer';
+
+export const CustomUITraceScreen: React.FC = () => {
+ const [traceName, setTraceName] = useState('');
+
+ function startUITrace() {
+ if (!traceName.trim()) {
+ console.log('Please enter a trace name before starting.');
+ return;
+ }
+ APM.startUITrace(traceName);
+
+ console.log(`UI trace "${traceName}" started.`);
+ }
+
+ function startDelayedUITrace() {
+ if (!traceName.trim()) {
+ console.log('Please enter a trace name before starting.');
+ return;
+ }
+ return BackgroundTimer.setTimeout(() => {
+ APM.startUITrace(traceName);
+ console.log(`Delayed UI trace "${traceName}" started.`);
+ }, 5000);
+ }
+
+ function endUITrace() {
+ APM.endUITrace();
+ console.log('UI trace ended.');
+ }
+
+ return (
+
+
+
+
+ setTraceName(text)}
+ value={traceName}
+ />
+
+
+
+
+
+
+
+ );
+};
diff --git a/examples/default/src/screens/apm/TracesScreen.tsx b/examples/default/src/screens/apm/ExecutionTraceScreen.tsx
similarity index 97%
rename from examples/default/src/screens/apm/TracesScreen.tsx
rename to examples/default/src/screens/apm/ExecutionTraceScreen.tsx
index bd3e41838..c25c14cae 100644
--- a/examples/default/src/screens/apm/TracesScreen.tsx
+++ b/examples/default/src/screens/apm/ExecutionTraceScreen.tsx
@@ -8,7 +8,7 @@ import { InputField } from '../../components/InputField';
import { CustomButton } from '../../components/CustomButton';
import BackgroundTimer from 'react-native-background-timer';
-export const TracesScreen: React.FC = () => {
+export const ExecutionTraceScreen: React.FC = () => {
const [traceName, setTraceName] = useState('');
const [traceAttributeKey, setTraceAttributeKey] = useState('');
const [traceAttributeValue, setTraceAttributeValue] = useState('');
diff --git a/examples/default/src/screens/apm/ScreenRender.tsx b/examples/default/src/screens/apm/ScreenRender.tsx
new file mode 100644
index 000000000..f9113a2c8
--- /dev/null
+++ b/examples/default/src/screens/apm/ScreenRender.tsx
@@ -0,0 +1,445 @@
+/* eslint-disable react-native/no-inline-styles */
+import type { NativeStackScreenProps } from '@react-navigation/native-stack';
+import React, { useEffect, useRef, useState } from 'react';
+import {
+ Animated,
+ SafeAreaView,
+ ScrollView,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+import type { HomeStackParamList } from '../../navigation/HomeStack';
+import { APM } from 'instabug-reactnative';
+
+// Custom Components
+const ScreenRenderSwitch: React.FC = () => {
+ const [isEnabled, setIsEnabled] = useState(false);
+
+ return (
+
+ Screen Render Monitoring
+ {
+ setIsEnabled(!isEnabled);
+ APM.setScreenRenderEnabled(isEnabled);
+ }}>
+
+
+
+ );
+};
+
+const AnimatedBox: React.FC<{ isBlocking: boolean; blockingIntensity: number }> = ({
+ isBlocking,
+ blockingIntensity,
+}) => {
+ const [counter, setCounter] = useState(0);
+ const [layoutThrasher, setLayoutThrasher] = useState(0);
+ const animatedValue = useRef(new Animated.Value(0)).current;
+ const intervalRef = useRef(null);
+
+ // Continuous animation - Use native driver for native thread work
+ useEffect(() => {
+ const animation = Animated.loop(
+ Animated.sequence([
+ Animated.timing(animatedValue, {
+ toValue: 1,
+ duration: 1000,
+ useNativeDriver: true, // Native driver for native thread
+ }),
+ Animated.timing(animatedValue, {
+ toValue: 0,
+ duration: 1000,
+ useNativeDriver: true, // Native driver for native thread
+ }),
+ ]),
+ );
+ animation.start();
+
+ return () => animation.stop();
+ }, [animatedValue]);
+
+ // High frequency counter updates
+ useEffect(() => {
+ intervalRef.current = setInterval(() => {
+ setCounter((prev) => prev + 1);
+
+ // Layout thrashing to block native thread
+ if (isBlocking) {
+ setLayoutThrasher((prev) => prev + 1);
+ }
+ }, 16); // ~60fps updates
+
+ return () => {
+ if (intervalRef.current) {
+ clearInterval(intervalRef.current);
+ }
+ };
+ }, [isBlocking]);
+
+ const translateX = animatedValue.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, 100],
+ });
+
+ const getStatusText = () => {
+ if (!isBlocking) {
+ return 'Running Smoothly';
+ }
+ if (blockingIntensity === 1) {
+ return 'SLOW NATIVE RENDERING!';
+ }
+ if (blockingIntensity === 2) {
+ return 'FROZEN NATIVE THREAD!';
+ }
+ return 'BLOCKING NATIVE THREAD!';
+ };
+
+ const getBoxColor = () => {
+ if (!isBlocking) {
+ return '#4ECDC4';
+ }
+ if (blockingIntensity === 1) {
+ return '#FFB347';
+ } // Orange for slow
+ if (blockingIntensity === 2) {
+ return '#FF6B6B';
+ } // Red for frozen
+ return '#FF6B6B';
+ };
+
+ // Generate many layout-heavy elements to stress native thread
+ const generateHeavyNativeElements = () => {
+ if (!isBlocking) {
+ return null;
+ }
+
+ const elementCount = blockingIntensity === 1 ? 50 : 200; // More elements = more native work
+
+ return Array.from({ length: elementCount }, (_, i) => (
+
+ ));
+ };
+
+ return (
+
+ Frame Counter: {counter}
+
+ Status: {getStatusText()}
+
+
+ {/* Native thread heavy work area */}
+
+
+
+ {blockingIntensity === 1 ? 'Slow!' : blockingIntensity === 2 ? 'Frozen!' : 'Smooth'}
+
+
+
+ {/* Heavy native rendering elements */}
+ {generateHeavyNativeElements()}
+
+
+ {/* Additional native-heavy components */}
+ {isBlocking && (
+
+ {/* Multiple ScrollViews to stress native scrolling */}
+
+ {Array.from({ length: 100 }, (_, i) => (
+
+ ))}
+
+
+ {/* Text that forces layout recalculation */}
+
+ Layout Thrashing Text: {layoutThrasher}
+
+
+ )}
+
+ );
+};
+
+interface InstabugButtonProps {
+ text: string;
+ onPress: () => void;
+ disabled?: boolean;
+}
+
+const InstabugButton: React.FC = ({ text, onPress, disabled }) => {
+ return (
+
+ {text}
+
+ );
+};
+
+// Main Component
+const ScreenRenderPage: React.FC> = ({
+ navigation,
+}) => {
+ const [isBlocking, setIsBlocking] = useState(false);
+ const [blockingIntensity, setBlockingIntensity] = useState(0); // 0 = none, 1 = slow, 2 = frozen
+ const blockingTimeoutRef = useRef(null);
+
+ const triggerFrozenFrames = (): void => {
+ setIsBlocking(true);
+ setBlockingIntensity(2); // Frozen frames mode
+
+ // Clear any existing timeout
+ if (blockingTimeoutRef.current) {
+ clearTimeout(blockingTimeoutRef.current);
+ }
+
+ // Stop blocking after 5 seconds
+ blockingTimeoutRef.current = setTimeout(() => {
+ setIsBlocking(false);
+ setBlockingIntensity(0);
+ }, 5000);
+ };
+
+ const navigateToComplexPage = (): void => {
+ navigation.navigate('ComplexViews', { initialDepth: 10, initialBreadth: 2 });
+ };
+
+ // Cleanup timeout on unmount
+ useEffect(() => {
+ return () => {
+ if (blockingTimeoutRef.current) {
+ clearTimeout(blockingTimeoutRef.current);
+ }
+ };
+ }, []);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#f5f5f5',
+ },
+ scrollContent: {
+ padding: 20,
+ },
+ title: {
+ fontSize: 24,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ marginBottom: 20,
+ color: '#333',
+ },
+ spacer: {
+ height: 16,
+ },
+ largeSpacer: {
+ height: 50,
+ },
+ buttonContainer: {
+ gap: 12,
+ },
+ button: {
+ backgroundColor: '#007AFF',
+ paddingVertical: 12,
+ paddingHorizontal: 20,
+ borderRadius: 8,
+ alignItems: 'center',
+ marginVertical: 4,
+ },
+ buttonText: {
+ color: 'white',
+ fontSize: 16,
+ fontWeight: '600',
+ },
+ buttonDisabled: {
+ backgroundColor: '#ccc',
+ opacity: 0.7,
+ },
+ buttonTextDisabled: {
+ color: '#888',
+ },
+ switchContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ paddingVertical: 12,
+ paddingHorizontal: 16,
+ backgroundColor: 'white',
+ borderRadius: 8,
+ marginVertical: 8,
+ },
+ switchLabel: {
+ fontSize: 16,
+ color: '#333',
+ },
+ switch: {
+ width: 50,
+ height: 30,
+ borderRadius: 15,
+ backgroundColor: '#ccc',
+ justifyContent: 'center',
+ padding: 2,
+ },
+ switchEnabled: {
+ backgroundColor: '#007AFF',
+ },
+ switchThumb: {
+ width: 26,
+ height: 26,
+ borderRadius: 13,
+ backgroundColor: 'white',
+ alignSelf: 'flex-start',
+ },
+ switchThumbEnabled: {
+ alignSelf: 'flex-end',
+ },
+ animatedContainer: {
+ alignItems: 'center',
+ paddingVertical: 20,
+ backgroundColor: 'white',
+ borderRadius: 8,
+ marginVertical: 8,
+ },
+ counterText: {
+ fontSize: 18,
+ fontWeight: 'bold',
+ color: '#333',
+ marginBottom: 15,
+ },
+ animatedBox: {
+ width: 100,
+ height: 60,
+ backgroundColor: '#FF6B6B',
+ borderRadius: 8,
+ justifyContent: 'center',
+ alignItems: 'center',
+ transform: [{ scale: 1 }],
+ },
+ animatedBoxActive: {
+ backgroundColor: '#4ECDC4',
+ transform: [{ scale: 1.1 }],
+ },
+ animatedBoxText: {
+ color: 'white',
+ fontSize: 14,
+ fontWeight: '600',
+ textAlign: 'center',
+ },
+ statusText: {
+ fontSize: 16,
+ color: '#666',
+ marginBottom: 10,
+ },
+ statusTextAlert: {
+ color: '#FF6B6B', // Red for alert
+ fontWeight: 'bold',
+ },
+ additionalElements: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ justifyContent: 'center',
+ marginTop: 20,
+ },
+ smallBox: {
+ width: 30,
+ height: 30,
+ margin: 5,
+ borderRadius: 15,
+ },
+ nativeWorkArea: {
+ position: 'relative',
+ width: 200,
+ height: 200,
+ backgroundColor: '#f0f0f0',
+ borderRadius: 10,
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginVertical: 10,
+ borderWidth: 1,
+ borderColor: '#ccc',
+ },
+ heavyNativeSection: {
+ marginTop: 20,
+ alignItems: 'center',
+ },
+ miniScrollView: {
+ width: '100%',
+ height: 100,
+ backgroundColor: '#e0e0e0',
+ borderRadius: 8,
+ marginBottom: 10,
+ },
+});
+
+export default ScreenRenderPage;
diff --git a/examples/default/src/screens/user-steps/ComplexViewsScreen.tsx b/examples/default/src/screens/user-steps/ComplexViewsScreen.tsx
index 0035d5775..b6fc337a6 100644
--- a/examples/default/src/screens/user-steps/ComplexViewsScreen.tsx
+++ b/examples/default/src/screens/user-steps/ComplexViewsScreen.tsx
@@ -1,4 +1,6 @@
import React, { useRef, useState } from 'react';
+import type { NativeStackScreenProps } from '@react-navigation/native-stack';
+import type { HomeStackParamList } from '../../navigation/HomeStack';
import { Screen } from '../../components/Screen';
import { Section } from '../../components/Section';
@@ -7,10 +9,11 @@ import { Button } from 'react-native';
import { ScrollView, VStack } from 'native-base';
import { InputField } from '../../components/InputField';
-export const ComplexViewsScreen: React.FC = () => {
- const initialDepth = 10;
- const initialBreadth = 2;
-
+export const ComplexViewsScreen: React.FC<
+ NativeStackScreenProps
+> = ({ route }) => {
+ const initialDepth = route.params?.initialDepth ?? 10;
+ const initialBreadth = route.params?.initialBreadth ?? 2;
const depthRef = useRef(initialDepth);
const breadthRef = useRef(initialBreadth);
diff --git a/ios/RNInstabug/InstabugAPMBridge.h b/ios/RNInstabug/InstabugAPMBridge.h
index 0a0ea397c..509e7fae3 100644
--- a/ios/RNInstabug/InstabugAPMBridge.h
+++ b/ios/RNInstabug/InstabugAPMBridge.h
@@ -27,6 +27,8 @@
- (void)startUITrace:(NSString *)name;
- (void)endUITrace;
+- (void)setScreenRenderEnabled:(BOOL)isEnabled;
+
extern NSMutableDictionary *traces;
@end
diff --git a/ios/RNInstabug/InstabugAPMBridge.m b/ios/RNInstabug/InstabugAPMBridge.m
index c28c7f425..3fe3effe4 100644
--- a/ios/RNInstabug/InstabugAPMBridge.m
+++ b/ios/RNInstabug/InstabugAPMBridge.m
@@ -124,6 +124,10 @@ - (id) init
[IBGAPM endUITrace];
}
+// Enables or disables screen render.
+RCT_EXPORT_METHOD(setScreenRenderEnabled:(BOOL)isEnabled) {
+ IBGAPM.screenRenderingEnabled = isEnabled;
+}
diff --git a/ios/native.rb b/ios/native.rb
index 41f497687..8296dbcdb 100644
--- a/ios/native.rb
+++ b/ios/native.rb
@@ -1,4 +1,4 @@
-$instabug = { :version => '15.1.1' }
+$instabug = { :version => '15.1.26' }
def use_instabug! (spec = nil)
version = $instabug[:version]
diff --git a/src/modules/APM.ts b/src/modules/APM.ts
index 92d401389..d81d3cbb5 100644
--- a/src/modules/APM.ts
+++ b/src/modules/APM.ts
@@ -139,3 +139,11 @@ export const endUITrace = () => {
export const _ibgSleep = () => {
NativeAPM.ibgSleep();
};
+
+/**
+ * Enables or disables Screen Render feature
+ * @param isEnabled
+ */
+export const setScreenRenderEnabled = (isEnabled: boolean) => {
+ NativeAPM.setScreenRenderEnabled(isEnabled);
+};
diff --git a/src/native/NativeAPM.ts b/src/native/NativeAPM.ts
index 9fa30b702..67c7d8cd1 100644
--- a/src/native/NativeAPM.ts
+++ b/src/native/NativeAPM.ts
@@ -48,6 +48,9 @@ export interface ApmNativeModule extends NativeModule {
startUITrace(name: string): void;
endUITrace(): void;
ibgSleep(): void;
+
+ // Screen Rendering //
+ setScreenRenderEnabled(isEnabled: boolean): void;
}
export const NativeAPM = NativeModules.IBGAPM;
diff --git a/test/mocks/mockAPM.ts b/test/mocks/mockAPM.ts
index 27644c694..beb0b068b 100644
--- a/test/mocks/mockAPM.ts
+++ b/test/mocks/mockAPM.ts
@@ -17,6 +17,7 @@ const mockAPM: ApmNativeModule = {
endAppLaunch: jest.fn(),
ibgSleep: jest.fn(),
networkLogAndroid: jest.fn(),
+ setScreenRenderEnabled: jest.fn(),
};
export default mockAPM;
diff --git a/test/modules/APM.spec.ts b/test/modules/APM.spec.ts
index cf932d25c..39d5df4be 100644
--- a/test/modules/APM.spec.ts
+++ b/test/modules/APM.spec.ts
@@ -155,4 +155,11 @@ describe('APM Module', () => {
expect(NativeAPM.ibgSleep).toBeCalledTimes(1);
expect(NativeAPM.ibgSleep).toBeCalledWith();
});
+
+ it('should call the native method setScreenRenderEnabled', () => {
+ APM.setScreenRenderEnabled(true);
+
+ expect(NativeAPM.setScreenRenderEnabled).toBeCalledTimes(1);
+ expect(NativeAPM.setScreenRenderEnabled).toBeCalledWith(true);
+ });
});