square / radiography

Text-ray goggles for your Android UI.
Apache License 2.0
851 stars 35 forks source link

Text values not written out in newer Compose (1.5.1) #156

Closed jebware closed 10 months ago

jebware commented 1 year ago

Radiography is not able to write out the text value of a Text composable anymore. To reproduce, you can upgrade the Compose version in this project and run the tests in the compose-tests module.

Old Compose was writing the text value of the Text composable into the text value in the semantics, but this is no longer the case. The text value is available in a Modifier node called TextStringSimpleElement or TextAnnotatedStringElement, but those classes are internal in Compose. As a hacky proof of concept, I was able to grab the value using reflection:

(view as? ComposeView)
      ?.modifiers
      ?.filterIsInstance<ModifierNodeElement<Node>>()
      ?.forEach {
        val clazz = Class.forName("androidx.compose.foundation.text.modifiers.TextStringSimpleElement")
        if (!clazz.isInstance(it)) return@forEach
        val textField = clazz.getDeclaredField("text")
        textField.isAccessible = true
        val stringValue = textField.get(it) as? String
        appendTextValue(label = "text",  text = stringValue, renderTextValue, textValueMaxLength)
      }

I'm working with Compose 1.5.1 - I see that the Radiography tests use Compose 1.0.1. I didn't bisect to see when this broke, but I could probably do so, if that would be helpful.

If I come up with a better solution, I'll open a PR.

pyricau commented 1 year ago

If you can isolate the issue and suggest a fix or better yet open a PR, that'd be amazing!

elihart commented 11 months ago

As far as I can tell this is a problem with all (or most?) semantics values. With the internal refactor to use Nodes instead of modifiers, the semantic information is now in the Semantics Nodes hierarchy and the information can be accessed without reflection. I have it working by accessing the semanticsOwner off the RootForTest interface of the AndroidComposeView, and then filtering the semantics node by id to match the id of each layout node.

The semantics node data is still backed by a SemanticsConfiguration, so thankfully accessing it doesn't have to change much, but it can no longer be taken from the modifiers list of the ScannableView. I'll put up a PR next week

elihart commented 11 months ago

I've submitted a fix for this at https://github.com/square/radiography/pull/157

yogurtearl commented 10 months ago

Looks like this fix went out in version 2.5 ?

if so, can this be closed?

jebware commented 10 months ago

I just tried it and this is fixed in version 2.5. Thanks!