Live update sidebar with click and focus accessibility events

Summary: Lets AX inspector live update the sidebar when a view is clicked (state may change) or accessibility focus changes (previously only updated the sidebar live if it became the focused element).

Differential Revision: D9489376

fbshipit-source-id: 8959f722370ce1d3a622b24c7b049b03f0d662e6
This commit is contained in:
Sara Valderrama
2018-08-24 09:41:35 -07:00
committed by Facebook Github Bot
parent 61258d4b64
commit 364883f661
3 changed files with 56 additions and 32 deletions

View File

@@ -221,7 +221,8 @@ public class InspectorSonarPlugin implements SonarPlugin {
final SonarArray.Builder result = new SonarArray.Builder();
// getNodes called to refresh accessibility focus
final boolean forFocusEvent = params.getBoolean("forFocusEvent");
final boolean forAccessibilityEvent = params.getBoolean("forAccessibilityEvent");
final String selected = params.getString("selected");
for (int i = 0, count = ids.length(); i < count; i++) {
final String id = ids.getString(i);
@@ -231,7 +232,7 @@ public class InspectorSonarPlugin implements SonarPlugin {
if (node == null) {
// some nodes may be null since we are searching through all current and previous known nodes
if (forFocusEvent) {
if (forAccessibilityEvent) {
continue;
}
@@ -243,11 +244,11 @@ public class InspectorSonarPlugin implements SonarPlugin {
return;
} else {
// only need to get the focused node in this case
if (forFocusEvent) {
if (node.getObject("extraInfo").getBoolean("focused")) {
// always add currently selected node for live updates to the sidebar
// also add focused node for updates
if (forAccessibilityEvent) {
if (id.equals(selected) || node.getObject("extraInfo").getBoolean("focused")) {
result.put(node);
break;
}
// normal getNodes call, put any nodes in result

View File

@@ -101,6 +101,12 @@ public class ApplicationDescriptor extends NodeDescriptor<ApplicationWrapper> {
new SonarObject.Builder()
.put("isFocus", false)
.build());
} else if (eventType == AccessibilityEvent.TYPE_VIEW_CLICKED) {
mConnection.send("axFocusEvent",
new SonarObject.Builder()
.put("isFocus", false)
.put("isClick", true)
.build());
}
}

View File

@@ -76,6 +76,7 @@ type UpdateAXElementsArgs = {|
type AXFocusEventResult = {|
isFocus: boolean,
isClick?: boolean,
|};
type SetRootArgs = {|
@@ -89,7 +90,7 @@ type GetNodesResult = {|
type GetNodesOptions = {|
force: boolean,
ax: boolean,
forFocusEvent?: boolean,
forAccessibilityEvent?: boolean,
|};
type TrackArgs = {|
@@ -519,36 +520,51 @@ export default class Layout extends SonarPlugin<InspectorState> {
});
});
this.client.subscribe('axFocusEvent', ({isFocus}: AXFocusEventResult) => {
this.props.logger.track('usage', 'accessibility:focusEvent', {
isFocus,
inAXMode: this.state.inAXMode,
});
this.client.subscribe(
'axFocusEvent',
({isFocus, isClick}: AXFocusEventResult) => {
this.props.logger.track('usage', 'accessibility:focusEvent', {
isFocus,
isClick,
inAXMode: this.state.inAXMode,
});
// if focusing, need to update all elements in the tree because
// we don't know which one now has focus
const keys = isFocus ? Object.keys(this.state.AXelements) : [];
// if focusing, need to update all elements in the tree because
// we don't know which one now has focus
const keys = isFocus ? Object.keys(this.state.AXelements) : [];
// if unfocusing and currently focused element exists, update only the
// focused element (and only if it is/was loaded in tree)
if (
!isFocus &&
this.state.AXfocused &&
this.state.AXelements[this.state.AXfocused]
) {
keys.push(this.state.AXfocused);
}
// if unfocusing, update only the focused and selected elements and
// only if they have been loaded into tree
if (!isFocus) {
if (
this.state.AXfocused &&
this.state.AXelements[this.state.AXfocused]
) {
keys.push(this.state.AXfocused);
}
this.getNodes(keys, {force: true, ax: true, forFocusEvent: true}).then(
(elements: Array<Element>) => {
// also update current selected element live, so data shown is not invalid
if (
this.state.AXselected &&
this.state.AXelements[this.state.AXselected]
) {
keys.push(this.state.AXselected);
}
}
this.getNodes(keys, {
force: true,
ax: true,
forAccessibilityEvent: true,
}).then((elements: Array<Element>) => {
this.dispatchAction({
elements,
forFocusEvent: true,
forFocusEvent: !isClick,
type: 'UpdateAXElements',
});
},
);
});
});
},
);
this.client.subscribe(
'invalidateAX',
@@ -668,7 +684,7 @@ export default class Layout extends SonarPlugin<InspectorState> {
ids: Array<ElementID> = [],
options: GetNodesOptions,
): Promise<Array<Element>> {
const {force, ax, forFocusEvent} = options;
const {force, ax, forAccessibilityEvent} = options;
if (!force) {
const elems = ax ? this.state.AXelements : this.state.elements;
// always force undefined elements and elements that need to be expanded
@@ -692,7 +708,8 @@ export default class Layout extends SonarPlugin<InspectorState> {
return this.client
.call(ax ? 'getAXNodes' : 'getNodes', {
ids,
forFocusEvent,
forAccessibilityEvent,
selected: this.state.AXselected,
})
.then(({elements}: GetNodesResult) => {
this.props.logger.trackTimeSince(mark, eventName);