Remove accessibility panel from Layout Inspector in non-accessibility mode
Summary: Removes the Accessibility panel from the layout inspector since all of these properties are shown (and logged) in the Accessibility Inspector along with other properties that may be useful. This will make it easier to track accessibility use and also will help more people discover the accessibility feature when they need it. Reviewed By: blavalla Differential Revision: D9523532 fbshipit-source-id: f6d3a745980ec631ec8bf2e59017382f4c2edd5a
This commit is contained in:
committed by
Facebook Github Bot
parent
a75b3f22ea
commit
7bd264bd10
@@ -196,8 +196,7 @@ public class ViewDescriptor extends NodeDescriptor<View> {
|
||||
}
|
||||
|
||||
return Arrays.asList(
|
||||
new Named<>("View", viewProps.build()),
|
||||
new Named<>("Accessibility", getAccessibilityData(node)));
|
||||
new Named<>("View", viewProps.build()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -205,36 +204,13 @@ public class ViewDescriptor extends NodeDescriptor<View> {
|
||||
return Arrays.asList(
|
||||
new Named<>(axNodeInfoPropsTitle, AccessibilityUtil.getAccessibilityNodeInfoData(node)),
|
||||
new Named<>(axTalkbackPropsTitle, AccessibilityUtil.getTalkbackData(node)),
|
||||
new Named<>(axViewPropsTitle, AccessibilityUtil.getViewAXData(node)));
|
||||
}
|
||||
|
||||
private static SonarObject getAccessibilityData(View view) {
|
||||
final SonarObject.Builder accessibilityProps = new SonarObject.Builder();
|
||||
|
||||
// This needs to be an empty string to be mutable. See t20470623.
|
||||
CharSequence contentDescription =
|
||||
view.getContentDescription() != null ? view.getContentDescription() : "";
|
||||
accessibilityProps.put("content-description", InspectorValue.mutable(contentDescription));
|
||||
accessibilityProps.put("focusable", InspectorValue.mutable(view.isFocusable()));
|
||||
accessibilityProps.put("node-info", AccessibilityUtil.getAccessibilityNodeInfoProperties(view));
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
accessibilityProps.put(
|
||||
"important-for-accessibility",
|
||||
AccessibilityUtil.sImportantForAccessibilityMapping.get(
|
||||
view.getImportantForAccessibility()));
|
||||
}
|
||||
|
||||
AccessibilityUtil.addTalkbackProperties(accessibilityProps, view);
|
||||
|
||||
return accessibilityProps.build();
|
||||
new Named<>(axViewPropsTitle, AccessibilityUtil.getViewData(node)));
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
|
||||
@Override
|
||||
public void setValue(View node, String[] path, SonarDynamic value) {
|
||||
if (path[0].equals("Accessibility")
|
||||
|| path[0].equals(axViewPropsTitle)
|
||||
if (path[0].equals(axViewPropsTitle)
|
||||
|| path[0].equals(axNodeInfoPropsTitle)
|
||||
|| path[0].equals(axTalkbackPropsTitle)) {
|
||||
setAccessibilityValue(node, path, value);
|
||||
|
||||
@@ -510,75 +510,6 @@ public final class AccessibilityUtil {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SonarObject} of useful properties of AccessibilityNodeInfo, to be shown in the
|
||||
* Sonar Layout Inspector. All properties are immutable since they are all derived from various
|
||||
* {@link View} properties.
|
||||
*
|
||||
* @param view The {@link View} to derive the AccessibilityNodeInfo properties from.
|
||||
* @return {@link SonarObject} containing the properties.
|
||||
*/
|
||||
@Nullable
|
||||
public static SonarObject getAccessibilityNodeInfoProperties(View view) {
|
||||
final AccessibilityNodeInfoCompat nodeInfo =
|
||||
ViewAccessibilityHelper.createNodeInfoFromView(view);
|
||||
if (nodeInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final SonarObject.Builder nodeInfoProps = new SonarObject.Builder();
|
||||
final Rect bounds = new Rect();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
final SonarArray.Builder actionsArrayBuilder = new SonarArray.Builder();
|
||||
for (AccessibilityNodeInfoCompat.AccessibilityActionCompat action :
|
||||
nodeInfo.getActionList()) {
|
||||
final String actionLabel = (String) action.getLabel();
|
||||
if (actionLabel != null) {
|
||||
actionsArrayBuilder.put(actionLabel);
|
||||
} else {
|
||||
actionsArrayBuilder.put(
|
||||
AccessibilityUtil.sAccessibilityActionMapping.get(action.getId(), false));
|
||||
}
|
||||
}
|
||||
nodeInfoProps.put("actions", actionsArrayBuilder.build());
|
||||
}
|
||||
|
||||
nodeInfoProps
|
||||
.put("clickable", nodeInfo.isClickable())
|
||||
.put("content-description", nodeInfo.getContentDescription())
|
||||
.put("text", nodeInfo.getText())
|
||||
.put("accessibility-focused", nodeInfo.isAccessibilityFocused())
|
||||
.put("long-clickable", nodeInfo.isLongClickable())
|
||||
.put("focusable", nodeInfo.isFocusable());
|
||||
|
||||
nodeInfo.getBoundsInParent(bounds);
|
||||
nodeInfoProps.put(
|
||||
"parent-bounds",
|
||||
new SonarObject.Builder()
|
||||
.put("width", bounds.width())
|
||||
.put("height", bounds.height())
|
||||
.put("top", bounds.top)
|
||||
.put("left", bounds.left)
|
||||
.put("bottom", bounds.bottom)
|
||||
.put("right", bounds.right));
|
||||
|
||||
nodeInfo.getBoundsInScreen(bounds);
|
||||
nodeInfoProps.put(
|
||||
"screen-bounds",
|
||||
new SonarObject.Builder()
|
||||
.put("width", bounds.width())
|
||||
.put("height", bounds.height())
|
||||
.put("top", bounds.top)
|
||||
.put("left", bounds.left)
|
||||
.put("bottom", bounds.bottom)
|
||||
.put("right", bounds.right));
|
||||
|
||||
nodeInfo.recycle();
|
||||
|
||||
return nodeInfoProps.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link SonarObject} of useful properties of AccessibilityNodeInfo, to be shown in the
|
||||
* Sonar Layout Inspector accessibility extension. All properties are immutable since they are all derived from
|
||||
@@ -697,7 +628,7 @@ public final class AccessibilityUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static SonarObject getViewAXData(View view) {
|
||||
public static SonarObject getViewData(View view) {
|
||||
final SonarObject.Builder props = new SonarObject.Builder();
|
||||
|
||||
// This needs to be an empty string to be mutable. See t20470623.
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
package com.facebook.sonar.plugins.litho;
|
||||
|
||||
import static com.facebook.litho.annotations.ImportantForAccessibility.IMPORTANT_FOR_ACCESSIBILITY_NO;
|
||||
import static com.facebook.litho.annotations.ImportantForAccessibility.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
|
||||
import static com.facebook.sonar.plugins.inspector.InspectorValue.Type.Color;
|
||||
import static com.facebook.sonar.plugins.inspector.InspectorValue.Type.Enum;
|
||||
import static com.facebook.sonar.plugins.inspector.InspectorValue.Type.Number;
|
||||
@@ -30,8 +28,6 @@ import com.facebook.sonar.plugins.inspector.Named;
|
||||
import com.facebook.sonar.plugins.inspector.NodeDescriptor;
|
||||
import com.facebook.sonar.plugins.inspector.Touch;
|
||||
import com.facebook.sonar.plugins.inspector.descriptors.ObjectDescriptor;
|
||||
import com.facebook.sonar.plugins.inspector.descriptors.utils.AccessibilityRoleUtil;
|
||||
import com.facebook.sonar.plugins.inspector.descriptors.utils.AccessibilityUtil;
|
||||
import com.facebook.yoga.YogaAlign;
|
||||
import com.facebook.yoga.YogaDirection;
|
||||
import com.facebook.yoga.YogaEdge;
|
||||
@@ -49,9 +45,6 @@ import javax.annotation.Nullable;
|
||||
|
||||
public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
|
||||
private static final String axViewPropsTitle = "DebugLayoutNode";
|
||||
private static final String axNodeInfoPropsTitle = "NodeInfo & TalkBack";
|
||||
|
||||
private Map<String, List<Pair<String[], SonarDynamic>>> mOverrides = new HashMap<>();
|
||||
private DebugComponent.Overrider mOverrider =
|
||||
new DebugComponent.Overrider() {
|
||||
@@ -100,10 +93,6 @@ public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
override.second);
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
} else if (override.first[0].equals("Accessibility")
|
||||
|| override.first[0].equals(axViewPropsTitle)
|
||||
|| override.first[0].equals(axNodeInfoPropsTitle)) {
|
||||
applyAccessibilityOverride(node, override.first[1], override.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -175,98 +164,9 @@ public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
data.add(new Named<>("State", stateData));
|
||||
}
|
||||
|
||||
final SonarObject accessibilityData = getAccessibilityData(node);
|
||||
if (accessibilityData != null) {
|
||||
data.add(new Named<>("Accessibility", accessibilityData));
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Named<SonarObject>> getAXData(DebugComponent node) throws Exception {
|
||||
NodeDescriptor componentDescriptor = descriptorForClass(node.getComponent().getClass());
|
||||
if (componentDescriptor.getClass() != ObjectDescriptor.class) {
|
||||
return componentDescriptor.getAXData(node.getComponent());
|
||||
}
|
||||
final List<Named<SonarObject>> sections = new ArrayList<>();
|
||||
|
||||
final SonarObject derivedData = getDerivedAXData(node);
|
||||
if (derivedData != null) {
|
||||
sections.add(new Named<>(axNodeInfoPropsTitle, derivedData));
|
||||
}
|
||||
|
||||
final SonarObject viewData = getViewAXData(node);
|
||||
if (viewData != null) {
|
||||
sections.add(new Named<>(axViewPropsTitle, viewData));
|
||||
}
|
||||
|
||||
return sections;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SonarObject getViewAXData(DebugComponent node) {
|
||||
final DebugLayoutNode layout = node.getLayoutNode();
|
||||
if (layout == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final SonarObject.Builder props = new SonarObject.Builder();
|
||||
|
||||
// This needs to be an empty string to be mutable. See t20470623.
|
||||
final CharSequence contentDescription =
|
||||
layout.getContentDescription() != null ? layout.getContentDescription() : "";
|
||||
props.put("content-description", InspectorValue.mutable(contentDescription));
|
||||
props.put("focusable", InspectorValue.mutable(layout.getFocusable()));
|
||||
props.put(
|
||||
"important-for-accessibility",
|
||||
AccessibilityUtil.sImportantForAccessibilityMapping.get(
|
||||
layout.getImportantForAccessibility()));
|
||||
|
||||
return props.build();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SonarObject getDerivedAXData(DebugComponent node) {
|
||||
final DebugLayoutNode layout = node.getLayoutNode();
|
||||
if (layout == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final View hostView = node.getComponentHost();
|
||||
final SonarObject.Builder props = new SonarObject.Builder();
|
||||
|
||||
// No host view exists, so this component is inherently not accessible. Add the reason why this
|
||||
// is the case and then return.
|
||||
if (hostView == node.getLithoView() || hostView == null) {
|
||||
final int importantForAccessibility = layout.getImportantForAccessibility();
|
||||
final boolean isAccessibilityEnabled =
|
||||
AccessibilityUtil.isAccessibilityEnabled(node.getContext());
|
||||
String ignoredReason;
|
||||
|
||||
if (!isAccessibilityEnabled) {
|
||||
ignoredReason = "No accessibility service is running.";
|
||||
} else if (importantForAccessibility == IMPORTANT_FOR_ACCESSIBILITY_NO) {
|
||||
ignoredReason = "Component has importantForAccessibility set to NO.";
|
||||
} else if (importantForAccessibility == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
|
||||
ignoredReason = "Component has importantForAccessibility set to NO_HIDE_DESCENDANTS.";
|
||||
} else {
|
||||
ignoredReason = "Component does not have content, or accessibility handlers.";
|
||||
}
|
||||
|
||||
props.put("talkback-ignored", true);
|
||||
props.put("talkback-ignored-reasons", ignoredReason);
|
||||
|
||||
return props.build();
|
||||
}
|
||||
|
||||
// host view exists so add node info and TalkBack properties
|
||||
props.put("node-info", AccessibilityUtil.getAccessibilityNodeInfoData(hostView));
|
||||
AccessibilityUtil.addTalkbackProperties(props, hostView);
|
||||
|
||||
return props.build();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SonarObject getLayoutData(DebugComponent node) {
|
||||
final DebugLayoutNode layout = node.getLayoutNode();
|
||||
@@ -466,57 +366,6 @@ public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SonarObject getAccessibilityData(DebugComponent node) {
|
||||
final DebugLayoutNode layout = node.getLayoutNode();
|
||||
if (layout == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final View hostView = node.getComponentHost();
|
||||
final SonarObject.Builder accessibilityProps = new SonarObject.Builder();
|
||||
|
||||
// This needs to be an empty string to be mutable. See t20470623.
|
||||
final CharSequence contentDescription =
|
||||
layout.getContentDescription() != null ? layout.getContentDescription() : "";
|
||||
accessibilityProps.put("content-description", InspectorValue.mutable(contentDescription));
|
||||
accessibilityProps.put("focusable", InspectorValue.mutable(layout.getFocusable()));
|
||||
accessibilityProps.put(
|
||||
"important-for-accessibility",
|
||||
AccessibilityUtil.sImportantForAccessibilityMapping.get(
|
||||
layout.getImportantForAccessibility()));
|
||||
|
||||
// No host view exists, so this component is inherently not accessible. Add the reason why this
|
||||
// is the case and then return.
|
||||
if (hostView == node.getLithoView() || hostView == null) {
|
||||
final int importantForAccessibility = layout.getImportantForAccessibility();
|
||||
final boolean isAccessibilityEnabled =
|
||||
AccessibilityUtil.isAccessibilityEnabled(node.getContext());
|
||||
String ignoredReason;
|
||||
|
||||
if (!isAccessibilityEnabled) {
|
||||
ignoredReason = "No accessibility service is running.";
|
||||
} else if (importantForAccessibility == IMPORTANT_FOR_ACCESSIBILITY_NO) {
|
||||
ignoredReason = "Component has importantForAccessibility set to NO.";
|
||||
} else if (importantForAccessibility == IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
|
||||
ignoredReason = "Component has importantForAccessibility set to NO_HIDE_DESCENDANTS.";
|
||||
} else {
|
||||
ignoredReason = "Component does not have content, or accessibility handlers.";
|
||||
}
|
||||
|
||||
accessibilityProps.put("talkback-ignored", true);
|
||||
accessibilityProps.put("talkback-ignored-reasons", ignoredReason);
|
||||
|
||||
return accessibilityProps.build();
|
||||
}
|
||||
|
||||
accessibilityProps.put(
|
||||
"node-info", AccessibilityUtil.getAccessibilityNodeInfoProperties(hostView));
|
||||
AccessibilityUtil.addTalkbackProperties(accessibilityProps, hostView);
|
||||
|
||||
return accessibilityProps.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setValue(DebugComponent node, String[] path, SonarDynamic value) {
|
||||
List<Pair<String[], SonarDynamic>> overrides = mOverrides.get(node.getGlobalKey());
|
||||
@@ -547,17 +396,6 @@ public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Named<String>> getAXAttributes(DebugComponent node) {
|
||||
final View hostView = node.getComponentHost();
|
||||
List<Named<String>> attributes = new ArrayList<>();
|
||||
String role = AccessibilityRoleUtil.getRole(hostView).toString();
|
||||
if (!role.equals("NONE")) {
|
||||
attributes.add(new Named<>("role", role));
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SonarObject getExtraInfo(DebugComponent node) {
|
||||
SonarObject.Builder extraInfo = new SonarObject.Builder();
|
||||
@@ -659,22 +497,6 @@ public class DebugComponentDescriptor extends NodeDescriptor<DebugComponent> {
|
||||
return descriptor.matches(query, node);
|
||||
}
|
||||
|
||||
private static void applyAccessibilityOverride(
|
||||
DebugLayoutNode node, String key, SonarDynamic value) {
|
||||
switch (key) {
|
||||
case "focusable":
|
||||
node.setFocusable(value.asBoolean());
|
||||
break;
|
||||
case "important-for-accessibility":
|
||||
node.setImportantForAccessibility(
|
||||
AccessibilityUtil.sImportantForAccessibilityMapping.get(value.asString()));
|
||||
break;
|
||||
case "content-description":
|
||||
node.setContentDescription(value.asString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void applyLayoutOverride(DebugLayoutNode node, String[] path, SonarDynamic value) {
|
||||
switch (path[0]) {
|
||||
case "background":
|
||||
|
||||
Reference in New Issue
Block a user