feat(react-native): fix lagging masks and imageQuality option - #734
Merged
Conversation
…e SDKs Match Flutter's SessionReplayOptions capture set by forwarding imageQuality through the JS/Android/iOS bridges, and bump observability-android to 0.66.0 and LaunchDarklySessionReplay to ~> 0.53.0. Co-authored-by: Cursor <cursoragent@cursor.com>
Vadman97
approved these changes
Aug 18, 2026
abelonogov-ld
enabled auto-merge (squash)
August 19, 2026 23:58
Merged
abelonogov-ld
pushed a commit
that referenced
this pull request
Aug 20, 2026
🤖 I have created a release *beep* *boop* --- <details><summary>session-replay-react-native: 0.23.0</summary> ## [0.23.0](session-replay-react-native-0.22.2...session-replay-react-native-0.23.0) (2026-08-20) ### Features * **react-native:** fix lagging masks and imageQuality option ([#734](#734)) ([d0e2f99](d0e2f99)) </details> --- This PR was generated with [Release Please](https://github.com/googleapis/release-please). See [documentation](https://github.com/googleapis/release-please#release-please). <!-- CURSOR_SUMMARY --> --- > [!NOTE] > <sup>[Cursor Bugbot](https://cursor.com/bugbot) is generating a summary for commit b4c86a6. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY -->
abelonogov-ld
added a commit
that referenced
this pull request
Aug 20, 2026
* main: chore: release main (#741) feat(react-native): fix lagging masks and imageQuality option (#734) chore: release main (#736) fix(android): anchor session replay masks to the rendered frame and cover stretch overscroll (Rubber animation) (#739) fix: remediate dependency vulnerabilities across npm, go, pip, and rubygems (#732) chore: release main (#735)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Session replay masks drifted off the content they are meant to cover whenever the
screen was moving — while scrolling, while overscrolling, and across view
transitions. The fixes landed natively in
observability-androidandswift-launchdarkly-observability; this PR pulls them into the React Nativebridge and forwards the new
imageQualitycapture option that shipped alongsidethem.
Lagging masks
Android —
launchdarkly-observability-android0.65.0 → 0.66.1Choreographercallback,which runs in the animation phase before that frame's measure/layout/draw,
so it described the previous traversal — and
PixelCopyreturned whatever thesurface held, usually older still. Nothing guaranteed the captured pixels fell
between the before and after mask passes, so masks trailed the content they
covered. Geometry is now read from inside the draw pass that produces the frame
(
ViewTreeObserver.OnDrawListener) and the capture waits for that specificframe to finish rendering (
Window.addOnFrameMetricsAvailableListener) beforecopying pixels.
RenderEffectapplied by the RenderThread: no view moves, no layout changes, and Compose's
boundsInWindowis equally unaware. Mask geometry faithfully described alayout that was never rendered, so content slid out from under its mask at the
edges. Masks in a stretched container's subtree now inflate using the
framework's own damping curve.
RecyclerView,ViewPager2,NestedScrollViewand Compose containers are covered; framework
ScrollView/ListViewkeeptheir edge effects behind blocked non-SDK fields and are not inflated.
iOS —
LaunchDarklySessionReplay> 0.47.0 → **> 0.53.1**masks of everything behind it, so masked content was captured in the clear for
the length of the transition.
UIView.animatewrites the animation's finalvalue to the model layer immediately, so an incoming cover read as fully opaque
while the screen behind it was still on display. Opacity is now accumulated
down the layer tree, and a layer with a live opacity animation counts as
transparent for the redundant-mask pass.
captured frame, so they landed off their content.
animated positions rather than final model-layer values.
New capture option
imageQuality(0.0–1.0, default0.3) sets the JPEG encoding quality ofexported frames, carried over the JS → Android/iOS bridges into native
ReplayOptions/SessionReplayOptions. This matches Flutter's capture optionset and lets apps trade replay fidelity against payload size.
Also picked up by the bumps
DedupingHookonboth platforms (android 0.66.0, iOS 0.53.0).
symbolication (0.48.0, 0.49.0); session replay stops on unrecoverable
initialization errors (0.49.0); dSYM upload is a one-line build phase (0.50.0);
lite OTel core (0.51.0); iOS Client SDK 11.4.0 (0.52.1).
Version changes
com.launchdarkly:launchdarkly-observability-androidLaunchDarklySessionReplay(CocoaPods)com.launchdarkly:launchdarkly-android-client-sdkTest plan
yarn test --watchman=false --testPathPattern='src/__tests__/index.test'insdk/@launchdarkly/react-native-ld-session-replay(18 passed)./gradlew :launchdarkly_session-replay-react-native:testDebugUnitTest --tests 'com.sessionreplayreactnative.SessionReplayClientAdapterTest'inexample/androidLaunchDarklySessionReplay0.53.1 and buildsimageQualityvisibly changes replay frame size