11#include < reanimated/CSS/core/transition/CSSPlatformTransitionProxy.h>
2- #include < reanimated/Tools/FeatureFlags.h>
32
43#include < react/debug/react_native_assert.h>
54
@@ -9,23 +8,36 @@ namespace reanimated::css {
98
109CSSPlatformTransitionProxy::CSSPlatformTransitionProxy (
1110 CSSCanRoutePropertyFunction canRoute,
12- CSSApplyTransitionFunction applyTransition,
11+ CSSApplyTransitionJSIFunction applyJSI,
12+ CSSApplyTransitionDynamicFunction applyDynamic,
1313 CSSRemoveTransitionFunction removeTransition)
1414 : canRoute_(std::move(canRoute)),
15- applyTransition_ (std::move(applyTransition)),
15+ applyJSI_ (std::move(applyJSI)),
16+ applyDynamic_(std::move(applyDynamic)),
1617 removeTransition_(std::move(removeTransition)) {}
1718
1819bool CSSPlatformTransitionProxy::canRoute (const std::string &propertyName, const EasingConfig &easing) const {
19- if constexpr (!StaticFeatureFlags::getFlag (" IOS_CSS_CORE_ANIMATION" )) {
20- return false ;
21- }
2220 return canRoute_ && canRoute_ (propertyName, easing);
2321}
2422
25- void CSSPlatformTransitionProxy::run (const CSSPlatformTransitionPropertyConfig &config) const {
26- if (applyTransition_) {
27- applyTransition_ (config);
28- }
23+ bool CSSPlatformTransitionProxy::apply (
24+ jsi::Runtime &rt,
25+ const Tag viewTag,
26+ const std::string &propertyName,
27+ const jsi::Value &fromValue,
28+ const jsi::Value &toValue,
29+ const CSSTransitionPropertySettings &settings,
30+ const double timestamp) const {
31+ return applyJSI_ && applyJSI_ (rt, viewTag, propertyName, fromValue, toValue, settings, timestamp);
32+ }
33+
34+ bool CSSPlatformTransitionProxy::apply (
35+ const Tag viewTag,
36+ const std::string &propertyName,
37+ const folly::dynamic &fromValue,
38+ const folly::dynamic &toValue,
39+ const double timestamp) const {
40+ return applyDynamic_ && applyDynamic_ (viewTag, propertyName, fromValue, toValue, timestamp);
2941}
3042
3143void CSSPlatformTransitionProxy::remove (const Tag viewTag, const std::string &propertyName) const {
@@ -34,67 +46,92 @@ void CSSPlatformTransitionProxy::remove(const Tag viewTag, const std::string &pr
3446 }
3547}
3648
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.
41- CSSPlatformTransitionProxy::ProcessedConfig CSSPlatformTransitionProxy::processConfig (
42- CSSTransitionConfig &&config,
43- const CSSTransitionRouting &previousRouting) const {
44- ProcessedConfig result;
45- result.routing = previousRouting;
46-
47- // Drain changedPropertiesSettings; for each, decide routing and bucket.
48- // extract() preserves move-only PropertyValueDiff (jsi::Value pair).
49- while (!config.changedPropertiesSettings .empty ()) {
50- auto settingsNode = config.changedPropertiesSettings .extract (config.changedPropertiesSettings .begin ());
51- const auto &propertyName = settingsNode.key ();
52- const auto &settings = settingsNode.mapped ();
49+ CSSTransitionConfig CSSPlatformTransitionProxy::processConfig (
50+ jsi::Runtime &rt,
51+ const Tag viewTag,
52+ const CSSTransitionConfig &config,
53+ CSSTransitionRouting &routing,
54+ const double timestamp) const {
55+ CSSTransitionConfig loopConfig;
56+ size_t matchedValues = 0 ;
57+
58+ for (const auto &[propertyName, settings] : config.changedPropertiesSettings ) {
5359 const auto valueIt = config.changedProperties .find (propertyName);
60+ const bool hasValue = valueIt != config.changedProperties .end ();
61+ if (hasValue) {
62+ ++matchedValues;
63+ }
5464
55- if (canRoute (propertyName, settings.easingConfig )) {
56- // loop -> platform migration: cancel on loop.
57- if (result.routing .loop .erase (propertyName) > 0 ) {
58- result.loop .removedProperties .push_back (propertyName);
59- }
60- result.routing .platform .insert (propertyName);
65+ bool routable = canRoute (propertyName, settings.easingConfig );
66+ if (routable && hasValue) {
67+ routable = apply (rt, viewTag, propertyName, valueIt->second .first , valueIt->second .second , settings, timestamp);
68+ } else if (routable) {
69+ // Settings-only: stay on the platform only if already animating there.
70+ routable = routing.platform .contains (propertyName);
71+ }
6172
62- if (valueIt != config. changedProperties . end () ) {
63- auto valueNode = config. changedProperties . extract (valueIt);
64- result. platform . changedProperties . push_back (
65- CSSPlatformTransitionRawEntry{propertyName, std::move (valueNode. mapped ()), settings} );
73+ if (routable ) {
74+ // loop -> platform migration cancels on the loop side.
75+ if (routing. loop . erase (propertyName) > 0 ) {
76+ loopConfig. removedProperties . push_back (propertyName );
6677 }
67- result .platform .changedPropertiesSettings . insert (std::move (settingsNode) );
78+ routing .platform .insert (propertyName );
6879 } else {
69- // platform -> loop migration: cancel on platform.
70- if (result. routing .platform .erase (propertyName) > 0 ) {
71- result. platform . removedProperties . push_back ( propertyName);
80+ // platform -> loop migration cancels on the platform side .
81+ if (routing.platform .erase (propertyName) > 0 ) {
82+ remove (viewTag, propertyName);
7283 }
73- result. routing .loop .insert (propertyName);
74-
75- if (valueIt != config .changedProperties .end ()) {
76- auto valueNode = config. changedProperties . extract (valueIt);
77- result. loop . changedProperties . insert ( std::move (valueNode ));
84+ routing.loop .insert (propertyName);
85+ if (hasValue) {
86+ loopConfig .changedProperties .emplace (
87+ propertyName,
88+ std::make_pair ( jsi::Value (rt, valueIt-> second . first ), jsi::Value (rt, valueIt-> second . second ) ));
7889 }
79- result. loop . changedPropertiesSettings .insert ( std::move (settingsNode) );
90+ loopConfig. changedPropertiesSettings .emplace (propertyName, settings );
8091 }
8192 }
8293
83- // The parser pairs every value diff with settings, so the drain above must
84- // have consumed all of changedProperties.
85- react_native_assert (config.changedProperties .empty () && " [Reanimated] CSS transition value diff without settings" );
86-
87- // Props JS asked to stop transitioning: look up the owning side in routing
88- // and forward the cancel there.
89- for (auto &propertyName : config.removedProperties ) {
90- if (result.routing .platform .erase (propertyName) > 0 ) {
91- result.platform .removedProperties .push_back (std::move (propertyName));
92- } else if (result.routing .loop .erase (propertyName) > 0 ) {
93- result.loop .removedProperties .push_back (std::move (propertyName));
94+ // The parser pairs every value diff with settings, so all must have matched one.
95+ react_native_assert (
96+ matchedValues == config.changedProperties .size () && " [Reanimated] CSS transition value diff without settings" );
97+
98+ for (const auto &propertyName : config.removedProperties ) {
99+ if (routing.platform .erase (propertyName) > 0 ) {
100+ remove (viewTag, propertyName);
101+ } else if (routing.loop .erase (propertyName) > 0 ) {
102+ loopConfig.removedProperties .push_back (propertyName);
94103 }
95104 }
96105
97- return result;
106+ return loopConfig;
107+ }
108+
109+ PropertyValueDynamicDiffsMap CSSPlatformTransitionProxy::processDynamicDiffs (
110+ const Tag viewTag,
111+ const PropertyValueDynamicDiffsMap &propertyDiffs,
112+ CSSTransitionRouting &routing,
113+ const double timestamp) const {
114+ PropertyValueDynamicDiffsMap loopDiffs;
115+ for (const auto &[propertyName, propertyDiff] : propertyDiffs) {
116+ // A platform-routed property keeps animating natively while the platform can
117+ // still express the toggled value; otherwise it migrates to the loop.
118+ if (routing.platform .contains (propertyName)) {
119+ if (apply (viewTag, propertyName, propertyDiff.first , propertyDiff.second , timestamp)) {
120+ continue ;
121+ }
122+ routing.platform .erase (propertyName);
123+ remove (viewTag, propertyName);
124+ routing.loop .insert (propertyName);
125+ }
126+ loopDiffs.emplace (propertyName, propertyDiff);
127+ }
128+ return loopDiffs;
129+ }
130+
131+ void CSSPlatformTransitionProxy::cancelAll (const Tag viewTag, const TransitionProperties &properties) const {
132+ for (const auto &propertyName : properties) {
133+ remove (viewTag, propertyName);
134+ }
98135}
99136
100137} // namespace reanimated::css
0 commit comments