Add theme information for Application, Activity and View descriptors
Summary: This will query for and display all of the associated theme information for each of the descriptors. Reviewed By: passy Differential Revision: D19987003 fbshipit-source-id: c9b51311d28712a1af76c45a434bfb25d28d5c54
This commit is contained in:
committed by
Facebook Github Bot
parent
97f9b2494d
commit
6f4de969fb
@@ -14,6 +14,7 @@ import com.facebook.flipper.core.FlipperObject;
|
|||||||
import com.facebook.flipper.plugins.inspector.Named;
|
import com.facebook.flipper.plugins.inspector.Named;
|
||||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||||
import com.facebook.flipper.plugins.inspector.Touch;
|
import com.facebook.flipper.plugins.inspector.Touch;
|
||||||
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.ContextDescriptorUtils;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentActivityAccessor;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentActivityAccessor;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentCompat;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentCompat;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentManagerAccessor;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.FragmentManagerAccessor;
|
||||||
@@ -65,7 +66,7 @@ public class ActivityDescriptor extends NodeDescriptor<Activity> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Named<FlipperObject>> getData(Activity node) {
|
public List<Named<FlipperObject>> getData(Activity node) {
|
||||||
return Collections.EMPTY_LIST;
|
return Collections.singletonList(new Named<>("Theme", ContextDescriptorUtils.themeData(node)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import com.facebook.flipper.plugins.inspector.ApplicationWrapper;
|
|||||||
import com.facebook.flipper.plugins.inspector.Named;
|
import com.facebook.flipper.plugins.inspector.Named;
|
||||||
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
import com.facebook.flipper.plugins.inspector.NodeDescriptor;
|
||||||
import com.facebook.flipper.plugins.inspector.Touch;
|
import com.facebook.flipper.plugins.inspector.Touch;
|
||||||
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.ContextDescriptorUtils;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -204,7 +205,8 @@ public class ApplicationDescriptor extends NodeDescriptor<ApplicationWrapper> {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Named<FlipperObject>> getData(ApplicationWrapper node) {
|
public List<Named<FlipperObject>> getData(ApplicationWrapper node) {
|
||||||
return Collections.EMPTY_LIST;
|
return Collections.singletonList(
|
||||||
|
new Named<>("Theme", ContextDescriptorUtils.themeData(node.getApplication())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ import com.facebook.flipper.plugins.inspector.Touch;
|
|||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityEvaluationUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityEvaluationUtil;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityRoleUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityRoleUtil;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.AccessibilityUtil;
|
||||||
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.ContextDescriptorUtils;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.EnumMapping;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.EnumMapping;
|
||||||
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.ResourcesUtil;
|
import com.facebook.flipper.plugins.inspector.descriptors.utils.stethocopies.ResourcesUtil;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
@@ -190,7 +191,9 @@ public class ViewDescriptor extends NodeDescriptor<View> {
|
|||||||
viewProps.put("foreground", fromDrawable(node.getForeground()));
|
viewProps.put("foreground", fromDrawable(node.getForeground()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Arrays.asList(new Named<>("View", viewProps.build()));
|
return Arrays.asList(
|
||||||
|
new Named<>("View", viewProps.build()),
|
||||||
|
new Named<>("Theme", ContextDescriptorUtils.themeData(node.getContext())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the MIT license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.facebook.flipper.plugins.inspector.descriptors.utils;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.AssetManager;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import com.facebook.flipper.core.FlipperObject;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public final class ContextDescriptorUtils {
|
||||||
|
private static String TAG = "ContextDescriptor";
|
||||||
|
|
||||||
|
private static Field sThemeImplField;
|
||||||
|
private static Field sThemeImplThemeKeyField;
|
||||||
|
private static Field sThemeImplAssetManagerField;
|
||||||
|
private static Field sThemeKeyResIdField;
|
||||||
|
private static Method sAssetManagerGetStyleAttributesMethod;
|
||||||
|
|
||||||
|
private ContextDescriptorUtils() {}
|
||||||
|
|
||||||
|
public static FlipperObject themeData(Context context) {
|
||||||
|
FlipperObject.Builder themeData = new FlipperObject.Builder();
|
||||||
|
Map<String, FlipperObject.Builder> builders = collectThemeValues(context);
|
||||||
|
for (Map.Entry<String, FlipperObject.Builder> entry : builders.entrySet()) {
|
||||||
|
themeData.put(entry.getKey(), entry.getValue().build());
|
||||||
|
}
|
||||||
|
return themeData.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Map<String, FlipperObject.Builder> collectThemeValues(Context context) {
|
||||||
|
Map<String, FlipperObject.Builder> builderMap = new HashMap<>(3);
|
||||||
|
try {
|
||||||
|
Resources.Theme theme = context.getTheme();
|
||||||
|
AssetManager assetManager = context.getAssets();
|
||||||
|
final Object themeImpl;
|
||||||
|
final Object themeKey;
|
||||||
|
|
||||||
|
// Nasty reflection to get a list of theme attributes that apply to this context.
|
||||||
|
if (sThemeImplField == null
|
||||||
|
|| sThemeImplThemeKeyField == null
|
||||||
|
|| sThemeKeyResIdField == null
|
||||||
|
|| sThemeImplAssetManagerField == null) {
|
||||||
|
sThemeImplField = theme.getClass().getDeclaredField("mThemeImpl");
|
||||||
|
sThemeImplField.setAccessible(true);
|
||||||
|
|
||||||
|
themeImpl = sThemeImplField.get(theme);
|
||||||
|
sThemeImplThemeKeyField = themeImpl.getClass().getDeclaredField("mKey");
|
||||||
|
sThemeImplThemeKeyField.setAccessible(true);
|
||||||
|
|
||||||
|
sThemeImplAssetManagerField = themeImpl.getClass().getDeclaredField("mAssets");
|
||||||
|
sThemeImplAssetManagerField.setAccessible(true);
|
||||||
|
|
||||||
|
sAssetManagerGetStyleAttributesMethod =
|
||||||
|
assetManager.getClass().getDeclaredMethod("getStyleAttributes", int.class);
|
||||||
|
sAssetManagerGetStyleAttributesMethod.setAccessible(true);
|
||||||
|
|
||||||
|
themeKey = sThemeImplThemeKeyField.get(themeImpl);
|
||||||
|
sThemeKeyResIdField = themeKey.getClass().getDeclaredField("mResId");
|
||||||
|
sThemeKeyResIdField.setAccessible(true);
|
||||||
|
} else {
|
||||||
|
themeImpl = sThemeImplField.get(theme);
|
||||||
|
themeKey = sThemeImplThemeKeyField.get(themeImpl);
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] appliedThemeResIds = (int[]) sThemeKeyResIdField.get(themeKey);
|
||||||
|
TypedValue typedValue = new TypedValue();
|
||||||
|
Resources resources = context.getResources();
|
||||||
|
for (int themeId : appliedThemeResIds) {
|
||||||
|
String name = resources.getResourceName(themeId);
|
||||||
|
// The res id array can have duplicates
|
||||||
|
if (builderMap.containsKey(name)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
FlipperObject.Builder builder = new FlipperObject.Builder();
|
||||||
|
builderMap.put(name, builder);
|
||||||
|
|
||||||
|
int[] attributes =
|
||||||
|
(int[]) sAssetManagerGetStyleAttributesMethod.invoke(assetManager, themeId);
|
||||||
|
for (int attribute : attributes) {
|
||||||
|
if (!theme.resolveAttribute(attribute, typedValue, true)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String attributeName = context.getResources().getResourceName(attribute);
|
||||||
|
String[] nameParts = attributeName.split(":");
|
||||||
|
if (nameParts.length < 2) {
|
||||||
|
Log.d(TAG, "Unknown attribute name format " + attributeName);
|
||||||
|
} else {
|
||||||
|
attributeName = nameParts[1].split("/")[1];
|
||||||
|
}
|
||||||
|
String strValue = TypedValue.coerceToString(typedValue.type, typedValue.data);
|
||||||
|
if (strValue == null) {
|
||||||
|
strValue = "null";
|
||||||
|
} else if (strValue.startsWith("@")) {
|
||||||
|
int resId = Integer.parseInt(strValue.substring(1));
|
||||||
|
if (resId == 0) {
|
||||||
|
strValue = "null";
|
||||||
|
} else {
|
||||||
|
strValue = context.getResources().getResourceName(resId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.put(attributeName, strValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
Log.d(TAG, "Failed to generate theme attribute data!", ignored);
|
||||||
|
}
|
||||||
|
return builderMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user