Skip to content

feat: enable/disable auto masking screenshots in rn #1389

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 20, 2025
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Added

- Add support enable/disable screenshot auto masking. ([#1389](https://github.com/Instabug/Instabug-React-Native/pull/1389))

- Add support for BugReporting user consents. ([#1383](https://github.com/Instabug/Instabug-React-Native/pull/1383))

- Add support for xCode 16. ([#1370](https://github.com/Instabug/Instabug-React-Native/pull/1370))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import com.instabug.library.invocation.util.InstabugVideoRecordingButtonPosition;
import com.instabug.library.sessionreplay.model.SessionMetadata;
import com.instabug.library.ui.onboarding.WelcomeMessage;
import com.instabug.library.MaskingType;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -60,6 +61,7 @@ static Map<String, Object> getAll() {
putAll(locales);
putAll(placeholders);
putAll(launchType);
putAll(autoMaskingTypes);
putAll(userConsentActionType);
}};
}
Expand Down Expand Up @@ -260,5 +262,10 @@ static Map<String, Object> getAll() {
put(SessionMetadata.LaunchType.COLD,"cold");
put(SessionMetadata.LaunchType.WARM,"warm" );
}};

public static final ArgsMap<Integer> autoMaskingTypes = new ArgsMap<Integer>() {{
put("labels", MaskingType.LABELS);
put("textInputs", MaskingType.TEXT_INPUTS);
put("media", MaskingType.MEDIA);
put("none", MaskingType.MASK_NOTHING);
}};
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ public void setEnabled(final boolean isEnabled) {
@Override
public void run() {
try {
if(isEnabled)
if (isEnabled)
Instabug.enable();
else
Instabug.disable();
Expand All @@ -133,10 +133,11 @@ public void run() {

/**
* Initializes the SDK.
* @param token The token that identifies the app. You can find it on your dashboard.
*
* @param token The token that identifies the app. You can find it on your dashboard.
* @param invocationEventValues The events that invoke the SDK's UI.
* @param logLevel The level of detail in logs that you want to print.
* @param codePushVersion The Code Push version to be used for all reports.
* @param logLevel The level of detail in logs that you want to print.
* @param codePushVersion The Code Push version to be used for all reports.
*/
@ReactMethod
public void init(
Expand All @@ -162,8 +163,8 @@ public void run() {
.setInvocationEvents(invocationEvents)
.setLogLevel(parsedLogLevel);

if(codePushVersion != null) {
if(Instabug.isBuilt()) {
if (codePushVersion != null) {
if (Instabug.isBuilt()) {
Instabug.setCodePushVersion(codePushVersion);
} else {
builder.setCodePushVersion(codePushVersion);
Expand Down Expand Up @@ -329,7 +330,7 @@ public void run() {
*
* @param userEmail User's default email
* @param userName Username.
* @param userId User's ID
* @param userId User's ID
*/
@ReactMethod
public void identifyUser(
Expand Down Expand Up @@ -749,15 +750,15 @@ public void addFileAttachmentWithDataToReport(String data, String fileName) {

private WritableMap convertFromHashMapToWriteableMap(HashMap hashMap) {
WritableMap writableMap = new WritableNativeMap();
for(int i = 0; i < hashMap.size(); i++) {
for (int i = 0; i < hashMap.size(); i++) {
Object key = hashMap.keySet().toArray()[i];
Object value = hashMap.get(key);
writableMap.putString((String) key,(String) value);
writableMap.putString((String) key, (String) value);
}
return writableMap;
}

private static JSONObject objectToJSONObject(Object object){
private static JSONObject objectToJSONObject(Object object) {
Object json = null;
JSONObject jsonObject = null;
try {
Expand All @@ -774,13 +775,12 @@ private static JSONObject objectToJSONObject(Object object){
private WritableArray convertArrayListToWritableArray(List arrayList) {
WritableArray writableArray = new WritableNativeArray();

for(int i = 0; i < arrayList.size(); i++) {
for (int i = 0; i < arrayList.size(); i++) {
Object object = arrayList.get(i);

if(object instanceof String) {
if (object instanceof String) {
writableArray.pushString((String) object);
}
else {
} else {
JSONObject jsonObject = objectToJSONObject(object);
writableArray.pushMap((WritableMap) jsonObject);
}
Expand Down Expand Up @@ -836,7 +836,7 @@ public void run() {
* Shows the welcome message in a specific mode.
*
* @param welcomeMessageMode An enum to set the welcome message mode to
* live, or beta.
* live, or beta.
*/
@ReactMethod
public void showWelcomeMessageWithMode(final String welcomeMessageMode) {
Expand All @@ -858,7 +858,7 @@ public void run() {
* Sets the welcome message mode to live, beta or disabled.
*
* @param welcomeMessageMode An enum to set the welcome message mode to
* live, beta or disabled.
* live, beta or disabled.
*/
@ReactMethod
public void setWelcomeMessageMode(final String welcomeMessageMode) {
Expand Down Expand Up @@ -993,7 +993,6 @@ public void run() {
* Reports that the screen name been changed (Current View).
*
* @param screenName string containing the screen name
*
*/
@ReactMethod
public void reportCurrentViewChange(final String screenName) {
Expand All @@ -1016,7 +1015,6 @@ public void run() {
* Reports that the screen has been changed (Repro Steps) the screen sent to this method will be the 'current view' on the dashboard
*
* @param screenName string containing the screen name
*
*/
@ReactMethod
public void reportScreenChange(final String screenName) {
Expand All @@ -1026,7 +1024,7 @@ public void run() {
try {
Method method = getMethod(Class.forName("com.instabug.library.Instabug"), "reportScreenChange", Bitmap.class, String.class);
if (method != null) {
method.invoke(null , null, screenName);
method.invoke(null, null, screenName);
}
} catch (Exception e) {
e.printStackTrace();
Expand Down Expand Up @@ -1120,7 +1118,7 @@ public void removeFeatureFlags(final ReadableArray featureFlags) {
@Override
public void run() {
try {
ArrayList<String> stringArray = ArrayUtil.parseReadableArrayOfStrings(featureFlags);
ArrayList<String> stringArray = ArrayUtil.parseReadableArrayOfStrings(featureFlags);
Instabug.removeFeatureFlag(stringArray);
} catch (Exception e) {
e.printStackTrace();
Expand Down Expand Up @@ -1156,11 +1154,12 @@ public void run() {
}
});
}

/**
* Register a listener for W3C flags value change
*/
@ReactMethod
public void registerW3CFlagsChangeListener(){
public void registerW3CFlagsChangeListener() {

MainThreadHandler.runOnMainThread(new Runnable() {
@Override
Expand All @@ -1177,8 +1176,7 @@ public void invoke(@NonNull CoreFeaturesState featuresState) {
sendEvent(Constants.IBG_ON_NEW_W3C_FLAGS_UPDATE_RECEIVED_CALLBACK, params);
}
});
}
catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
}

Expand All @@ -1189,18 +1187,17 @@ public void invoke(@NonNull CoreFeaturesState featuresState) {


/**
* Get first time Value of W3ExternalTraceID flag
* Get first time Value of W3ExternalTraceID flag
*/
@ReactMethod
public void isW3ExternalTraceIDEnabled(Promise promise){
public void isW3ExternalTraceIDEnabled(Promise promise) {

MainThreadHandler.runOnMainThread(new Runnable() {
@Override
public void run() {
try {
promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_EXTERNAL_TRACE_ID));
}
catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
promise.resolve(false);
}
Expand All @@ -1212,18 +1209,17 @@ public void run() {


/**
* Get first time Value of W3ExternalGeneratedHeader flag
* Get first time Value of W3ExternalGeneratedHeader flag
*/
@ReactMethod
public void isW3ExternalGeneratedHeaderEnabled(Promise promise){
public void isW3ExternalGeneratedHeaderEnabled(Promise promise) {

MainThreadHandler.runOnMainThread(new Runnable() {
@Override
public void run() {
try {
promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_GENERATED_HEADER));
}
catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
promise.resolve(false);
}
Expand All @@ -1234,18 +1230,17 @@ public void run() {
}

/**
* Get first time Value of W3CaughtHeader flag
* Get first time Value of W3CaughtHeader flag
*/
@ReactMethod
public void isW3CaughtHeaderEnabled(Promise promise){
public void isW3CaughtHeaderEnabled(Promise promise) {

MainThreadHandler.runOnMainThread(new Runnable() {
@Override
public void run() {
try {
promise.resolve(InternalCore.INSTANCE._isFeatureEnabled(CoreFeature.W3C_ATTACHING_CAPTURED_HEADER));
}
catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
promise.resolve(false);
}
Expand Down Expand Up @@ -1292,4 +1287,29 @@ public void run() {
}
});
}
/**
/**
* Sets the auto mask screenshots types.
*
* @param autoMaskingTypes The masking type to be applied.
*/
@ReactMethod
public void enableAutoMasking(@NonNull ReadableArray autoMaskingTypes) {
MainThreadHandler.runOnMainThread(new Runnable() {

@Override
public void run() {
int[] autoMassingTypesArray = new int[autoMaskingTypes.size()];
for (int i = 0; i < autoMaskingTypes.size(); i++) {
String key = autoMaskingTypes.getString(i);

autoMassingTypesArray[i] = ArgsRegistry.autoMaskingTypes.get(key);

}

Instabug.setAutoMaskScreenshotsTypes(autoMassingTypesArray);
}

});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import com.instabug.library.internal.module.InstabugLocale;
import com.instabug.library.ui.onboarding.WelcomeMessage;
import com.instabug.reactlibrary.utils.MainThreadHandler;
import com.instabug.library.MaskingType;

import org.junit.After;
import org.junit.Assert;
Expand Down Expand Up @@ -677,4 +678,17 @@ public void testSetNetworkLogBodyDisabled() {

mockInstabug.verify(() -> Instabug.setNetworkLogBodyEnabled(false));
}

@Test
public void testEnableAutoMasking(){

String maskLabel = "labels";
String maskTextInputs = "textInputs";
String maskMedia = "media";
String maskNone = "none";

rnModule.enableAutoMasking(JavaOnlyArray.of(maskLabel, maskMedia, maskTextInputs,maskNone));

mockInstabug.verify(() -> Instabug.setAutoMaskScreenshotsTypes(MaskingType.LABELS,MaskingType.MEDIA,MaskingType.TEXT_INPUTS,MaskingType.MASK_NOTHING));
}
}
16 changes: 16 additions & 0 deletions examples/default/ios/InstabugTests/InstabugSampleTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -608,6 +608,22 @@ - (void) testIsW3CaughtHeaderEnabled {
OCMVerify([mock w3CaughtHeaderEnabled]);
}

- (void)testEnableAutoMasking {
id mock = OCMClassMock([Instabug class]);

NSArray *autoMaskingTypes = [NSArray arrayWithObjects:
[NSNumber numberWithInteger:IBGAutoMaskScreenshotOptionLabels],
[NSNumber numberWithInteger:IBGAutoMaskScreenshotOptionTextInputs],
[NSNumber numberWithInteger:IBGAutoMaskScreenshotOptionMedia],
[NSNumber numberWithInteger:IBGAutoMaskScreenshotOptionMaskNothing],
nil];

OCMStub([mock setAutoMaskScreenshots:IBGAutoMaskScreenshotOptionLabels | IBGAutoMaskScreenshotOptionTextInputs | IBGAutoMaskScreenshotOptionMedia | IBGAutoMaskScreenshotOptionMaskNothing]);

[self.instabugBridge enableAutoMasking:autoMaskingTypes];

OCMVerify([mock setAutoMaskScreenshots:IBGAutoMaskScreenshotOptionLabels | IBGAutoMaskScreenshotOptionTextInputs | IBGAutoMaskScreenshotOptionMedia | IBGAutoMaskScreenshotOptionMaskNothing]);
}

- (void)testSetNetworkLogBodyEnabled {
id mock = OCMClassMock([IBGNetworkLogger class]);
Expand Down
1 change: 1 addition & 0 deletions ios/RNInstabug/ArgsRegistry.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ typedef NSDictionary<NSString*, NSNumber*> ArgsDictionary;
+ (ArgsDictionary *) userConsentActionTypes;

+ (NSDictionary<NSString *, NSString *> *) placeholders;
+ (ArgsDictionary *)autoMaskingTypes;

@end
9 changes: 9 additions & 0 deletions ios/RNInstabug/ArgsRegistry.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ + (NSMutableDictionary *) getAll {
[all addEntriesFromDictionary:ArgsRegistry.nonFatalExceptionLevel];
[all addEntriesFromDictionary:ArgsRegistry.placeholders];
[all addEntriesFromDictionary:ArgsRegistry.launchType];
[all addEntriesFromDictionary:ArgsRegistry.autoMaskingTypes];
[all addEntriesFromDictionary:ArgsRegistry.userConsentActionTypes];

return all;
Expand Down Expand Up @@ -256,4 +257,12 @@ + (ArgsDictionary *) launchType {
};
}

+ (ArgsDictionary *)autoMaskingTypes {
return @{
@"labels" : @(IBGAutoMaskScreenshotOptionLabels),
@"textInputs" : @(IBGAutoMaskScreenshotOptionTextInputs),
@"media" : @(IBGAutoMaskScreenshotOptionMedia),
@"none" : @(IBGAutoMaskScreenshotOptionMaskNothing)
};
}
@end
1 change: 1 addition & 0 deletions ios/RNInstabug/InstabugReactBridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,5 +139,6 @@ w3cExternalTraceAttributes:(NSDictionary * _Nullable)w3cExternalTraceAttributes;
- (void)removeFeatureFlags:(NSArray *)featureFlags;
- (void)removeAllFeatureFlags;
- (void)setNetworkLogBodyEnabled:(BOOL)isEnabled;
- (void)enableAutoMasking:(NSArray *)autoMaskingTypes;

@end
13 changes: 13 additions & 0 deletions ios/RNInstabug/InstabugReactBridge.m
Original file line number Diff line number Diff line change
Expand Up @@ -443,4 +443,17 @@ + (BOOL)iOSVersionIsLessThan:(NSString *)iOSVersion {
RCT_EXPORT_METHOD(setNetworkLogBodyEnabled:(BOOL)isEnabled) {
IBGNetworkLogger.logBodyEnabled = isEnabled;
}

RCT_EXPORT_METHOD(enableAutoMasking:(NSArray *)autoMaskingTypes) {

IBGAutoMaskScreenshotOption autoMaskingOptions = 0;

for (NSNumber *event in autoMaskingTypes) {

autoMaskingOptions |= [event intValue];
}

[Instabug setAutoMaskScreenshots: autoMaskingOptions];

};
@end
Loading