-
-
Notifications
You must be signed in to change notification settings - Fork 450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix tags missing for compose view hierarchies #4275
base: main
Are you sure you want to change the base?
Conversation
Performance metrics 🚀
|
Revision | Plain | With Sentry | Diff |
---|---|---|---|
f63778b | 413.88 ms | 482.02 ms | 68.14 ms |
6f1848f | 384.70 ms | 441.52 ms | 56.82 ms |
eb39954 | 436.12 ms | 493.80 ms | 57.68 ms |
b159a6d | 378.41 ms | 464.32 ms | 85.91 ms |
App size
Revision | Plain | With Sentry | Diff |
---|---|---|---|
f63778b | 1.58 MiB | 2.22 MiB | 652.84 KiB |
6f1848f | 1.58 MiB | 2.22 MiB | 652.90 KiB |
eb39954 | 1.58 MiB | 2.22 MiB | 652.89 KiB |
b159a6d | 1.58 MiB | 2.22 MiB | 653.07 KiB |
...-compose-helper/src/jvmMain/java/io/sentry/compose/gestures/ComposeGestureTargetLocator.java
Outdated
Show resolved
Hide resolved
...-compose-helper/src/jvmMain/java/io/sentry/compose/gestures/ComposeGestureTargetLocator.java
Outdated
Show resolved
Hide resolved
@@ -99,6 +105,21 @@ private static void setTag( | |||
} | |||
} | |||
} | |||
} else if ("androidx.compose.ui.platform.TestTagElement".equals(type) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it possible to test it with robolectric/instrumented tests to avoid regressions in future?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be nice to have tests for this (and extract that logic into a separate class if possible), but LGTM otherwise!
….com:getsentry/sentry-java into markushi/fix/compose-view-hierarchy-exporter
sentry-compose-helper/src/jvmMain/java/io/sentry/compose/SentryComposeHelper.java
Outdated
Show resolved
Hide resolved
return value as String? | ||
} | ||
} catch (e: Throwable) { | ||
// ignored |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe worth to add a debug log here so we can troubleshoot easier?
fun getLayoutNodeBoundsInWindow(node: LayoutNode): Rect? { | ||
if (layoutDelegateField != null) { | ||
try { | ||
val delegate = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, I'm thinking you could directly access coordinates in LayoutNode node.coordinates.boundsInWindow()
without reflection. At least that's what I'm doing in here:
Line 85 in 801e677
val visibleRect = node.coordinates.boundsInWindow(_rootCoordinates?.get()) |
however I think it returns an innerCoordinator as opposed to outerCoordinator you use - do you know the difference between those? 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I think you could make use of this vendored boundsInWindow
method too right?
sentry-java/sentry-android-replay/src/main/java/io/sentry/android/replay/util/Nodes.kt
Lines 161 to 206 in 801e677
/** | |
* A faster copy of https://github.com/androidx/androidx/blob/fc7df0dd68466ac3bb16b1c79b7a73dd0bfdd4c1/compose/ui/ui/src/commonMain/kotlin/androidx/compose/ui/layout/LayoutCoordinates.kt#L187 | |
* | |
* Since we traverse the tree from the root, we don't need to find it again from the leaf node and | |
* just pass it as an argument. | |
* | |
* @return boundaries of this layout relative to the window's origin. | |
*/ | |
internal fun LayoutCoordinates.boundsInWindow(rootCoordinates: LayoutCoordinates?): Rect { | |
val root = rootCoordinates ?: findRootCoordinates() | |
val rootWidth = root.size.width.toFloat() | |
val rootHeight = root.size.height.toFloat() | |
val bounds = root.localBoundingBoxOf(this) | |
val boundsLeft = bounds.left.fastCoerceIn(0f, rootWidth) | |
val boundsTop = bounds.top.fastCoerceIn(0f, rootHeight) | |
val boundsRight = bounds.right.fastCoerceIn(0f, rootWidth) | |
val boundsBottom = bounds.bottom.fastCoerceIn(0f, rootHeight) | |
if (boundsLeft == boundsRight || boundsTop == boundsBottom) { | |
return Rect() | |
} | |
val topLeft = root.localToWindow(Offset(boundsLeft, boundsTop)) | |
val topRight = root.localToWindow(Offset(boundsRight, boundsTop)) | |
val bottomRight = root.localToWindow(Offset(boundsRight, boundsBottom)) | |
val bottomLeft = root.localToWindow(Offset(boundsLeft, boundsBottom)) | |
val topLeftX = topLeft.x | |
val topRightX = topRight.x | |
val bottomLeftX = bottomLeft.x | |
val bottomRightX = bottomRight.x | |
val left = fastMinOf(topLeftX, topRightX, bottomLeftX, bottomRightX) | |
val right = fastMaxOf(topLeftX, topRightX, bottomLeftX, bottomRightX) | |
val topLeftY = topLeft.y | |
val topRightY = topRight.y | |
val bottomLeftY = bottomLeft.y | |
val bottomRightY = bottomRight.y | |
val top = fastMinOf(topLeftY, topRightY, bottomLeftY, bottomRightY) | |
val bottom = fastMaxOf(topLeftY, topRightY, bottomLeftY, bottomRightY) | |
return Rect(left.toInt(), top.toInt(), right.toInt(), bottom.toInt()) |
You also have access to the root node (at least in the view hierarchy exporter), I think it would speed up things by quite a bit. Ideally we'd share that method via a separate module, but for simplicity I'd suggest just copying it over in this package for now to not deal with another module.
val nodeA = Mockito.mock( | ||
LayoutNode::class.java | ||
) | ||
`when`(nodeA.isPlaced).thenReturn(isPlaced) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess we could use whenever
from mockito-kotlin here
node: LayoutNode, | ||
vhNode: ViewHierarchyNode | ||
) { | ||
// needs to be in-sync with ComposeGestureTargetLocator |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// needs to be in-sync with ComposeGestureTargetLocator |
val nodeHeight = node.height | ||
val nodeWidth = node.width | ||
|
||
vhNode.height = nodeHeight.toDouble() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wondering if we could use bounds.bottom
and bounds.right
here? should be the same value (in theory 😅 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM again, but these two comments I guess would be nice to address: https://github.com/getsentry/sentry-java/pull/4275/files#r2014326540
Great tests btw, and very happy to get rid of that workaround with the java-only module
📜 Description
Only on newer versions of Jetpack Compose
💡 Motivation and Context
Fixes #4273
💚 How did you test it?
📝 Checklist
sendDefaultPII
is enabled.🔮 Next steps