diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.cpp index 33c990c66ad9..90199fe0cd29 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/ArrayPropertiesInterpolator.cpp @@ -52,21 +52,33 @@ void ArrayPropertiesInterpolator::updateKeyframesFromStyleChange( jsi::Runtime &rt, const jsi::Value &oldStyleValue, const jsi::Value &newStyleValue) { - const size_t valuesCount = newStyleValue.isObject() - ? newStyleValue.asObject(rt).asArray(rt).size(rt) - : oldStyleValue.asObject(rt).asArray(rt).size(rt); + auto getArrayFromStyle = [&rt](const jsi::Value &style) { + if (!style.isObject()) { + return jsi::Array(rt, 0); + } + auto obj = style.asObject(rt); + return obj.isArray(rt) ? obj.asArray(rt) : jsi::Array(rt, 0); + }; + + const auto oldStyleArray = getArrayFromStyle(oldStyleValue); + const auto newStyleArray = getArrayFromStyle(newStyleValue); + + const size_t valuesCount = + std::max(oldStyleArray.size(rt), newStyleArray.size(rt)); resizeInterpolators(valuesCount); for (size_t i = 0; i < valuesCount; ++i) { - interpolators_[i]->updateKeyframesFromStyleChange( - rt, - oldStyleValue.isObject() - ? oldStyleValue.asObject(rt).asArray(rt).getValueAtIndex(rt, i) - : jsi::Value::undefined(), - newStyleValue.isObject() - ? newStyleValue.asObject(rt).asArray(rt).getValueAtIndex(rt, i) - : jsi::Value::undefined()); + // These index checks ensure that interpolation works between 2 arrays + // with different lengths + const auto oldValue = oldStyleArray.size(rt) > i + ? oldStyleArray.getValueAtIndex(rt, i) + : jsi::Value::undefined(); + const auto newValue = newStyleArray.size(rt) > i + ? newStyleArray.getValueAtIndex(rt, i) + : jsi::Value::undefined(); + + interpolators_[i]->updateKeyframesFromStyleChange(rt, oldValue, newValue); } } diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.cpp index 4889f8466e39..fcf2927e0b70 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.cpp @@ -53,20 +53,9 @@ void RecordPropertiesInterpolator::updateKeyframes( propertyNames.getValueAtIndex(rt, i).asString(rt).utf8(rt); const jsi::Value &propertyKeyframes = keyframesObject.getProperty( rt, jsi::PropNameID::forUtf8(rt, propertyName)); - auto interpolatorIt = interpolators_.find(propertyName); - - if (interpolatorIt == interpolators_.end()) { - const auto newInterpolator = createPropertyInterpolator( - propertyName, - propertyPath_, - factories_, - progressProvider_, - viewStylesRepository_); - interpolatorIt = - interpolators_.emplace(propertyName, newInterpolator).first; - } - interpolatorIt->second->updateKeyframes(rt, propertyKeyframes); + maybeCreateInterpolator(propertyName); + interpolators_.at(propertyName)->updateKeyframes(rt, propertyKeyframes); } } @@ -76,35 +65,34 @@ void RecordPropertiesInterpolator::updateKeyframesFromStyleChange( const jsi::Value &newStyleValue) { // TODO - maybe add a possibility to remove interpolators that are no longer // used (for now, for simplicity, we only add new ones) - const jsi::Array propertyNames = newStyleValue.isObject() - ? newStyleValue.asObject(rt).getPropertyNames(rt) - : oldStyleValue.asObject(rt).getPropertyNames(rt); - const size_t propertiesCount = propertyNames.size(rt); - for (size_t i = 0; i < propertiesCount; ++i) { - const std::string propertyName = - propertyNames.getValueAtIndex(rt, i).asString(rt).utf8(rt); - auto interpolatorIt = interpolators_.find(propertyName); - - if (interpolatorIt == interpolators_.end()) { - const auto newInterpolator = createPropertyInterpolator( - propertyName, - propertyPath_, - factories_, - progressProvider_, - viewStylesRepository_); - interpolatorIt = - interpolators_.emplace(propertyName, newInterpolator).first; + const auto oldStyleObject = + oldStyleValue.isObject() ? oldStyleValue.asObject(rt) : jsi::Object(rt); + const auto newStyleObject = + newStyleValue.isObject() ? newStyleValue.asObject(rt) : jsi::Object(rt); + + std::unordered_set propertyNamesSet; + const jsi::Object *objects[] = {&oldStyleObject, &newStyleObject}; + for (const auto *styleObject : objects) { + const auto propertyNames = styleObject->getPropertyNames(rt); + for (size_t i = 0; i < propertyNames.size(rt); ++i) { + propertyNamesSet.insert( + propertyNames.getValueAtIndex(rt, i).asString(rt).utf8(rt)); } + } - interpolatorIt->second->updateKeyframesFromStyleChange( - rt, - oldStyleValue.isObject() - ? oldStyleValue.asObject(rt).getProperty(rt, propertyName.c_str()) - : jsi::Value::undefined(), - newStyleValue.isObject() - ? newStyleValue.asObject(rt).getProperty(rt, propertyName.c_str()) - : jsi::Value::undefined()); + for (const auto &propertyName : propertyNamesSet) { + maybeCreateInterpolator(propertyName); + + auto getValue = [&](const jsi::Object &obj) { + return obj.hasProperty(rt, propertyName.c_str()) + ? obj.getProperty(rt, jsi::PropNameID::forUtf8(rt, propertyName)) + : jsi::Value::undefined(); + }; + + interpolators_.at(propertyName) + ->updateKeyframesFromStyleChange( + rt, getValue(oldStyleObject), getValue(newStyleObject)); } } @@ -121,6 +109,19 @@ jsi::Value RecordPropertiesInterpolator::mapInterpolators( return result; } +void RecordPropertiesInterpolator::maybeCreateInterpolator( + const std::string &propertyName) { + if (interpolators_.find(propertyName) == interpolators_.end()) { + const auto newInterpolator = createPropertyInterpolator( + propertyName, + propertyPath_, + factories_, + progressProvider_, + viewStylesRepository_); + interpolators_.emplace(propertyName, newInterpolator); + } +} + } // namespace reanimated #endif // RCT_NEW_ARCH_ENABLED diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h index 2065e8f556b8..b5914d890dda 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h +++ b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/interpolation/groups/RecordPropertiesInterpolator.h @@ -34,6 +34,8 @@ class RecordPropertiesInterpolator : public GroupPropertiesInterpolator { const std::function &callback) const override; + void maybeCreateInterpolator(const std::string &propertyName); + private: const InterpolatorFactoriesRecord &factories_; PropertyInterpolatorsRecord interpolators_; diff --git a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/registry/CSSTransitionsRegistry.cpp b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/registry/CSSTransitionsRegistry.cpp index c582436c13b7..60e875cb66b3 100644 --- a/packages/react-native-reanimated/Common/cpp/reanimated/CSS/registry/CSSTransitionsRegistry.cpp +++ b/packages/react-native-reanimated/Common/cpp/reanimated/CSS/registry/CSSTransitionsRegistry.cpp @@ -1,8 +1,12 @@ #ifdef RCT_NEW_ARCH_ENABLED #include +#include + namespace reanimated { +using namespace worklets; + CSSTransitionsRegistry::CSSTransitionsRegistry( const std::shared_ptr &staticPropsRegistry, const GetAnimationTimestampFunction &getCurrentTimestamp) @@ -139,6 +143,9 @@ PropsObserver CSSTransitionsRegistry::createPropsObserver(const Tag viewTag) { return; } + LOG(INFO) << "oldProps: " << stringifyJSIValue(rt, changedProps.oldProps); + LOG(INFO) << "newProps: " << stringifyJSIValue(rt, changedProps.newProps); + { std::lock_guard lock{strongThis->mutex_};