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 = {|