react-native-reanimated 4.3.0 → 4.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.cpp +12 -5
- package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.cpp +59 -37
- package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h +11 -8
- package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp +11 -3
- package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.h +9 -2
- package/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.cpp +6 -2
- package/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.h +8 -2
- package/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.cpp +17 -4
- package/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.h +5 -0
- package/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.cpp +5 -0
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +25 -12
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +3 -0
- package/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.cpp +12 -5
- package/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h +6 -3
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +4 -6
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +25 -7
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +38 -0
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +106 -33
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +165 -92
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +12 -34
- package/README.md +1 -1
- package/android/CMakeLists.txt +4 -1
- package/android/build.gradle +2 -0
- package/android/generate-stub-pch.gradle.kts +84 -0
- package/android/src/main/cpp/ReanimatedPCH.h +46 -0
- package/android/src/main/java/com/swmansion/reanimated/NativeProxy.java +14 -1
- package/android/src/main/java/com/swmansion/reanimated/keyboard/KeyboardAnimationCallback.java +9 -1
- package/apple/reanimated/apple/ReanimatedModule.mm +12 -1
- package/lib/module/common/constants/platform.js +5 -5
- package/lib/module/common/constants/platform.js.map +1 -1
- package/lib/module/createAnimatedComponent/AnimatedComponent.js +1 -7
- package/lib/module/createAnimatedComponent/AnimatedComponent.js.map +1 -1
- package/lib/module/createAnimatedComponent/getViewInfo.js +3 -1
- package/lib/module/createAnimatedComponent/getViewInfo.js.map +1 -1
- package/lib/module/css/component/AnimatedComponent.js +0 -2
- package/lib/module/css/component/AnimatedComponent.js.map +1 -1
- package/lib/module/css/native/managers/CSSManager.js +16 -7
- package/lib/module/css/native/managers/CSSManager.js.map +1 -1
- package/lib/module/css/native/managers/CSSTransitionsManager.js +8 -1
- package/lib/module/css/native/managers/CSSTransitionsManager.js.map +1 -1
- package/lib/module/css/svg/native/processors/stroke.js +9 -5
- package/lib/module/css/svg/native/processors/stroke.js.map +1 -1
- package/lib/module/css/utils/props.js +6 -0
- package/lib/module/css/utils/props.js.map +1 -1
- package/lib/module/hook/useAnimatedRef.js +2 -2
- package/lib/module/hook/useAnimatedRef.js.map +1 -1
- package/lib/module/mutables.js +5 -1
- package/lib/module/mutables.js.map +1 -1
- package/lib/module/platform-specific/findHostInstance.js +8 -5
- package/lib/module/platform-specific/findHostInstance.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/module/updateProps/updateProps.js +3 -2
- package/lib/module/updateProps/updateProps.js.map +1 -1
- package/lib/module/valueSetter.js +1 -1
- package/lib/module/valueSetter.js.map +1 -1
- package/lib/typescript/common/constants/platform.d.ts.map +1 -1
- package/lib/typescript/createAnimatedComponent/AnimatedComponent.d.ts.map +1 -1
- package/lib/typescript/createAnimatedComponent/commonTypes.d.ts +0 -1
- package/lib/typescript/createAnimatedComponent/commonTypes.d.ts.map +1 -1
- package/lib/typescript/createAnimatedComponent/getViewInfo.d.ts.map +1 -1
- package/lib/typescript/css/component/AnimatedComponent.d.ts +0 -1
- package/lib/typescript/css/component/AnimatedComponent.d.ts.map +1 -1
- package/lib/typescript/css/native/managers/CSSManager.d.ts +7 -0
- package/lib/typescript/css/native/managers/CSSManager.d.ts.map +1 -1
- package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts +5 -1
- package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts.map +1 -1
- package/lib/typescript/css/svg/native/processors/stroke.d.ts.map +1 -1
- package/lib/typescript/css/utils/props.d.ts.map +1 -1
- package/lib/typescript/mutables.d.ts.map +1 -1
- package/lib/typescript/platform-specific/findHostInstance.d.ts.map +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/lib/typescript/platform-specific/types.d.ts +1 -0
- package/lib/typescript/platform-specific/types.d.ts.map +1 -1
- package/lib/typescript/updateProps/updateProps.d.ts.map +1 -1
- package/lib/typescript/valueSetter.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/common/constants/platform.ts +6 -5
- package/src/createAnimatedComponent/AnimatedComponent.tsx +1 -7
- package/src/createAnimatedComponent/commonTypes.ts +0 -1
- package/src/createAnimatedComponent/getViewInfo.ts +3 -1
- package/src/css/component/AnimatedComponent.tsx +0 -2
- package/src/css/native/managers/CSSManager.ts +33 -12
- package/src/css/native/managers/CSSTransitionsManager.ts +9 -2
- package/src/css/svg/native/processors/stroke.ts +9 -6
- package/src/css/utils/props.ts +7 -0
- package/src/hook/useAnimatedRef.ts +2 -2
- package/src/mutables.ts +5 -1
- package/src/platform-specific/findHostInstance.ts +7 -7
- package/src/platform-specific/jsVersion.ts +1 -1
- package/src/platform-specific/types.ts +2 -0
- package/src/updateProps/updateProps.ts +3 -2
- package/src/valueSetter.ts +2 -1
package/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.cpp
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
#include <reanimated/CSS/interpolation/transforms/operations/skew.h>
|
|
6
6
|
#include <reanimated/CSS/interpolation/transforms/operations/translate.h>
|
|
7
7
|
|
|
8
|
+
#include <cmath>
|
|
9
|
+
#include <limits>
|
|
8
10
|
#include <utility>
|
|
9
11
|
|
|
10
12
|
namespace reanimated::css {
|
|
@@ -31,14 +33,19 @@ std::unique_ptr<StyleOperation> TransformOperationInterpolator<PerspectiveOperat
|
|
|
31
33
|
const std::shared_ptr<StyleOperation> &from,
|
|
32
34
|
const std::shared_ptr<StyleOperation> &to,
|
|
33
35
|
const StyleOperationsInterpolationContext & /* context */) const {
|
|
34
|
-
// TODO - check if this implementation is correct
|
|
35
36
|
const auto &fromValue = std::static_pointer_cast<PerspectiveOperation>(from)->value;
|
|
36
37
|
const auto &toValue = std::static_pointer_cast<PerspectiveOperation>(to)->value;
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
// The default "no perspective" is infinity, so interpolating the distance
|
|
40
|
+
// directly gives inf + t*(d - inf) = NaN. Interpolate in reciprocal space
|
|
41
|
+
// instead (1/inf = 0, matching how perspective enters the matrix as -1/d).
|
|
42
|
+
if (std::isinf(fromValue.value) || std::isinf(toValue.value)) {
|
|
43
|
+
const double fromReciprocal = 1.0 / fromValue.value;
|
|
44
|
+
const double toReciprocal = 1.0 / toValue.value;
|
|
45
|
+
const double reciprocal = fromReciprocal + progress * (toReciprocal - fromReciprocal);
|
|
46
|
+
return std::make_unique<PerspectiveOperation>(
|
|
47
|
+
reciprocal == 0.0 ? std::numeric_limits<double>::infinity() : 1.0 / reciprocal);
|
|
48
|
+
}
|
|
42
49
|
|
|
43
50
|
return std::make_unique<PerspectiveOperation>(fromValue.interpolate(progress, toValue));
|
|
44
51
|
}
|
|
@@ -13,13 +13,11 @@ ViewStylesRepository::ViewStylesRepository(
|
|
|
13
13
|
jsi::Value ViewStylesRepository::getNodeProp(
|
|
14
14
|
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
15
15
|
const std::string &propName) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
auto &cachedNode = shadowNodeCache_[tag];
|
|
19
|
-
updateCacheIfNeeded(cachedNode, shadowNode);
|
|
16
|
+
const auto resolvedNode = getNewestNode(shadowNode);
|
|
17
|
+
const auto *layoutableShadowNode = dynamic_cast<const LayoutableShadowNode *>(resolvedNode.get());
|
|
20
18
|
|
|
21
19
|
if (propName == "width" || propName == "height" || propName == "top" || propName == "left") {
|
|
22
|
-
const auto
|
|
20
|
+
const auto layoutMetrics = layoutableShadowNode ? layoutableShadowNode->layoutMetrics_ : LayoutMetrics{};
|
|
23
21
|
|
|
24
22
|
if (propName == "width") {
|
|
25
23
|
return {layoutMetrics.frame.size.width};
|
|
@@ -31,7 +29,13 @@ jsi::Value ViewStylesRepository::getNodeProp(
|
|
|
31
29
|
return {layoutMetrics.frame.origin.x};
|
|
32
30
|
}
|
|
33
31
|
} else {
|
|
34
|
-
|
|
32
|
+
if (!layoutableShadowNode) {
|
|
33
|
+
return jsi::Value::undefined();
|
|
34
|
+
}
|
|
35
|
+
const auto viewProps = std::static_pointer_cast<const ViewProps>(resolvedNode->getProps());
|
|
36
|
+
if (!viewProps) {
|
|
37
|
+
return jsi::Value::undefined();
|
|
38
|
+
}
|
|
35
39
|
|
|
36
40
|
if (propName == "opacity") {
|
|
37
41
|
return {viewProps->opacity};
|
|
@@ -48,15 +52,7 @@ jsi::Value ViewStylesRepository::getNodeProp(
|
|
|
48
52
|
jsi::Value ViewStylesRepository::getParentNodeProp(
|
|
49
53
|
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
50
54
|
const std::string &propName) {
|
|
51
|
-
const auto
|
|
52
|
-
const auto &shadowTreeRegistry = uiManager_->getShadowTreeRegistry();
|
|
53
|
-
|
|
54
|
-
std::shared_ptr<const ShadowNode> parentNode = nullptr;
|
|
55
|
-
|
|
56
|
-
shadowTreeRegistry.visit(surfaceId, [&](ShadowTree const &shadowTree) {
|
|
57
|
-
auto currentRevision = shadowTree.getCurrentRevision();
|
|
58
|
-
parentNode = dom::getParentNode(currentRevision.rootShadowNode, *shadowNode);
|
|
59
|
-
});
|
|
55
|
+
const auto parentNode = getParentNode(shadowNode);
|
|
60
56
|
|
|
61
57
|
if (!parentNode) {
|
|
62
58
|
return jsi::Value::undefined();
|
|
@@ -65,37 +61,63 @@ jsi::Value ViewStylesRepository::getParentNodeProp(
|
|
|
65
61
|
return getNodeProp(parentNode, propName);
|
|
66
62
|
}
|
|
67
63
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
std::shared_ptr<const ShadowNode> ViewStylesRepository::getNewestNode(
|
|
65
|
+
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
66
|
+
// Resolve shadowNode against the last mounted root instead of reading the live
|
|
67
|
+
// ShadowTree: uiManager_->getNewestCloneOfShadowNode takes the ShadowTree commit
|
|
68
|
+
// lock, and this method runs under the updates-registry lock while a concurrent
|
|
69
|
+
// Fabric commit takes the same two locks in the opposite order (the ANR
|
|
70
|
+
// deadlock). Falls back to the passed node. Mirrors RN's getShadowNodeInSubtree:
|
|
71
|
+
// https://github.com/facebook/react-native/blob/v0.86.0-rc.3/packages/react-native/ReactCommon/react/renderer/uimanager/UIManager.cpp#L339
|
|
72
|
+
RootShadowNode::Shared root;
|
|
73
|
+
{
|
|
74
|
+
const std::lock_guard<std::mutex> lock{lastMountedRootMutex_};
|
|
75
|
+
const auto it = lastMountedRootBySurface_.find(shadowNode->getSurfaceId());
|
|
76
|
+
if (it == lastMountedRootBySurface_.end()) {
|
|
77
|
+
return shadowNode;
|
|
78
|
+
}
|
|
79
|
+
root = it->second;
|
|
72
80
|
}
|
|
73
81
|
|
|
74
|
-
|
|
75
|
-
|
|
82
|
+
if (ShadowNode::sameFamily(*root, *shadowNode)) {
|
|
83
|
+
return root;
|
|
84
|
+
}
|
|
76
85
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
86
|
+
const auto ancestors = shadowNode->getFamily().getAncestors(*root);
|
|
87
|
+
if (ancestors.empty()) {
|
|
88
|
+
return shadowNode;
|
|
89
|
+
}
|
|
80
90
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
auto newestCloneOfShadowNode = uiManager_->getNewestCloneOfShadowNode(*shadowNode);
|
|
91
|
+
const auto &deepest = ancestors.back();
|
|
92
|
+
return deepest.first.get().getChildren().at(deepest.second);
|
|
93
|
+
}
|
|
85
94
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
95
|
+
std::shared_ptr<const ShadowNode> ViewStylesRepository::getParentNode(
|
|
96
|
+
const std::shared_ptr<const ShadowNode> &shadowNode) const {
|
|
97
|
+
RootShadowNode::Shared root;
|
|
98
|
+
{
|
|
99
|
+
const std::lock_guard<std::mutex> lock{lastMountedRootMutex_};
|
|
100
|
+
const auto it = lastMountedRootBySurface_.find(shadowNode->getSurfaceId());
|
|
101
|
+
if (it == lastMountedRootBySurface_.end()) {
|
|
102
|
+
return nullptr;
|
|
103
|
+
}
|
|
104
|
+
root = it->second;
|
|
90
105
|
}
|
|
106
|
+
return dom::getParentNode(root, *shadowNode);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
void ViewStylesRepository::setLastMountedRoot(const RootShadowNode::Shared &rootShadowNode) {
|
|
110
|
+
const std::lock_guard<std::mutex> lock{lastMountedRootMutex_};
|
|
111
|
+
lastMountedRootBySurface_[rootShadowNode->getSurfaceId()] = rootShadowNode;
|
|
112
|
+
}
|
|
91
113
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
114
|
+
folly::dynamic ViewStylesRepository::getStyleProp(const Tag tag, const PropertyPath &propertyPath) {
|
|
115
|
+
auto animatedValue = getPropertyValue(animatedPropsRegistry_->get(tag), propertyPath);
|
|
116
|
+
if (!animatedValue.isNull()) {
|
|
117
|
+
return animatedValue;
|
|
95
118
|
}
|
|
96
119
|
|
|
97
|
-
|
|
98
|
-
cachedNode.viewProps = std::static_pointer_cast<const ViewProps>(newestCloneOfShadowNode->getProps());
|
|
120
|
+
return getPropertyValue(staticPropsRegistry_->get(tag), propertyPath);
|
|
99
121
|
}
|
|
100
122
|
|
|
101
123
|
folly::dynamic ViewStylesRepository::getPropertyValue(const folly::dynamic &value, const PropertyPath &propertyPath) {
|
|
@@ -4,11 +4,14 @@
|
|
|
4
4
|
#include <reanimated/CSS/registries/StaticPropsRegistry.h>
|
|
5
5
|
#include <reanimated/Fabric/updates/AnimatedPropsRegistry.h>
|
|
6
6
|
|
|
7
|
+
#include <react/renderer/components/root/RootShadowNode.h>
|
|
7
8
|
#include <react/renderer/components/view/ViewProps.h>
|
|
8
9
|
#include <react/renderer/core/LayoutableShadowNode.h>
|
|
9
10
|
#include <react/renderer/dom/DOM.h>
|
|
11
|
+
#include <react/renderer/uimanager/UIManager.h>
|
|
10
12
|
|
|
11
13
|
#include <memory>
|
|
14
|
+
#include <mutex>
|
|
12
15
|
#include <string>
|
|
13
16
|
#include <unordered_map>
|
|
14
17
|
|
|
@@ -17,11 +20,6 @@ namespace reanimated::css {
|
|
|
17
20
|
using namespace facebook;
|
|
18
21
|
using namespace react;
|
|
19
22
|
|
|
20
|
-
struct CachedShadowNode {
|
|
21
|
-
LayoutMetrics layoutMetrics;
|
|
22
|
-
std::shared_ptr<const ViewProps> viewProps;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
23
|
class ViewStylesRepository {
|
|
26
24
|
public:
|
|
27
25
|
ViewStylesRepository(
|
|
@@ -36,16 +34,21 @@ class ViewStylesRepository {
|
|
|
36
34
|
jsi::Value getParentNodeProp(const std::shared_ptr<const ShadowNode> &shadowNode, const std::string &propName);
|
|
37
35
|
folly::dynamic getStyleProp(Tag tag, const PropertyPath &propertyPath);
|
|
38
36
|
|
|
39
|
-
void
|
|
37
|
+
void setLastMountedRoot(const RootShadowNode::Shared &rootShadowNode);
|
|
40
38
|
|
|
41
39
|
private:
|
|
42
40
|
std::shared_ptr<UIManager> uiManager_;
|
|
43
41
|
std::shared_ptr<StaticPropsRegistry> staticPropsRegistry_;
|
|
44
42
|
std::shared_ptr<AnimatedPropsRegistry> animatedPropsRegistry_;
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
// Transition setup resolves relative lengths on the JS thread without the
|
|
45
|
+
// updates-registry lock, while the mount hook records roots under it, so the
|
|
46
|
+
// map needs its own guard.
|
|
47
|
+
mutable std::mutex lastMountedRootMutex_;
|
|
48
|
+
std::unordered_map<SurfaceId, RootShadowNode::Shared> lastMountedRootBySurface_;
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
std::shared_ptr<const ShadowNode> getNewestNode(const std::shared_ptr<const ShadowNode> &shadowNode) const;
|
|
51
|
+
std::shared_ptr<const ShadowNode> getParentNode(const std::shared_ptr<const ShadowNode> &shadowNode) const;
|
|
49
52
|
|
|
50
53
|
static folly::dynamic getPropertyValue(const folly::dynamic &value, const PropertyPath &propertyPath);
|
|
51
54
|
};
|
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
namespace reanimated::css {
|
|
10
10
|
|
|
11
11
|
bool CSSAnimationsRegistry::isEmpty() const {
|
|
12
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
12
13
|
// The registry is empty if has no registered animations and no updates
|
|
13
14
|
// stored in the updates registry
|
|
14
|
-
return
|
|
15
|
+
return updatesRegistry_.empty() && registry_.empty();
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
bool CSSAnimationsRegistry::hasUpdates() const {
|
|
19
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
18
20
|
return !runningAnimationIndicesMap_.empty() || !delayedAnimationsManager_.empty() || !animationsToRevertMap_.empty();
|
|
19
21
|
}
|
|
20
22
|
|
|
@@ -25,11 +27,13 @@ void CSSAnimationsRegistry::apply(
|
|
|
25
27
|
const CSSAnimationsMap &newAnimations,
|
|
26
28
|
const CSSAnimationSettingsUpdatesMap &settingsUpdates,
|
|
27
29
|
double timestamp) {
|
|
30
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
31
|
+
|
|
28
32
|
auto animationsVector = buildAnimationsVector(rt, shadowNode, animationNames, newAnimations);
|
|
29
33
|
|
|
30
34
|
const auto viewTag = shadowNode->getTag();
|
|
31
35
|
if (animationsVector.empty()) {
|
|
32
|
-
|
|
36
|
+
removeTag(viewTag);
|
|
33
37
|
return;
|
|
34
38
|
}
|
|
35
39
|
|
|
@@ -56,7 +60,7 @@ void CSSAnimationsRegistry::apply(
|
|
|
56
60
|
applyViewAnimationsStyle(viewTag, timestamp);
|
|
57
61
|
}
|
|
58
62
|
|
|
59
|
-
void CSSAnimationsRegistry::
|
|
63
|
+
void CSSAnimationsRegistry::removeTag(const Tag viewTag) {
|
|
60
64
|
removeViewAnimations(viewTag);
|
|
61
65
|
removeFromUpdatesRegistry(viewTag);
|
|
62
66
|
registry_.erase(viewTag);
|
|
@@ -289,6 +293,10 @@ void CSSAnimationsRegistry::applyViewAnimationsStyle(const Tag viewTag, const do
|
|
|
289
293
|
}
|
|
290
294
|
|
|
291
295
|
setInUpdatesRegistry(shadowNode, updatedStyle);
|
|
296
|
+
|
|
297
|
+
if (shadowNode && !updatedStyle.empty()) {
|
|
298
|
+
addUpdatesToBatch(shadowNode, updatedStyle);
|
|
299
|
+
}
|
|
292
300
|
}
|
|
293
301
|
|
|
294
302
|
void CSSAnimationsRegistry::activateDelayedAnimations(const double timestamp) {
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
#include <reanimated/Fabric/updates/UpdatesRegistry.h>
|
|
8
8
|
|
|
9
9
|
#include <memory>
|
|
10
|
+
#include <mutex>
|
|
10
11
|
#include <set>
|
|
11
12
|
#include <string>
|
|
12
13
|
#include <unordered_map>
|
|
@@ -33,9 +34,12 @@ class CSSAnimationsRegistry : public UpdatesRegistry, std::enable_shared_from_th
|
|
|
33
34
|
const CSSAnimationsMap &newAnimations,
|
|
34
35
|
const CSSAnimationSettingsUpdatesMap &settingsUpdates,
|
|
35
36
|
double timestamp);
|
|
36
|
-
void remove(Tag viewTag) override;
|
|
37
37
|
|
|
38
|
-
void
|
|
38
|
+
void updateAndFlush(double timestamp, UpdatesBatch &updatesBatch) {
|
|
39
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
40
|
+
update(timestamp);
|
|
41
|
+
flush(updatesBatch);
|
|
42
|
+
}
|
|
39
43
|
|
|
40
44
|
private:
|
|
41
45
|
using AnimationToIndexMap = std::unordered_map<std::shared_ptr<CSSAnimation>, size_t>;
|
|
@@ -54,6 +58,9 @@ class CSSAnimationsRegistry : public UpdatesRegistry, std::enable_shared_from_th
|
|
|
54
58
|
AnimationsToRevertMap animationsToRevertMap_;
|
|
55
59
|
DelayedItemsManager<std::shared_ptr<CSSAnimation>> delayedAnimationsManager_;
|
|
56
60
|
|
|
61
|
+
void removeTag(Tag viewTag) override;
|
|
62
|
+
void update(double timestamp);
|
|
63
|
+
|
|
57
64
|
CSSAnimationsVector buildAnimationsVector(
|
|
58
65
|
jsi::Runtime &rt,
|
|
59
66
|
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
@@ -11,12 +11,14 @@ CSSTransitionsRegistry::CSSTransitionsRegistry(
|
|
|
11
11
|
: getCurrentTimestamp_(getCurrentTimestamp), viewStylesRepository_(viewStylesRepository) {}
|
|
12
12
|
|
|
13
13
|
bool CSSTransitionsRegistry::isEmpty() const {
|
|
14
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
14
15
|
// The registry is empty if has no registered animations and no updates
|
|
15
16
|
// stored in the updates registry
|
|
16
|
-
return
|
|
17
|
+
return updatesRegistry_.empty() && registry_.empty();
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
bool CSSTransitionsRegistry::hasUpdates() const {
|
|
21
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
20
22
|
return !runningTransitionTags_.empty() || !delayedTransitionsManager_.empty();
|
|
21
23
|
}
|
|
22
24
|
|
|
@@ -24,6 +26,8 @@ void CSSTransitionsRegistry::run(
|
|
|
24
26
|
jsi::Runtime &rt,
|
|
25
27
|
const std::shared_ptr<const ShadowNode> &shadowNode,
|
|
26
28
|
const CSSTransitionConfig &config) {
|
|
29
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
30
|
+
|
|
27
31
|
const auto viewTag = shadowNode->getTag();
|
|
28
32
|
|
|
29
33
|
if (!registry_.contains(viewTag)) {
|
|
@@ -42,7 +46,7 @@ void CSSTransitionsRegistry::run(
|
|
|
42
46
|
updateInUpdatesRegistry(transition, initialUpdate);
|
|
43
47
|
}
|
|
44
48
|
|
|
45
|
-
void CSSTransitionsRegistry::
|
|
49
|
+
void CSSTransitionsRegistry::removeTag(const Tag viewTag) {
|
|
46
50
|
removeFromUpdatesRegistry(viewTag);
|
|
47
51
|
delayedTransitionsManager_.remove(viewTag);
|
|
48
52
|
runningTransitionTags_.erase(viewTag);
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
#include <reanimated/Tools/PlatformDepMethodsHolder.h>
|
|
9
9
|
|
|
10
10
|
#include <memory>
|
|
11
|
+
#include <mutex>
|
|
11
12
|
#include <set>
|
|
12
13
|
#include <unordered_map>
|
|
13
14
|
#include <unordered_set>
|
|
@@ -26,9 +27,12 @@ class CSSTransitionsRegistry : public UpdatesRegistry, public std::enable_shared
|
|
|
26
27
|
bool hasUpdates() const;
|
|
27
28
|
|
|
28
29
|
void run(jsi::Runtime &rt, const std::shared_ptr<const ShadowNode> &shadowNode, const CSSTransitionConfig &config);
|
|
29
|
-
void remove(Tag viewTag) override;
|
|
30
30
|
|
|
31
|
-
void
|
|
31
|
+
void updateAndFlush(double timestamp, UpdatesBatch &updatesBatch) {
|
|
32
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
33
|
+
update(timestamp);
|
|
34
|
+
flush(updatesBatch);
|
|
35
|
+
}
|
|
32
36
|
|
|
33
37
|
private:
|
|
34
38
|
using Registry = std::unordered_map<Tag, std::shared_ptr<CSSTransition>>;
|
|
@@ -41,6 +45,8 @@ class CSSTransitionsRegistry : public UpdatesRegistry, public std::enable_shared
|
|
|
41
45
|
std::unordered_set<Tag> runningTransitionTags_;
|
|
42
46
|
DelayedItemsManager<Tag> delayedTransitionsManager_;
|
|
43
47
|
|
|
48
|
+
void removeTag(Tag viewTag) override;
|
|
49
|
+
void update(double timestamp);
|
|
44
50
|
void activateDelayedTransitions(double timestamp);
|
|
45
51
|
void scheduleOrActivateTransition(const std::shared_ptr<CSSTransition> &transition);
|
|
46
52
|
void updateInUpdatesRegistry(const std::shared_ptr<CSSTransition> &transition, const folly::dynamic &updates);
|
|
@@ -7,16 +7,26 @@ namespace reanimated::css {
|
|
|
7
7
|
void StaticPropsRegistry::set(jsi::Runtime &rt, const Tag viewTag, const jsi::Value &props) {
|
|
8
8
|
if (props.isNull() || props.isUndefined()) {
|
|
9
9
|
remove(viewTag);
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const auto newProps = dynamicFromValue(rt, props);
|
|
14
|
+
folly::dynamic oldProps;
|
|
15
|
+
{
|
|
16
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
17
|
+
const auto it = registry_.find(viewTag);
|
|
18
|
+
if (it != registry_.end()) {
|
|
19
|
+
oldProps = it->second;
|
|
14
20
|
}
|
|
15
21
|
registry_[viewTag] = newProps;
|
|
16
22
|
}
|
|
23
|
+
if (!oldProps.isNull()) {
|
|
24
|
+
notifyObservers(viewTag, oldProps, newProps);
|
|
25
|
+
}
|
|
17
26
|
}
|
|
18
27
|
|
|
19
28
|
folly::dynamic StaticPropsRegistry::get(const Tag viewTag) const {
|
|
29
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
20
30
|
auto it = registry_.find(viewTag);
|
|
21
31
|
if (it == registry_.end()) {
|
|
22
32
|
return nullptr;
|
|
@@ -25,14 +35,17 @@ folly::dynamic StaticPropsRegistry::get(const Tag viewTag) const {
|
|
|
25
35
|
}
|
|
26
36
|
|
|
27
37
|
bool StaticPropsRegistry::has(const Tag viewTag) const {
|
|
38
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
28
39
|
return registry_.find(viewTag) != registry_.end();
|
|
29
40
|
}
|
|
30
41
|
|
|
31
42
|
void StaticPropsRegistry::remove(const Tag viewTag) {
|
|
43
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
32
44
|
registry_.erase(viewTag);
|
|
33
45
|
}
|
|
34
46
|
|
|
35
47
|
bool StaticPropsRegistry::isEmpty() const {
|
|
48
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
36
49
|
return registry_.empty() && observers_.empty();
|
|
37
50
|
}
|
|
38
51
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
#include <react/renderer/core/ShadowNode.h>
|
|
4
4
|
|
|
5
|
+
#include <mutex>
|
|
5
6
|
#include <unordered_map>
|
|
6
7
|
|
|
7
8
|
namespace reanimated::css {
|
|
@@ -24,6 +25,10 @@ class StaticPropsRegistry {
|
|
|
24
25
|
void removeObserver(Tag viewTag);
|
|
25
26
|
|
|
26
27
|
private:
|
|
28
|
+
/// registry_ is written on the JS thread (setViewStyle) and read on the UI
|
|
29
|
+
/// thread during interpolation and on the commit/mount thread during node
|
|
30
|
+
/// removals, so it needs its own guard. observers_ is JS-thread-only.
|
|
31
|
+
mutable std::mutex mutex_;
|
|
27
32
|
std::unordered_map<Tag, folly::dynamic> registry_;
|
|
28
33
|
std::unordered_map<Tag, PropsObserver> observers_;
|
|
29
34
|
|
|
@@ -43,6 +43,11 @@ bool SVGStrokeDashArray::canConstruct(const folly::dynamic &value) {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
folly::dynamic SVGStrokeDashArray::toDynamic() const {
|
|
46
|
+
// Empty means "no dashing" - emit null instead of [], which react-native-svg
|
|
47
|
+
// would feed to Android's DashPathEffect that requires at least 2 intervals.
|
|
48
|
+
if (values.empty()) {
|
|
49
|
+
return nullptr;
|
|
50
|
+
}
|
|
46
51
|
folly::dynamic array = folly::dynamic::array;
|
|
47
52
|
array.reserve(values.size());
|
|
48
53
|
for (const auto &value : values) {
|
|
@@ -9,8 +9,12 @@ namespace reanimated {
|
|
|
9
9
|
ReanimatedMountHook::ReanimatedMountHook(
|
|
10
10
|
const std::shared_ptr<UIManager> &uiManager,
|
|
11
11
|
const std::shared_ptr<UpdatesRegistryManager> &updatesRegistryManager,
|
|
12
|
+
const std::shared_ptr<css::ViewStylesRepository> &viewStylesRepository,
|
|
12
13
|
const std::function<void()> &requestFlush)
|
|
13
|
-
: uiManager_(uiManager),
|
|
14
|
+
: uiManager_(uiManager),
|
|
15
|
+
updatesRegistryManager_(updatesRegistryManager),
|
|
16
|
+
viewStylesRepository_(viewStylesRepository),
|
|
17
|
+
requestFlush_(requestFlush) {
|
|
14
18
|
uiManager_->registerMountHook(*this);
|
|
15
19
|
}
|
|
16
20
|
|
|
@@ -26,24 +30,33 @@ void ReanimatedMountHook::shadowTreeDidMount(
|
|
|
26
30
|
auto reaShadowNode = std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(
|
|
27
31
|
std::const_pointer_cast<RootShadowNode>(rootShadowNode));
|
|
28
32
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
33
|
+
// We mark reanimated commits with ReanimatedMountTrait. We don't want other
|
|
34
|
+
// shadow nodes to use this trait, but since this rootShadowNode is Shared,
|
|
35
|
+
// we don't have that guarantee. That's why we also unset this trait in the
|
|
36
|
+
// commit hook. We remove it here mainly for the sake of cleanliness.
|
|
37
|
+
const bool isReanimatedMount = reaShadowNode->hasReanimatedMountTrait();
|
|
38
|
+
if (isReanimatedMount) {
|
|
34
39
|
reaShadowNode->unsetReanimatedMountTrait();
|
|
35
|
-
return;
|
|
36
40
|
}
|
|
37
41
|
|
|
38
42
|
{
|
|
39
43
|
auto lock = updatesRegistryManager_->lock();
|
|
44
|
+
// Record the mounted tree for relative-length resolution.
|
|
45
|
+
viewStylesRepository_->setLastMountedRoot(rootShadowNode);
|
|
46
|
+
|
|
47
|
+
// Always drain removable nodes, even on Reanimated's own commits. While CSS
|
|
48
|
+
// animations run every mount carries the mount trait, so returning early here
|
|
49
|
+
// would skip removals for the whole animation and leak unmounted nodes if the
|
|
50
|
+
// tree is torn down mid-animation.
|
|
40
51
|
updatesRegistryManager_->handleNodeRemovals(*rootShadowNode);
|
|
41
52
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
53
|
+
if (!isReanimatedMount) {
|
|
54
|
+
// When a commit from React Native has finished, we reset the skip commit
|
|
55
|
+
// flag in order to allow Reanimated to commit its tree.
|
|
56
|
+
updatesRegistryManager_->unpauseReanimatedCommits();
|
|
57
|
+
if (updatesRegistryManager_->shouldCommitAfterPause()) {
|
|
58
|
+
requestFlush_();
|
|
59
|
+
}
|
|
47
60
|
}
|
|
48
61
|
}
|
|
49
62
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
+
#include <reanimated/CSS/misc/ViewStylesRepository.h>
|
|
3
4
|
#include <reanimated/Fabric/ShadowTreeCloner.h>
|
|
4
5
|
#include <reanimated/Fabric/updates/UpdatesRegistryManager.h>
|
|
5
6
|
|
|
@@ -16,6 +17,7 @@ class ReanimatedMountHook : public UIManagerMountHook {
|
|
|
16
17
|
ReanimatedMountHook(
|
|
17
18
|
const std::shared_ptr<UIManager> &uiManager,
|
|
18
19
|
const std::shared_ptr<UpdatesRegistryManager> &updatesRegistryManager,
|
|
20
|
+
const std::shared_ptr<css::ViewStylesRepository> &viewStylesRepository,
|
|
19
21
|
const std::function<void()> &requestFlush);
|
|
20
22
|
~ReanimatedMountHook() noexcept override;
|
|
21
23
|
|
|
@@ -24,6 +26,7 @@ class ReanimatedMountHook : public UIManagerMountHook {
|
|
|
24
26
|
private:
|
|
25
27
|
const std::shared_ptr<UIManager> uiManager_;
|
|
26
28
|
const std::shared_ptr<UpdatesRegistryManager> updatesRegistryManager_;
|
|
29
|
+
const std::shared_ptr<css::ViewStylesRepository> viewStylesRepository_;
|
|
27
30
|
const std::function<void()> requestFlush_;
|
|
28
31
|
};
|
|
29
32
|
|
|
@@ -15,6 +15,7 @@ static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
|
|
|
15
15
|
void AnimatedPropsRegistry::update(jsi::Runtime &rt, const jsi::Value &operations, const double timestamp) {
|
|
16
16
|
auto operationsArray = operations.asObject(rt).asArray(rt);
|
|
17
17
|
|
|
18
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
18
19
|
for (size_t i = 0, length = operationsArray.size(rt); i < length; ++i) {
|
|
19
20
|
auto item = operationsArray.getValueAtIndex(rt, i).asObject(rt);
|
|
20
21
|
auto shadowNodeWrapper = item.getProperty(rt, "shadowNodeWrapper");
|
|
@@ -29,12 +30,13 @@ void AnimatedPropsRegistry::update(jsi::Runtime &rt, const jsi::Value &operation
|
|
|
29
30
|
}
|
|
30
31
|
}
|
|
31
32
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
jsi::Value AnimatedPropsRegistry::getUpdatesOlderThanTimestamp(
|
|
34
|
+
jsi::Runtime &rt,
|
|
35
|
+
const double timestamp,
|
|
36
|
+
const double cleanupTimestamp) {
|
|
37
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
38
|
+
removeUpdatesOlderThanTimestamp(cleanupTimestamp);
|
|
36
39
|
|
|
37
|
-
jsi::Value AnimatedPropsRegistry::getUpdatesOlderThanTimestamp(jsi::Runtime &rt, const double timestamp) {
|
|
38
40
|
std::vector<std::pair<Tag, std::reference_wrapper<const folly::dynamic>>> updates;
|
|
39
41
|
|
|
40
42
|
for (const auto &[viewTag, pair] : updatesRegistry_) {
|
|
@@ -69,4 +71,9 @@ void AnimatedPropsRegistry::removeUpdatesOlderThanTimestamp(const double timesta
|
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
|
|
74
|
+
void AnimatedPropsRegistry::removeTag(const Tag tag) {
|
|
75
|
+
updatesRegistry_.erase(tag);
|
|
76
|
+
timestampMap_.erase(tag);
|
|
77
|
+
}
|
|
78
|
+
|
|
72
79
|
} // namespace reanimated
|
|
@@ -14,12 +14,15 @@ namespace reanimated {
|
|
|
14
14
|
class AnimatedPropsRegistry : public UpdatesRegistry {
|
|
15
15
|
public:
|
|
16
16
|
void update(jsi::Runtime &rt, const jsi::Value &operations, double timestamp);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
|
|
18
|
+
/// Also removes updates older than `cleanupTimestamp` from the registry.
|
|
19
|
+
jsi::Value getUpdatesOlderThanTimestamp(jsi::Runtime &rt, double timestamp, double cleanupTimestamp);
|
|
20
20
|
|
|
21
21
|
private:
|
|
22
22
|
std::unordered_map<Tag, double> timestampMap_; // viewTag -> timestamp, protected by `mutex_`
|
|
23
|
+
|
|
24
|
+
void removeUpdatesOlderThanTimestamp(double timestamp);
|
|
25
|
+
void removeTag(Tag tag) override;
|
|
23
26
|
};
|
|
24
27
|
|
|
25
28
|
} // namespace reanimated
|
|
@@ -8,11 +8,8 @@
|
|
|
8
8
|
|
|
9
9
|
namespace reanimated {
|
|
10
10
|
|
|
11
|
-
std::lock_guard<std::mutex> UpdatesRegistry::lock() const {
|
|
12
|
-
return std::lock_guard<std::mutex>{mutex_};
|
|
13
|
-
}
|
|
14
|
-
|
|
15
11
|
bool UpdatesRegistry::isEmpty() const {
|
|
12
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
16
13
|
return updatesRegistry_.empty();
|
|
17
14
|
}
|
|
18
15
|
|
|
@@ -26,7 +23,7 @@ folly::dynamic UpdatesRegistry::get(const Tag tag) const {
|
|
|
26
23
|
return it->second.second;
|
|
27
24
|
}
|
|
28
25
|
|
|
29
|
-
void UpdatesRegistry::
|
|
26
|
+
void UpdatesRegistry::flush(UpdatesBatch &updatesBatch) {
|
|
30
27
|
auto copiedUpdatesBatch = std::move(updatesBatch_);
|
|
31
28
|
updatesBatch_.clear();
|
|
32
29
|
|
|
@@ -39,7 +36,7 @@ void UpdatesRegistry::flushUpdates(UpdatesBatch &updatesBatch) {
|
|
|
39
36
|
}
|
|
40
37
|
|
|
41
38
|
UpdatesBatch UpdatesRegistry::getPendingUpdates() {
|
|
42
|
-
|
|
39
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
43
40
|
flushUpdatesToRegistry(updatesBatch_);
|
|
44
41
|
|
|
45
42
|
UpdatesBatch updatesBatch;
|
|
@@ -116,6 +113,7 @@ void UpdatesRegistry::flushUpdatesToRegistry(const UpdatesBatch &updatesBatch) {
|
|
|
116
113
|
#ifdef ANDROID
|
|
117
114
|
|
|
118
115
|
bool UpdatesRegistry::hasPropsToRevert() const {
|
|
116
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
119
117
|
return !propsToRevertMap_.empty();
|
|
120
118
|
}
|
|
121
119
|
|