Skip to content

Commit 960f850

Browse files
committed
fix(session-replay): Fixes orientation change misalignment for session replay
1 parent b7aa1aa commit 960f850

1 file changed

Lines changed: 78 additions & 0 deletions

File tree

packages/core/android/src/main/java/io/sentry/react/RNSentryReactFragmentLifecycleTracer.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import android.os.Bundle;
44
import android.view.View;
55
import android.view.ViewGroup;
6+
import android.view.ViewTreeObserver;
67
import androidx.annotation.NonNull;
78
import androidx.fragment.app.Fragment;
89
import androidx.fragment.app.FragmentManager;
@@ -13,9 +14,13 @@
1314
import com.facebook.react.uimanager.events.EventDispatcher;
1415
import com.facebook.react.uimanager.events.EventDispatcherListener;
1516
import io.sentry.ILogger;
17+
import io.sentry.Integration;
18+
import io.sentry.ScopesAdapter;
1619
import io.sentry.SentryLevel;
20+
import io.sentry.SentryOptions;
1721
import io.sentry.android.core.BuildInfoProvider;
1822
import io.sentry.android.core.internal.util.FirstDrawDoneListener;
23+
import io.sentry.android.replay.ReplayIntegration;
1924
import org.jetbrains.annotations.NotNull;
2025
import org.jetbrains.annotations.Nullable;
2126

@@ -25,6 +30,10 @@ public class RNSentryReactFragmentLifecycleTracer extends FragmentLifecycleCallb
2530
private @NotNull final Runnable emitNewFrameEvent;
2631
private @NotNull final ILogger logger;
2732

33+
private @Nullable ReplayIntegration replayIntegration;
34+
private int lastWidth = -1;
35+
private int lastHeight = -1;
36+
2837
public RNSentryReactFragmentLifecycleTracer(
2938
@NotNull BuildInfoProvider buildInfoProvider,
3039
@NotNull Runnable emitNewFrameEvent,
@@ -95,6 +104,75 @@ public void onEventDispatch(Event event) {
95104
}
96105
}
97106
});
107+
108+
// Add layout listener to detect configuration changes
109+
attachLayoutChangeListener(v);
110+
}
111+
112+
private void attachLayoutChangeListener(final View view) {
113+
view.getViewTreeObserver()
114+
.addOnGlobalLayoutListener(
115+
new ViewTreeObserver.OnGlobalLayoutListener() {
116+
@Override
117+
public void onGlobalLayout() {
118+
checkAndNotifyWindowSizeChange(view);
119+
}
120+
});
121+
}
122+
123+
private void checkAndNotifyWindowSizeChange(View view) {
124+
try {
125+
android.util.DisplayMetrics metrics = view.getContext().getResources().getDisplayMetrics();
126+
int currentWidth = metrics.widthPixels;
127+
int currentHeight = metrics.heightPixels;
128+
129+
if (lastWidth != currentWidth || lastHeight != currentHeight) {
130+
lastWidth = currentWidth;
131+
lastHeight = currentHeight;
132+
133+
notifyReplayIntegrationOfSizeChange(currentWidth, currentHeight);
134+
}
135+
} catch (Exception e) {
136+
logger.log(SentryLevel.DEBUG, "Failed to check window size", e);
137+
}
138+
}
139+
140+
private void notifyReplayIntegrationOfSizeChange(int width, int height) {
141+
try {
142+
if (replayIntegration == null) {
143+
replayIntegration = getReplayIntegration();
144+
}
145+
146+
if (replayIntegration == null) {
147+
return;
148+
}
149+
150+
if (!replayIntegration.isRecording()) {
151+
return;
152+
}
153+
154+
replayIntegration.onWindowSizeChanged(width, height);
155+
} catch (Exception e) {
156+
logger.log(SentryLevel.DEBUG, "Failed to notify replay integration of size change", e);
157+
}
158+
}
159+
160+
private @Nullable ReplayIntegration getReplayIntegration() {
161+
try {
162+
final SentryOptions options = ScopesAdapter.getInstance().getOptions();
163+
if (options == null) {
164+
return null;
165+
}
166+
167+
for (Integration integration : options.getIntegrations()) {
168+
if (integration instanceof ReplayIntegration) {
169+
return (ReplayIntegration) integration;
170+
}
171+
}
172+
} catch (Exception e) {
173+
logger.log(SentryLevel.DEBUG, "Error getting replay integration", e);
174+
}
175+
return null;
98176
}
99177

100178
private static @Nullable EventDispatcher getEventDispatcherForReactTag(

0 commit comments

Comments
 (0)