Skip to content

Commit

Permalink
fix(react-native): react-native no longer requires the Gradle Kotli…
Browse files Browse the repository at this point in the history
…n plugin
  • Loading branch information
lemnik committed May 26, 2022
1 parent 9551d51 commit 2c07ece
Show file tree
Hide file tree
Showing 7 changed files with 349 additions and 390 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@

- Added `Bugsnag.isStarted()` to check whether Bugsnag has initialized [#1737](https://github.com/bugsnag/bugsnag-js/pull/1737)

### Fixed

- (react-native) Fixed Kotlin related [version conflict](https://github.com/bugsnag/bugsnag-js/issues/1734) with Android Gradle Plugin []()

## v7.16.6 (2022-05-25)

### Changed
Expand Down
7 changes: 4 additions & 3 deletions packages/react-native/android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
buildscript {
ext {
androidToolsVersion = '3.5.3'
}
repositories {
google()
mavenCentral()
Expand All @@ -7,13 +10,11 @@ buildscript {
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.61"
classpath "com.android.tools.build:gradle:${project.ext.androidToolsVersion}"
}
}

apply plugin: 'com.android.library'
apply plugin: "kotlin-android"

def safeExtGet(prop, fallback) {
rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
package com.bugsnag.android;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;

import java.util.Map;

import static com.facebook.react.modules.core.DeviceEventManagerModule.RCTDeviceEventEmitter;

public class BugsnagReactNative extends ReactContextBaseJavaModule {

private static final String UPDATE_CONTEXT = "ContextUpdate";
private static final String UPDATE_USER = "UserUpdate";
private static final String UPDATE_METADATA = "MetadataUpdate";
private static final String ADD_FEATURE_FLAG = "AddFeatureFlag";
private static final String CLEAR_FEATURE_FLAG = "ClearFeatureFlag";
private static final String SYNC_KEY = "bugsnag::sync";
private static final String DATA_KEY = "data";

private final ReactApplicationContext reactContext;

private RCTDeviceEventEmitter bridge;
private BugsnagReactNativePlugin plugin;
private Logger logger;

public BugsnagReactNative(ReactApplicationContext reactContext) {
super(reactContext);
this.reactContext = reactContext;
}

private void logFailure(String msg, Throwable exc) {
logger.e("Failed to call " + msg + " on bugsnag-plugin-react-native, continuing", exc);
}

@Override
public String getName() {
return "BugsnagReactNative";
}

@ReactMethod
public void configureAsync(ReadableMap env, Promise promise) {
promise.resolve(configure(env));
}

@ReactMethod(isBlockingSynchronousMethod = true)
public WritableMap configure(ReadableMap env) {
Client client;
try {
client = Bugsnag.getClient();
} catch (IllegalStateException ise) {
throw new IllegalStateException("Failed to initialise the native Bugsnag Android client, please check you have " +
"added Bugsnag.start() in the onCreate() method of your Application subclass");
}

try {
bridge = reactContext.getJSModule(RCTDeviceEventEmitter.class);
logger = client.getLogger();
plugin = (BugsnagReactNativePlugin) client.getPlugin(BugsnagReactNativePlugin.class);
plugin.registerForMessageEvents(new Function1<MessageEvent, Unit>() {
@Override
public Unit invoke(MessageEvent messageEvent) {
emitEvent(messageEvent);
return Unit.INSTANCE;
}
});

return ReactNativeCompat.toWritableMap(plugin.configure(env.toHashMap()));
} catch (Throwable error) {
logFailure("configure", error);
return new WritableNativeMap();
}
}

@SuppressWarnings("unchecked")
void emitEvent(MessageEvent event) {
logger.d("Received MessageEvent: " + event.getType());

WritableMap map = Arguments.createMap();
map.putString("type", event.getType());

switch (event.getType()) {
case UPDATE_CONTEXT:
map.putString(DATA_KEY, (String) event.getData());
break;
case UPDATE_USER:
case UPDATE_METADATA:
case ADD_FEATURE_FLAG:
case CLEAR_FEATURE_FLAG:
map.putMap(DATA_KEY, event.getData() != null
? Arguments.makeNativeMap((Map<String, Object>) event.getData())
: null);
break;
default:
logger.w("Received unknown message event " + event.getType() + ", ignoring");
}

bridge.emit(SYNC_KEY, map);
}

@ReactMethod
void updateCodeBundleId(@Nullable String id) {
try {
plugin.updateCodeBundleId(id);
} catch (Throwable exc) {
logFailure("updateCodeBundleId", exc);
}
}

@ReactMethod
void leaveBreadcrumb(@NonNull ReadableMap map) {
try {
plugin.leaveBreadcrumb(map.toHashMap());
} catch (Throwable exc) {
logFailure("leaveBreadcrumb", exc);
}
}

@ReactMethod
void startSession() {
try {
plugin.startSession();
} catch (Throwable exc) {
logFailure("startSession", exc);
}
}

@ReactMethod
void pauseSession() {
try {
plugin.pauseSession();
} catch (Throwable exc) {
logFailure("pauseSession", exc);
}
}

@ReactMethod
void resumeSession() {
try {
plugin.resumeSession();
} catch (Throwable exc) {
logFailure("resumeSession", exc);
}
}

@ReactMethod
void updateContext(@Nullable String context) {
try {
plugin.updateContext(context);
} catch (Throwable exc) {
logFailure("updateContext", exc);
}
}

@ReactMethod
void addMetadata(@NonNull String section, @Nullable ReadableMap data) {
try {
plugin.addMetadata(section, data != null ? data.toHashMap() : null);
} catch (Throwable exc) {
logFailure("addMetadata", exc);
}
}

@ReactMethod
void clearMetadata(@NonNull String section, @Nullable String key) {
try {
plugin.clearMetadata(section, key);
} catch (Throwable exc) {
logFailure("clearMetadata", exc);
}
}

@ReactMethod
void updateUser(@Nullable String id, @Nullable String email, @Nullable String name) {
try {
plugin.updateUser(id, email, name);
} catch (Throwable exc) {
logFailure("updateUser", exc);
}
}

@ReactMethod
void dispatch(@NonNull ReadableMap payload, @NonNull Promise promise) {
try {
plugin.dispatch(payload.toHashMap());
promise.resolve(true);
} catch (Throwable exc) {
logFailure("dispatch", exc);
promise.resolve(false);
}
}

@ReactMethod
void getPayloadInfo(@NonNull ReadableMap payload, @NonNull Promise promise) {
try {
boolean unhandled = payload.getBoolean("unhandled");
Map<String, Object> info = plugin.getPayloadInfo(unhandled);
promise.resolve(ReactNativeCompat.toWritableMap(info));
} catch (Throwable exc) {
logFailure("dispatch", exc);
promise.resolve(null);
}
}

@ReactMethod
void addFeatureFlag(@NonNull String name, @Nullable String variant) {
try {
plugin.addFeatureFlag(name, variant);
} catch (Throwable exc) {
logFailure("addFeatureFlag", exc);
}
}

@ReactMethod
void addFeatureFlags(@NonNull ReadableArray flags) {
try {
final int flagCount = flags.size();
for (int index = 0; index < flagCount; index++) {
ReadableMap flag = flags.getMap(index);
String name = safeGetString(flag, "name");

if (name != null) {
plugin.addFeatureFlag(name, safeGetString(flag, "variant"));
}
}
} catch (Throwable exc) {
logFailure("addFeatureFlags", exc);
}
}

@ReactMethod
void clearFeatureFlag(@NonNull String name) {
try {
plugin.clearFeatureFlag(name);
} catch (Throwable exc) {
logFailure("clearFeatureFlag", exc);
}
}

@ReactMethod
void clearFeatureFlags() {
try {
plugin.clearFeatureFlags();
} catch (Throwable exc) {
logFailure("clearFeatureFlags", exc);
}
}

private String safeGetString(@NonNull ReadableMap map, @NonNull String key) {
return map.hasKey(key) ? map.getString(key) : null;
}
}
Loading

0 comments on commit 2c07ece

Please sign in to comment.