Expand trees together - including fragments, not including litho components

Summary: When expanding one tree, the other tree also expands. This expanding jumps over fragments (which are not in the accessibility tree) so that the trees can stay in sync even when there are extra wrappers in the main tree. Need to figure out functionality for litho components (these simply don't expand together right now since the relationship between the trees at these nodes are less obvious).

Differential Revision: D8943229

fbshipit-source-id: 289c3511a6495508b45a62da13ae4c50209e6118
This commit is contained in:
Sara Valderrama
2018-07-25 10:11:59 -07:00
committed by Facebook Github Bot
parent 2155c7799f
commit c57e6e4396
9 changed files with 64 additions and 28 deletions

View File

@@ -490,6 +490,7 @@ public class InspectorSonarPlugin implements SonarPlugin {
.put("children", children)
.put("attributes", attributes)
.put("decoration", descriptor.getDecoration(obj))
.put("extraInfo", descriptor.getExtraInfo(obj))
.build();
}

View File

@@ -162,6 +162,15 @@ public abstract class NodeDescriptor<T> {
*/
public abstract String getDecoration(T node) throws Exception;
/**
* @return Extra data about the node indicating whether the node corresponds to a node in the
* other tree or if it is not represented in the other tree bu has children that should show
* up, etc.
*/
public SonarObject getExtraInfo(T node) {
return new SonarObject.Builder().build();
}
/**
* Test this node against a given query to see if it matches. This is used for finding search
* results.

View File

@@ -64,6 +64,12 @@ public class DialogFragmentDescriptor extends NodeDescriptor<DialogFragment> {
return descriptor.getAttributes(node);
}
@Override
public SonarObject getExtraInfo(DialogFragment node) {
final NodeDescriptor descriptor = descriptorForClass(Fragment.class);
return descriptor.getExtraInfo(node);
}
@Override
public void setHighlighted(DialogFragment node, boolean selected) throws Exception {
final NodeDescriptor descriptor = descriptorForClass(Dialog.class);

View File

@@ -77,6 +77,11 @@ public class FragmentDescriptor extends NodeDescriptor<Fragment> {
return Arrays.asList(new Named<>("id", resourceId));
}
@Override
public SonarObject getExtraInfo(Fragment node) {
return new SonarObject.Builder().put("nonAXWithAXChild", true).build();
}
@Nullable
private static String getResourceId(Fragment node) {
final int id = node.getId();

View File

@@ -64,6 +64,12 @@ public class SupportDialogFragmentDescriptor extends NodeDescriptor<DialogFragme
return descriptor.getAttributes(node);
}
@Override
public SonarObject getExtraInfo(DialogFragment node) {
final NodeDescriptor descriptor = descriptorForClass(Fragment.class);
return descriptor.getExtraInfo(node);
}
@Override
public void setHighlighted(DialogFragment node, boolean selected) throws Exception {
final NodeDescriptor descriptor = descriptorForClass(Dialog.class);

View File

@@ -78,6 +78,11 @@ public class SupportFragmentDescriptor extends NodeDescriptor<Fragment> {
"id", ResourcesUtil.getIdStringQuietly(node.getContext(), node.getResources(), id)));
}
@Override
public SonarObject getExtraInfo(Fragment node) {
return new SonarObject.Builder().put("nonAXWithAXChild", true).build();
}
@Override
public void setHighlighted(Fragment node, boolean selected) throws Exception {
if (node.getView() == null) {

View File

@@ -103,6 +103,7 @@ public class InspectorSonarPluginTest {
.put("children", new SonarArray.Builder().put("test"))
.put("attributes", new SonarArray.Builder())
.put("decoration", (String) null)
.put("extraInfo", new SonarObject.Builder())
.build()));
}
@@ -138,7 +139,8 @@ public class InspectorSonarPluginTest {
.put("data", new SonarObject.Builder())
.put("children", new SonarArray.Builder())
.put("attributes", new SonarArray.Builder())
.put("decoration", (String) null)))
.put("decoration", (String) null)
.put("extraInfo", new SonarObject.Builder())))
.build()));
}

View File

@@ -179,6 +179,13 @@ export default class Layout extends SonarPlugin<InspectorState> {
expanded: expand,
},
},
AXelements: {
...state.AXelements,
[key]: {
...state.AXelements[key],
expanded: expand,
},
},
};
},
@@ -322,9 +329,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
}
return this.performInitialExpand(
ax
? this.state.AXelements[element.children[0]]
: this.state.elements[element.children[0]],
(ax ? this.state.AXelements : this.state.elements)[element.children[0]],
ax,
);
});
@@ -540,11 +545,22 @@ export default class Layout extends SonarPlugin<InspectorState> {
performance.mark('LayoutInspectorExpandElement');
if (expand) {
return this.getChildren(key, ax).then((elements: Array<Element>) => {
this.props.logger.trackTimeSince('LayoutInspectorExpandElement');
this.dispatchAction({
elements,
type: ax ? 'UpdateAXElements' : 'UpdateElements',
});
// only expand extra components in the main tree when in AX mode
if (this.state.inAXMode && !ax) {
// expand child wrapper elements that aren't in the AX tree (e.g. fragments)
for (const childElem of elements) {
if (childElem.extraInfo.nonAXWithAXChild) {
this.setElementExpanded(childElem.id, true, false);
}
}
}
this.props.logger.trackTimeSince('LayoutInspectorExpandElement');
return Promise.resolve(elements);
});
} else {
@@ -583,19 +599,9 @@ export default class Layout extends SonarPlugin<InspectorState> {
onElementExpanded = (key: ElementID, deep: boolean) => {
if (deep) {
this.deepExpandElement(key, false);
} else {
this.expandElement(key, false);
}
this.props.logger.track('usage', 'layout:element-expanded', {
id: key,
deep: deep,
});
};
onAXElementExpanded = (key: ElementID, deep: boolean) => {
if (deep) {
this.deepExpandElement(key, true);
} else {
this.expandElement(key, false);
this.expandElement(key, true);
}
this.props.logger.track('usage', 'layout:element-expanded', {
@@ -621,11 +627,6 @@ export default class Layout extends SonarPlugin<InspectorState> {
this.getNodes([key], true, false).then((elements: Array<Element>) => {
this.dispatchAction({elements, type: 'UpdateElements'});
});
});
onAXElementSelected = debounce((key: ElementID) => {
this.dispatchAction({key, type: 'SelectElement'});
this.client.send('setHighlighted', {id: key});
this.getNodes([key], true, true).then((elements: Array<Element>) => {
this.dispatchAction({elements, type: 'UpdateAXElements'});
});
@@ -635,10 +636,6 @@ export default class Layout extends SonarPlugin<InspectorState> {
this.client.send('setHighlighted', {id: key});
});
onAXElementHovered = debounce((key: ?ElementID) => {
this.client.send('setHighlighted', {id: key});
});
onDataValueChanged = (path: Array<string>, value: any) => {
const selected = this.state.inAXMode
? this.state.AXselected
@@ -757,9 +754,9 @@ export default class Layout extends SonarPlugin<InspectorState> {
{AXinitialised && inAXMode ? <VerticalRule /> : null}
{AXinitialised && inAXMode ? (
<AXElementsInspector
onElementSelected={this.onAXElementSelected}
onElementHovered={this.onAXElementHovered}
onElementExpanded={this.onAXElementExpanded}
onElementSelected={this.onElementSelected}
onElementHovered={this.onElementHovered}
onElementExpanded={this.onElementExpanded}
onValueChanged={this.onDataValueChanged}
selected={AXselected}
searchResults={null}

View File

@@ -34,6 +34,10 @@ export type ElementAttribute = {|
value: string,
|};
export type ElementExtraInfo = {|
nonAXWithAXChild?: boolean,
|};
export type Element = {|
id: ElementID,
name: string,
@@ -42,6 +46,7 @@ export type Element = {|
attributes: Array<ElementAttribute>,
data: ElementData,
decoration: string,
extraInfo: ElementExtraInfo,
|};
export default class ElementsInspector extends Component<{