Use context from view when resolving platform color if activity doesn't exist

Summary:
There are cases where the activity may not exist (such as for VRShell panel apps). In this case we will search for a view associated with a PropsAnimatedNode to get the context.

Changelog:
[Internal][Fixed] - Use context from view when resolving platform color if activity doesn't exist

Reviewed By: javache

Differential Revision: D34022882

fbshipit-source-id: c316935af1034ea770f3ef9334f77d6dc783fb27
This commit is contained in:
Genki Kondo
2022-02-08 11:41:17 -08:00
committed by Facebook GitHub Bot
parent cd79317672
commit 1a044123fc
2 changed files with 56 additions and 12 deletions
@@ -7,7 +7,9 @@
package com.facebook.react.animated;
import android.content.Context;
import android.graphics.Color;
import android.view.View;
import com.facebook.react.bridge.ColorPropConverter;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReadableMap;
@@ -22,7 +24,8 @@ import com.facebook.react.views.view.ColorUtil;
private final int mGNodeId;
private final int mBNodeId;
private final int mANodeId;
private int mColor;
private final ReadableMap mNativeColor;
private boolean mNativeColorApplied;
public ColorAnimatedNode(
ReadableMap config,
@@ -34,15 +37,13 @@ import com.facebook.react.views.view.ColorUtil;
mGNodeId = config.getInt("g");
mBNodeId = config.getInt("b");
mANodeId = config.getInt("a");
setNativeColor(config.getMap("nativeColor"));
mNativeColor = config.getMap("nativeColor");
tryApplyNativeColor();
}
public int getColor() {
return mColor;
}
tryApplyNativeColor();
@Override
public void update() {
ValueAnimatedNode rNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mRNodeId);
ValueAnimatedNode gNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mGNodeId);
ValueAnimatedNode bNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mBNodeId);
@@ -53,7 +54,7 @@ import com.facebook.react.views.view.ColorUtil;
double b = bNode.getValue();
double a = aNode.getValue();
mColor = ColorUtil.normalize(r, g, b, a);
return ColorUtil.normalize(r, g, b, a);
}
@Override
@@ -70,13 +71,17 @@ import com.facebook.react.views.view.ColorUtil;
+ mANodeId;
}
private void setNativeColor(ReadableMap nativeColor) {
if (nativeColor == null) {
private void tryApplyNativeColor() {
if (mNativeColor == null || mNativeColorApplied) {
return;
}
int color =
ColorPropConverter.getColor(nativeColor, mReactApplicationContext.getCurrentActivity());
Context context = getContext();
if (context == null) {
return;
}
int color = ColorPropConverter.getColor(mNativeColor, context);
ValueAnimatedNode rNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mRNodeId);
ValueAnimatedNode gNode = (ValueAnimatedNode) mNativeAnimatedNodesManager.getNodeById(mGNodeId);
@@ -88,6 +93,33 @@ import com.facebook.react.views.view.ColorUtil;
bNode.mValue = Color.blue(color);
aNode.mValue = Color.alpha(color) / 255.0;
update();
mNativeColorApplied = true;
}
private Context getContext() {
Context context = mReactApplicationContext.getCurrentActivity();
if (context != null) {
return context;
}
// There are cases where the activity may not exist (such as for VRShell panel apps). In this
// case we will search for a view associated with a PropsAnimatedNode to get the context.
return getContextHelper(this);
}
private static Context getContextHelper(AnimatedNode node) {
// Search children depth-first until we get to a PropsAnimatedNode, from which we can
// get the view and its context
if (node.mChildren != null) {
for (AnimatedNode child : node.mChildren) {
if (child instanceof PropsAnimatedNode) {
View view = ((PropsAnimatedNode) child).getConnectedView();
return view != null ? view.getContext() : null;
} else {
return getContextHelper(child);
}
}
}
return null;
}
}
@@ -7,12 +7,14 @@
package com.facebook.react.animated;
import android.view.View;
import androidx.annotation.Nullable;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.UIManager;
import com.facebook.react.uimanager.IllegalViewOperationException;
import com.facebook.react.uimanager.common.UIManagerType;
import com.facebook.react.uimanager.common.ViewUtil;
import java.util.HashMap;
@@ -116,6 +118,16 @@ import java.util.Map;
mUIManager.synchronouslyUpdateViewOnUIThread(mConnectedViewTag, mPropMap);
}
public View getConnectedView() {
try {
return mUIManager.resolveView(mConnectedViewTag);
} catch (IllegalViewOperationException ex) {
// resolveView throws an {@link IllegalViewOperationException} when the view doesn't exist
// (this can happen if the surface is being deallocated).
return null;
}
}
public String prettyPrint() {
return "PropsAnimatedNode["
+ mTag