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