Allow for multiple view roots, include accessibility focus changing between view roots
Summary: Ax mode now works with multiple view roots/windows, accessibility focus is also updated when new windows are opened. Reviewed By: danielbuechele Differential Revision: D9121844 fbshipit-source-id: 1da9327f5d6a784793db8076c2ad2d84e860ac1c
This commit is contained in:
committed by
Facebook Github Bot
parent
0b0f59f096
commit
ff0b045bde
@@ -27,6 +27,8 @@ import com.facebook.sonar.plugins.common.MainThreadSonarReceiver;
|
|||||||
import com.facebook.sonar.plugins.console.iface.ConsoleCommandReceiver;
|
import com.facebook.sonar.plugins.console.iface.ConsoleCommandReceiver;
|
||||||
import com.facebook.sonar.plugins.console.iface.NullScriptingEnvironment;
|
import com.facebook.sonar.plugins.console.iface.NullScriptingEnvironment;
|
||||||
import com.facebook.sonar.plugins.console.iface.ScriptingEnvironment;
|
import com.facebook.sonar.plugins.console.iface.ScriptingEnvironment;
|
||||||
|
import com.facebook.sonar.plugins.inspector.descriptors.ApplicationDescriptor;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -153,6 +155,9 @@ public class InspectorSonarPlugin implements SonarPlugin {
|
|||||||
mHighlightedId = null;
|
mHighlightedId = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// remove any added accessibility delegates
|
||||||
|
ApplicationDescriptor.clearEditedDelegates();
|
||||||
|
|
||||||
mObjectTracker.clear();
|
mObjectTracker.clear();
|
||||||
mDescriptorMapping.onDisconnect();
|
mDescriptorMapping.onDisconnect();
|
||||||
mConnection = null;
|
mConnection = null;
|
||||||
@@ -172,41 +177,8 @@ public class InspectorSonarPlugin implements SonarPlugin {
|
|||||||
@Override
|
@Override
|
||||||
public void onReceiveOnMainThread(SonarObject params, SonarResponder responder)
|
public void onReceiveOnMainThread(SonarObject params, SonarResponder responder)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
final List<View> viewRoots = mApplication.getViewRoots();
|
// applicationWrapper is not used by accessibility, but is a common ancestor for multiple view roots
|
||||||
|
responder.success(getAXNode(trackObject(mApplication)));
|
||||||
ViewGroup root = null;
|
|
||||||
for (int i = viewRoots.size() - 1; i >= 0; i--) {
|
|
||||||
if (viewRoots.get(i) instanceof ViewGroup) {
|
|
||||||
root = (ViewGroup) viewRoots.get(i);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (root != null) {
|
|
||||||
|
|
||||||
// unlikely, but check to make sure accessibility functionality doesn't change
|
|
||||||
if (!ViewCompat.hasAccessibilityDelegate(root)) {
|
|
||||||
|
|
||||||
// add delegate to root to catch accessibility events so we can update focus in sonar
|
|
||||||
root.setAccessibilityDelegate(new View.AccessibilityDelegate() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event) {
|
|
||||||
int eventType = event.getEventType();
|
|
||||||
if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED || eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED) {
|
|
||||||
mConnection.send("axFocusEvent",
|
|
||||||
new SonarObject.Builder()
|
|
||||||
.put("isFocus", eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.onRequestSendAccessibilityEvent(host, child, event);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
responder.success(getAXNode(trackObject(root)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -245,21 +217,42 @@ public class InspectorSonarPlugin implements SonarPlugin {
|
|||||||
final SonarArray ids = params.getArray("ids");
|
final SonarArray ids = params.getArray("ids");
|
||||||
final SonarArray.Builder result = new SonarArray.Builder();
|
final SonarArray.Builder result = new SonarArray.Builder();
|
||||||
|
|
||||||
|
// getNodes called to refresh accessibility focus
|
||||||
|
final boolean forFocusEvent = params.getBoolean("forFocusEvent");
|
||||||
|
|
||||||
for (int i = 0, count = ids.length(); i < count; i++) {
|
for (int i = 0, count = ids.length(); i < count; i++) {
|
||||||
final String id = ids.getString(i);
|
final String id = ids.getString(i);
|
||||||
final SonarObject node = getAXNode(id);
|
final SonarObject node = getAXNode(id);
|
||||||
if (node != null) {
|
|
||||||
result.put(node);
|
// sent request for non-existent node, potentially in error
|
||||||
} else {
|
if (node == null) {
|
||||||
|
|
||||||
|
// some nodes may be null since we are searching through all current and previous known nodes
|
||||||
|
if (forFocusEvent) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
responder.error(
|
responder.error(
|
||||||
new SonarObject.Builder()
|
new SonarObject.Builder()
|
||||||
.put("message", "No node with given id")
|
.put("message", "No node with given id")
|
||||||
.put("id", id)
|
.put("id", id)
|
||||||
.build());
|
.build());
|
||||||
return;
|
return;
|
||||||
}
|
} else {
|
||||||
|
|
||||||
|
// only need to get the focused node in this case
|
||||||
|
if (forFocusEvent) {
|
||||||
|
if (node.getObject("extraInfo").getBoolean("focused")) {
|
||||||
|
result.put(node);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// normal getNodes call, put any nodes in result
|
||||||
|
} else {
|
||||||
|
result.put(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
responder.success(new SonarObject.Builder().put("elements", result).build());
|
responder.success(new SonarObject.Builder().put("elements", result).build());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import javax.annotation.Nullable;
|
|||||||
* data can be exposed to the inspector.
|
* data can be exposed to the inspector.
|
||||||
*/
|
*/
|
||||||
public abstract class NodeDescriptor<T> {
|
public abstract class NodeDescriptor<T> {
|
||||||
private SonarConnection mConnection;
|
protected SonarConnection mConnection;
|
||||||
private DescriptorMapping mDescriptorMapping;
|
private DescriptorMapping mDescriptorMapping;
|
||||||
|
|
||||||
void setConnection(SonarConnection connection) {
|
void setConnection(SonarConnection connection) {
|
||||||
@@ -63,6 +63,26 @@ public abstract class NodeDescriptor<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidate a node in the ax tree. This tells Sonar that this node is no longer valid and its properties and/or
|
||||||
|
* children have changed. This will trigger Sonar to re-query this node getting any new data.
|
||||||
|
*/
|
||||||
|
protected final void invalidateAX(final T node) {
|
||||||
|
if (mConnection != null) {
|
||||||
|
new ErrorReportingRunnable() {
|
||||||
|
@Override
|
||||||
|
protected void runOrThrow() throws Exception {
|
||||||
|
SonarArray array =
|
||||||
|
new SonarArray.Builder()
|
||||||
|
.put(new SonarObject.Builder().put("id", getId(node)).build())
|
||||||
|
.build();
|
||||||
|
SonarObject params = new SonarObject.Builder().put("nodes", array).build();
|
||||||
|
mConnection.send("invalidateAX", params);
|
||||||
|
}
|
||||||
|
}.run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected final boolean connected() {
|
protected final boolean connected() {
|
||||||
return mConnection != null;
|
return mConnection != null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,14 +9,18 @@
|
|||||||
package com.facebook.sonar.plugins.inspector.descriptors;
|
package com.facebook.sonar.plugins.inspector.descriptors;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.support.v4.view.ViewCompat;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
import com.facebook.sonar.core.SonarDynamic;
|
import com.facebook.sonar.core.SonarDynamic;
|
||||||
import com.facebook.sonar.core.SonarObject;
|
import com.facebook.sonar.core.SonarObject;
|
||||||
import com.facebook.sonar.plugins.inspector.ApplicationWrapper;
|
import com.facebook.sonar.plugins.inspector.ApplicationWrapper;
|
||||||
import com.facebook.sonar.plugins.inspector.Named;
|
import com.facebook.sonar.plugins.inspector.Named;
|
||||||
import com.facebook.sonar.plugins.inspector.NodeDescriptor;
|
import com.facebook.sonar.plugins.inspector.NodeDescriptor;
|
||||||
import com.facebook.sonar.plugins.inspector.Touch;
|
import com.facebook.sonar.plugins.inspector.Touch;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -55,6 +59,50 @@ public class ApplicationDescriptor extends NodeDescriptor<ApplicationWrapper> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<ViewGroup> editedDelegates = new ArrayList<>();
|
||||||
|
|
||||||
|
private void setDelegates(ApplicationWrapper node) {
|
||||||
|
clearEditedDelegates();
|
||||||
|
|
||||||
|
for (View view : node.getViewRoots()) {
|
||||||
|
// unlikely, but check to make sure accessibility functionality doesn't change
|
||||||
|
if (view instanceof ViewGroup && !ViewCompat.hasAccessibilityDelegate(view)) {
|
||||||
|
|
||||||
|
// add delegate to root to catch accessibility events so we can update focus in sonar
|
||||||
|
view.setAccessibilityDelegate(new View.AccessibilityDelegate() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onRequestSendAccessibilityEvent(ViewGroup host, View child, AccessibilityEvent event) {
|
||||||
|
if (mConnection != null) {
|
||||||
|
|
||||||
|
int eventType = event.getEventType();
|
||||||
|
if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED) {
|
||||||
|
mConnection.send("axFocusEvent",
|
||||||
|
new SonarObject.Builder()
|
||||||
|
.put("isFocus", true)
|
||||||
|
.build());
|
||||||
|
} else if (eventType == AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED) {
|
||||||
|
mConnection.send("axFocusEvent",
|
||||||
|
new SonarObject.Builder()
|
||||||
|
.put("isFocus", false)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return super.onRequestSendAccessibilityEvent(host, child, event);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
editedDelegates.add((ViewGroup) view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void clearEditedDelegates() {
|
||||||
|
for (ViewGroup viewGroup : editedDelegates) {
|
||||||
|
viewGroup.setAccessibilityDelegate(null);
|
||||||
|
}
|
||||||
|
editedDelegates.clear();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(final ApplicationWrapper node) {
|
public void init(final ApplicationWrapper node) {
|
||||||
node.setListener(
|
node.setListener(
|
||||||
@@ -62,6 +110,8 @@ public class ApplicationDescriptor extends NodeDescriptor<ApplicationWrapper> {
|
|||||||
@Override
|
@Override
|
||||||
public void onActivityStackChanged(List<Activity> stack) {
|
public void onActivityStackChanged(List<Activity> stack) {
|
||||||
invalidate(node);
|
invalidate(node);
|
||||||
|
invalidateAX(node);
|
||||||
|
setDelegates(node);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -73,6 +123,8 @@ public class ApplicationDescriptor extends NodeDescriptor<ApplicationWrapper> {
|
|||||||
if (connected()) {
|
if (connected()) {
|
||||||
if (key.set(node)) {
|
if (key.set(node)) {
|
||||||
invalidate(node);
|
invalidate(node);
|
||||||
|
invalidateAX(node);
|
||||||
|
setDelegates(node);
|
||||||
}
|
}
|
||||||
node.postDelayed(this, 1000);
|
node.postDelayed(this, 1000);
|
||||||
}
|
}
|
||||||
@@ -92,6 +144,11 @@ public class ApplicationDescriptor extends NodeDescriptor<ApplicationWrapper> {
|
|||||||
return node.getApplication().getPackageName();
|
return node.getApplication().getPackageName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getAXName(ApplicationWrapper node) throws Exception {
|
||||||
|
return "Application";
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getChildCount(ApplicationWrapper node) {
|
public int getChildCount(ApplicationWrapper node) {
|
||||||
return node.getViewRoots().size();
|
return node.getViewRoots().size();
|
||||||
@@ -110,6 +167,11 @@ public class ApplicationDescriptor extends NodeDescriptor<ApplicationWrapper> {
|
|||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object getAXChildAt(ApplicationWrapper node, int index) {
|
||||||
|
return node.getViewRoots().get(index);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Named<SonarObject>> getData(ApplicationWrapper node) {
|
public List<Named<SonarObject>> getData(ApplicationWrapper node) {
|
||||||
return Collections.EMPTY_LIST;
|
return Collections.EMPTY_LIST;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import android.os.Build;
|
|||||||
import android.support.v4.view.MarginLayoutParamsCompat;
|
import android.support.v4.view.MarginLayoutParamsCompat;
|
||||||
import android.support.v4.view.ViewCompat;
|
import android.support.v4.view.ViewCompat;
|
||||||
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
|
||||||
|
import android.util.Log;
|
||||||
import android.util.SparseArray;
|
import android.util.SparseArray;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
@@ -85,14 +86,19 @@ public class ViewDescriptor extends NodeDescriptor<View> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getAXName(View node) {
|
public String getAXName(View node) throws Exception {
|
||||||
AccessibilityNodeInfoCompat nodeInfo = ViewAccessibilityHelper.createNodeInfoFromView(node);
|
AccessibilityNodeInfoCompat nodeInfo = ViewAccessibilityHelper.createNodeInfoFromView(node);
|
||||||
if (nodeInfo == null) {
|
if (nodeInfo != null) {
|
||||||
return "NULL NODEINFO";
|
|
||||||
}
|
CharSequence name = nodeInfo.getClassName();
|
||||||
String name = nodeInfo.getClassName().toString();
|
|
||||||
nodeInfo.recycle();
|
nodeInfo.recycle();
|
||||||
return name;
|
|
||||||
|
if (name != null) {
|
||||||
|
return name.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "NULL NODEINFO OR CLASSNAME";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -418,7 +424,7 @@ public class ViewDescriptor extends NodeDescriptor<View> {
|
|||||||
node.setSelected(value.asBoolean());
|
node.setSelected(value.asBoolean());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
invalidate(node);
|
invalidateAX(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ public class ViewGroupDescriptor extends NodeDescriptor<ViewGroup> {
|
|||||||
if (connected()) {
|
if (connected()) {
|
||||||
if (key.set(node)) {
|
if (key.set(node)) {
|
||||||
invalidate(node);
|
invalidate(node);
|
||||||
|
invalidateAX(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hasAttachedToWindow =
|
final boolean hasAttachedToWindow =
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ public class LithoViewDescriptor extends NodeDescriptor<LithoView> {
|
|||||||
@Override
|
@Override
|
||||||
public void onDirtyMount(LithoView view) {
|
public void onDirtyMount(LithoView view) {
|
||||||
invalidate(view);
|
invalidate(view);
|
||||||
|
invalidateAX(view);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ type GetNodesResult = {|
|
|||||||
type GetNodesOptions = {|
|
type GetNodesOptions = {|
|
||||||
force: boolean,
|
force: boolean,
|
||||||
ax: boolean,
|
ax: boolean,
|
||||||
|
forFocusEvent?: boolean,
|
||||||
|};
|
|};
|
||||||
|
|
||||||
type SearchResultTree = {|
|
type SearchResultTree = {|
|
||||||
@@ -436,22 +437,22 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.client.subscribe('axFocusEvent', (focusEvent: AXFocusEventResult) => {
|
this.client.subscribe('axFocusEvent', ({isFocus}: AXFocusEventResult) => {
|
||||||
// if focusing, need to update all elements in the tree because
|
// if focusing, need to update all elements in the tree because
|
||||||
// we don't know which one now has focus
|
// we don't know which one now has focus
|
||||||
const keys = focusEvent.isFocus ? Object.keys(this.state.AXelements) : [];
|
const keys = isFocus ? Object.keys(this.state.AXelements) : [];
|
||||||
|
|
||||||
// if unfocusing and currently focused element exists, update only the
|
// if unfocusing and currently focused element exists, update only the
|
||||||
// focused element (and only if it is loaded in tree)
|
// focused element (and only if it is/was loaded in tree)
|
||||||
if (
|
if (
|
||||||
!focusEvent.isFocus &&
|
!isFocus &&
|
||||||
this.state.AXfocused &&
|
this.state.AXfocused &&
|
||||||
this.state.AXelements[this.state.AXfocused]
|
this.state.AXelements[this.state.AXfocused]
|
||||||
) {
|
) {
|
||||||
keys.push(this.state.AXfocused);
|
keys.push(this.state.AXfocused);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.getNodes(keys, {force: true, ax: true}).then(
|
this.getNodes(keys, {force: true, ax: true, forFocusEvent: true}).then(
|
||||||
(elements: Array<Element>) => {
|
(elements: Array<Element>) => {
|
||||||
this.dispatchAction({
|
this.dispatchAction({
|
||||||
elements,
|
elements,
|
||||||
@@ -461,6 +462,17 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.client.subscribe(
|
||||||
|
'invalidateAX',
|
||||||
|
({nodes}: {nodes: Array<{id: ElementID}>}) => {
|
||||||
|
this.invalidate(nodes.map(node => node.id), true).then(
|
||||||
|
(elements: Array<Element>) => {
|
||||||
|
this.dispatchAction({elements, type: 'UpdateAXElements'});
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
@@ -477,14 +489,9 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
this.client.subscribe(
|
this.client.subscribe(
|
||||||
'invalidate',
|
'invalidate',
|
||||||
({nodes}: {nodes: Array<{id: ElementID}>}) => {
|
({nodes}: {nodes: Array<{id: ElementID}>}) => {
|
||||||
this.invalidate(nodes.map(node => node.id)).then(
|
this.invalidate(nodes.map(node => node.id), false).then(
|
||||||
(elements: Array<Element>) => {
|
(elements: Array<Element>) => {
|
||||||
if (this.state.inAXMode) {
|
|
||||||
// to be removed once trees are separate - will have own invalidate
|
|
||||||
this.dispatchAction({elements, type: 'UpdateAXElements'});
|
|
||||||
} else {
|
|
||||||
this.dispatchAction({elements, type: 'UpdateElements'});
|
this.dispatchAction({elements, type: 'UpdateElements'});
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -514,12 +521,11 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invalidate(ids: Array<ElementID>): Promise<Array<Element>> {
|
invalidate(ids: Array<ElementID>, ax: boolean): Promise<Array<Element>> {
|
||||||
if (ids.length === 0) {
|
if (ids.length === 0) {
|
||||||
return Promise.resolve([]);
|
return Promise.resolve([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const ax = this.state.inAXMode;
|
|
||||||
return this.getNodes(ids, {force: true, ax}).then(
|
return this.getNodes(ids, {force: true, ax}).then(
|
||||||
(elements: Array<Element>) => {
|
(elements: Array<Element>) => {
|
||||||
const children = elements
|
const children = elements
|
||||||
@@ -532,9 +538,11 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
.map(element => element.children)
|
.map(element => element.children)
|
||||||
.reduce((acc, val) => acc.concat(val), []);
|
.reduce((acc, val) => acc.concat(val), []);
|
||||||
|
|
||||||
return Promise.all([elements, this.invalidate(children)]).then(arr => {
|
return Promise.all([elements, this.invalidate(children, ax)]).then(
|
||||||
|
arr => {
|
||||||
return arr.reduce((acc, val) => acc.concat(val), []);
|
return arr.reduce((acc, val) => acc.concat(val), []);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -570,7 +578,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
ids: Array<ElementID> = [],
|
ids: Array<ElementID> = [],
|
||||||
options: GetNodesOptions,
|
options: GetNodesOptions,
|
||||||
): Promise<Array<Element>> {
|
): Promise<Array<Element>> {
|
||||||
const {force, ax} = options;
|
const {force, ax, forFocusEvent} = options;
|
||||||
if (!force) {
|
if (!force) {
|
||||||
ids = ids.filter(id => {
|
ids = ids.filter(id => {
|
||||||
return (
|
return (
|
||||||
@@ -582,7 +590,10 @@ export default class Layout extends SonarPlugin<InspectorState> {
|
|||||||
if (ids.length > 0) {
|
if (ids.length > 0) {
|
||||||
performance.mark('LayoutInspectorGetNodes');
|
performance.mark('LayoutInspectorGetNodes');
|
||||||
return this.client
|
return this.client
|
||||||
.call(ax ? 'getAXNodes' : 'getNodes', {ids})
|
.call(ax ? 'getAXNodes' : 'getNodes', {
|
||||||
|
ids,
|
||||||
|
forFocusEvent,
|
||||||
|
})
|
||||||
.then(({elements}: GetNodesResult) => {
|
.then(({elements}: GetNodesResult) => {
|
||||||
this.props.logger.trackTimeSince('LayoutInspectorGetNodes');
|
this.props.logger.trackTimeSince('LayoutInspectorGetNodes');
|
||||||
return Promise.resolve(elements);
|
return Promise.resolve(elements);
|
||||||
|
|||||||
Reference in New Issue
Block a user