react-native-reanimated 3.18.0 → 3.18.1

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.
Files changed (73) hide show
  1. package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +14 -2
  2. package/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +6 -1
  3. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +6 -1
  4. package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +6 -1
  5. package/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp +3 -2
  6. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +69 -21
  7. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h +29 -4
  8. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +4 -5
  9. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +57 -25
  10. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +4 -1
  11. package/README.md +1 -13
  12. package/RNReanimated.podspec +1 -1
  13. package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +16 -17
  14. package/android/src/main/cpp/reanimated/android/NativeProxy.h +3 -3
  15. package/lib/module/PlatformChecker.js +6 -0
  16. package/lib/module/PlatformChecker.js.map +1 -1
  17. package/lib/module/animation/util.js +7 -4
  18. package/lib/module/animation/util.js.map +1 -1
  19. package/lib/module/component/FlatList.js +9 -3
  20. package/lib/module/component/FlatList.js.map +1 -1
  21. package/lib/module/core.js +0 -2
  22. package/lib/module/core.js.map +1 -1
  23. package/lib/module/createAnimatedComponent/NativeEventsManager.js +1 -1
  24. package/lib/module/createAnimatedComponent/NativeEventsManager.js.map +1 -1
  25. package/lib/module/createAnimatedComponent/createAnimatedComponent.js +24 -37
  26. package/lib/module/createAnimatedComponent/createAnimatedComponent.js.map +1 -1
  27. package/lib/module/hook/useAnimatedRef.js +70 -35
  28. package/lib/module/hook/useAnimatedRef.js.map +1 -1
  29. package/lib/module/hook/useHandler.js +7 -0
  30. package/lib/module/hook/useHandler.js.map +1 -1
  31. package/lib/module/hook/useScrollViewOffset.js +28 -26
  32. package/lib/module/hook/useScrollViewOffset.js.map +1 -1
  33. package/lib/module/hook/utils.js +20 -9
  34. package/lib/module/hook/utils.js.map +1 -1
  35. package/lib/module/index.js +3 -0
  36. package/lib/module/index.js.map +1 -1
  37. package/lib/module/platform-specific/jsVersion.js +1 -1
  38. package/lib/module/platformFunctions/setNativeProps.js +1 -1
  39. package/lib/module/platformFunctions/setNativeProps.js.map +1 -1
  40. package/lib/typescript/PlatformChecker.d.ts +2 -0
  41. package/lib/typescript/PlatformChecker.d.ts.map +1 -1
  42. package/lib/typescript/animation/util.d.ts.map +1 -1
  43. package/lib/typescript/component/FlatList.d.ts +10 -2
  44. package/lib/typescript/component/FlatList.d.ts.map +1 -1
  45. package/lib/typescript/core.d.ts.map +1 -1
  46. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts +1 -0
  47. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts.map +1 -1
  48. package/lib/typescript/createAnimatedComponent/createAnimatedComponent.d.ts.map +1 -1
  49. package/lib/typescript/hook/commonTypes.d.ts +7 -4
  50. package/lib/typescript/hook/commonTypes.d.ts.map +1 -1
  51. package/lib/typescript/hook/useAnimatedRef.d.ts +3 -1
  52. package/lib/typescript/hook/useAnimatedRef.d.ts.map +1 -1
  53. package/lib/typescript/hook/useHandler.d.ts.map +1 -1
  54. package/lib/typescript/hook/useScrollViewOffset.d.ts.map +1 -1
  55. package/lib/typescript/hook/utils.d.ts.map +1 -1
  56. package/lib/typescript/index.d.ts.map +1 -1
  57. package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
  58. package/package.json +1 -1
  59. package/src/PlatformChecker.ts +8 -0
  60. package/src/animation/util.ts +7 -4
  61. package/src/component/FlatList.tsx +44 -6
  62. package/src/core.ts +0 -3
  63. package/src/createAnimatedComponent/NativeEventsManager.ts +1 -1
  64. package/src/createAnimatedComponent/commonTypes.ts +9 -0
  65. package/src/createAnimatedComponent/createAnimatedComponent.tsx +61 -73
  66. package/src/hook/commonTypes.ts +9 -4
  67. package/src/hook/useAnimatedRef.ts +107 -48
  68. package/src/hook/useHandler.ts +10 -0
  69. package/src/hook/useScrollViewOffset.ts +34 -29
  70. package/src/hook/utils.ts +34 -9
  71. package/src/index.ts +4 -0
  72. package/src/platform-specific/jsVersion.ts +1 -1
  73. package/src/platformFunctions/setNativeProps.ts +1 -1
@@ -52,7 +52,12 @@ void ReanimatedCommitHook::maybeInitializeLayoutAnimations(
52
52
  RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
53
53
  ShadowTree const &,
54
54
  RootShadowNode::Shared const &,
55
- RootShadowNode::Unshared const &newRootShadowNode) noexcept {
55
+ RootShadowNode::Unshared const &newRootShadowNode
56
+ #if REACT_NATIVE_MINOR_VERSION >= 80
57
+ ,
58
+ const ShadowTreeCommitOptions &commitOptions
59
+ #endif
60
+ ) noexcept {
56
61
  maybeInitializeLayoutAnimations(newRootShadowNode->getSurfaceId());
57
62
 
58
63
  auto reaShadowNode =
@@ -89,8 +94,15 @@ RootShadowNode::Unshared ReanimatedCommitHook::shadowTreeWillCommit(
89
94
  // PropsRegistry.
90
95
  // This is very important, since if we didn't pause Reanimated commits,
91
96
  // it could lead to RN commits being delayed until the animation is finished
92
- // (very bad).
97
+ // (very bad). We don't pause Reanimated commits for state updates coming
98
+ // from React Native as this would break sticky header animations.
99
+ #if REACT_NATIVE_MINOR_VERSION >= 80
100
+ if (commitOptions.source == ShadowTreeCommitSource::React) {
101
+ propsRegistry_->pauseReanimatedCommits();
102
+ }
103
+ #else
93
104
  propsRegistry_->pauseReanimatedCommits();
105
+ #endif
94
106
  }
95
107
 
96
108
  return rootNode;
@@ -32,7 +32,12 @@ class ReanimatedCommitHook
32
32
  RootShadowNode::Unshared shadowTreeWillCommit(
33
33
  ShadowTree const &shadowTree,
34
34
  RootShadowNode::Shared const &oldRootShadowNode,
35
- RootShadowNode::Unshared const &newRootShadowNode) noexcept override;
35
+ RootShadowNode::Unshared const &newRootShadowNode
36
+ #if REACT_NATIVE_MINOR_VERSION >= 80
37
+ ,
38
+ const ShadowTreeCommitOptions &commitOptions
39
+ #endif
40
+ ) noexcept override;
36
41
 
37
42
  private:
38
43
  std::shared_ptr<PropsRegistry> propsRegistry_;
@@ -18,7 +18,12 @@ ReanimatedMountHook::~ReanimatedMountHook() noexcept {
18
18
 
19
19
  void ReanimatedMountHook::shadowTreeDidMount(
20
20
  const RootShadowNode::Shared &rootShadowNode,
21
- double) noexcept {
21
+ #if REACT_NATIVE_MINOR_VERSION >= 81
22
+ HighResTimeStamp
23
+ #else
24
+ double
25
+ #endif // REACT_NATIVE_MINOR_VERSION >= 81
26
+ ) noexcept {
22
27
  auto reaShadowNode =
23
28
  std::reinterpret_pointer_cast<ReanimatedCommitShadowNode>(
24
29
  std::const_pointer_cast<RootShadowNode>(rootShadowNode));
@@ -21,7 +21,12 @@ class ReanimatedMountHook : public UIManagerMountHook {
21
21
 
22
22
  void shadowTreeDidMount(
23
23
  RootShadowNode::Shared const &rootShadowNode,
24
- double mountTime) noexcept override;
24
+ #if REACT_NATIVE_MINOR_VERSION >= 81
25
+ HighResTimeStamp /*unmountTime*/
26
+ #else
27
+ double /*unmountTime*/
28
+ #endif // REACT_NATIVE_MINOR_VERSION >= 81
29
+ ) noexcept override;
25
30
 
26
31
  private:
27
32
  const std::shared_ptr<PropsRegistry> propsRegistry_;
@@ -42,7 +42,7 @@ Props::Shared mergeProps(
42
42
  return newProps;
43
43
  }
44
44
 
45
- ShadowNode::Unshared cloneShadowTreeWithNewPropsRecursive(
45
+ std::shared_ptr<ShadowNode> cloneShadowTreeWithNewPropsRecursive(
46
46
  const ShadowNode &shadowNode,
47
47
  const ChildrenMap &childrenMap,
48
48
  const PropsMap &propsMap) {
@@ -59,7 +59,8 @@ ShadowNode::Unshared cloneShadowTreeWithNewPropsRecursive(
59
59
 
60
60
  return shadowNode.clone(
61
61
  {mergeProps(shadowNode, propsMap, *family),
62
- std::make_shared<ShadowNode::ListOfShared>(children),
62
+ std::make_shared<std::vector<std::shared_ptr<const ShadowNode>>>(
63
+ children),
63
64
  shadowNode.getState()});
64
65
  }
65
66
 
@@ -31,13 +31,25 @@ std::optional<MountingTransaction> LayoutAnimationsProxy::pullTransaction(
31
31
  auto lock = std::unique_lock<std::recursive_mutex>(mutex);
32
32
  PropsParserContext propsParserContext{surfaceId, *contextContainer_};
33
33
  ShadowViewMutationList filteredMutations;
34
+ auto &[deadNodes] = surfaceContext_[surfaceId];
34
35
 
35
36
  std::vector<std::shared_ptr<MutationNode>> roots;
36
- std::unordered_map<Tag, ShadowView> movedViews;
37
+ std::unordered_map<Tag, Tag> movedViews;
38
+
39
+ addOngoingAnimations(surfaceId, filteredMutations);
40
+
41
+ for (const auto tag : finishedAnimationTags_) {
42
+ auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
43
+ layoutAnimations_.erase(tag);
44
+ updateMap.erase(tag);
45
+ }
46
+ finishedAnimationTags_.clear();
37
47
 
38
48
  parseRemoveMutations(movedViews, mutations, roots);
39
49
 
40
- handleRemovals(filteredMutations, roots);
50
+ auto shouldAnimate = !surfacesToRemove_.contains(surfaceId);
51
+ surfacesToRemove_.erase(surfaceId);
52
+ handleRemovals(filteredMutations, roots, deadNodes, shouldAnimate);
41
53
 
42
54
  handleUpdatesAndEnterings(
43
55
  filteredMutations, movedViews, mutations, propsParserContext, surfaceId);
@@ -70,7 +82,7 @@ std::optional<SurfaceId> LayoutAnimationsProxy::progressLayoutAnimation(
70
82
 
71
83
  PropsParserContext propsParserContext{
72
84
  layoutAnimation.finalView->surfaceId, *contextContainer_};
73
- #ifdef ANDROID
85
+ #ifdef RN_SERIALIZABLE_STATE
74
86
  rawProps = std::make_shared<RawProps>(folly::dynamic::merge(
75
87
  layoutAnimation.finalView->props->rawProps, (folly::dynamic)*rawProps));
76
88
  #endif
@@ -112,11 +124,8 @@ std::optional<SurfaceId> LayoutAnimationsProxy::endLayoutAnimation(
112
124
  layoutAnimation.count--;
113
125
  return {};
114
126
  }
115
-
127
+ finishedAnimationTags_.push_back(tag);
116
128
  auto surfaceId = layoutAnimation.finalView->surfaceId;
117
- auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
118
- layoutAnimations_.erase(tag);
119
- updateMap.erase(tag);
120
129
 
121
130
  if (!shouldRemove || !nodeForTag_.contains(tag)) {
122
131
  return {};
@@ -125,6 +134,7 @@ std::optional<SurfaceId> LayoutAnimationsProxy::endLayoutAnimation(
125
134
  auto node = nodeForTag_[tag];
126
135
  auto mutationNode = std::static_pointer_cast<MutationNode>(node);
127
136
  mutationNode->state = DEAD;
137
+ auto &[deadNodes] = surfaceContext_[surfaceId];
128
138
  deadNodes.insert(mutationNode);
129
139
 
130
140
  return surfaceId;
@@ -135,7 +145,7 @@ std::optional<SurfaceId> LayoutAnimationsProxy::endLayoutAnimation(
135
145
  traversals and index maintenance
136
146
  */
137
147
  void LayoutAnimationsProxy::parseRemoveMutations(
138
- std::unordered_map<Tag, ShadowView> &movedViews,
148
+ std::unordered_map<Tag, Tag> &movedViews,
139
149
  ShadowViewMutationList &mutations,
140
150
  std::vector<std::shared_ptr<MutationNode>> &roots) const {
141
151
  std::set<Tag> deletedViews;
@@ -180,8 +190,7 @@ void LayoutAnimationsProxy::parseRemoveMutations(
180
190
  }
181
191
  if (!deletedViews.contains(mutation.oldChildShadowView.tag)) {
182
192
  mutationNode->state = MOVED;
183
- movedViews.insert_or_assign(
184
- mutation.oldChildShadowView.tag, mutation.oldChildShadowView);
193
+ movedViews.insert_or_assign(mutation.oldChildShadowView.tag, -1);
185
194
  }
186
195
  nodeForTag_[tag] = mutationNode;
187
196
 
@@ -211,7 +220,13 @@ void LayoutAnimationsProxy::parseRemoveMutations(
211
220
  auto node = nodeForTag_[mutation.newChildShadowView.tag];
212
221
  auto mutationNode = std::static_pointer_cast<MutationNode>(node);
213
222
  mutationNode->mutation.oldChildShadowView = mutation.oldChildShadowView;
214
- movedViews[mutation.newChildShadowView.tag] = mutation.oldChildShadowView;
223
+ }
224
+ }
225
+
226
+ for (const auto &mutation : mutations) {
227
+ if (mutation.type == ShadowViewMutation::Insert &&
228
+ movedViews.contains(mutation.newChildShadowView.tag)) {
229
+ movedViews[mutation.newChildShadowView.tag] = mutation.parentTag;
215
230
  }
216
231
  }
217
232
 
@@ -239,13 +254,15 @@ void LayoutAnimationsProxy::parseRemoveMutations(
239
254
 
240
255
  void LayoutAnimationsProxy::handleRemovals(
241
256
  ShadowViewMutationList &filteredMutations,
242
- std::vector<std::shared_ptr<MutationNode>> &roots) const {
257
+ std::vector<std::shared_ptr<MutationNode>> &roots,
258
+ std::unordered_set<std::shared_ptr<MutationNode>> &deadNodes,
259
+ bool shouldAnimate) const {
243
260
  // iterate from the end, so that children
244
261
  // with higher indices appear first in the mutations list
245
262
  for (auto it = roots.rbegin(); it != roots.rend(); it++) {
246
263
  auto &node = *it;
247
264
  if (!startAnimationsRecursively(
248
- node, true, true, false, filteredMutations)) {
265
+ node, true, shouldAnimate, false, filteredMutations)) {
249
266
  filteredMutations.push_back(node->mutation);
250
267
  node->unflattenedParent->removeChildFromUnflattenedTree(node); //???
251
268
  if (node->state != MOVED) {
@@ -253,6 +270,7 @@ void LayoutAnimationsProxy::handleRemovals(
253
270
  filteredMutations.push_back(ShadowViewMutation::DeleteMutation(
254
271
  node->mutation.oldChildShadowView));
255
272
  nodeForTag_.erase(node->tag);
273
+ node->state = DELETED;
256
274
  #ifdef LAYOUT_ANIMATIONS_LOGS
257
275
  LOG(INFO) << "delete " << node->tag << std::endl;
258
276
  #endif
@@ -271,7 +289,7 @@ void LayoutAnimationsProxy::handleRemovals(
271
289
 
272
290
  void LayoutAnimationsProxy::handleUpdatesAndEnterings(
273
291
  ShadowViewMutationList &filteredMutations,
274
- const std::unordered_map<Tag, ShadowView> &movedViews,
292
+ const std::unordered_map<Tag, Tag> &movedViews,
275
293
  ShadowViewMutationList &mutations,
276
294
  const PropsParserContext &propsParserContext,
277
295
  SurfaceId surfaceId) const {
@@ -320,6 +338,9 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
320
338
  auto oldView = *layoutAnimationIt->second.currentView;
321
339
  filteredMutations.push_back(ShadowViewMutation::InsertMutation(
322
340
  mutationParent, oldView, mutation.index));
341
+ if (movedViews.contains(tag)) {
342
+ layoutAnimationIt->second.parentTag = movedViews.at(tag);
343
+ }
323
344
  continue;
324
345
  }
325
346
 
@@ -364,7 +385,12 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
364
385
  // store the oldChildShadowView, so that we can use this ShadowView when
365
386
  // the view is inserted
366
387
  oldShadowViewsForReparentings[tag] = mutation.oldChildShadowView;
367
- startLayoutAnimation(tag, mutation);
388
+ if (movedViews.contains(tag)) {
389
+ mutation.parentTag = movedViews.at(tag);
390
+ }
391
+ if (mutation.parentTag != -1) {
392
+ startLayoutAnimation(tag, mutation);
393
+ }
368
394
  break;
369
395
  }
370
396
 
@@ -449,6 +475,7 @@ void LayoutAnimationsProxy::maybeDropAncestors(
449
475
  nodeForTag_.erase(node->tag);
450
476
  cleanupMutations.push_back(node->mutation);
451
477
  maybeCancelAnimation(node->tag);
478
+ node->state = DELETED;
452
479
  #ifdef LAYOUT_ANIMATIONS_LOGS
453
480
  LOG(INFO) << "delete " << node->tag << std::endl;
454
481
  #endif
@@ -483,7 +510,8 @@ bool LayoutAnimationsProxy::startAnimationsRecursively(
483
510
  bool hasAnimatedChildren = false;
484
511
 
485
512
  shouldRemoveSubviewsWithoutAnimations =
486
- shouldRemoveSubviewsWithoutAnimations && !hasExitAnimation;
513
+ shouldRemoveSubviewsWithoutAnimations &&
514
+ (!hasExitAnimation || node->state == MOVED);
487
515
  std::vector<std::shared_ptr<MutationNode>> toBeRemoved;
488
516
 
489
517
  // iterate from the end, so that children
@@ -669,15 +697,16 @@ void LayoutAnimationsProxy::startEnteringAnimation(
669
697
  auto &mutex = strongThis->mutex;
670
698
  auto lock = std::unique_lock<std::recursive_mutex>(mutex);
671
699
  strongThis->layoutAnimations_.insert_or_assign(
672
- tag, LayoutAnimation {
673
- finalView, current,
700
+ tag,
701
+ LayoutAnimation{
702
+ finalView,
703
+ current,
674
704
  #if REACT_NATIVE_MINOR_VERSION >= 78
675
- mutation.parentTag,
705
+ mutation.parentTag,
676
706
  #else
677
707
  parent,
678
708
  #endif // REACT_NATIVE_MINOR_VERSION >= 78
679
- opacity
680
- });
709
+ opacity});
681
710
  window = strongThis->surfaceManager.getWindow(
682
711
  mutation.newChildShadowView.surfaceId);
683
712
  }
@@ -865,6 +894,25 @@ void LayoutAnimationsProxy::maybeUpdateWindowDimensions(
865
894
  }
866
895
  }
867
896
 
897
+ // UIManagerAnimationDelegate
898
+
899
+ void LayoutAnimationsProxy::uiManagerDidConfigureNextLayoutAnimation(
900
+ jsi::Runtime &runtime,
901
+ const RawValue &config,
902
+ const jsi::Value &successCallbackValue,
903
+ const jsi::Value &failureCallbackValue) const {}
904
+
905
+ void LayoutAnimationsProxy::setComponentDescriptorRegistry(
906
+ const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {}
907
+
908
+ bool LayoutAnimationsProxy::shouldAnimateFrame() const {
909
+ return false;
910
+ }
911
+
912
+ void LayoutAnimationsProxy::stopSurface(SurfaceId surfaceId) {
913
+ surfacesToRemove_.insert(surfaceId);
914
+ }
915
+
868
916
  } // namespace reanimated
869
917
 
870
918
  #endif // RCT_NEW_ARCH_ENABLED
@@ -10,6 +10,7 @@
10
10
  #include <react/renderer/componentregistry/ComponentDescriptorFactory.h>
11
11
  #include <react/renderer/mounting/MountingOverrideDelegate.h>
12
12
  #include <react/renderer/mounting/ShadowView.h>
13
+ #include <react/renderer/uimanager/UIManagerAnimationDelegate.h>
13
14
 
14
15
  #include <memory>
15
16
  #include <string>
@@ -35,15 +36,22 @@ struct LayoutAnimation {
35
36
  LayoutAnimation &operator=(const LayoutAnimation &other) = default;
36
37
  };
37
38
 
39
+ struct SurfaceContext {
40
+ mutable std::unordered_set<std::shared_ptr<MutationNode>> deadNodes;
41
+ };
42
+
38
43
  struct LayoutAnimationsProxy
39
44
  : public MountingOverrideDelegate,
45
+ public UIManagerAnimationDelegate,
40
46
  public std::enable_shared_from_this<LayoutAnimationsProxy> {
41
47
  mutable std::unordered_map<Tag, std::shared_ptr<Node>> nodeForTag_;
42
48
  mutable std::unordered_map<Tag, LayoutAnimation> layoutAnimations_;
43
49
  mutable std::recursive_mutex mutex;
44
50
  mutable SurfaceManager surfaceManager;
45
- mutable std::unordered_set<std::shared_ptr<MutationNode>> deadNodes;
51
+ mutable std::unordered_map<SurfaceId, SurfaceContext> surfaceContext_;
46
52
  mutable std::unordered_map<Tag, int> leastRemoved;
53
+ mutable std::unordered_set<SurfaceId> surfacesToRemove_;
54
+ mutable std::vector<Tag> finishedAnimationTags_;
47
55
  std::shared_ptr<LayoutAnimationsManager> layoutAnimationsManager_;
48
56
  ContextContainer::Shared contextContainer_;
49
57
  SharedComponentDescriptorRegistry componentDescriptorRegistry_;
@@ -76,16 +84,18 @@ struct LayoutAnimationsProxy
76
84
  void maybeCancelAnimation(const int tag) const;
77
85
 
78
86
  void parseRemoveMutations(
79
- std::unordered_map<Tag, ShadowView> &movedViews,
87
+ std::unordered_map<Tag, Tag> &movedViews,
80
88
  ShadowViewMutationList &mutations,
81
89
  std::vector<std::shared_ptr<MutationNode>> &roots) const;
82
90
  void handleRemovals(
83
91
  ShadowViewMutationList &filteredMutations,
84
- std::vector<std::shared_ptr<MutationNode>> &roots) const;
92
+ std::vector<std::shared_ptr<MutationNode>> &roots,
93
+ std::unordered_set<std::shared_ptr<MutationNode>> &deadNodes,
94
+ bool shouldAnimate) const;
85
95
 
86
96
  void handleUpdatesAndEnterings(
87
97
  ShadowViewMutationList &filteredMutations,
88
- const std::unordered_map<Tag, ShadowView> &movedViews,
98
+ const std::unordered_map<Tag, Tag> &movedViews,
89
99
  ShadowViewMutationList &mutations,
90
100
  const PropsParserContext &propsParserContext,
91
101
  SurfaceId surfaceId) const;
@@ -140,6 +150,21 @@ struct LayoutAnimationsProxy
140
150
  MountingTransaction::Number number,
141
151
  const TransactionTelemetry &telemetry,
142
152
  ShadowViewMutationList mutations) const override;
153
+
154
+ // UIManagerAnimationDelegate
155
+
156
+ void uiManagerDidConfigureNextLayoutAnimation(
157
+ jsi::Runtime &runtime,
158
+ const RawValue &config,
159
+ const jsi::Value &successCallbackValue,
160
+ const jsi::Value &failureCallbackValue) const override;
161
+
162
+ void setComponentDescriptorRegistry(const SharedComponentDescriptorRegistry &
163
+ componentDescriptorRegistry) override;
164
+
165
+ bool shouldAnimateFrame() const override;
166
+
167
+ void stopSurface(SurfaceId surfaceId) override;
143
168
  };
144
169
 
145
170
  } // namespace reanimated
@@ -136,11 +136,10 @@ static inline void updateLayoutMetrics(
136
136
  }
137
137
 
138
138
  static inline bool isRNSScreen(std::shared_ptr<MutationNode> node) {
139
- return !std::strcmp(
140
- node->mutation.oldChildShadowView.componentName,
141
- "RNSScreenStack") ||
142
- !std::strcmp(
143
- node->mutation.oldChildShadowView.componentName, "RNSScreen");
139
+ const auto &componentName = node->mutation.oldChildShadowView.componentName;
140
+ return !std::strcmp(componentName, "RNSScreenStack") ||
141
+ !std::strcmp(componentName, "RNSScreen") ||
142
+ !std::strcmp(componentName, "RNSModalScreen");
144
143
  }
145
144
 
146
145
  static inline bool hasLayoutChanged(const ShadowViewMutation &mutation) {
@@ -23,7 +23,6 @@
23
23
  #ifdef RCT_NEW_ARCH_ENABLED
24
24
  #include <react/renderer/scheduler/Scheduler.h>
25
25
  #include <react/renderer/uimanager/UIManagerBinding.h>
26
- #include <react/renderer/uimanager/primitives.h>
27
26
  #endif // RCT_NEW_ARCH_ENABLED
28
27
 
29
28
  #include <functional>
@@ -37,6 +36,15 @@
37
36
 
38
37
  namespace reanimated {
39
38
 
39
+ #if REACT_NATIVE_MINOR_VERSION >= 81
40
+ static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
41
+ jsi::Runtime &rt,
42
+ const jsi::Value &shadowNodeWrapper) {
43
+ return Bridging<std::shared_ptr<const ShadowNode>>::fromJs(
44
+ rt, shadowNodeWrapper);
45
+ }
46
+ #endif
47
+
40
48
  ReanimatedModuleProxy::ReanimatedModuleProxy(
41
49
  const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
42
50
  jsi::Runtime &rnRuntime,
@@ -49,13 +57,14 @@ ReanimatedModuleProxy::ReanimatedModuleProxy(
49
57
  isReducedMotion_(isReducedMotion),
50
58
  workletsModuleProxy_(workletsModuleProxy),
51
59
  valueUnpackerCode_(workletsModuleProxy->getValueUnpackerCode()),
52
- uiWorkletRuntime_(std::make_shared<WorkletRuntime>(
53
- rnRuntime,
54
- workletsModuleProxy->getJSQueue(),
55
- workletsModuleProxy->getJSScheduler(),
56
- "Reanimated UI runtime",
57
- true /* supportsLocking */,
58
- valueUnpackerCode_)),
60
+ uiWorkletRuntime_(
61
+ std::make_shared<WorkletRuntime>(
62
+ rnRuntime,
63
+ workletsModuleProxy->getJSQueue(),
64
+ workletsModuleProxy->getJSScheduler(),
65
+ "Reanimated UI runtime",
66
+ true /* supportsLocking */,
67
+ valueUnpackerCode_)),
59
68
  eventHandlerRegistry_(std::make_unique<EventHandlerRegistry>()),
60
69
  requestRender_(platformDepMethodsHolder.requestRender),
61
70
  animatedSensorModule_(platformDepMethodsHolder),
@@ -161,14 +170,20 @@ void ReanimatedModuleProxy::init(
161
170
  if (!surfaceId) {
162
171
  return;
163
172
  }
164
- strongThis->uiManager_->getShadowTreeRegistry().visit(
165
- *surfaceId, [](const ShadowTree &shadowTree) {
166
- shadowTree.notifyDelegatesOfUpdates();
167
- });
173
+ strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
168
174
  };
169
175
 
176
+ auto requestLayoutAnimationRender = [weakThis = weak_from_this()](double) {
177
+ auto strongThis = weakThis.lock();
178
+ if (!strongThis) {
179
+ return;
180
+ }
181
+ strongThis->layoutAnimationRenderRequested_ = false;
182
+ };
183
+
170
184
  EndLayoutAnimationFunction endLayoutAnimation =
171
- [weakThis = weak_from_this()](int tag, bool shouldRemove) {
185
+ [weakThis = weak_from_this(), requestLayoutAnimationRender](
186
+ int tag, bool shouldRemove) {
172
187
  auto strongThis = weakThis.lock();
173
188
  if (!strongThis) {
174
189
  return;
@@ -176,14 +191,19 @@ void ReanimatedModuleProxy::init(
176
191
 
177
192
  auto surfaceId = strongThis->layoutAnimationsProxy_->endLayoutAnimation(
178
193
  tag, shouldRemove);
194
+
195
+ if (!strongThis->layoutAnimationRenderRequested_) {
196
+ strongThis->layoutAnimationRenderRequested_ = true;
197
+ // if an animation has duration 0, performOperations would not get
198
+ // called for it so we call requestRender to have it called in the
199
+ // next frame
200
+ strongThis->requestRender_(requestLayoutAnimationRender);
201
+ }
202
+
179
203
  if (!surfaceId) {
180
204
  return;
181
205
  }
182
-
183
- strongThis->uiManager_->getShadowTreeRegistry().visit(
184
- *surfaceId, [](const ShadowTree &shadowTree) {
185
- shadowTree.notifyDelegatesOfUpdates();
186
- });
206
+ strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
187
207
  };
188
208
 
189
209
  auto obtainProp = [weakThis = weak_from_this()](
@@ -355,7 +375,7 @@ static inline std::string intColorToHex(const int val) {
355
375
  std::string ReanimatedModuleProxy::obtainPropFromShadowNode(
356
376
  jsi::Runtime &rt,
357
377
  const std::string &propName,
358
- const ShadowNode::Shared &shadowNode) {
378
+ const std::shared_ptr<const ShadowNode> &shadowNode) {
359
379
  auto newestCloneOfShadowNode =
360
380
  uiManager_->getNewestCloneOfShadowNode(*shadowNode);
361
381
 
@@ -390,9 +410,10 @@ std::string ReanimatedModuleProxy::obtainPropFromShadowNode(
390
410
  }
391
411
  }
392
412
 
393
- throw std::runtime_error(std::string(
394
- "Getting property `" + propName +
395
- "` with function `getViewProp` is not supported"));
413
+ throw std::runtime_error(
414
+ std::string(
415
+ "Getting property `" + propName +
416
+ "` with function `getViewProp` is not supported"));
396
417
  }
397
418
 
398
419
  jsi::Value ReanimatedModuleProxy::getViewProp(
@@ -700,13 +721,23 @@ void ReanimatedModuleProxy::updateProps(
700
721
  }
701
722
 
702
723
  void ReanimatedModuleProxy::performOperations() {
724
+ ReanimatedSystraceSection s("performOperations");
725
+
726
+ if (!layoutAnimationFlushRequests_.empty()) {
727
+ auto flushRequestsCopy = std::move(layoutAnimationFlushRequests_);
728
+ for (const auto surfaceId : flushRequestsCopy) {
729
+ uiManager_->getShadowTreeRegistry().visit(
730
+ surfaceId, [](const ShadowTree &shadowTree) {
731
+ shadowTree.notifyDelegatesOfUpdates();
732
+ });
733
+ }
734
+ }
735
+
703
736
  if (operationsInBatch_.empty() && tagsToRemove_.empty()) {
704
737
  // nothing to do
705
738
  return;
706
739
  }
707
740
 
708
- ReanimatedSystraceSection s("performOperations");
709
-
710
741
  auto copiedOperationsQueue = std::move(operationsInBatch_);
711
742
  operationsInBatch_.clear();
712
743
 
@@ -809,7 +840,7 @@ void ReanimatedModuleProxy::dispatchCommand(
809
840
  const jsi::Value &shadowNodeValue,
810
841
  const jsi::Value &commandNameValue,
811
842
  const jsi::Value &argsValue) {
812
- ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
843
+ const auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
813
844
  std::string commandName = stringFromValue(rt, commandNameValue);
814
845
  folly::dynamic args = commandArgsFromValue(rt, argsValue);
815
846
  const auto &scheduler = static_cast<Scheduler *>(uiManager_->getDelegate());
@@ -911,6 +942,7 @@ void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
911
942
  scheduler->getContextContainer(),
912
943
  uiWorkletRuntime_->getJSIRuntime(),
913
944
  workletsModuleProxy_->getUIScheduler());
945
+ uiManager_->setAnimationDelegate(layoutAnimationsProxy_.get());
914
946
  }
915
947
  }
916
948
 
@@ -23,6 +23,7 @@
23
23
  #endif // RCT_NEW_ARCH_ENABLED
24
24
 
25
25
  #include <memory>
26
+ #include <set>
26
27
  #include <string>
27
28
  #include <unordered_set>
28
29
  #include <utility>
@@ -150,7 +151,7 @@ class ReanimatedModuleProxy
150
151
  std::string obtainPropFromShadowNode(
151
152
  jsi::Runtime &rt,
152
153
  const std::string &propName,
153
- const ShadowNode::Shared &shadowNode);
154
+ const std::shared_ptr<const ShadowNode> &shadowNode);
154
155
 
155
156
  #ifdef IS_REANIMATED_EXAMPLE_APP
156
157
  std::function<std::string()> createRegistriesLeakCheck();
@@ -233,6 +234,8 @@ class ReanimatedModuleProxy
233
234
  std::shared_ptr<PropsRegistry> propsRegistry_;
234
235
  std::shared_ptr<ReanimatedCommitHook> commitHook_;
235
236
  std::shared_ptr<ReanimatedMountHook> mountHook_;
237
+ std::set<SurfaceId> layoutAnimationFlushRequests_;
238
+ bool layoutAnimationRenderRequested_;
236
239
 
237
240
  std::vector<Tag> tagsToRemove_; // from `propsRegistry_`
238
241
  #else
package/README.md CHANGED
@@ -6,21 +6,9 @@
6
6
 
7
7
  React Native Reanimated provides a more comprehensive,
8
8
  low-level abstraction for the Animated library API on which to build,
9
- allowing for much greater flexibility, especially when it comes to
9
+ allowing for much greater flexibility, especially when it comes to
10
10
  gesture-based interactions.
11
11
 
12
- ### Nightly CI state
13
-
14
- [![NPM Reanimated publish nightly](https://github.com/software-mansion/react-native-reanimated/actions/workflows/npm-reanimated-publish-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/npm-reanimated-publish-nightly.yml)
15
- [![Reanimated compatibility check](https://github.com/software-mansion/react-native-reanimated/actions/workflows/reanimated-compatibility-check-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/reanimated-compatibility-check-nightly.yml)
16
- [![Static framework Reanimated build check](https://github.com/software-mansion/react-native-reanimated/actions/workflows/static-framework-reanimated-build-check-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/static-framework-reanimated-build-check-nightly.yml)
17
- [![React Native nightly Reanimated build check](https://github.com/software-mansion/react-native-reanimated/actions/workflows/react-native-nightly-reanimated-build-check-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/react-native-nightly-reanimated-build-check-nightly.yml)
18
- [![Expo DevClient build check](https://github.com/software-mansion/react-native-reanimated/actions/workflows/expo-devclient-build-check-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/expo-devclient-build-check-nightly.yml)
19
- [![Reanimated TypeScript compatibility test](https://github.com/software-mansion/react-native-reanimated/actions/workflows/reanimated-typescript-compatibility-test-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/reanimated-typescript-compatibility-test-nightly.yml)
20
- [![V8 Reanimated build check](https://github.com/software-mansion/react-native-reanimated/actions/workflows/V8-reanimated-build-check-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/V8-reanimated-build-check-nightly.yml)
21
- [![Windows hosted app Reanimated build check](https://github.com/software-mansion/react-native-reanimated/actions/workflows/windows-hosted-app-reanimated-build-check-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/windows-hosted-app-reanimated-build-check-nightly.yml)
22
- [![URL validation](https://github.com/software-mansion/react-native-reanimated/actions/workflows/url-validation-nightly.yml/badge.svg)](https://github.com/software-mansion/react-native-reanimated/actions/workflows/url-validation-nightly.yml)
23
-
24
12
  ## Installation
25
13
 
26
14
  Check out the [installation](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/getting-started/#installation) section of our docs for the detailed installation instructions.
@@ -81,7 +81,7 @@ Pod::Spec.new do |s|
81
81
  '"$(PODS_ROOT)/Headers/Private/Yoga"',
82
82
  ].join(' '),
83
83
  "FRAMEWORK_SEARCH_PATHS" => '"${PODS_CONFIGURATION_BUILD_DIR}/React-hermes"',
84
- "CLANG_CXX_LANGUAGE_STANDARD" => "c++17",
84
+ "CLANG_CXX_LANGUAGE_STANDARD" => "c++20",
85
85
  "GCC_PREPROCESSOR_DEFINITIONS[config=*Debug*]" => hermes_debug_hidden_flags,
86
86
  "GCC_PREPROCESSOR_DEFINITIONS[config=*Release*]" => '$(inherited)',
87
87
  }