ObjectAnimatedNode.java->.kt (#45721)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/45721

# Changelog:
[Internal] -

As in the title.

Reviewed By: tdn120

Differential Revision: D60284429

fbshipit-source-id: 056a7860b75c8f33e38daf1baffc8ad52c3b386c
This commit is contained in:
Ruslan Shestopalyuk
2024-07-28 09:13:23 -07:00
committed by Facebook GitHub Bot
parent 9e7760210f
commit 19a63e1b16
2 changed files with 120 additions and 161 deletions
@@ -1,161 +0,0 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.react.animated;
import androidx.annotation.Nullable;
import com.facebook.infer.annotation.Nullsafe;
import com.facebook.react.bridge.JavaOnlyArray;
import com.facebook.react.bridge.JavaOnlyMap;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.ReadableMapKeySetIterator;
import com.facebook.react.bridge.ReadableType;
/**
* Native counterpart of object animated node (see AnimatedObject class in
* AnimatedImplementation.js)
*/
/* package */ @Nullsafe(Nullsafe.Mode.LOCAL)
class ObjectAnimatedNode extends AnimatedNode {
private static final String VALUE_KEY = "value";
private static final String NODE_TAG_KEY = "nodeTag";
private final NativeAnimatedNodesManager mNativeAnimatedNodesManager;
private final JavaOnlyMap mConfig;
ObjectAnimatedNode(ReadableMap config, NativeAnimatedNodesManager nativeAnimatedNodesManager) {
mConfig = JavaOnlyMap.deepClone(config);
mNativeAnimatedNodesManager = nativeAnimatedNodesManager;
}
public void collectViewUpdates(String propKey, JavaOnlyMap propsMap) {
ReadableType valueType = mConfig.getType(VALUE_KEY);
if (valueType == ReadableType.Map) {
propsMap.putMap(propKey, collectViewUpdatesHelper(mConfig.getMap(VALUE_KEY)));
} else if (valueType == ReadableType.Array) {
propsMap.putArray(propKey, collectViewUpdatesHelper(mConfig.getArray(VALUE_KEY)));
} else {
throw new IllegalArgumentException("Invalid value type for ObjectAnimatedNode");
}
}
private @Nullable JavaOnlyArray collectViewUpdatesHelper(@Nullable ReadableArray source) {
if (source == null) {
return null;
}
JavaOnlyArray result = new JavaOnlyArray();
for (int i = 0; i < source.size(); i++) {
switch (source.getType(i)) {
case Null:
result.pushNull();
break;
case Boolean:
result.pushBoolean(source.getBoolean(i));
break;
case Number:
result.pushDouble(source.getDouble(i));
break;
case String:
result.pushString(source.getString(i));
break;
case Map:
ReadableMap map = source.getMap(i);
if (map.hasKey(NODE_TAG_KEY) && map.getType(NODE_TAG_KEY) == ReadableType.Number) {
AnimatedNode node = mNativeAnimatedNodesManager.getNodeById(map.getInt(NODE_TAG_KEY));
if (node == null) {
throw new IllegalArgumentException("Mapped value node does not exist");
} else if (node instanceof ValueAnimatedNode) {
ValueAnimatedNode valueAnimatedNode = (ValueAnimatedNode) node;
Object animatedObject = valueAnimatedNode.getAnimatedObject();
if (animatedObject instanceof Integer) {
result.pushInt((Integer) animatedObject);
} else if (animatedObject instanceof String) {
result.pushString((String) animatedObject);
} else {
result.pushDouble(valueAnimatedNode.getValue());
}
} else if (node instanceof ColorAnimatedNode) {
result.pushInt(((ColorAnimatedNode) node).getColor());
}
} else {
result.pushMap(collectViewUpdatesHelper(source.getMap(i)));
}
break;
case Array:
result.pushArray(collectViewUpdatesHelper(source.getArray(i)));
break;
}
}
return result;
}
private @Nullable JavaOnlyMap collectViewUpdatesHelper(@Nullable ReadableMap source) {
if (source == null) {
return null;
}
JavaOnlyMap result = new JavaOnlyMap();
ReadableMapKeySetIterator iter = source.keySetIterator();
while (iter.hasNextKey()) {
String propKey = iter.nextKey();
switch (source.getType(propKey)) {
case Null:
result.putNull(propKey);
break;
case Boolean:
result.putBoolean(propKey, source.getBoolean(propKey));
break;
case Number:
result.putDouble(propKey, source.getDouble(propKey));
break;
case String:
result.putString(propKey, source.getString(propKey));
break;
case Map:
ReadableMap map = source.getMap(propKey);
if (map != null
&& map.hasKey(NODE_TAG_KEY)
&& map.getType(NODE_TAG_KEY) == ReadableType.Number) {
AnimatedNode node = mNativeAnimatedNodesManager.getNodeById(map.getInt(NODE_TAG_KEY));
if (node == null) {
throw new IllegalArgumentException("Mapped value node does not exist");
} else if (node instanceof ValueAnimatedNode) {
ValueAnimatedNode valueAnimatedNode = (ValueAnimatedNode) node;
Object animatedObject = valueAnimatedNode.getAnimatedObject();
if (animatedObject instanceof Integer) {
result.putInt(propKey, (Integer) animatedObject);
} else if (animatedObject instanceof String) {
result.putString(propKey, (String) animatedObject);
} else {
result.putDouble(propKey, valueAnimatedNode.getValue());
}
} else if (node instanceof ColorAnimatedNode) {
result.putInt(propKey, ((ColorAnimatedNode) node).getColor());
}
} else {
result.putMap(propKey, collectViewUpdatesHelper(map));
}
break;
case Array:
result.putArray(propKey, collectViewUpdatesHelper(source.getArray(propKey)));
break;
}
}
return result;
}
@Override
public String prettyPrint() {
return "ObjectAnimatedNode["
+ tag
+ "]: mConfig: "
+ (mConfig != null ? mConfig.toString() : "null");
}
}
@@ -0,0 +1,120 @@
/*
* Copyright (c) Meta Platforms, Inc. and 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.react.animated
import com.facebook.react.bridge.JavaOnlyArray
import com.facebook.react.bridge.JavaOnlyMap
import com.facebook.react.bridge.ReadableArray
import com.facebook.react.bridge.ReadableMap
import com.facebook.react.bridge.ReadableType
/**
* Native counterpart of object animated node (see AnimatedObject class in
* AnimatedImplementation.js)
*/
internal class ObjectAnimatedNode(
config: ReadableMap,
private val nativeAnimatedNodesManager: NativeAnimatedNodesManager
) : AnimatedNode() {
private val configClone: JavaOnlyMap = JavaOnlyMap.deepClone(config)
fun collectViewUpdates(propKey: String, propsMap: JavaOnlyMap) {
val valueType = configClone.getType(VALUE_KEY)
if (valueType == ReadableType.Map) {
propsMap.putMap(propKey, collectViewUpdatesHelper(configClone.getMap(VALUE_KEY)))
} else if (valueType == ReadableType.Array) {
propsMap.putArray(propKey, collectViewUpdatesHelper(configClone.getArray(VALUE_KEY)))
} else {
throw IllegalArgumentException("Invalid value type for ObjectAnimatedNode")
}
}
private fun collectViewUpdatesHelper(source: ReadableArray?): JavaOnlyArray? {
source ?: return null
val result = JavaOnlyArray()
for (i in 0 until source.size()) {
when (source.getType(i)) {
ReadableType.Null -> result.pushNull()
ReadableType.Boolean -> result.pushBoolean(source.getBoolean(i))
ReadableType.Number -> result.pushDouble(source.getDouble(i))
ReadableType.String -> result.pushString(source.getString(i))
ReadableType.Map -> {
val map = source.getMap(i)
if (map.hasKey(NODE_TAG_KEY) && map.getType(NODE_TAG_KEY) == ReadableType.Number) {
val node = nativeAnimatedNodesManager.getNodeById(map.getInt(NODE_TAG_KEY))
requireNotNull(node) { "Mapped value node does not exist" }
if (node is ValueAnimatedNode) {
val animatedObject = node.getAnimatedObject()
if (animatedObject is Int) {
result.pushInt(animatedObject)
} else if (animatedObject is String) {
result.pushString(animatedObject)
} else {
result.pushDouble(node.getValue())
}
} else if (node is ColorAnimatedNode) {
result.pushInt(node.color)
}
} else {
result.pushMap(collectViewUpdatesHelper(source.getMap(i)))
}
}
ReadableType.Array -> result.pushArray(collectViewUpdatesHelper(source.getArray(i)))
}
}
return result
}
private fun collectViewUpdatesHelper(source: ReadableMap?): JavaOnlyMap? {
source ?: return null
val result = JavaOnlyMap()
val iter = source.keySetIterator()
while (iter.hasNextKey()) {
val propKey = iter.nextKey()
when (source.getType(propKey)) {
ReadableType.Null -> result.putNull(propKey)
ReadableType.Boolean -> result.putBoolean(propKey, source.getBoolean(propKey))
ReadableType.Number -> result.putDouble(propKey, source.getDouble(propKey))
ReadableType.String -> result.putString(propKey, source.getString(propKey))
ReadableType.Map -> {
val map = source.getMap(propKey)
if (map != null &&
map.hasKey(NODE_TAG_KEY) &&
map.getType(NODE_TAG_KEY) == ReadableType.Number) {
val node = nativeAnimatedNodesManager.getNodeById(map.getInt(NODE_TAG_KEY))
requireNotNull(node) { "Mapped value node does not exist" }
if (node is ValueAnimatedNode) {
val animatedObject = node.getAnimatedObject()
if (animatedObject is Int) {
result.putInt(propKey, animatedObject)
} else if (animatedObject is String) {
result.putString(propKey, animatedObject)
} else {
result.putDouble(propKey, node.getValue())
}
} else if (node is ColorAnimatedNode) {
result.putInt(propKey, node.color)
}
} else {
result.putMap(propKey, collectViewUpdatesHelper(map))
}
}
ReadableType.Array ->
result.putArray(propKey, collectViewUpdatesHelper(source.getArray(propKey)))
}
}
return result
}
override fun prettyPrint(): String = "ObjectAnimatedNode[$tag]: mConfig: $configClone"
companion object {
private const val VALUE_KEY = "value"
private const val NODE_TAG_KEY = "nodeTag"
}
}