From 6f655179333eb1ffefd6d9a3efbad8103dbc6ad7 Mon Sep 17 00:00:00 2001 From: Lorenzo Blasa Date: Mon, 26 Sep 2022 06:03:49 -0700 Subject: [PATCH] getSnapshot Summary: This change introduces a new Descriptor method to obtain snapshots of an item in the layout hierarchy. Only implemented by the ViewDescritor but it can be potentially extended to Windows, Fragments, Activities, ... Reviewed By: LukeDefeo Differential Revision: D39690548 fbshipit-source-id: cf3a1ccd63eb28c1de328310e8635829a40964dd --- .../uidebugger/litho/LithoDescriptors.kt | 12 +++++++++- .../descriptors/ChainedDescriptor.kt | 10 +++++++++ .../uidebugger/descriptors/NodeDescriptor.kt | 8 +++++++ .../descriptors/ObjectDescriptor.kt | 4 ++++ .../uidebugger/descriptors/ViewDescriptor.kt | 22 +++++++++++++++++++ 5 files changed, 55 insertions(+), 1 deletion(-) diff --git a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/LithoDescriptors.kt b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/LithoDescriptors.kt index 5bff01a95..7776fbada 100644 --- a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/LithoDescriptors.kt +++ b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/LithoDescriptors.kt @@ -7,6 +7,7 @@ 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 @@ -36,6 +37,8 @@ object LithoViewDescriptor : NodeDescriptor { override fun getBounds(node: LithoView): Bounds? = null override fun getTags(node: LithoView): Set = setOf() + + override fun getSnapshot(node: LithoView, bitmap: Bitmap?): Bitmap? = null } const val LithoTag = "Litho" @@ -67,9 +70,13 @@ object MountedObjectDescriptor : NodeDescriptor { node.descriptor.getData(node.obj) override fun getTags(node: MountedObject): Set = node.descriptor.getTags(node.obj) + + override fun getSnapshot(node: MountedObject, bitmap: Bitmap?): Bitmap? = + node.descriptor.getSnapshot(node.obj, bitmap) } -class DebugComponentDescriptor(val register: DescriptorRegister) : NodeDescriptor { +class DebugComponentDescriptor(private val register: DescriptorRegister) : + NodeDescriptor { override fun getName(node: DebugComponent): String { return node.component.simpleName @@ -100,10 +107,13 @@ class DebugComponentDescriptor(val register: DescriptorRegister) : NodeDescripto override fun getActiveChild(node: DebugComponent): Any? = null override fun getData(node: DebugComponent) = mapOf() + 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 = setOf(BaseTags.Declarative, LithoTag) + + override fun getSnapshot(node: DebugComponent, bitmap: Bitmap?): Bitmap? = null } diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ChainedDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ChainedDescriptor.kt index b3a96e039..ffdf7163d 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ChainedDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ChainedDescriptor.kt @@ -7,6 +7,7 @@ package com.facebook.flipper.plugins.uidebugger.descriptors +import android.graphics.Bitmap import com.facebook.flipper.plugins.uidebugger.common.InspectableObject import com.facebook.flipper.plugins.uidebugger.model.Bounds @@ -101,4 +102,13 @@ abstract class ChainedDescriptor : NodeDescriptor { * own section */ open fun onGetData(node: T, attributeSections: MutableMap) {} + + /** Get a snapshot of the node. */ + final override fun getSnapshot(node: T, bitmap: Bitmap?): Bitmap? { + return onGetSnapshot(node, bitmap) + } + + open fun onGetSnapshot(node: T, bitmap: Bitmap?): Bitmap? { + return null + } } diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/NodeDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/NodeDescriptor.kt index 24fedb17b..182094ddc 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/NodeDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/NodeDescriptor.kt @@ -7,6 +7,7 @@ package com.facebook.flipper.plugins.uidebugger.descriptors +import android.graphics.Bitmap import com.facebook.flipper.plugins.uidebugger.common.InspectableObject import com.facebook.flipper.plugins.uidebugger.model.Bounds @@ -42,6 +43,13 @@ interface NodeDescriptor { /** The children this node exposes in the inspector. */ fun getChildren(node: T): List + /** + * Get a snapshot of the node. Bitmaps are not cheap to create, so accept one as an optional + * parameter. If a bitmap is provided, it will be used by the canvas to draw on it. Otherwise, a + * bitmap will be created. + */ + fun getSnapshot(node: T, bitmap: Bitmap?): Bitmap? + /** * If you have overlapping children this indicates which child is active / on top, we will only * listen to / traverse this child. If return null we assume all children are 'active' diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ObjectDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ObjectDescriptor.kt index 48c1d756b..7e9c0a0f3 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ObjectDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ObjectDescriptor.kt @@ -7,6 +7,7 @@ package com.facebook.flipper.plugins.uidebugger.descriptors +import android.graphics.Bitmap import com.facebook.flipper.plugins.uidebugger.common.InspectableObject import com.facebook.flipper.plugins.uidebugger.model.Bounds @@ -23,5 +24,8 @@ object ObjectDescriptor : NodeDescriptor { override fun getData(node: Any) = mutableMapOf() override fun getBounds(node: Any): Bounds? = null + override fun getTags(node: Any): Set = setOf(BaseTags.Unknown) + + override fun getSnapshot(node: Any, bitmap: Bitmap?): Bitmap? = null } diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewDescriptor.kt index 3cc151f4b..7259c4685 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewDescriptor.kt @@ -8,6 +8,8 @@ package com.facebook.flipper.plugins.uidebugger.descriptors import android.annotation.SuppressLint +import android.graphics.Bitmap +import android.graphics.Canvas import android.graphics.drawable.ColorDrawable import android.graphics.drawable.Drawable import android.os.Build @@ -105,6 +107,26 @@ object ViewDescriptor : ChainedDescriptor() { attributeSections["View"] = InspectableObject(props.toMap()) } + override fun onGetSnapshot(node: View, bitmap: Bitmap?): Bitmap? { + var workingBitmap = bitmap + + try { + if (workingBitmap == null) { + val viewWidth: Int = node.width + val viewHeight: Int = node.height + + workingBitmap = Bitmap.createBitmap(viewWidth, viewHeight, Bitmap.Config.RGB_565) + } + + workingBitmap?.let { b -> + val canvas = Canvas(b) + node.draw(canvas) + } + } catch (e: OutOfMemoryError) {} + + return workingBitmap + } + private fun fromDrawable(d: Drawable?): Inspectable? { return if (d is ColorDrawable) { InspectableValue.Color(d.color, mutable = false)