@sentry/react-native 6.0.0-rc.1 → 6.1.0
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.
- package/README.md +8 -0
- package/RNSentry.podspec +1 -1
- package/android/build.gradle +1 -1
- package/android/src/main/java/io/sentry/react/RNSentryBreadcrumb.java +67 -66
- package/android/src/main/java/io/sentry/react/RNSentryMapConverter.java +110 -110
- package/android/src/main/java/io/sentry/react/RNSentryModuleImpl.java +868 -813
- package/android/src/main/java/io/sentry/react/RNSentryOnDrawReporterManager.java +128 -121
- package/android/src/main/java/io/sentry/react/RNSentryPackage.java +8 -14
- package/android/src/main/java/io/sentry/react/RNSentryReactFragmentLifecycleTracer.java +76 -70
- package/android/src/main/java/io/sentry/react/RNSentryReplayBreadcrumbConverter.java +29 -38
- package/android/src/newarch/java/io/sentry/react/RNSentryModule.java +164 -165
- package/android/src/oldarch/java/io/sentry/react/RNSentryModule.java +164 -165
- package/dist/js/integrations/nativelinkederrors.js +7 -2
- package/dist/js/integrations/nativelinkederrors.js.map +1 -1
- package/dist/js/tracing/timetodisplay.d.ts.map +1 -1
- package/dist/js/tracing/timetodisplay.js +3 -1
- package/dist/js/tracing/timetodisplay.js.map +1 -1
- package/dist/js/version.d.ts +1 -1
- package/dist/js/version.d.ts.map +1 -1
- package/dist/js/version.js +1 -1
- package/dist/js/version.js.map +1 -1
- package/dist/js/wrapper.d.ts +1 -1
- package/dist/js/wrapper.d.ts.map +1 -1
- package/dist/js/wrapper.js +37 -5
- package/dist/js/wrapper.js.map +1 -1
- package/ios/RNSentry.mm +9 -1
- package/package.json +9 -9
- package/plugin/build/utils.js +6 -6
- package/plugin/build/withSentry.js +2 -2
- package/plugin/build/withSentryAndroid.js +2 -2
- package/plugin/build/withSentryIOS.js +3 -3
- package/ts3.8/dist/js/version.d.ts +1 -1
- package/ts3.8/dist/js/wrapper.d.ts +1 -1
|
@@ -3,7 +3,6 @@ package io.sentry.react;
|
|
|
3
3
|
import android.app.Activity;
|
|
4
4
|
import android.content.Context;
|
|
5
5
|
import android.view.View;
|
|
6
|
-
|
|
7
6
|
import com.facebook.react.bridge.Arguments;
|
|
8
7
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
9
8
|
import com.facebook.react.bridge.WritableMap;
|
|
@@ -12,12 +11,6 @@ import com.facebook.react.uimanager.SimpleViewManager;
|
|
|
12
11
|
import com.facebook.react.uimanager.ThemedReactContext;
|
|
13
12
|
import com.facebook.react.uimanager.annotations.ReactProp;
|
|
14
13
|
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
|
15
|
-
|
|
16
|
-
import org.jetbrains.annotations.NotNull;
|
|
17
|
-
import org.jetbrains.annotations.Nullable;
|
|
18
|
-
|
|
19
|
-
import java.util.Map;
|
|
20
|
-
|
|
21
14
|
import io.sentry.ILogger;
|
|
22
15
|
import io.sentry.SentryDate;
|
|
23
16
|
import io.sentry.SentryDateProvider;
|
|
@@ -26,131 +19,145 @@ import io.sentry.android.core.AndroidLogger;
|
|
|
26
19
|
import io.sentry.android.core.BuildInfoProvider;
|
|
27
20
|
import io.sentry.android.core.SentryAndroidDateProvider;
|
|
28
21
|
import io.sentry.android.core.internal.util.FirstDrawDoneListener;
|
|
22
|
+
import java.util.Map;
|
|
23
|
+
import org.jetbrains.annotations.NotNull;
|
|
24
|
+
import org.jetbrains.annotations.Nullable;
|
|
29
25
|
|
|
30
|
-
public class RNSentryOnDrawReporterManager
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
public class RNSentryOnDrawReporterManager
|
|
27
|
+
extends SimpleViewManager<RNSentryOnDrawReporterManager.RNSentryOnDrawReporterView> {
|
|
28
|
+
|
|
29
|
+
public static final String REACT_CLASS = "RNSentryOnDrawReporter";
|
|
30
|
+
private final @NotNull ReactApplicationContext mCallerContext;
|
|
31
|
+
|
|
32
|
+
public RNSentryOnDrawReporterManager(ReactApplicationContext reactContext) {
|
|
33
|
+
mCallerContext = reactContext;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
@NotNull
|
|
37
|
+
@Override
|
|
38
|
+
public String getName() {
|
|
39
|
+
return REACT_CLASS;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@NotNull
|
|
43
|
+
@Override
|
|
44
|
+
protected RNSentryOnDrawReporterView createViewInstance(
|
|
45
|
+
@NotNull ThemedReactContext themedReactContext) {
|
|
46
|
+
return new RNSentryOnDrawReporterView(
|
|
47
|
+
mCallerContext, new BuildInfoProvider(new AndroidLogger()));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@ReactProp(name = "initialDisplay", defaultBoolean = false)
|
|
51
|
+
public void setInitialDisplay(RNSentryOnDrawReporterView view, boolean initialDisplay) {
|
|
52
|
+
view.setInitialDisplay(initialDisplay);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@ReactProp(name = "fullDisplay", defaultBoolean = false)
|
|
56
|
+
public void setFullDisplay(RNSentryOnDrawReporterView view, boolean fullDisplay) {
|
|
57
|
+
view.setFullDisplay(fullDisplay);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public Map getExportedCustomBubblingEventTypeConstants() {
|
|
61
|
+
return MapBuilder.builder()
|
|
62
|
+
.put(
|
|
63
|
+
"onDrawNextFrameView",
|
|
64
|
+
MapBuilder.of("phasedRegistrationNames", MapBuilder.of("bubbled", "onDrawNextFrame")))
|
|
65
|
+
.build();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
public static class RNSentryOnDrawReporterView extends View {
|
|
69
|
+
|
|
70
|
+
private static final ILogger logger = new AndroidLogger("RNSentryOnDrawReporterView");
|
|
71
|
+
|
|
72
|
+
private final @Nullable ReactApplicationContext reactContext;
|
|
73
|
+
private final @NotNull SentryDateProvider dateProvider = new SentryAndroidDateProvider();
|
|
74
|
+
private final @Nullable Runnable emitInitialDisplayEvent;
|
|
75
|
+
private final @Nullable Runnable emitFullDisplayEvent;
|
|
76
|
+
private final @Nullable BuildInfoProvider buildInfo;
|
|
77
|
+
|
|
78
|
+
public RNSentryOnDrawReporterView(@NotNull Context context) {
|
|
79
|
+
super(context);
|
|
80
|
+
reactContext = null;
|
|
81
|
+
buildInfo = null;
|
|
82
|
+
emitInitialDisplayEvent = null;
|
|
83
|
+
emitFullDisplayEvent = null;
|
|
37
84
|
}
|
|
38
85
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
86
|
+
public RNSentryOnDrawReporterView(
|
|
87
|
+
@NotNull ReactApplicationContext context, @NotNull BuildInfoProvider buildInfoProvider) {
|
|
88
|
+
super(context);
|
|
89
|
+
reactContext = context;
|
|
90
|
+
buildInfo = buildInfoProvider;
|
|
91
|
+
emitInitialDisplayEvent = () -> emitDisplayEvent("initialDisplay");
|
|
92
|
+
emitFullDisplayEvent = () -> emitDisplayEvent("fullDisplay");
|
|
43
93
|
}
|
|
44
94
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
95
|
+
public void setFullDisplay(boolean fullDisplay) {
|
|
96
|
+
if (!fullDisplay) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
50
99
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
view.setInitialDisplay(initialDisplay);
|
|
100
|
+
logger.log(SentryLevel.DEBUG, "[TimeToDisplay] Register full display event emitter.");
|
|
101
|
+
registerForNextDraw(emitFullDisplayEvent);
|
|
54
102
|
}
|
|
55
103
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
104
|
+
public void setInitialDisplay(boolean initialDisplay) {
|
|
105
|
+
if (!initialDisplay) {
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
logger.log(SentryLevel.DEBUG, "[TimeToDisplay] Register initial display event emitter.");
|
|
110
|
+
registerForNextDraw(emitInitialDisplayEvent);
|
|
59
111
|
}
|
|
60
112
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
113
|
+
private void registerForNextDraw(@Nullable Runnable emitter) {
|
|
114
|
+
if (emitter == null) {
|
|
115
|
+
logger.log(
|
|
116
|
+
SentryLevel.ERROR,
|
|
117
|
+
"[TimeToDisplay] Won't emit next frame drawn event, emitter is null.");
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (buildInfo == null) {
|
|
121
|
+
logger.log(
|
|
122
|
+
SentryLevel.ERROR,
|
|
123
|
+
"[TimeToDisplay] Won't emit next frame drawn event, buildInfo is null.");
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
if (reactContext == null) {
|
|
127
|
+
logger.log(
|
|
128
|
+
SentryLevel.ERROR,
|
|
129
|
+
"[TimeToDisplay] Won't emit next frame drawn event, reactContext is null.");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@Nullable Activity activity = reactContext.getCurrentActivity();
|
|
134
|
+
if (activity == null) {
|
|
135
|
+
logger.log(
|
|
136
|
+
SentryLevel.ERROR,
|
|
137
|
+
"[TimeToDisplay] Won't emit next frame drawn event, reactContext is null.");
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
FirstDrawDoneListener.registerForNextDraw(activity, emitter, buildInfo);
|
|
69
142
|
}
|
|
70
143
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
public RNSentryOnDrawReporterView(@NotNull ReactApplicationContext context, @NotNull BuildInfoProvider buildInfoProvider) {
|
|
91
|
-
super(context);
|
|
92
|
-
reactContext = context;
|
|
93
|
-
buildInfo = buildInfoProvider;
|
|
94
|
-
emitInitialDisplayEvent = () -> emitDisplayEvent("initialDisplay");
|
|
95
|
-
emitFullDisplayEvent = () -> emitDisplayEvent("fullDisplay");
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
public void setFullDisplay(boolean fullDisplay) {
|
|
99
|
-
if (!fullDisplay) {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
logger.log(SentryLevel.DEBUG, "[TimeToDisplay] Register full display event emitter.");
|
|
104
|
-
registerForNextDraw(emitFullDisplayEvent);
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
public void setInitialDisplay(boolean initialDisplay) {
|
|
108
|
-
if (!initialDisplay) {
|
|
109
|
-
return;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
logger.log(SentryLevel.DEBUG, "[TimeToDisplay] Register initial display event emitter.");
|
|
113
|
-
registerForNextDraw(emitInitialDisplayEvent);
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
private void registerForNextDraw(@Nullable Runnable emitter) {
|
|
117
|
-
if (emitter == null) {
|
|
118
|
-
logger.log(SentryLevel.ERROR, "[TimeToDisplay] Won't emit next frame drawn event, emitter is null.");
|
|
119
|
-
return;
|
|
120
|
-
}
|
|
121
|
-
if (buildInfo == null) {
|
|
122
|
-
logger.log(SentryLevel.ERROR, "[TimeToDisplay] Won't emit next frame drawn event, buildInfo is null.");
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
if (reactContext == null) {
|
|
126
|
-
logger.log(SentryLevel.ERROR, "[TimeToDisplay] Won't emit next frame drawn event, reactContext is null.");
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
@Nullable Activity activity = reactContext.getCurrentActivity();
|
|
131
|
-
if (activity == null) {
|
|
132
|
-
logger.log(SentryLevel.ERROR, "[TimeToDisplay] Won't emit next frame drawn event, reactContext is null.");
|
|
133
|
-
return;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
FirstDrawDoneListener
|
|
137
|
-
.registerForNextDraw(activity, emitter, buildInfo);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
private void emitDisplayEvent(String type) {
|
|
141
|
-
final SentryDate endDate = dateProvider.now();
|
|
142
|
-
|
|
143
|
-
WritableMap event = Arguments.createMap();
|
|
144
|
-
event.putString("type", type);
|
|
145
|
-
event.putDouble("newFrameTimestampInSeconds", endDate.nanoTimestamp() / 1e9);
|
|
146
|
-
|
|
147
|
-
if (reactContext == null) {
|
|
148
|
-
logger.log(SentryLevel.ERROR, "[TimeToDisplay] Recorded next frame draw but can't emit the event, reactContext is null.");
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
reactContext
|
|
152
|
-
.getJSModule(RCTEventEmitter.class)
|
|
153
|
-
.receiveEvent(getId(), "onDrawNextFrameView", event);
|
|
154
|
-
}
|
|
144
|
+
private void emitDisplayEvent(String type) {
|
|
145
|
+
final SentryDate endDate = dateProvider.now();
|
|
146
|
+
|
|
147
|
+
WritableMap event = Arguments.createMap();
|
|
148
|
+
event.putString("type", type);
|
|
149
|
+
event.putDouble("newFrameTimestampInSeconds", endDate.nanoTimestamp() / 1e9);
|
|
150
|
+
|
|
151
|
+
if (reactContext == null) {
|
|
152
|
+
logger.log(
|
|
153
|
+
SentryLevel.ERROR,
|
|
154
|
+
"[TimeToDisplay] Recorded next frame draw but can't emit the event, reactContext is"
|
|
155
|
+
+ " null.");
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
reactContext
|
|
159
|
+
.getJSModule(RCTEventEmitter.class)
|
|
160
|
+
.receiveEvent(getId(), "onDrawNextFrameView", event);
|
|
155
161
|
}
|
|
162
|
+
}
|
|
156
163
|
}
|
|
@@ -2,18 +2,16 @@ package io.sentry.react;
|
|
|
2
2
|
|
|
3
3
|
import androidx.annotation.NonNull;
|
|
4
4
|
import androidx.annotation.Nullable;
|
|
5
|
-
|
|
6
|
-
import java.util.Arrays;
|
|
7
|
-
import java.util.HashMap;
|
|
8
|
-
import java.util.List;
|
|
9
|
-
import java.util.Map;
|
|
10
|
-
|
|
5
|
+
import com.facebook.react.TurboReactPackage;
|
|
11
6
|
import com.facebook.react.bridge.NativeModule;
|
|
12
7
|
import com.facebook.react.bridge.ReactApplicationContext;
|
|
13
8
|
import com.facebook.react.module.model.ReactModuleInfo;
|
|
14
9
|
import com.facebook.react.module.model.ReactModuleInfoProvider;
|
|
15
|
-
import com.facebook.react.TurboReactPackage;
|
|
16
10
|
import com.facebook.react.uimanager.ViewManager;
|
|
11
|
+
import java.util.Arrays;
|
|
12
|
+
import java.util.HashMap;
|
|
13
|
+
import java.util.List;
|
|
14
|
+
import java.util.Map;
|
|
17
15
|
|
|
18
16
|
public class RNSentryPackage extends TurboReactPackage {
|
|
19
17
|
|
|
@@ -42,18 +40,14 @@ public class RNSentryPackage extends TurboReactPackage {
|
|
|
42
40
|
true, // hasConstants
|
|
43
41
|
false, // isCxxModule
|
|
44
42
|
isTurboModule // isTurboModule
|
|
45
|
-
|
|
43
|
+
));
|
|
46
44
|
return moduleInfos;
|
|
47
45
|
};
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
@NonNull
|
|
51
49
|
@Override
|
|
52
|
-
public List<ViewManager> createViewManagers(
|
|
53
|
-
|
|
54
|
-
return Arrays.asList(
|
|
55
|
-
new RNSentryOnDrawReporterManager(reactContext)
|
|
56
|
-
);
|
|
50
|
+
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
|
51
|
+
return Arrays.asList(new RNSentryOnDrawReporterManager(reactContext));
|
|
57
52
|
}
|
|
58
|
-
|
|
59
53
|
}
|
|
@@ -1,99 +1,105 @@
|
|
|
1
1
|
package io.sentry.react;
|
|
2
2
|
|
|
3
|
+
import android.os.Bundle;
|
|
4
|
+
import android.view.View;
|
|
5
|
+
import android.view.ViewGroup;
|
|
3
6
|
import androidx.annotation.NonNull;
|
|
4
7
|
import androidx.fragment.app.Fragment;
|
|
5
8
|
import androidx.fragment.app.FragmentManager;
|
|
6
9
|
import androidx.fragment.app.FragmentManager.FragmentLifecycleCallbacks;
|
|
7
|
-
|
|
8
|
-
import android.os.Bundle;
|
|
9
|
-
import android.view.View;
|
|
10
|
-
import android.view.ViewGroup;
|
|
11
|
-
|
|
12
10
|
import com.facebook.react.bridge.ReactContext;
|
|
13
11
|
import com.facebook.react.uimanager.UIManagerHelper;
|
|
14
12
|
import com.facebook.react.uimanager.events.Event;
|
|
15
13
|
import com.facebook.react.uimanager.events.EventDispatcher;
|
|
16
14
|
import com.facebook.react.uimanager.events.EventDispatcherListener;
|
|
17
|
-
|
|
18
|
-
import org.jetbrains.annotations.Nullable;
|
|
19
|
-
import org.jetbrains.annotations.NotNull;
|
|
20
|
-
|
|
21
15
|
import io.sentry.ILogger;
|
|
22
16
|
import io.sentry.SentryLevel;
|
|
23
17
|
import io.sentry.android.core.BuildInfoProvider;
|
|
24
18
|
import io.sentry.android.core.internal.util.FirstDrawDoneListener;
|
|
19
|
+
import org.jetbrains.annotations.NotNull;
|
|
20
|
+
import org.jetbrains.annotations.Nullable;
|
|
25
21
|
|
|
26
22
|
public class RNSentryReactFragmentLifecycleTracer extends FragmentLifecycleCallbacks {
|
|
27
23
|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
private @NotNull final BuildInfoProvider buildInfoProvider;
|
|
25
|
+
private @NotNull final Runnable emitNewFrameEvent;
|
|
26
|
+
private @NotNull final ILogger logger;
|
|
27
|
+
|
|
28
|
+
public RNSentryReactFragmentLifecycleTracer(
|
|
29
|
+
@NotNull BuildInfoProvider buildInfoProvider,
|
|
30
|
+
@NotNull Runnable emitNewFrameEvent,
|
|
31
|
+
@NotNull ILogger logger) {
|
|
32
|
+
this.buildInfoProvider = buildInfoProvider;
|
|
33
|
+
this.emitNewFrameEvent = emitNewFrameEvent;
|
|
34
|
+
this.logger = logger;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Override
|
|
38
|
+
public void onFragmentViewCreated(
|
|
39
|
+
@NotNull FragmentManager fm,
|
|
40
|
+
@NotNull Fragment f,
|
|
41
|
+
@NotNull View v,
|
|
42
|
+
@Nullable Bundle savedInstanceState) {
|
|
43
|
+
if (!"com.swmansion.rnscreens.ScreenStackFragment".equals(f.getClass().getCanonicalName())) {
|
|
44
|
+
logger.log(
|
|
45
|
+
SentryLevel.DEBUG,
|
|
46
|
+
"Fragment is not a ScreenStackFragment, won't listen for the first draw.");
|
|
47
|
+
return;
|
|
39
48
|
}
|
|
40
49
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!("com.swmansion.rnscreens.ScreenStackFragment".equals(f.getClass().getCanonicalName()))) {
|
|
48
|
-
logger.log(SentryLevel.DEBUG, "Fragment is not a ScreenStackFragment, won't listen for the first draw.");
|
|
49
|
-
return;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if (!(v instanceof ViewGroup)) {
|
|
53
|
-
logger.log(SentryLevel.WARNING, "Fragment view is not a ViewGroup, won't listen for the first draw.");
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
50
|
+
if (!(v instanceof ViewGroup)) {
|
|
51
|
+
logger.log(
|
|
52
|
+
SentryLevel.WARNING,
|
|
53
|
+
"Fragment view is not a ViewGroup, won't listen for the first draw.");
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
56
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
57
|
+
final ViewGroup viewGroup = (ViewGroup) v;
|
|
58
|
+
if (viewGroup.getChildCount() == 0) {
|
|
59
|
+
logger.log(
|
|
60
|
+
SentryLevel.WARNING, "Fragment view has no children, won't listen for the first draw.");
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
62
63
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
64
|
+
final @Nullable View screen = viewGroup.getChildAt(0);
|
|
65
|
+
if (screen == null || !(screen.getContext() instanceof ReactContext)) {
|
|
66
|
+
logger.log(
|
|
67
|
+
SentryLevel.WARNING,
|
|
68
|
+
"Fragment view has no ReactContext, won't listen for the first draw.");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
final int screenId = screen.getId();
|
|
73
|
+
if (screenId == View.NO_ID) {
|
|
74
|
+
logger.log(SentryLevel.WARNING, "Screen has no id, won't listen for the first draw.");
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
final @Nullable EventDispatcher eventDispatcher =
|
|
79
|
+
getEventDispatcherForReactTag(screen, screenId);
|
|
80
|
+
if (eventDispatcher == null) {
|
|
81
|
+
logger.log(
|
|
82
|
+
SentryLevel.WARNING, "Screen has no event dispatcher, won't listen for the first draw.");
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
80
85
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
86
|
+
final @NotNull Runnable emitNewFrameEvent = this.emitNewFrameEvent;
|
|
87
|
+
eventDispatcher.addListener(
|
|
88
|
+
new EventDispatcherListener() {
|
|
89
|
+
@Override
|
|
90
|
+
public void onEventDispatch(Event event) {
|
|
91
|
+
if ("com.swmansion.rnscreens.events.ScreenAppearEvent"
|
|
92
|
+
.equals(event.getClass().getCanonicalName())) {
|
|
93
|
+
eventDispatcher.removeListener(this);
|
|
94
|
+
FirstDrawDoneListener.registerForNextDraw(v, emitNewFrameEvent, buildInfoProvider);
|
|
90
95
|
}
|
|
96
|
+
}
|
|
91
97
|
});
|
|
92
|
-
|
|
98
|
+
}
|
|
93
99
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
100
|
+
private static @Nullable EventDispatcher getEventDispatcherForReactTag(
|
|
101
|
+
@NonNull View screen, int screenId) {
|
|
102
|
+
return UIManagerHelper.getEventDispatcherForReactTag(
|
|
103
|
+
UIManagerHelper.getReactContext(screen), screenId);
|
|
104
|
+
}
|
|
99
105
|
}
|
|
@@ -2,22 +2,17 @@ package io.sentry.react;
|
|
|
2
2
|
|
|
3
3
|
import io.sentry.Breadcrumb;
|
|
4
4
|
import io.sentry.android.replay.DefaultReplayBreadcrumbConverter;
|
|
5
|
-
import io.sentry.rrweb.RRWebEvent;
|
|
6
5
|
import io.sentry.rrweb.RRWebBreadcrumbEvent;
|
|
6
|
+
import io.sentry.rrweb.RRWebEvent;
|
|
7
7
|
import io.sentry.rrweb.RRWebSpanEvent;
|
|
8
|
-
|
|
9
8
|
import java.util.HashMap;
|
|
9
|
+
import java.util.List;
|
|
10
|
+
import java.util.Map;
|
|
10
11
|
import org.jetbrains.annotations.NotNull;
|
|
11
12
|
import org.jetbrains.annotations.Nullable;
|
|
12
13
|
import org.jetbrains.annotations.TestOnly;
|
|
13
14
|
|
|
14
|
-
import java.util.List;
|
|
15
|
-
import java.util.Map;
|
|
16
|
-
|
|
17
15
|
public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadcrumbConverter {
|
|
18
|
-
public RNSentryReplayBreadcrumbConverter() {
|
|
19
|
-
}
|
|
20
|
-
|
|
21
16
|
@Override
|
|
22
17
|
public @Nullable RRWebEvent convert(final @NotNull Breadcrumb breadcrumb) {
|
|
23
18
|
if (breadcrumb.getCategory() == null) {
|
|
@@ -25,22 +20,22 @@ public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadc
|
|
|
25
20
|
}
|
|
26
21
|
|
|
27
22
|
// Do not add Sentry Event breadcrumbs to replay
|
|
28
|
-
if (
|
|
29
|
-
|
|
23
|
+
if ("sentry.event".equals(breadcrumb.getCategory())
|
|
24
|
+
|| "sentry.transaction".equals(breadcrumb.getCategory())) {
|
|
30
25
|
return null;
|
|
31
26
|
}
|
|
32
|
-
if (breadcrumb.getCategory()
|
|
27
|
+
if ("http".equals(breadcrumb.getCategory())) {
|
|
33
28
|
// Drop native http breadcrumbs to avoid duplicates
|
|
34
29
|
return null;
|
|
35
30
|
}
|
|
36
31
|
|
|
37
|
-
if (breadcrumb.getCategory()
|
|
32
|
+
if ("touch".equals(breadcrumb.getCategory())) {
|
|
38
33
|
return convertTouchBreadcrumb(breadcrumb);
|
|
39
34
|
}
|
|
40
|
-
if (breadcrumb.getCategory()
|
|
35
|
+
if ("navigation".equals(breadcrumb.getCategory())) {
|
|
41
36
|
return convertNavigationBreadcrumb(breadcrumb);
|
|
42
37
|
}
|
|
43
|
-
if (breadcrumb.getCategory()
|
|
38
|
+
if ("xhr".equals(breadcrumb.getCategory())) {
|
|
44
39
|
return convertNetworkBreadcrumb(breadcrumb);
|
|
45
40
|
}
|
|
46
41
|
|
|
@@ -49,7 +44,7 @@ public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadc
|
|
|
49
44
|
// ignore native navigation breadcrumbs
|
|
50
45
|
if (nativeBreadcrumb instanceof RRWebBreadcrumbEvent) {
|
|
51
46
|
final RRWebBreadcrumbEvent rrWebBreadcrumb = (RRWebBreadcrumbEvent) nativeBreadcrumb;
|
|
52
|
-
if (
|
|
47
|
+
if ("navigation".equals(rrWebBreadcrumb.getCategory())) {
|
|
53
48
|
return null;
|
|
54
49
|
}
|
|
55
50
|
}
|
|
@@ -71,8 +66,7 @@ public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadc
|
|
|
71
66
|
|
|
72
67
|
rrWebBreadcrumb.setCategory("ui.tap");
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
.getTouchPathMessage(breadcrumb.getData("path")));
|
|
69
|
+
rrWebBreadcrumb.setMessage(getTouchPathMessage(breadcrumb.getData("path")));
|
|
76
70
|
|
|
77
71
|
setRRWebEventDefaultsFrom(rrWebBreadcrumb, breadcrumb);
|
|
78
72
|
return rrWebBreadcrumb;
|
|
@@ -85,7 +79,7 @@ public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadc
|
|
|
85
79
|
}
|
|
86
80
|
|
|
87
81
|
final @NotNull List path = (List) maybePath;
|
|
88
|
-
if (path.
|
|
82
|
+
if (path.isEmpty()) {
|
|
89
83
|
return null;
|
|
90
84
|
}
|
|
91
85
|
|
|
@@ -93,7 +87,7 @@ public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadc
|
|
|
93
87
|
for (int i = Math.min(3, path.size() - 1); i >= 0; i--) {
|
|
94
88
|
final @Nullable Object maybeItem = path.get(i);
|
|
95
89
|
if (!(maybeItem instanceof Map)) {
|
|
96
|
-
|
|
90
|
+
return null;
|
|
97
91
|
}
|
|
98
92
|
|
|
99
93
|
final @NotNull Map item = (Map) maybeItem;
|
|
@@ -115,19 +109,11 @@ public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadc
|
|
|
115
109
|
boolean hasElement = maybeElement instanceof String;
|
|
116
110
|
boolean hasFile = maybeFile instanceof String;
|
|
117
111
|
if (hasElement && hasFile) {
|
|
118
|
-
message.append('(')
|
|
119
|
-
.append(maybeElement)
|
|
120
|
-
.append(", ")
|
|
121
|
-
.append(maybeFile)
|
|
122
|
-
.append(')');
|
|
112
|
+
message.append('(').append(maybeElement).append(", ").append(maybeFile).append(')');
|
|
123
113
|
} else if (hasElement) {
|
|
124
|
-
message.append('(')
|
|
125
|
-
.append(maybeElement)
|
|
126
|
-
.append(')');
|
|
114
|
+
message.append('(').append(maybeElement).append(')');
|
|
127
115
|
} else if (hasFile) {
|
|
128
|
-
message.append('(')
|
|
129
|
-
.append(maybeFile)
|
|
130
|
-
.append(')');
|
|
116
|
+
message.append('(').append(maybeFile).append(')');
|
|
131
117
|
}
|
|
132
118
|
|
|
133
119
|
if (i > 0) {
|
|
@@ -140,18 +126,22 @@ public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadc
|
|
|
140
126
|
|
|
141
127
|
@TestOnly
|
|
142
128
|
public @Nullable RRWebEvent convertNetworkBreadcrumb(final @NotNull Breadcrumb breadcrumb) {
|
|
143
|
-
final Double startTimestamp =
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
final
|
|
148
|
-
|
|
129
|
+
final Double startTimestamp =
|
|
130
|
+
breadcrumb.getData("start_timestamp") instanceof Number
|
|
131
|
+
? (Double) breadcrumb.getData("start_timestamp")
|
|
132
|
+
: null;
|
|
133
|
+
final Double endTimestamp =
|
|
134
|
+
breadcrumb.getData("end_timestamp") instanceof Number
|
|
135
|
+
? (Double) breadcrumb.getData("end_timestamp")
|
|
136
|
+
: null;
|
|
137
|
+
final String url =
|
|
138
|
+
breadcrumb.getData("url") instanceof String ? (String) breadcrumb.getData("url") : null;
|
|
149
139
|
|
|
150
140
|
if (startTimestamp == null || endTimestamp == null || url == null) {
|
|
151
141
|
return null;
|
|
152
142
|
}
|
|
153
143
|
|
|
154
|
-
final
|
|
144
|
+
final Map<String, Object> data = new HashMap<>();
|
|
155
145
|
if (breadcrumb.getData("method") instanceof String) {
|
|
156
146
|
data.put("method", breadcrumb.getData("method"));
|
|
157
147
|
}
|
|
@@ -177,7 +167,8 @@ public final class RNSentryReplayBreadcrumbConverter extends DefaultReplayBreadc
|
|
|
177
167
|
return rrWebSpanEvent;
|
|
178
168
|
}
|
|
179
169
|
|
|
180
|
-
private void setRRWebEventDefaultsFrom(
|
|
170
|
+
private void setRRWebEventDefaultsFrom(
|
|
171
|
+
final @NotNull RRWebBreadcrumbEvent rrWebBreadcrumb, final @NotNull Breadcrumb breadcrumb) {
|
|
181
172
|
rrWebBreadcrumb.setLevel(breadcrumb.getLevel());
|
|
182
173
|
rrWebBreadcrumb.setData(breadcrumb.getData());
|
|
183
174
|
rrWebBreadcrumb.setTimestamp(breadcrumb.getTimestamp().getTime());
|