Export jetpack-compose code
Summary: Move the jetpack plugin to a location that will get exported to GitHub. It won't get built as part of Gradle just yet. Reviewed By: lblasa Differential Revision: D46932691 fbshipit-source-id: 5837bbb2f31aad4221ee745fd145b91b2783d7fe
This commit is contained in:
committed by
Facebook GitHub Bot
parent
0d364dc6b6
commit
b35cbaae55
@@ -0,0 +1,24 @@
|
|||||||
|
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.jetpackcompose
|
||||||
|
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import com.facebook.flipper.plugins.jetpackcompose.descriptors.*
|
||||||
|
import com.facebook.flipper.plugins.jetpackcompose.model.*
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.core.UIDContext
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister
|
||||||
|
|
||||||
|
const val JetpackComposeTag = "JetpackCompose"
|
||||||
|
|
||||||
|
object UIDebuggerComposeSupport {
|
||||||
|
|
||||||
|
fun enable(context: UIDContext) {
|
||||||
|
addDescriptors(context.descriptorRegister)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addDescriptors(register: DescriptorRegister) {
|
||||||
|
register.register(ComposeView::class.java, ComposeViewDescriptor)
|
||||||
|
register.register(ComposeNode::class.java, ComposeNodeDescriptor)
|
||||||
|
register.register(ComposeInnerViewNode::class.java, ComposeInnerViewDescriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.jetpackcompose.descriptors
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import com.facebook.flipper.plugins.jetpackcompose.model.ComposeInnerViewNode
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.descriptors.ViewDescriptor
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.descriptors.ViewGroupDescriptor
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
|
|
||||||
|
object ComposeInnerViewDescriptor : NodeDescriptor<ComposeInnerViewNode> {
|
||||||
|
|
||||||
|
override fun getBounds(node: ComposeInnerViewNode): Bounds {
|
||||||
|
return node.bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getName(node: ComposeInnerViewNode): String {
|
||||||
|
if (node.view is ViewGroup) {
|
||||||
|
return ViewGroupDescriptor.getName(node.view)
|
||||||
|
}
|
||||||
|
return ViewDescriptor.getName(node.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getQualifiedName(node: ComposeInnerViewNode): String {
|
||||||
|
if (node.view is ViewGroup) {
|
||||||
|
return ViewGroupDescriptor.getQualifiedName(node.view)
|
||||||
|
}
|
||||||
|
return ViewDescriptor.getQualifiedName(node.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getChildren(node: ComposeInnerViewNode): List<Any> {
|
||||||
|
if (node.view is ViewGroup) {
|
||||||
|
return ViewGroupDescriptor.getChildren(node.view)
|
||||||
|
}
|
||||||
|
return ViewDescriptor.getChildren(node.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSnapshot(node: ComposeInnerViewNode, bitmap: Bitmap?): Bitmap? {
|
||||||
|
if (node.view is ViewGroup) {
|
||||||
|
return ViewGroupDescriptor.getSnapshot(node.view, bitmap)
|
||||||
|
}
|
||||||
|
return ViewDescriptor.getSnapshot(node.view, bitmap)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getActiveChild(node: ComposeInnerViewNode): Any? {
|
||||||
|
if (node.view is ViewGroup) {
|
||||||
|
return ViewGroupDescriptor.getActiveChild(node.view)
|
||||||
|
}
|
||||||
|
return ViewDescriptor.getActiveChild(node.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAttributes(
|
||||||
|
node: ComposeInnerViewNode
|
||||||
|
): MaybeDeferred<Map<MetadataId, InspectableObject>> {
|
||||||
|
if (node.view is ViewGroup) {
|
||||||
|
return ViewGroupDescriptor.getAttributes(node.view)
|
||||||
|
}
|
||||||
|
return ViewDescriptor.getAttributes(node.view)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getTags(node: ComposeInnerViewNode): Set<String> {
|
||||||
|
if (node.view is ViewGroup) {
|
||||||
|
return ViewGroupDescriptor.getTags(node.view)
|
||||||
|
}
|
||||||
|
return ViewDescriptor.getTags(node.view)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.jetpackcompose.descriptors
|
||||||
|
|
||||||
|
import android.graphics.Bitmap
|
||||||
|
import com.facebook.flipper.plugins.jetpackcompose.model.ComposeNode
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.descriptors.BaseTags
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.descriptors.MetadataRegister
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.Coordinate
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.Inspectable
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.InspectableObject
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.InspectableValue
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.MetadataId
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.Immediate
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.util.MaybeDeferred
|
||||||
|
|
||||||
|
object ComposeNodeDescriptor : NodeDescriptor<ComposeNode> {
|
||||||
|
|
||||||
|
private const val NAMESPACE = "ComposeNode"
|
||||||
|
|
||||||
|
private var SectionId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, NAMESPACE)
|
||||||
|
private val IdAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "id")
|
||||||
|
private val KeyAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "key")
|
||||||
|
private val NameAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_IDENTITY, NAMESPACE, "name")
|
||||||
|
private val FilenameAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_IDENTITY, NAMESPACE, "filename")
|
||||||
|
private val PackageHashAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_IDENTITY, NAMESPACE, "packageHash")
|
||||||
|
private val LineNumberAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_IDENTITY, NAMESPACE, "lineNumber")
|
||||||
|
private val OffsetAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_IDENTITY, NAMESPACE, "offset")
|
||||||
|
private val LengthAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_IDENTITY, NAMESPACE, "length")
|
||||||
|
private val BoxAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "box")
|
||||||
|
private val BoundsAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "bounds")
|
||||||
|
private val Bounds0AttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "(x0, y0)")
|
||||||
|
private val Bounds1AttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "(x1, y1)")
|
||||||
|
private val Bounds2AttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "(x2, y2)")
|
||||||
|
private val Bounds3AttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "(x3, y3)")
|
||||||
|
private val ViewIdAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "viewId")
|
||||||
|
private val MergedSemanticsAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "mergedSemantics")
|
||||||
|
private val UnmergedSemanticsAttributeId =
|
||||||
|
MetadataRegister.register(MetadataRegister.TYPE_ATTRIBUTE, NAMESPACE, "unmergedSemantics")
|
||||||
|
|
||||||
|
override fun getName(node: ComposeNode): String = node.inspectorNode.name
|
||||||
|
|
||||||
|
override fun getChildren(node: ComposeNode): List<Any> {
|
||||||
|
return node.children
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getAttributes(node: ComposeNode): MaybeDeferred<Map<MetadataId, InspectableObject>> {
|
||||||
|
|
||||||
|
val builder = mutableMapOf<MetadataId, InspectableObject>()
|
||||||
|
val props = mutableMapOf<Int, Inspectable>()
|
||||||
|
|
||||||
|
props[IdAttributeId] = InspectableValue.Number(node.inspectorNode.id)
|
||||||
|
props[ViewIdAttributeId] = InspectableValue.Number(node.inspectorNode.viewId)
|
||||||
|
props[KeyAttributeId] = InspectableValue.Number(node.inspectorNode.key)
|
||||||
|
props[NameAttributeId] = InspectableValue.Text(node.inspectorNode.name)
|
||||||
|
props[FilenameAttributeId] = InspectableValue.Text(node.inspectorNode.fileName)
|
||||||
|
props[PackageHashAttributeId] = InspectableValue.Number(node.inspectorNode.packageHash)
|
||||||
|
props[LineNumberAttributeId] = InspectableValue.Number(node.inspectorNode.lineNumber)
|
||||||
|
props[OffsetAttributeId] = InspectableValue.Number(node.inspectorNode.offset)
|
||||||
|
props[LengthAttributeId] = InspectableValue.Number(node.inspectorNode.length)
|
||||||
|
|
||||||
|
props[BoxAttributeId] =
|
||||||
|
InspectableValue.Bounds(
|
||||||
|
Bounds(
|
||||||
|
node.inspectorNode.left,
|
||||||
|
node.inspectorNode.top,
|
||||||
|
node.inspectorNode.width,
|
||||||
|
node.inspectorNode.height))
|
||||||
|
|
||||||
|
node.inspectorNode.bounds?.let { bounds ->
|
||||||
|
val quadBounds = mutableMapOf<Int, Inspectable>()
|
||||||
|
quadBounds[Bounds0AttributeId] = InspectableValue.Coordinate(Coordinate(bounds.x0, bounds.y0))
|
||||||
|
quadBounds[Bounds1AttributeId] = InspectableValue.Coordinate(Coordinate(bounds.x1, bounds.y1))
|
||||||
|
quadBounds[Bounds2AttributeId] = InspectableValue.Coordinate(Coordinate(bounds.x2, bounds.y2))
|
||||||
|
quadBounds[Bounds3AttributeId] = InspectableValue.Coordinate(Coordinate(bounds.x3, bounds.y3))
|
||||||
|
props[BoundsAttributeId] = InspectableObject(quadBounds.toMap())
|
||||||
|
}
|
||||||
|
|
||||||
|
val mergedSemantics = mutableMapOf<Int, Inspectable>()
|
||||||
|
node.inspectorNode.mergedSemantics.forEach {
|
||||||
|
val keyAttributeId =
|
||||||
|
MetadataRegister.register(
|
||||||
|
MetadataRegister.TYPE_ATTRIBUTE, node.inspectorNode.name, it.name)
|
||||||
|
mergedSemantics[keyAttributeId] = InspectableValue.Text(it.value.toString())
|
||||||
|
}
|
||||||
|
props[MergedSemanticsAttributeId] = InspectableObject(mergedSemantics.toMap())
|
||||||
|
|
||||||
|
val unmergedSemantics = mutableMapOf<Int, Inspectable>()
|
||||||
|
node.inspectorNode.unmergedSemantics.forEach {
|
||||||
|
val keyAttributeId =
|
||||||
|
MetadataRegister.register(
|
||||||
|
MetadataRegister.TYPE_ATTRIBUTE, node.inspectorNode.name, it.name)
|
||||||
|
mergedSemantics[keyAttributeId] = InspectableValue.Text(it.value.toString())
|
||||||
|
}
|
||||||
|
props[UnmergedSemanticsAttributeId] = InspectableObject(unmergedSemantics.toMap())
|
||||||
|
|
||||||
|
builder[SectionId] = InspectableObject(props.toMap())
|
||||||
|
|
||||||
|
return Immediate(builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getBounds(node: ComposeNode): Bounds {
|
||||||
|
return node.bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getQualifiedName(node: ComposeNode): String = node.inspectorNode.name
|
||||||
|
|
||||||
|
override fun getSnapshot(node: ComposeNode, bitmap: Bitmap?): Bitmap? = null
|
||||||
|
|
||||||
|
override fun getActiveChild(node: ComposeNode): Any? = null
|
||||||
|
|
||||||
|
override fun getTags(node: ComposeNode): Set<String> = setOf(BaseTags.Android, "Compose")
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.jetpackcompose.descriptors
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.View
|
||||||
|
import androidx.compose.ui.platform.ComposeView
|
||||||
|
import com.facebook.flipper.plugins.jetpackcompose.model.ComposeNode
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.descriptors.ChainedDescriptor
|
||||||
|
import facebook.internal.androidx.compose.ui.inspection.inspector.InspectorNode
|
||||||
|
import facebook.internal.androidx.compose.ui.inspection.inspector.LayoutInspectorTree
|
||||||
|
|
||||||
|
object ComposeViewDescriptor : ChainedDescriptor<ComposeView>() {
|
||||||
|
override fun onGetName(node: ComposeView): String = node.javaClass.simpleName
|
||||||
|
|
||||||
|
private fun transform(view: View, nodes: List<InspectorNode>): List<ComposeNode> {
|
||||||
|
val positionOnScreen = IntArray(2)
|
||||||
|
view.getLocationOnScreen(positionOnScreen)
|
||||||
|
|
||||||
|
val xOffset = positionOnScreen[0]
|
||||||
|
val yOffset = positionOnScreen[1]
|
||||||
|
|
||||||
|
return nodes.map { node -> ComposeNode(view, node, xOffset, yOffset) }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onGetChildren(node: ComposeView): List<Any> {
|
||||||
|
val children = mutableListOf<Any>()
|
||||||
|
val count = node.childCount - 1
|
||||||
|
for (i in 0..count) {
|
||||||
|
val child: View = node.getChildAt(i)
|
||||||
|
children.add(child)
|
||||||
|
|
||||||
|
if (child.javaClass.simpleName.contains("AndroidComposeView") &&
|
||||||
|
(Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)) {
|
||||||
|
val layoutInspector = LayoutInspectorTree()
|
||||||
|
layoutInspector.hideSystemNodes = false
|
||||||
|
return transform(child, layoutInspector.convert(child))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return children
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.jetpackcompose.model
|
||||||
|
|
||||||
|
import android.view.View
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.Bounds
|
||||||
|
|
||||||
|
class ComposeInnerViewNode(
|
||||||
|
val view: View,
|
||||||
|
) {
|
||||||
|
val bounds: Bounds = Bounds(0, 0, view.width, view.height)
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
// (c) Meta Platforms, Inc. and affiliates. Confidential and proprietary.
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.jetpackcompose.model
|
||||||
|
|
||||||
|
import android.os.Build
|
||||||
|
import android.view.View
|
||||||
|
import android.view.ViewGroup
|
||||||
|
import androidx.annotation.RequiresApi
|
||||||
|
import com.facebook.flipper.plugins.uidebugger.model.*
|
||||||
|
import facebook.internal.androidx.compose.ui.inspection.inspector.InspectorNode
|
||||||
|
|
||||||
|
class ComposeNode(
|
||||||
|
private val parentComposeView: View,
|
||||||
|
val inspectorNode: InspectorNode,
|
||||||
|
xOffset: Int,
|
||||||
|
yOffset: Int
|
||||||
|
) {
|
||||||
|
val bounds: Bounds =
|
||||||
|
Bounds(
|
||||||
|
inspectorNode.left - xOffset,
|
||||||
|
inspectorNode.top - yOffset,
|
||||||
|
inspectorNode.width,
|
||||||
|
inspectorNode.height)
|
||||||
|
|
||||||
|
val children: List<Any> = collectChildren()
|
||||||
|
|
||||||
|
private fun collectChildren(): List<Any> {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
|
val viewId = inspectorNode.viewId
|
||||||
|
if (viewId != 0L) {
|
||||||
|
val view = parentComposeView.findViewByDrawingId(viewId)
|
||||||
|
if (view != null) {
|
||||||
|
return listOf(ComposeInnerViewNode(view))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return inspectorNode.children.map { child ->
|
||||||
|
ComposeNode(parentComposeView, child, inspectorNode.left, inspectorNode.top)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequiresApi(Build.VERSION_CODES.Q)
|
||||||
|
private fun View.findViewByDrawingId(drawingId: Long): View? {
|
||||||
|
if (this.uniqueDrawingId == drawingId) {
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
if (this is ViewGroup) {
|
||||||
|
for (i in 0 until this.childCount) {
|
||||||
|
val child = this.getChildAt(i)
|
||||||
|
val foundView = child.findViewByDrawingId(drawingId)
|
||||||
|
if (foundView != null) {
|
||||||
|
return foundView
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user