fix(replay): improve CSS fidelity for multi-window, elevation, text, and border-radius#476
Open
jgibson02 wants to merge 8 commits intofix/session-replay-fidelity_issuesfrom
Open
Conversation
jgibson02
added a commit
that referenced
this pull request
Mar 18, 2026
d952a41 to
ba6d3b3
Compare
098e2a8 to
690b4d0
Compare
…and border-radius - Capture all visible windows via Curtains.getRootViews() so dialogs render with the activity behind them instead of on a blank background - Inject a scrim overlay (rgba(0,0,0,0.6)) between the activity and dialog windows to replicate Android's FLAG_DIM_BEHIND behavior - Map View.getElevation() to CSS box-shadow for Material Design depth - Extract corner radius from ViewOutlineProvider for dialogs, CardViews, and FABs that don't use GradientDrawable backgrounds - Emit overflow:hidden on ViewGroup containers based on clipChildren - Fix double semicolons in getFontFamily() that broke CSS parsing - Replace blanket overflow:hidden on text views with white-space:nowrap to prevent false truncation from font metric differences - Add flexbox vertical centering for views with CENTER_VERTICAL gravity - Include font-family:sans-serif for null-typeface views (e.g. buttons) - Add line-height CSS property from TextView.getLineHeight() - Use Locale.US in String.format for CSS numeric values - Simplify incremental-vs-full snapshot decision in processFrames
…radius - Only inject dialog scrim when FLAG_DIM_BEHIND is set on the window, preventing false dimming behind popups, toasts, and menus - Use white-space:nowrap only for single-line TextViews (maxLines==1), fall back to pre-wrap for multi-line text to preserve wrapping - Only extract outline radius when view.getClipToOutline() is true, preventing border-radius on views that use outline for shadow shape only without visual clipping
ba6d3b3 to
9b0a09f
Compare
1cf2428 to
e442da0
Compare
Contributor
|
Waiting for performance testing |
a38dddf to
ad7afe4
Compare
…fidelity Resolve conflicts: - SessionReplayProcessor.java: keep Attributes import (HEAD) + NewRelicIdGenerator/SessionReplayViewThingyInterface imports (base) - ComposeBlockedViewThingy.java: use updated viewMapper.SessionReplayViewThingyInterface path (base) - ViewTouchHandler.java: keep superset of imports from base (includes HEAD's ComposeSessionReplayConstants) - ViewDetails.java: keep Outline/Paint/Field/Locale imports needed for CSS fidelity code (HEAD) - performance.md: take consolidated Round 2 data with updated terminology (base)
…play-css-fidelity
Contributor
|
@diegomtz5 we need test this on lambada test with multi devices. |
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.
fix(replay): improve CSS fidelity for multi-window, elevation, text, and border-radius
What & Why
This is a group of CSS fidelity fixes for this particular test app screen which highlighted the gap with layered windows.
Visual Progression
Ground Truth (Android Emulator)
Before: Dialog only, no activity content
Only the topmost window (dialog) was captured. The activity behind it was missing.
+ Multi-window snapshots
Activity and dialog now render together. No shadows, no scrim, sharp corners.
+ Elevation box-shadow
CardViews, AppBar, FAB, dialog, and buttons now have depth shadows.
+ Dialog scrim
Semi-transparent overlay dims the activity behind the dialog.
Final: + Text fixes, outline border-radius, container overflow
Labels no longer truncated, buttons vertically centered with sans-serif font,
CardViews and dialog have correct corner radii from outline detection, containers
clip overflow.
Changes by Area
Multi-window snapshots (
ViewDrawInterceptor,SessionReplayFrame,SessionReplayProcessor)When a dialog was open, only the topmost window was captured. Each
ViewTreeObserver.OnDrawListenerhad its own captureddecorViewsarray fromregistration time, so no listener ever saw all windows simultaneously.
Now
Curtains.getRootViews()is called at capture time inside the drawlistener to get ALL visible windows. They're combined as sibling children under
<body>. When a secondary window hasFLAG_DIM_BEHINDset (dialogs), a scrimoverlay div (
rgba(0,0,0,0.6)) is injected between the activity and dialog.Elevation → box-shadow (
ViewDetails)View.getElevation()is mapped to CSSbox-shadowusing a Material Designapproximation:
0px {e*0.5}px {e}px rgba(0, 0, 0, 0.24).Outline-based border-radius (
ViewDetails)ViewOutlineProvideris queried at capture time to extract corner radii forviews that clip to their outline (
clipToOutline==true) but don't useGradientDrawablebackgrounds (dialogs, CardViews, FABs).Container overflow (
ViewDetails)ViewGroup.getClipChildren()drivesoverflow: hiddenon containers, fixingtext overflow in clipped views like CardViews.
Text CSS fixes (
SessionReplayTextViewThingy)getFontFamily()that broke CSS parsingwhite-space: nowrapfor single-line TextViews (maxLines==1),pre-wrapfor multi-line text to preserve wrappingCENTER_VERTICALgravityfont-family: sans-seriffor null-typeface views (e.g. buttons)line-heightfromTextView.getLineHeight()Incremental diff safety (
SessionReplayProcessor)Simplified the snapshot decision: incremental diff only runs for single-window
frames with matching root view IDs and viewport dimensions. All other cases
produce a full snapshot.
Callouts
FLAG_DIM_BEHINDis set — popups, toasts, andmenus don't get a false dimming overlay
clipToOutline==true— views that useoutline for shadow shape only won't get false border-radius
dimAmountis hardcoded to 0.6 (Android default) — readingWindowManager.LayoutParams.dimAmountat capture time is a follow-upString.formatcalls useLocale.USto prevent locale-dependentdecimal separators in CSS values
Test plan
overflow clipping, text not truncated
snapshot (activity + dialog visible), button vertical centering and
sans-serif font