11#include < reanimated/CSS/core/transition/CSSPlatformTransitionProxy.h>
2- #include < reanimated/Tools/FeatureFlags.h>
32
43#include < react/debug/react_native_assert.h>
54
65#include < utility>
76
87namespace reanimated ::css {
98
9+ namespace {
10+
11+ // Reduces a jsi::Value transition endpoint to the representation-agnostic shape
12+ // the platform parses (a number, a size, or monostate for null / absent).
13+ CSSEndpointValue endpointFromJSI (jsi::Runtime &rt, const jsi::Value &value) {
14+ if (value.isNumber ()) {
15+ return value.asNumber ();
16+ }
17+ if (value.isObject ()) {
18+ const auto object = value.asObject (rt);
19+ const auto width = object.getProperty (rt, " width" );
20+ const auto height = object.getProperty (rt, " height" );
21+ return std::array<double , 2 >{
22+ width.isNumber () ? width.asNumber () : 0.0 ,
23+ height.isNumber () ? height.asNumber () : 0.0 ,
24+ };
25+ }
26+ return std::monostate{};
27+ }
28+
29+ // The same reduction for the runtime-free pseudo-selector toggle path.
30+ CSSEndpointValue endpointFromDynamic (const folly::dynamic &value) {
31+ if (value.isNumber ()) {
32+ return value.asDouble ();
33+ }
34+ if (value.isObject ()) {
35+ const auto *width = value.get_ptr (" width" );
36+ const auto *height = value.get_ptr (" height" );
37+ return std::array<double , 2 >{
38+ width != nullptr && width->isNumber () ? width->asDouble () : 0.0 ,
39+ height != nullptr && height->isNumber () ? height->asDouble () : 0.0 ,
40+ };
41+ }
42+ return std::monostate{};
43+ }
44+
45+ } // namespace
46+
1047CSSPlatformTransitionProxy::CSSPlatformTransitionProxy (
1148 CSSCanRoutePropertyFunction canRoute,
49+ CSSParseValueFunction parseValue,
1250 CSSApplyTransitionFunction applyTransition,
1351 CSSRemoveTransitionFunction removeTransition)
1452 : canRoute_(std::move(canRoute)),
53+ parseValue_ (std::move(parseValue)),
1554 applyTransition_(std::move(applyTransition)),
1655 removeTransition_(std::move(removeTransition)) {}
1756
1857bool CSSPlatformTransitionProxy::canRoute (const std::string &propertyName, const EasingConfig &easing) const {
19- if constexpr (!StaticFeatureFlags::getFlag (" IOS_CSS_CORE_ANIMATION" )) {
20- return false ;
21- }
2258 return canRoute_ && canRoute_ (propertyName, easing);
2359}
2460
61+ std::optional<PlatformValue> CSSPlatformTransitionProxy::parseValue (
62+ const std::string &propertyName,
63+ const CSSEndpointValue &value) const {
64+ return parseValue_ ? parseValue_ (propertyName, value) : std::nullopt ;
65+ }
66+
2567void CSSPlatformTransitionProxy::run (const CSSPlatformTransitionPropertyConfig &config) const {
2668 if (applyTransition_) {
2769 applyTransition_ (config);
@@ -34,35 +76,42 @@ void CSSPlatformTransitionProxy::remove(const Tag viewTag, const std::string &pr
3476 }
3577}
3678
37- // Splits the new split-shape config into loop / platform buckets. result.routing
38- // starts as a copy of the previous call's routing and is updated as we route
39- // each prop; erasing from the *other* side's set returns nonzero exactly when
40- // the prop is migrating sides - that's how we emit cancels.
79+ // Erasing from the other side's routing set returns nonzero exactly when the
80+ // property migrates sides - that's when the old side gets a cancel.
4181CSSPlatformTransitionProxy::ProcessedConfig CSSPlatformTransitionProxy::processConfig (
82+ jsi::Runtime &rt,
4283 CSSTransitionConfig &&config,
4384 const CSSTransitionRouting &previousRouting) const {
4485 ProcessedConfig result;
4586 result.routing = previousRouting;
4687
47- // Drain changedPropertiesSettings; for each, decide routing and bucket.
48- // extract() preserves move-only PropertyValueDiff (jsi::Value pair).
88+ // extract() preserves the move-only jsi::Value diffs.
4989 while (!config.changedPropertiesSettings .empty ()) {
5090 auto settingsNode = config.changedPropertiesSettings .extract (config.changedPropertiesSettings .begin ());
5191 const auto &propertyName = settingsNode.key ();
5292 const auto &settings = settingsNode.mapped ();
5393 const auto valueIt = config.changedProperties .find (propertyName);
5494
55- if (canRoute (propertyName, settings.easingConfig )) {
95+ bool routable = canRoute (propertyName, settings.easingConfig );
96+ std::optional<PlatformValue> fromValue;
97+ std::optional<PlatformValue> toValue;
98+ if (routable && valueIt != config.changedProperties .end ()) {
99+ fromValue = parseValue (propertyName, endpointFromJSI (rt, valueIt->second .first ));
100+ toValue = parseValue (propertyName, endpointFromJSI (rt, valueIt->second .second ));
101+ routable = fromValue.has_value () && toValue.has_value ();
102+ }
103+
104+ if (routable) {
56105 // loop -> platform migration: cancel on loop.
57106 if (result.routing .loop .erase (propertyName) > 0 ) {
58107 result.loop .removedProperties .push_back (propertyName);
59108 }
60109 result.routing .platform .insert (propertyName);
61110
62111 if (valueIt != config.changedProperties .end ()) {
63- auto valueNode = config.changedProperties .extract (valueIt);
112+ config.changedProperties .erase (valueIt);
64113 result.platform .changedProperties .push_back (
65- CSSPlatformTransitionRawEntry {propertyName, std::move (valueNode. mapped ()) , settings});
114+ CSSPlatformTransitionEntry {propertyName, *fromValue, *toValue , settings});
66115 }
67116 result.platform .changedPropertiesSettings .insert (std::move (settingsNode));
68117 } else {
@@ -84,8 +133,7 @@ CSSPlatformTransitionProxy::ProcessedConfig CSSPlatformTransitionProxy::processC
84133 // have consumed all of changedProperties.
85134 react_native_assert (config.changedProperties .empty () && " [Reanimated] CSS transition value diff without settings" );
86135
87- // Props JS asked to stop transitioning: look up the owning side in routing
88- // and forward the cancel there.
136+ // Forward removal cancels to the side that owns the property.
89137 for (auto &propertyName : config.removedProperties ) {
90138 if (result.routing .platform .erase (propertyName) > 0 ) {
91139 result.platform .removedProperties .push_back (std::move (propertyName));
@@ -97,4 +145,25 @@ CSSPlatformTransitionProxy::ProcessedConfig CSSPlatformTransitionProxy::processC
97145 return result;
98146}
99147
148+ CSSPlatformTransitionProxy::ProcessedDynamicDiffs CSSPlatformTransitionProxy::processDynamicDiffs (
149+ const CSSTransitionRouting &routing,
150+ const PropertyValueDynamicDiffsMap &propertyDiffs) const {
151+ ProcessedDynamicDiffs result;
152+ for (const auto &[propertyName, propertyDiff] : propertyDiffs) {
153+ // The routing was decided when the transition was registered; here we only
154+ // re-parse the toggled endpoints. Values the platform cannot express fall
155+ // back to the loop.
156+ if (routing.platform .contains (propertyName)) {
157+ auto fromValue = parseValue (propertyName, endpointFromDynamic (propertyDiff.first ));
158+ auto toValue = parseValue (propertyName, endpointFromDynamic (propertyDiff.second ));
159+ if (fromValue && toValue) {
160+ result.platform .emplace (propertyName, std::make_pair (*fromValue, *toValue));
161+ continue ;
162+ }
163+ }
164+ result.loop .emplace (propertyName, propertyDiff);
165+ }
166+ return result;
167+ }
168+
100169} // namespace reanimated::css
0 commit comments