From 0572808f1a3d585cd57df83aada17f0596c881cb Mon Sep 17 00:00:00 2001 From: Lorenzo Blasa Date: Tue, 18 Oct 2022 04:30:51 -0700 Subject: [PATCH] Add additional inspectables Summary: This change adds support for more inspectables and also introduces more complex types to be used as a value. This become specially useful for more complex yet primitive types like coordinate, size, bounds, etc. Reviewed By: LukeDefeo Differential Revision: D40307885 fbshipit-source-id: 125e832f06d6b31f56eb5405182d1c0d61388930 --- .../descriptors/DebugComponentDescriptor.kt | 2 +- .../litho/descriptors/LithoViewDescriptor.kt | 8 +- .../litho/descriptors/MountedDawable.kt | 20 ++-- .../descriptors/TextDrawableDescriptor.kt | 6 +- .../plugins/uidebugger/common/EnumMapping.kt | 4 +- .../descriptors/ActivityDescriptor.kt | 2 +- .../descriptors/ApplicationRefDescriptor.kt | 2 +- .../descriptors/ChainedDescriptor.kt | 2 +- .../descriptors/ColorDrawableDescriptor.kt | 10 +- .../descriptors/DescriptorRegister.kt | 2 + .../descriptors/DrawableDescriptor.kt | 17 ++- .../FragmentFrameworkDescriptor.kt | 23 +++- .../descriptors/FragmentSupportDescriptor.kt | 19 ++- .../descriptors/ImageViewDescriptor.kt | 42 +++++++ .../uidebugger/descriptors/NodeDescriptor.kt | 2 +- .../descriptors/ObjectDescriptor.kt | 2 +- .../descriptors/OffsetChildDescriptor.kt | 7 +- .../descriptors/TextViewDescriptor.kt | 12 +- .../uidebugger/descriptors/ViewDescriptor.kt | 108 +++++++++--------- .../descriptors/ViewGroupDescriptor.kt | 3 +- .../descriptors/ViewPagerDescriptor.kt | 6 +- .../descriptors/WindowDescriptor.kt | 86 ++++++++++++++ .../plugins/uidebugger/model/Inspectable.kt | 65 +++++++++-- .../flipper/plugins/uidebugger/model/Node.kt | 11 -- .../flipper/plugins/uidebugger/model/Types.kt | 67 +++++++++++ .../plugins/uidebugger/EnumMappingTest.kt | 6 +- desktop/plugins/public/ui-debugger/types.tsx | 15 ++- 27 files changed, 417 insertions(+), 132 deletions(-) create mode 100644 android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ImageViewDescriptor.kt create mode 100644 android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Types.kt diff --git a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/DebugComponentDescriptor.kt b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/DebugComponentDescriptor.kt index 50fc8d5dc..5d78b79e7 100644 --- a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/DebugComponentDescriptor.kt +++ b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/DebugComponentDescriptor.kt @@ -8,13 +8,13 @@ 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.flipper.plugins.uidebugger.model.InspectableObject import com.facebook.litho.DebugComponent class DebugComponentDescriptor(val register: DescriptorRegister) : NodeDescriptor { diff --git a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/LithoViewDescriptor.kt b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/LithoViewDescriptor.kt index 91cd41273..d77d4b6a4 100644 --- a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/LithoViewDescriptor.kt +++ b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/LithoViewDescriptor.kt @@ -7,11 +7,11 @@ 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.flipper.plugins.uidebugger.model.Inspectable +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue import com.facebook.litho.DebugComponent import com.facebook.litho.LithoView @@ -19,7 +19,7 @@ object LithoViewDescriptor : ChainedDescriptor() { override fun onGetName(node: LithoView): String = node.javaClass.simpleName - override fun onGetChildren(node: LithoView): List? { + override fun onGetChildren(node: LithoView): List { val result = mutableListOf() val debugComponent = DebugComponent.getRootInstance(node) if (debugComponent != null) { diff --git a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/MountedDawable.kt b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/MountedDawable.kt index 5205e0db2..37b81a412 100644 --- a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/MountedDawable.kt +++ b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/MountedDawable.kt @@ -8,9 +8,9 @@ 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 +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject /** a drawable or view that is mounted, along with the correct descriptor */ class MountedObject(val obj: Any, val descriptor: NodeDescriptor) @@ -19,14 +19,16 @@ object MountedObjectDescriptor : NodeDescriptor { 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) + bounds?.let { b -> + /** + * 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(0, 0, b.width, b.height) + } + return null } override fun getName(node: MountedObject): String = node.descriptor.getName(node.obj) diff --git a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/TextDrawableDescriptor.kt b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/TextDrawableDescriptor.kt index 8154dd97e..883de6f17 100644 --- a/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/TextDrawableDescriptor.kt +++ b/android/plugins/litho/src/main/java/com/facebook/flipper/plugins/uidebugger/litho/descriptors/TextDrawableDescriptor.kt @@ -7,11 +7,11 @@ 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.flipper.plugins.uidebugger.model.Inspectable +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue import com.facebook.litho.widget.TextDrawable object TextDrawableDescriptor : ChainedDescriptor() { diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/common/EnumMapping.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/common/EnumMapping.kt index 03d7047d1..da081f686 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/common/EnumMapping.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/common/EnumMapping.kt @@ -9,6 +9,8 @@ package com.facebook.flipper.plugins.uidebugger.common import android.util.Log import com.facebook.flipper.plugins.uidebugger.LogTag +import com.facebook.flipper.plugins.uidebugger.model.Enumeration +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue // Maintains 2 way mapping between some enum value and a readable string representation open class EnumMapping(private val mapping: Map) { @@ -32,7 +34,7 @@ open class EnumMapping(private val mapping: Map) { } fun toInspectable(value: T, mutable: Boolean): InspectableValue.Enum { - return InspectableValue.Enum(EnumData(mapping.keys, getStringRepresentation(value)), mutable) + return InspectableValue.Enum(Enumeration(mapping.keys, getStringRepresentation(value)), mutable) } companion object { const val NoMapping = "__UNKNOWN_ENUM_VALUE__" diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ActivityDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ActivityDescriptor.kt index 7aeda3a2d..81c745b65 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ActivityDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ActivityDescriptor.kt @@ -8,8 +8,8 @@ package com.facebook.flipper.plugins.uidebugger.descriptors import android.app.Activity -import com.facebook.flipper.plugins.uidebugger.common.InspectableObject import com.facebook.flipper.plugins.uidebugger.core.FragmentTracker +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject object ActivityDescriptor : ChainedDescriptor() { diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ApplicationRefDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ApplicationRefDescriptor.kt index d18131f47..38534fb39 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ApplicationRefDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ApplicationRefDescriptor.kt @@ -20,7 +20,7 @@ object ApplicationRefDescriptor : ChainedDescriptor() { } override fun onGetBounds(node: ApplicationRef): Bounds { - val displayMetrics = Resources.getSystem().getDisplayMetrics() + val displayMetrics = Resources.getSystem().displayMetrics return Bounds(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels) } 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 49b394ebf..fd675b4c6 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 @@ -8,8 +8,8 @@ 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 +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject /** * A chained descriptor is a special type of descriptor that models the inheritance hierarchy in diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ColorDrawableDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ColorDrawableDescriptor.kt index 48c40b6dc..78fc0c566 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ColorDrawableDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ColorDrawableDescriptor.kt @@ -9,9 +9,10 @@ package com.facebook.flipper.plugins.uidebugger.descriptors import android.graphics.drawable.ColorDrawable import android.os.Build -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.model.Color +import com.facebook.flipper.plugins.uidebugger.model.Inspectable +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue object ColorDrawableDescriptor : ChainedDescriptor() { @@ -22,9 +23,8 @@ object ColorDrawableDescriptor : ChainedDescriptor() { attributeSections: MutableMap ) { val props = mutableMapOf() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { - props.put("color", InspectableValue.Color(node.color, mutable = true)) + props["color"] = InspectableValue.Color(Color.fromColor(node.color), mutable = true) } attributeSections["ColorDrawable"] = InspectableObject(props.toMap()) diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/DescriptorRegister.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/DescriptorRegister.kt index 2224af62d..2166946f8 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/DescriptorRegister.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/DescriptorRegister.kt @@ -13,6 +13,7 @@ import android.graphics.drawable.Drawable import android.view.View import android.view.ViewGroup import android.view.Window +import android.widget.ImageView import android.widget.TextView import androidx.viewpager.widget.ViewPager import com.facebook.flipper.plugins.uidebugger.common.UIDebuggerException @@ -32,6 +33,7 @@ class DescriptorRegister { mapping.register(ViewGroup::class.java, ViewGroupDescriptor) mapping.register(View::class.java, ViewDescriptor) mapping.register(TextView::class.java, TextViewDescriptor) + mapping.register(ImageView::class.java, ImageViewDescriptor) mapping.register(ViewPager::class.java, ViewPagerDescriptor) mapping.register(Drawable::class.java, DrawableDescriptor) mapping.register(ColorDrawable::class.java, ColorDrawableDescriptor) diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/DrawableDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/DrawableDescriptor.kt index 616ca6d65..6d920482a 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/DrawableDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/DrawableDescriptor.kt @@ -9,10 +9,7 @@ package com.facebook.flipper.plugins.uidebugger.descriptors import android.graphics.drawable.Drawable import android.os.Build -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.model.Bounds +import com.facebook.flipper.plugins.uidebugger.model.* object DrawableDescriptor : ChainedDescriptor() { override fun onGetName(node: Drawable): String = node.javaClass.simpleName @@ -24,13 +21,15 @@ object DrawableDescriptor : ChainedDescriptor() { node: Drawable, attributeSections: MutableMap ) { - val props = mutableMapOf() - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { - props.put("alpha", InspectableValue.Number(node.getAlpha(), true)) - } + val props = mutableMapOf() + props["alpha"] = InspectableValue.Number(node.alpha, true) - attributeSections["Drawable"] = InspectableObject(props.toMap()) + val bounds = node.bounds + props["bounds"] = InspectableValue.SpaceBox(SpaceBox.fromRect(bounds)) + + attributeSections["Drawable"] = InspectableObject(props.toMap()) + } } override fun onGetTags(node: Drawable): Set = BaseTags.NativeAndroid diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/FragmentFrameworkDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/FragmentFrameworkDescriptor.kt index 4e05d9bb2..e8beb0a42 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/FragmentFrameworkDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/FragmentFrameworkDescriptor.kt @@ -7,7 +7,11 @@ package com.facebook.flipper.plugins.uidebugger.descriptors -import com.facebook.flipper.plugins.uidebugger.common.InspectableObject +import android.os.Build +import android.os.Bundle +import com.facebook.flipper.plugins.uidebugger.model.Inspectable +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue object FragmentFrameworkDescriptor : ChainedDescriptor() { @@ -21,5 +25,20 @@ object FragmentFrameworkDescriptor : ChainedDescriptor() { override fun onGetData( node: android.app.Fragment, attributeSections: MutableMap - ) {} + ) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + val args: Bundle = node.arguments + + val props = mutableMapOf() + for (key in args.keySet()) { + when (val value = args[key]) { + is Number -> props[key] = InspectableValue.Number(value) + is Boolean -> props[key] = InspectableValue.Boolean(value) + is String -> props[key] = InspectableValue.Text(value) + } + } + + attributeSections["Fragment"] = InspectableObject(props.toMap()) + } + } } diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/FragmentSupportDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/FragmentSupportDescriptor.kt index 0f3481558..24449379c 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/FragmentSupportDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/FragmentSupportDescriptor.kt @@ -7,7 +7,9 @@ package com.facebook.flipper.plugins.uidebugger.descriptors -import com.facebook.flipper.plugins.uidebugger.common.InspectableObject +import com.facebook.flipper.plugins.uidebugger.model.Inspectable +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue object FragmentSupportDescriptor : ChainedDescriptor() { @@ -21,5 +23,18 @@ object FragmentSupportDescriptor : ChainedDescriptor - ) {} + ) { + val args = node.arguments + args?.let { bundle -> + val props = mutableMapOf() + for (key in bundle.keySet()) { + when (val value = bundle[key]) { + is Number -> props[key] = InspectableValue.Number(value) + is Boolean -> props[key] = InspectableValue.Boolean(value) + is String -> props[key] = InspectableValue.Text(value) + } + } + attributeSections["Fragment"] = InspectableObject(props.toMap()) + } + } } diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ImageViewDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ImageViewDescriptor.kt new file mode 100644 index 000000000..3f07d5338 --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ImageViewDescriptor.kt @@ -0,0 +1,42 @@ +/* + * 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.descriptors + +import android.widget.ImageView +import android.widget.ImageView.ScaleType +import com.facebook.flipper.plugins.uidebugger.common.EnumMapping +import com.facebook.flipper.plugins.uidebugger.model.Inspectable +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject + +object ImageViewDescriptor : ChainedDescriptor() { + override fun onGetName(node: ImageView): String = node.javaClass.simpleName + + override fun onGetData( + node: ImageView, + attributeSections: MutableMap + ) { + val props = mutableMapOf() + props["scaleType"] = scaleTypeMapping.toInspectable(node.scaleType, true) + + attributeSections["ImageView"] = InspectableObject(props) + } + + private val scaleTypeMapping: EnumMapping = + object : + EnumMapping( + mapOf( + "CENTER" to ScaleType.CENTER, + "CENTER_CROP" to ScaleType.CENTER_CROP, + "CENTER_INSIDE" to ScaleType.CENTER_INSIDE, + "FIT_CENTER" to ScaleType.FIT_CENTER, + "FIT_END" to ScaleType.FIT_END, + "FIT_START" to ScaleType.FIT_START, + "FIT_XY" to ScaleType.FIT_XY, + "MATRIX" to ScaleType.MATRIX, + )) {} +} 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 a74c0c958..ca48eedb7 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 @@ -8,8 +8,8 @@ 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 +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject /* Descriptors are an extension point used during traversal to extract data out of arbitrary 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 7e9c0a0f3..4e733deae 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 @@ -8,8 +8,8 @@ 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 +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject object ObjectDescriptor : NodeDescriptor { diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/OffsetChildDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/OffsetChildDescriptor.kt index aeb48a866..d59d002ed 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/OffsetChildDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/OffsetChildDescriptor.kt @@ -8,8 +8,8 @@ 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 +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject /** a drawable or view that is mounted, along with the correct descriptor */ class OffsetChild(val child: Any, val descriptor: NodeDescriptor, val x: Int, val y: Int) { @@ -22,7 +22,10 @@ object OffsetChildDescriptor : NodeDescriptor { override fun getBounds(node: OffsetChild): Bounds? { val bounds = node.descriptor.getBounds(node.child) - return bounds?.copy(x = node.x, y = node.y) + bounds?.let { b -> + return Bounds(node.x, node.y, b.width, b.height) + } + return null } override fun getName(node: OffsetChild): String = node.descriptor.getName(node.child) diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/TextViewDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/TextViewDescriptor.kt index 22b07fa5e..c81e4c494 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/TextViewDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/TextViewDescriptor.kt @@ -9,9 +9,10 @@ package com.facebook.flipper.plugins.uidebugger.descriptors import android.os.Build import android.widget.TextView -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.model.Color +import com.facebook.flipper.plugins.uidebugger.model.Inspectable +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue object TextViewDescriptor : ChainedDescriptor() { @@ -26,7 +27,8 @@ object TextViewDescriptor : ChainedDescriptor() { mutableMapOf( "text" to InspectableValue.Text(node.text.toString(), false), "textSize" to InspectableValue.Number(node.textSize, false), - "textColor" to InspectableValue.Color(node.getTextColors().getDefaultColor(), false)) + "textColor" to + InspectableValue.Color(Color.fromColor(node.textColors.defaultColor), false)) val typeface = node.typeface if (typeface != null) { @@ -50,6 +52,6 @@ object TextViewDescriptor : ChainedDescriptor() { props["maxWidth"] = InspectableValue.Number(node.maxWidth, false) } - attributeSections.put("TextView", InspectableObject(props)) + attributeSections["TextView"] = InspectableObject(props) } } 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 0a6e8294e..2342a1cfa 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 @@ -20,8 +20,9 @@ import android.view.View import android.view.ViewGroup import android.widget.FrameLayout import android.widget.LinearLayout -import com.facebook.flipper.plugins.uidebugger.common.* -import com.facebook.flipper.plugins.uidebugger.model.Bounds +import com.facebook.flipper.plugins.uidebugger.common.BitmapPool +import com.facebook.flipper.plugins.uidebugger.common.EnumMapping +import com.facebook.flipper.plugins.uidebugger.model.* import com.facebook.flipper.plugins.uidebugger.util.ResourcesUtil import java.lang.reflect.Field @@ -47,14 +48,16 @@ object ViewDescriptor : ChainedDescriptor() { ) { val props = mutableMapOf() - props["height"] = InspectableValue.Number(node.height, mutable = true) - props["width"] = InspectableValue.Number(node.width, mutable = true) + props["size"] = InspectableValue.Size(Size(node.width, node.height), mutable = true) props["alpha"] = InspectableValue.Number(node.alpha, mutable = true) props["visibility"] = VisibilityMapping.toInspectable(node.visibility, mutable = false) - fromDrawable(node.background)?.let { props["background"] = it } + fromDrawable(node.background)?.let { background -> props["background"] = background } + + node.tag + ?.let { InspectableValue.fromAny(it, mutable = false) } + ?.let { tag -> props.put("tag", tag) } - node.tag?.let { InspectableValue.fromAny(it, mutable = false) }?.let { props.put("tag", it) } props["keyedTags"] = InspectableObject(getViewTags(node)) props["layoutParams"] = getLayoutParams(node) props["state"] = @@ -66,46 +69,20 @@ object ViewDescriptor : ChainedDescriptor() { "selected" to InspectableValue.Boolean(node.isSelected, mutable = false))) props["bounds"] = - InspectableObject( - mapOf( - "left" to InspectableValue.Number(node.left, mutable = true), - "right" to InspectableValue.Number(node.right, mutable = true), - "top" to InspectableValue.Number(node.top, mutable = true), - "bottom" to InspectableValue.Number(node.bottom, mutable = true))) + InspectableValue.SpaceBox(SpaceBox(node.top, node.right, node.bottom, node.left)) props["padding"] = - InspectableObject( - mapOf( - "left" to InspectableValue.Number(node.paddingLeft, mutable = true), - "right" to InspectableValue.Number(node.paddingRight, mutable = true), - "top" to InspectableValue.Number(node.paddingTop, mutable = true), - "bottom" to InspectableValue.Number(node.paddingBottom, mutable = true))) - + InspectableValue.SpaceBox( + SpaceBox(node.paddingTop, node.paddingRight, node.paddingBottom, node.paddingLeft)) props["rotation"] = - InspectableObject( - mapOf( - "x" to InspectableValue.Number(node.rotationX, mutable = true), - "y" to InspectableValue.Number(node.rotationY, mutable = true), - "z" to InspectableValue.Number(node.rotation, mutable = true))) - - props["scale"] = - InspectableObject( - mapOf( - "x" to InspectableValue.Number(node.scaleX, mutable = true), - "y" to InspectableValue.Number(node.scaleY, mutable = true))) - props["pivot"] = - InspectableObject( - mapOf( - "x" to InspectableValue.Number(node.pivotX, mutable = true), - "y" to InspectableValue.Number(node.pivotY, mutable = true))) + InspectableValue.Coordinate3D(Coordinate3D(node.rotationX, node.rotationY, node.rotation)) + props["scale"] = InspectableValue.Coordinate(Coordinate(node.scaleX, node.scaleY)) + props["pivot"] = InspectableValue.Coordinate(Coordinate(node.pivotX, node.pivotY)) val positionOnScreen = IntArray(2) node.getLocationOnScreen(positionOnScreen) props["globalPosition"] = - InspectableObject( - mapOf( - "x" to InspectableValue.Number(positionOnScreen[0], mutable = false), - "y" to InspectableValue.Number(positionOnScreen[1], mutable = false))) + InspectableValue.Coordinate(Coordinate(positionOnScreen[0], positionOnScreen[1])) val localVisible = Rect() node.getLocalVisibleRect(localVisible) @@ -113,12 +90,39 @@ object ViewDescriptor : ChainedDescriptor() { props["localVisible"] = InspectableObject( mapOf( - "x" to InspectableValue.Number(localVisible.left, mutable = true), - "y" to InspectableValue.Number(node.top, mutable = true), - "width" to InspectableValue.Number(node.width, mutable = true), - "height" to InspectableValue.Number(node.height, mutable = true)), + "position" to InspectableValue.Coordinate(Coordinate(localVisible.left, node.top)), + "size" to InspectableValue.Size(Size(node.width, node.height))), ) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + props["layoutDirection"] = LayoutDirectionMapping.toInspectable(node.layoutDirection, false) + props["textDirection"] = TextDirectionMapping.toInspectable(node.textDirection, false) + props["textAlignment"] = TextAlignmentMapping.toInspectable(node.textAlignment, false) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + props["elevation"] = InspectableValue.Number(node.elevation) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + props["translation"] = + InspectableValue.Coordinate3D( + Coordinate3D(node.translationX, node.translationY, node.translationZ)) + } else { + props["translation"] = + InspectableValue.Coordinate(Coordinate(node.translationX, node.translationY)) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP_MR1) { + props["position"] = InspectableValue.Coordinate3D(Coordinate3D(node.x, node.y, node.z)) + } else { + props["position"] = InspectableValue.Coordinate(Coordinate(node.x, node.y)) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + fromDrawable(node.foreground)?.let { foreground -> props["foreground"] = foreground } + } + attributeSections["View"] = InspectableObject(props.toMap()) } @@ -148,7 +152,7 @@ object ViewDescriptor : ChainedDescriptor() { private fun fromDrawable(d: Drawable?): Inspectable? { return if (d is ColorDrawable) { - InspectableValue.Color(d.color, mutable = false) + InspectableValue.Color(Color.fromColor(d.color), mutable = false) } else null } @@ -160,15 +164,13 @@ object ViewDescriptor : ChainedDescriptor() { params["height"] = LayoutParamsMapping.toInspectable(layoutParams.height, mutable = true) if (layoutParams is ViewGroup.MarginLayoutParams) { - val margin = - InspectableObject( - mapOf( - "left" to InspectableValue.Number(layoutParams.leftMargin, mutable = true), - "top" to InspectableValue.Number(layoutParams.topMargin, mutable = true), - "right" to InspectableValue.Number(layoutParams.rightMargin, mutable = true), - "bottom" to InspectableValue.Number(layoutParams.bottomMargin, mutable = true))) - - params["margin"] = margin + params["margin"] = + InspectableValue.SpaceBox( + SpaceBox( + layoutParams.topMargin, + layoutParams.rightMargin, + layoutParams.bottomMargin, + layoutParams.leftMargin)) } if (layoutParams is FrameLayout.LayoutParams) { params["gravity"] = GravityMapping.toInspectable(layoutParams.gravity, mutable = true) diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewGroupDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewGroupDescriptor.kt index 8e2d6c92d..cf70ce776 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewGroupDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewGroupDescriptor.kt @@ -11,8 +11,9 @@ import android.os.Build import android.view.View import android.view.ViewGroup import androidx.core.view.ViewGroupCompat -import com.facebook.flipper.plugins.uidebugger.common.* +import com.facebook.flipper.plugins.uidebugger.common.EnumMapping import com.facebook.flipper.plugins.uidebugger.core.FragmentTracker +import com.facebook.flipper.plugins.uidebugger.model.* object ViewGroupDescriptor : ChainedDescriptor() { diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewPagerDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewPagerDescriptor.kt index 95addee8d..e89161d26 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewPagerDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/ViewPagerDescriptor.kt @@ -8,8 +8,8 @@ package com.facebook.flipper.plugins.uidebugger.descriptors import androidx.viewpager.widget.ViewPager -import com.facebook.flipper.plugins.uidebugger.common.InspectableObject -import com.facebook.flipper.plugins.uidebugger.common.InspectableValue +import com.facebook.flipper.plugins.uidebugger.model.InspectableObject +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue object ViewPagerDescriptor : ChainedDescriptor() { @@ -25,6 +25,6 @@ object ViewPagerDescriptor : ChainedDescriptor() { InspectableObject( mapOf("currentItemIndex" to InspectableValue.Number(node.currentItem, false))) - attributeSections.put("ViewPager", props) + attributeSections["ViewPager"] = props } } diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/WindowDescriptor.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/WindowDescriptor.kt index f6e126e7f..42a85ea26 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/WindowDescriptor.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/descriptors/WindowDescriptor.kt @@ -7,13 +7,99 @@ package com.facebook.flipper.plugins.uidebugger.descriptors +import android.annotation.SuppressLint +import android.util.TypedValue import android.view.Window +import com.facebook.flipper.plugins.uidebugger.model.Color +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 java.lang.reflect.Field object WindowDescriptor : ChainedDescriptor() { + private var internalRStyleableClass: Class<*>? = null + private var internalRStyleableFields: Array? = null + private var internalRStyleableWindowField: Field? = null + private var internalRStyleable: Any? = null + override fun onGetName(node: Window): String { return node.javaClass.simpleName } override fun onGetChildren(node: Window): List = listOf(node.decorView) + + @SuppressLint("PrivateApi") + override fun onGetData( + node: Window, + attributeSections: MutableMap + ) { + try { + if (internalRStyleableClass == null) { + internalRStyleableClass = Class.forName("com.android.internal.R\$styleable") + internalRStyleableClass?.let { clazz -> + internalRStyleable = clazz.newInstance() + internalRStyleableFields = clazz.declaredFields + internalRStyleableWindowField = clazz.getDeclaredField("Window") + internalRStyleableWindowField?.isAccessible = true + } + } + } catch (e: Exception) { + return + } + + internalRStyleableWindowField?.let { field -> + val windowStyleable = field[internalRStyleable] as IntArray? ?: return + + val indexToName: MutableMap = mutableMapOf() + internalRStyleableFields?.forEach { f -> + if (f.name.startsWith("Window_") && f.type == Int::class.javaPrimitiveType) { + indexToName[f.getInt(internalRStyleable)] = f.name + } + } + + val props = mutableMapOf() + + val typedValue = TypedValue() + for ((index, attr) in windowStyleable.withIndex()) { + val fieldName = indexToName[index] ?: continue + + if (node.context.theme.resolveAttribute(attr, typedValue, true)) { + // Strip 'Windows_' (length: 7) from the name. + val name = fieldName.substring(7) + + when (typedValue.type) { + TypedValue.TYPE_STRING -> + props[name] = InspectableValue.Text(typedValue.string.toString()) + TypedValue.TYPE_INT_BOOLEAN -> + props[name] = InspectableValue.Boolean(typedValue.data != 0) + TypedValue.TYPE_INT_HEX -> + props[name] = InspectableValue.Text("0x" + Integer.toHexString(typedValue.data)) + TypedValue.TYPE_FLOAT -> + props[name] = + InspectableValue.Number(java.lang.Float.intBitsToFloat(typedValue.data)) + TypedValue.TYPE_REFERENCE -> { + val resId = typedValue.data + if (resId != 0) { + props[name] = InspectableValue.Text(node.context.resources.getResourceName(resId)) + } + } + else -> { + if (typedValue.type >= TypedValue.TYPE_FIRST_COLOR_INT && + typedValue.type <= TypedValue.TYPE_LAST_COLOR_INT) { + val hexColor = "#" + Integer.toHexString(typedValue.data) + val color = android.graphics.Color.parseColor(hexColor) + props[name] = InspectableValue.Color(Color.fromColor(color)) + } else if (typedValue.type >= TypedValue.TYPE_FIRST_INT && + typedValue.type <= TypedValue.TYPE_LAST_INT) { + props[name] = InspectableValue.Number(typedValue.data) + } + } + } + } + } + + attributeSections["Window"] = InspectableObject(props.toMap()) + } + } } diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Inspectable.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Inspectable.kt index 4e9e06909..503fbf867 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Inspectable.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Inspectable.kt @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. */ -package com.facebook.flipper.plugins.uidebugger.common +package com.facebook.flipper.plugins.uidebugger.model import kotlinx.serialization.KSerializer import kotlinx.serialization.SerialName @@ -21,13 +21,15 @@ sealed class Inspectable { abstract val mutable: kotlin.Boolean } -// mutable here means you can add/remove items, for native android this should probably be false +// In this context, mutable means you can add/remove items, +// for native android this should probably be false. @SerialName("array") @Serializable data class InspectableArray(val items: List, override val mutable: Boolean = false) : Inspectable() -// mutable here means you can add / remove keys, for native android this should probably be false +// In this context, mutable means you can add / remove keys, +// for native android this should probably be false. @SerialName("object") @Serializable data class InspectableObject( @@ -40,34 +42,75 @@ sealed class InspectableValue : Inspectable() { @kotlinx.serialization.Serializable @SerialName("text") - class Text(val value: String, override val mutable: kotlin.Boolean) : InspectableValue() + class Text(val value: String, override val mutable: kotlin.Boolean = false) : InspectableValue() @kotlinx.serialization.Serializable @SerialName("boolean") - class Boolean(val value: kotlin.Boolean, override val mutable: kotlin.Boolean) : + class Boolean(val value: kotlin.Boolean, override val mutable: kotlin.Boolean = false) : InspectableValue() @SerialName("number") @kotlinx.serialization.Serializable data class Number( @Serializable(with = NumberSerializer::class) val value: kotlin.Number, - override val mutable: kotlin.Boolean + override val mutable: kotlin.Boolean = false ) : InspectableValue() @SerialName("color") @kotlinx.serialization.Serializable - data class Color(val value: Int, override val mutable: kotlin.Boolean) : InspectableValue() + data class Color( + val value: com.facebook.flipper.plugins.uidebugger.model.Color, + override val mutable: kotlin.Boolean = false + ) : InspectableValue() + + @SerialName("coordinate") + @kotlinx.serialization.Serializable + data class Coordinate( + val value: com.facebook.flipper.plugins.uidebugger.model.Coordinate, + override val mutable: kotlin.Boolean = false + ) : InspectableValue() + + @SerialName("coordinate3d") + @kotlinx.serialization.Serializable + data class Coordinate3D( + val value: com.facebook.flipper.plugins.uidebugger.model.Coordinate3D, + override val mutable: kotlin.Boolean = false + ) : InspectableValue() + + @SerialName("size") + @kotlinx.serialization.Serializable + data class Size( + val value: com.facebook.flipper.plugins.uidebugger.model.Size, + override val mutable: kotlin.Boolean = false + ) : InspectableValue() + + @SerialName("bounds") + @kotlinx.serialization.Serializable + data class Bounds( + val value: com.facebook.flipper.plugins.uidebugger.model.Bounds, + override val mutable: kotlin.Boolean = false + ) : InspectableValue() + + @SerialName("space") + @kotlinx.serialization.Serializable + data class SpaceBox( + val value: com.facebook.flipper.plugins.uidebugger.model.SpaceBox, + override val mutable: kotlin.Boolean = false + ) : InspectableValue() @SerialName("enum") @kotlinx.serialization.Serializable - data class Enum(val value: EnumData, override val mutable: kotlin.Boolean) : InspectableValue() + data class Enum( + val value: com.facebook.flipper.plugins.uidebugger.model.Enumeration, + override val mutable: kotlin.Boolean = false + ) : InspectableValue() companion object { /** * Will attempt to convert Any ref to a suitable primitive inspectable value. Only use if you - * are dealing with an Any / object type. Prefer the specific contructors + * are dealing with an Any / object type. Prefer the specific constructors */ - fun fromAny(any: Any, mutable: kotlin.Boolean): Inspectable? { + fun fromAny(any: Any, mutable: kotlin.Boolean = false): Inspectable? { return when (any) { is kotlin.Number -> InspectableValue.Number(any, mutable) is kotlin.Boolean -> InspectableValue.Boolean(any, mutable) @@ -78,8 +121,6 @@ sealed class InspectableValue : Inspectable() { } } -@kotlinx.serialization.Serializable data class EnumData(val values: Set, val value: String) - object NumberSerializer : KSerializer { override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("com.meta.NumberSerializer", PrimitiveKind.DOUBLE) diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Node.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Node.kt index 0827f6ab2..5789e78e2 100644 --- a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Node.kt +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Node.kt @@ -7,8 +7,6 @@ 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 @kotlinx.serialization.Serializable @@ -21,12 +19,3 @@ data class Node( val children: List, val activeChild: Id?, ) - -@kotlinx.serialization.Serializable -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()) - } - } -} diff --git a/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Types.kt b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Types.kt new file mode 100644 index 000000000..9933d7c09 --- /dev/null +++ b/android/src/main/java/com/facebook/flipper/plugins/uidebugger/model/Types.kt @@ -0,0 +1,67 @@ +/* + * 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.model + +import android.graphics.Rect +import kotlinx.serialization.Serializable + +@kotlinx.serialization.Serializable +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()) + } + } +} + +@kotlinx.serialization.Serializable +data class SpaceBox(val top: Int, val right: Int, val bottom: Int, val left: Int) { + companion object { + fun fromRect(rect: Rect): SpaceBox { + return SpaceBox(rect.top, rect.right, rect.bottom, rect.left) + } + } +} + +@kotlinx.serialization.Serializable +data class Color(val r: Int, val g: Int, val b: Int, val alpha: Int) { + companion object { + fun fromColor(color: Int): Color { + val alpha: Int = (color shr 24) and 0xFF / 255 + val red: Int = (color shr 16) and 0xFF + val green: Int = (color shr 8) and 0xFF + val blue: Int = (color shr 0) and 0xFF + return Color(red, green, blue, alpha) + } + fun fromColor(color: android.graphics.Color): Color { + return fromColor(color.toArgb()) + } + } +} + +@kotlinx.serialization.Serializable +data class Coordinate( + @Serializable(with = NumberSerializer::class) val x: Number, + @Serializable(with = NumberSerializer::class) val y: Number +) {} + +@kotlinx.serialization.Serializable +data class Coordinate3D( + @Serializable(with = NumberSerializer::class) val x: Number, + @Serializable(with = NumberSerializer::class) val y: Number, + @Serializable(with = NumberSerializer::class) val z: Number +) {} + +@kotlinx.serialization.Serializable +data class Size( + @Serializable(with = NumberSerializer::class) val width: Number, + @Serializable(with = NumberSerializer::class) val height: Number +) {} + +@kotlinx.serialization.Serializable +data class Enumeration(val values: Set, val value: String) diff --git a/android/src/test/java/com/facebook/flipper/plugins/uidebugger/EnumMappingTest.kt b/android/src/test/java/com/facebook/flipper/plugins/uidebugger/EnumMappingTest.kt index 52b7144d0..d077225d7 100644 --- a/android/src/test/java/com/facebook/flipper/plugins/uidebugger/EnumMappingTest.kt +++ b/android/src/test/java/com/facebook/flipper/plugins/uidebugger/EnumMappingTest.kt @@ -8,9 +8,9 @@ package com.facebook.flipper.plugins.uidebugger import android.view.View -import com.facebook.flipper.plugins.uidebugger.common.EnumData import com.facebook.flipper.plugins.uidebugger.common.EnumMapping -import com.facebook.flipper.plugins.uidebugger.common.InspectableValue +import com.facebook.flipper.plugins.uidebugger.model.Enumeration +import com.facebook.flipper.plugins.uidebugger.model.InspectableValue import org.hamcrest.CoreMatchers.* import org.hamcrest.MatcherAssert.assertThat import org.junit.Test @@ -42,6 +42,6 @@ class EnumMappingTest { visibility.toInspectable(View.GONE, true), equalTo( InspectableValue.Enum( - EnumData(setOf("VISIBLE", "INVISIBLE", "GONE"), "GONE"), mutable = true))) + Enumeration(setOf("VISIBLE", "INVISIBLE", "GONE"), "GONE"), mutable = true))) } } diff --git a/desktop/plugins/public/ui-debugger/types.tsx b/desktop/plugins/public/ui-debugger/types.tsx index 4c9a54b71..38ba5041a 100644 --- a/desktop/plugins/public/ui-debugger/types.tsx +++ b/desktop/plugins/public/ui-debugger/types.tsx @@ -51,6 +51,13 @@ export type Bounds = { height: number; }; +export type Color = { + r: number; + g: number; + b: number; + alpha: number; +}; + export type Snapshot = string; export type Id = number; @@ -76,7 +83,13 @@ export type InspectableNumber = { export type InspectableColor = { type: 'number'; - value: number; + value: Color; + mutable: boolean; +}; + +export type InspectableBounds = { + type: 'bounds'; + value: Bounds; mutable: boolean; };