From 41f4478a7482093e87aabbeed34fe29da1a18c34 Mon Sep 17 00:00:00 2001 From: Sara Valderrama Date: Wed, 25 Jul 2018 10:12:01 -0700 Subject: [PATCH] Basic mutual highlighting for Litho components Summary: Shows basic relationship between the AX and nonAX tree litho nodes. When a litho component is selected from the nonAX tree, it's corresponding hostView or lithoView (root of the component tree) is highlighted in the AX tree giving priority to the hostView if it exists. If a hostView is selected in the AX tree, it's corresponding component is selected in the non-AX tree. If a lithoView is selected from the AX tree, it's corresponding lithoView is highlighted in the non-AX tree. This means that each hostView has a one-to-one highlighting between the two trees but lithoViews will have many nodes in the main tree that map to one node in the AX tree (which is accurate to litho components rendering but we may need to change in the future if it is not clear). Reviewed By: jknoxville Differential Revision: D8972205 fbshipit-source-id: d136f5b594d0ac1b66a82b35dc7b085186829fc4 --- .../inspector/InspectorSonarPlugin.java | 5 +- .../litho/DebugComponentDescriptor.java | 23 +++++++++ src/plugins/layout/index.js | 51 +++++++++++++++---- .../elements-inspector/ElementsInspector.js | 1 + 4 files changed, 70 insertions(+), 10 deletions(-) diff --git a/android/src/main/java/com/facebook/sonar/plugins/inspector/InspectorSonarPlugin.java b/android/src/main/java/com/facebook/sonar/plugins/inspector/InspectorSonarPlugin.java index 424eb9c5e..18148c525 100644 --- a/android/src/main/java/com/facebook/sonar/plugins/inspector/InspectorSonarPlugin.java +++ b/android/src/main/java/com/facebook/sonar/plugins/inspector/InspectorSonarPlugin.java @@ -541,9 +541,12 @@ public class InspectorSonarPlugin implements SonarPlugin { } }.run(); + String name = descriptor.getAXName(obj); + name = name.substring(name.lastIndexOf('.') + 1); + return new SonarObject.Builder() .put("id", descriptor.getId(obj)) - .put("name", descriptor.getAXName(obj)) + .put("name", name) .put("data", data) .put("children", children) .put("attributes", attributes) diff --git a/android/src/main/java/com/facebook/sonar/plugins/litho/DebugComponentDescriptor.java b/android/src/main/java/com/facebook/sonar/plugins/litho/DebugComponentDescriptor.java index 5a92e4c78..a4c9d75fd 100644 --- a/android/src/main/java/com/facebook/sonar/plugins/litho/DebugComponentDescriptor.java +++ b/android/src/main/java/com/facebook/sonar/plugins/litho/DebugComponentDescriptor.java @@ -558,6 +558,29 @@ public class DebugComponentDescriptor extends NodeDescriptor { return attributes; } + @Override + public SonarObject getExtraInfo(DebugComponent node) { + SonarObject.Builder extraInfo = new SonarObject.Builder(); + final NodeDescriptor descriptor = descriptorForClass(View.class); + final View hostView = node.getComponentHost(); + final View lithoView = node.getLithoView(); + + if (hostView != null) { + try { + extraInfo.put("linkedAXNode", descriptor.getId(hostView)); + } catch (Exception ignored) { + // doesn't have linked node descriptor + } + } else if (lithoView != null) { + try { + extraInfo.put("linkedAXNode", descriptor.getId(lithoView)); + } catch (Exception ignored) { + // doesn't add linked node descriptor + } + } + return extraInfo.build(); + } + @Override public void setHighlighted(DebugComponent node, boolean selected) { final LithoView lithoView = node.getLithoView(); diff --git a/src/plugins/layout/index.js b/src/plugins/layout/index.js index 507649a3e..b8cc61337 100644 --- a/src/plugins/layout/index.js +++ b/src/plugins/layout/index.js @@ -46,6 +46,7 @@ export type InspectorState = {| inAXMode: boolean, searchResults: ?ElementSearchResultSet, outstandingSearchQuery: ?string, + AXtoNonAXMapping: {[key: ElementID]: ElementID}, |}; type SelectElementArgs = {| @@ -160,14 +161,39 @@ export default class Layout extends SonarPlugin { AXselected: null, searchResults: null, outstandingSearchQuery: null, + AXtoNonAXMapping: {}, }; reducers = { SelectElement(state: InspectorState, {key}: SelectElementArgs) { - return { - selected: key, - AXselected: key, - }; + const linkedAXNode = + state.elements[key] && state.elements[key].extraInfo.linkedAXNode; + + // element only in main tree with linkedAXNode selected + if (linkedAXNode) { + return { + selected: key, + AXselected: linkedAXNode, + }; + + // element only in AX tree with linked nonAX element selected + } else if ( + (!state.elements[key] || + state.elements[key].name === 'ComponentHost') && + state.AXtoNonAXMapping[key] + ) { + return { + selected: state.AXtoNonAXMapping[key], + AXselected: key, + }; + + // keys are same for both trees or 'linked' element does not exist + } else { + return { + selected: key, + AXselected: key, + }; + } }, ExpandElement(state: InspectorState, {expand, key}: ExpandElementArgs) { @@ -235,6 +261,7 @@ export default class Layout extends SonarPlugin { UpdateElements(state: InspectorState, {elements}: UpdateElementsArgs) { const updatedElements = state.elements; + const updatedMapping = state.AXtoNonAXMapping; for (const element of elements) { const current = updatedElements[element.id] || {}; @@ -242,9 +269,13 @@ export default class Layout extends SonarPlugin { ...current, ...element, }; + const linked = element.extraInfo.linkedAXNode; + if (linked && !updatedMapping[linked]) { + updatedMapping[linked] = element.id; + } } - return {elements: updatedElements}; + return {elements: updatedElements, AXtoNonAXMapping: updatedMapping}; }, UpdateAXElements(state: InspectorState, {elements}: UpdateElementsArgs) { @@ -627,9 +658,11 @@ export default class Layout extends SonarPlugin { this.getNodes([key], true, false).then((elements: Array) => { this.dispatchAction({elements, type: 'UpdateElements'}); }); - this.getNodes([key], true, true).then((elements: Array) => { - this.dispatchAction({elements, type: 'UpdateAXElements'}); - }); + if (AXToggleButtonEnabled) { + this.getNodes([key], true, true).then((elements: Array) => { + this.dispatchAction({elements, type: 'UpdateAXElements'}); + }); + } }); onElementHovered = debounce((key: ?ElementID) => { @@ -693,7 +726,7 @@ export default class Layout extends SonarPlugin { diff --git a/src/ui/components/elements-inspector/ElementsInspector.js b/src/ui/components/elements-inspector/ElementsInspector.js index dfa94714a..53843305b 100644 --- a/src/ui/components/elements-inspector/ElementsInspector.js +++ b/src/ui/components/elements-inspector/ElementsInspector.js @@ -36,6 +36,7 @@ export type ElementAttribute = {| export type ElementExtraInfo = {| nonAXWithAXChild?: boolean, + linkedAXNode?: string, |}; export type Element = {|