Additional Litho descriptors

Summary: Moved to separate directory. These additional descriptors are useful for debugging the implementation but might not be useful for the end users so could potentially be removed down the road

Reviewed By: lblasa

Differential Revision: D40021834

fbshipit-source-id: f88c1186dd65cdabc816d5cd8256bb81c404a80c
This commit is contained in:
Luke De Feo
2022-10-10 04:13:06 -07:00
committed by Facebook GitHub Bot
parent 221f7ac1e5
commit b911c49667
8 changed files with 219 additions and 120 deletions

View File

@@ -1,119 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.flipper.plugins.uidebugger.litho
import android.graphics.Bitmap
import com.facebook.flipper.plugins.uidebugger.common.InspectableObject
import com.facebook.flipper.plugins.uidebugger.descriptors.BaseTags
import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister
import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
import com.facebook.flipper.plugins.uidebugger.descriptors.SectionName
import com.facebook.flipper.plugins.uidebugger.model.Bounds
import com.facebook.litho.DebugComponent
import com.facebook.litho.LithoView
object LithoViewDescriptor : NodeDescriptor<LithoView> {
override fun getName(node: LithoView): String = "LithoView"
override fun getChildren(node: LithoView): List<Any> {
val result = mutableListOf<Any>()
val debugComponent = DebugComponent.getRootInstance(node)
if (debugComponent != null) {
result.add(debugComponent)
}
return result
}
override fun getActiveChild(node: LithoView): Any? = null
override fun getData(node: LithoView) = mapOf<String, InspectableObject>()
override fun getBounds(node: LithoView): Bounds? = null
override fun getTags(node: LithoView): Set<String> = setOf()
override fun getSnapshot(node: LithoView, bitmap: Bitmap?): Bitmap? = null
}
const val LithoTag = "Litho"
/** a drawable or view that is mounted, along with the correct descriptor */
class MountedObject(val obj: Any, val descriptor: NodeDescriptor<Any>)
object MountedObjectDescriptor : NodeDescriptor<MountedObject> {
override fun getBounds(node: MountedObject): Bounds? {
val bounds = node.descriptor.getBounds(node.obj)
/**
* When we ask android for the bounds the x,y offset is w.r.t to the nearest android parent view
* group. From UI debuggers perspective using the raw android offset will double the total
* offset of this native view as the offset is included by the litho components between the
* mounted view and its native parent
*/
return bounds?.copy(x = 0, y = 0)
}
override fun getName(node: MountedObject): String = node.descriptor.getName(node.obj)
override fun getChildren(node: MountedObject): List<Any> = node.descriptor.getChildren(node.obj)
override fun getActiveChild(node: MountedObject): Any? = node.descriptor.getActiveChild(node.obj)
override fun getData(node: MountedObject): Map<SectionName, InspectableObject> =
node.descriptor.getData(node.obj)
override fun getTags(node: MountedObject): Set<String> = node.descriptor.getTags(node.obj)
override fun getSnapshot(node: MountedObject, bitmap: Bitmap?): Bitmap? =
node.descriptor.getSnapshot(node.obj, bitmap)
}
class DebugComponentDescriptor(private val register: DescriptorRegister) :
NodeDescriptor<DebugComponent> {
override fun getName(node: DebugComponent): String {
return node.component.simpleName
}
override fun getChildren(node: DebugComponent): List<Any> {
val result = mutableListOf<Any>()
val mountedView = node.mountedView
val mountedDrawable = node.mountedDrawable
if (mountedView != null) {
val descriptor: NodeDescriptor<Any> = register.descriptorForClassUnsafe(mountedView.javaClass)
result.add(MountedObject(mountedView, descriptor))
} else if (mountedDrawable != null) {
val descriptor: NodeDescriptor<Any> =
register.descriptorForClassUnsafe(mountedDrawable.javaClass)
result.add(MountedObject(mountedDrawable, descriptor))
} else {
for (child in node.childComponents) {
result.add(child)
}
}
return result
}
override fun getActiveChild(node: DebugComponent): Any? = null
override fun getData(node: DebugComponent) = mapOf<String, InspectableObject>()
override fun getBounds(node: DebugComponent): Bounds {
val bounds = node.bounds
return Bounds(bounds.left, bounds.top, bounds.width(), bounds.height())
}
override fun getTags(node: DebugComponent): Set<String> = setOf(BaseTags.Declarative, LithoTag)
override fun getSnapshot(node: DebugComponent, bitmap: Bitmap?): Bitmap? = null
}

View File

@@ -8,15 +8,22 @@
package com.facebook.flipper.plugins.uidebugger.litho
import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister
import com.facebook.flipper.plugins.uidebugger.litho.descriptors.*
import com.facebook.flipper.plugins.uidebugger.observers.TreeObserverFactory
import com.facebook.litho.DebugComponent
import com.facebook.litho.LithoView
import com.facebook.litho.MatrixDrawable
import com.facebook.litho.widget.TextDrawable
const val LithoTag = "Litho"
object UIDebuggerLithoSupport {
fun addDescriptors(register: DescriptorRegister) {
register.register(LithoView::class.java, LithoViewDescriptor)
register.register(DebugComponent::class.java, DebugComponentDescriptor(register))
register.register(TextDrawable::class.java, TextDrawableDescriptor)
register.register(MatrixDrawable::class.java, MatrixDrawableDescriptor)
}
fun addObserver(observerFactory: TreeObserverFactory) {

View File

@@ -0,0 +1,64 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.flipper.plugins.uidebugger.litho.descriptors
import android.graphics.Bitmap
import com.facebook.flipper.plugins.uidebugger.common.InspectableObject
import com.facebook.flipper.plugins.uidebugger.descriptors.BaseTags
import com.facebook.flipper.plugins.uidebugger.descriptors.DescriptorRegister
import com.facebook.flipper.plugins.uidebugger.descriptors.NodeDescriptor
import com.facebook.flipper.plugins.uidebugger.descriptors.OffsetChild
import com.facebook.flipper.plugins.uidebugger.litho.LithoTag
import com.facebook.flipper.plugins.uidebugger.model.Bounds
import com.facebook.litho.DebugComponent
class DebugComponentDescriptor(val register: DescriptorRegister) : NodeDescriptor<DebugComponent> {
override fun getName(node: DebugComponent): String {
return node.component.simpleName
}
override fun getChildren(node: DebugComponent): List<Any> {
val result = mutableListOf<Any>()
val mountedView = node.mountedView
val mountedDrawable = node.mountedDrawable
if (mountedView != null) {
val descriptor: NodeDescriptor<Any> = register.descriptorForClassUnsafe(mountedView.javaClass)
/**
* When we ask android for the bounds the x,y offset is w.r.t to the nearest android parent
* view group. From UI debuggers perspective using the raw android offset will double the
* total offset of this native view as the offset is included by the litho components between
* the mounted view and its native parent
*/
result.add(OffsetChild.zero(mountedView, descriptor))
} else if (mountedDrawable != null) {
val descriptor: NodeDescriptor<Any> =
register.descriptorForClassUnsafe(mountedDrawable.javaClass)
// same here
result.add(OffsetChild.zero(mountedDrawable, descriptor))
} else {
for (child in node.childComponents) {
result.add(child)
}
}
return result
}
override fun getActiveChild(node: DebugComponent): Any? = null
override fun getData(node: DebugComponent) = mapOf<String, InspectableObject>()
override fun getBounds(node: DebugComponent): Bounds = Bounds.fromRect(node.bounds)
override fun getTags(node: DebugComponent): Set<String> = setOf(BaseTags.Declarative, LithoTag)
override fun getSnapshot(node: DebugComponent, bitmap: Bitmap?): Bitmap? = null
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.flipper.plugins.uidebugger.litho.descriptors
import com.facebook.flipper.plugins.uidebugger.common.Inspectable
import com.facebook.flipper.plugins.uidebugger.common.InspectableObject
import com.facebook.flipper.plugins.uidebugger.common.InspectableValue
import com.facebook.flipper.plugins.uidebugger.descriptors.ChainedDescriptor
import com.facebook.flipper.plugins.uidebugger.descriptors.SectionName
import com.facebook.litho.DebugComponent
import com.facebook.litho.LithoView
object LithoViewDescriptor : ChainedDescriptor<LithoView>() {
override fun onGetName(node: LithoView): String = node.javaClass.simpleName
override fun onGetChildren(node: LithoView): List<Any>? {
val result = mutableListOf<Any>()
val debugComponent = DebugComponent.getRootInstance(node)
if (debugComponent != null) {
result.add(debugComponent)
}
return result
}
override fun onGetData(
node: LithoView,
attributeSections: MutableMap<SectionName, InspectableObject>
) {
attributeSections["Litho"] =
InspectableObject(
mapOf<String, Inspectable>(
"isIncrementalMountEnabled" to
InspectableValue.Boolean(node.isIncrementalMountEnabled, false)))
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.flipper.plugins.uidebugger.litho.descriptors
import com.facebook.flipper.plugins.uidebugger.descriptors.ChainedDescriptor
import com.facebook.litho.MatrixDrawable
object MatrixDrawableDescriptor : ChainedDescriptor<MatrixDrawable<*>>() {
override fun onGetChildren(node: MatrixDrawable<*>): List<Any>? {
val mountedDrawable = node.mountedDrawable
return if (mountedDrawable != null) {
listOf(mountedDrawable)
} else {
listOf()
}
}
override fun onGetName(node: MatrixDrawable<*>): String = node.javaClass.simpleName
}

View File

@@ -0,0 +1,45 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.flipper.plugins.uidebugger.litho.descriptors
import android.graphics.Bitmap
import com.facebook.flipper.plugins.uidebugger.common.InspectableObject
import com.facebook.flipper.plugins.uidebugger.descriptors.*
import com.facebook.flipper.plugins.uidebugger.model.Bounds
/** a drawable or view that is mounted, along with the correct descriptor */
class MountedObject(val obj: Any, val descriptor: NodeDescriptor<Any>)
object MountedObjectDescriptor : NodeDescriptor<MountedObject> {
override fun getBounds(node: MountedObject): Bounds? {
val bounds = node.descriptor.getBounds(node.obj)
/**
* When we ask android for the bounds the x,y offset is w.r.t to the nearest android parent view
* group. From UI debuggers perspective using the raw android offset will double the total
* offset of this native view as the offset is included by the litho components between the
* mounted view and its native parent
*/
return bounds?.copy(x = 0, y = 0)
}
override fun getName(node: MountedObject): String = node.descriptor.getName(node.obj)
override fun getChildren(node: MountedObject): List<Any> = node.descriptor.getChildren(node.obj)
override fun getActiveChild(node: MountedObject): Any? = node.descriptor.getActiveChild(node.obj)
override fun getData(node: MountedObject): Map<SectionName, InspectableObject> =
node.descriptor.getData(node.obj)
override fun getTags(node: MountedObject): Set<String> = node.descriptor.getTags(node.obj)
override fun getSnapshot(node: MountedObject, bitmap: Bitmap?): Bitmap? =
node.descriptor.getSnapshot(node.obj, bitmap)
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
package com.facebook.flipper.plugins.uidebugger.litho.descriptors
import com.facebook.flipper.plugins.uidebugger.common.Inspectable
import com.facebook.flipper.plugins.uidebugger.common.InspectableObject
import com.facebook.flipper.plugins.uidebugger.common.InspectableValue
import com.facebook.flipper.plugins.uidebugger.descriptors.ChainedDescriptor
import com.facebook.flipper.plugins.uidebugger.descriptors.SectionName
import com.facebook.litho.widget.TextDrawable
object TextDrawableDescriptor : ChainedDescriptor<TextDrawable>() {
override fun onGetName(node: TextDrawable): String = node.javaClass.simpleName
override fun onGetData(
node: TextDrawable,
attributeSections: MutableMap<SectionName, InspectableObject>
) {
val props =
mapOf<String, Inspectable>("text" to InspectableValue.Text(node.text.toString(), false))
attributeSections["TextDrawable"] = InspectableObject(props)
}
}

View File

@@ -7,6 +7,7 @@
package com.facebook.flipper.plugins.uidebugger.model
import android.graphics.Rect
import com.facebook.flipper.plugins.uidebugger.common.InspectableObject
import com.facebook.flipper.plugins.uidebugger.descriptors.Id
@@ -22,4 +23,10 @@ data class Node(
)
@kotlinx.serialization.Serializable
data class Bounds(val x: Int, val y: Int, val width: Int, val height: Int)
data class Bounds(val x: Int, val y: Int, val width: Int, val height: Int) {
companion object {
fun fromRect(rect: Rect): Bounds {
return Bounds(rect.left, rect.top, rect.width(), rect.height())
}
}
}