react-native-reanimated 3.18.0 → 3.18.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.
Files changed (84) 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 +86 -24
  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 +45 -15
  10. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +4 -1
  11. package/Common/cpp/reanimated/Tools/ReanimatedSystraceSection.h +1 -1
  12. package/README.md +1 -13
  13. package/RNReanimated.podspec +1 -1
  14. package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +25 -21
  15. package/android/src/main/cpp/reanimated/android/NativeProxy.h +5 -3
  16. package/apple/reanimated/apple/LayoutReanimation/REASharedTransitionManager.m +1 -2
  17. package/apple/reanimated/apple/LayoutReanimation/REASwizzledUIManager.mm +8 -7
  18. package/lib/module/PlatformChecker.js +6 -0
  19. package/lib/module/PlatformChecker.js.map +1 -1
  20. package/lib/module/animation/util.js +7 -4
  21. package/lib/module/animation/util.js.map +1 -1
  22. package/lib/module/component/FlatList.js +9 -3
  23. package/lib/module/component/FlatList.js.map +1 -1
  24. package/lib/module/core.js +0 -2
  25. package/lib/module/core.js.map +1 -1
  26. package/lib/module/createAnimatedComponent/NativeEventsManager.js +1 -1
  27. package/lib/module/createAnimatedComponent/NativeEventsManager.js.map +1 -1
  28. package/lib/module/createAnimatedComponent/createAnimatedComponent.js +24 -37
  29. package/lib/module/createAnimatedComponent/createAnimatedComponent.js.map +1 -1
  30. package/lib/module/hook/useAnimatedRef.js +70 -35
  31. package/lib/module/hook/useAnimatedRef.js.map +1 -1
  32. package/lib/module/hook/useHandler.js +7 -0
  33. package/lib/module/hook/useHandler.js.map +1 -1
  34. package/lib/module/hook/useScrollViewOffset.js +28 -26
  35. package/lib/module/hook/useScrollViewOffset.js.map +1 -1
  36. package/lib/module/hook/utils.js +20 -9
  37. package/lib/module/hook/utils.js.map +1 -1
  38. package/lib/module/index.js +3 -0
  39. package/lib/module/index.js.map +1 -1
  40. package/lib/module/platform-specific/jsVersion.js +1 -1
  41. package/lib/module/platformFunctions/setNativeProps.js +1 -1
  42. package/lib/module/platformFunctions/setNativeProps.js.map +1 -1
  43. package/lib/module/processBoxShadow.js.map +1 -1
  44. package/lib/typescript/PlatformChecker.d.ts +2 -0
  45. package/lib/typescript/PlatformChecker.d.ts.map +1 -1
  46. package/lib/typescript/animation/util.d.ts.map +1 -1
  47. package/lib/typescript/component/FlatList.d.ts +10 -2
  48. package/lib/typescript/component/FlatList.d.ts.map +1 -1
  49. package/lib/typescript/core.d.ts.map +1 -1
  50. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts +1 -0
  51. package/lib/typescript/createAnimatedComponent/commonTypes.d.ts.map +1 -1
  52. package/lib/typescript/createAnimatedComponent/createAnimatedComponent.d.ts.map +1 -1
  53. package/lib/typescript/helperTypes.d.ts +1 -3
  54. package/lib/typescript/helperTypes.d.ts.map +1 -1
  55. package/lib/typescript/hook/commonTypes.d.ts +7 -4
  56. package/lib/typescript/hook/commonTypes.d.ts.map +1 -1
  57. package/lib/typescript/hook/useAnimatedRef.d.ts +3 -1
  58. package/lib/typescript/hook/useAnimatedRef.d.ts.map +1 -1
  59. package/lib/typescript/hook/useHandler.d.ts.map +1 -1
  60. package/lib/typescript/hook/useScrollViewOffset.d.ts.map +1 -1
  61. package/lib/typescript/hook/utils.d.ts.map +1 -1
  62. package/lib/typescript/index.d.ts +1 -1
  63. package/lib/typescript/index.d.ts.map +1 -1
  64. package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
  65. package/lib/typescript/processBoxShadow.d.ts +6 -3
  66. package/lib/typescript/processBoxShadow.d.ts.map +1 -1
  67. package/package.json +2 -2
  68. package/src/PlatformChecker.ts +8 -0
  69. package/src/animation/util.ts +7 -4
  70. package/src/component/FlatList.tsx +44 -6
  71. package/src/core.ts +0 -3
  72. package/src/createAnimatedComponent/NativeEventsManager.ts +1 -1
  73. package/src/createAnimatedComponent/commonTypes.ts +9 -0
  74. package/src/createAnimatedComponent/createAnimatedComponent.tsx +61 -73
  75. package/src/helperTypes.ts +1 -6
  76. package/src/hook/commonTypes.ts +9 -4
  77. package/src/hook/useAnimatedRef.ts +107 -48
  78. package/src/hook/useHandler.ts +10 -0
  79. package/src/hook/useScrollViewOffset.ts +34 -29
  80. package/src/hook/utils.ts +34 -9
  81. package/src/index.ts +4 -1
  82. package/src/platform-specific/jsVersion.ts +1 -1
  83. package/src/platformFunctions/setNativeProps.ts +1 -1
  84. package/src/processBoxShadow.ts +8 -4
@@ -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,18 @@ 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
+ #if REACT_NATIVE_MINOR_VERSION >= 78
230
+ movedViews[mutation.newChildShadowView.tag] = mutation.parentTag;
231
+ #else
232
+ movedViews[mutation.newChildShadowView.tag] =
233
+ mutation.parentShadowView.tag;
234
+ #endif // REACT_NATIVE_MINOR_VERSION >= 78
215
235
  }
216
236
  }
217
237
 
@@ -239,13 +259,15 @@ void LayoutAnimationsProxy::parseRemoveMutations(
239
259
 
240
260
  void LayoutAnimationsProxy::handleRemovals(
241
261
  ShadowViewMutationList &filteredMutations,
242
- std::vector<std::shared_ptr<MutationNode>> &roots) const {
262
+ std::vector<std::shared_ptr<MutationNode>> &roots,
263
+ std::unordered_set<std::shared_ptr<MutationNode>> &deadNodes,
264
+ bool shouldAnimate) const {
243
265
  // iterate from the end, so that children
244
266
  // with higher indices appear first in the mutations list
245
267
  for (auto it = roots.rbegin(); it != roots.rend(); it++) {
246
268
  auto &node = *it;
247
269
  if (!startAnimationsRecursively(
248
- node, true, true, false, filteredMutations)) {
270
+ node, true, shouldAnimate, false, filteredMutations)) {
249
271
  filteredMutations.push_back(node->mutation);
250
272
  node->unflattenedParent->removeChildFromUnflattenedTree(node); //???
251
273
  if (node->state != MOVED) {
@@ -253,6 +275,7 @@ void LayoutAnimationsProxy::handleRemovals(
253
275
  filteredMutations.push_back(ShadowViewMutation::DeleteMutation(
254
276
  node->mutation.oldChildShadowView));
255
277
  nodeForTag_.erase(node->tag);
278
+ node->state = DELETED;
256
279
  #ifdef LAYOUT_ANIMATIONS_LOGS
257
280
  LOG(INFO) << "delete " << node->tag << std::endl;
258
281
  #endif
@@ -271,7 +294,7 @@ void LayoutAnimationsProxy::handleRemovals(
271
294
 
272
295
  void LayoutAnimationsProxy::handleUpdatesAndEnterings(
273
296
  ShadowViewMutationList &filteredMutations,
274
- const std::unordered_map<Tag, ShadowView> &movedViews,
297
+ const std::unordered_map<Tag, Tag> &movedViews,
275
298
  ShadowViewMutationList &mutations,
276
299
  const PropsParserContext &propsParserContext,
277
300
  SurfaceId surfaceId) const {
@@ -320,6 +343,11 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
320
343
  auto oldView = *layoutAnimationIt->second.currentView;
321
344
  filteredMutations.push_back(ShadowViewMutation::InsertMutation(
322
345
  mutationParent, oldView, mutation.index));
346
+ if (movedViews.contains(tag)) {
347
+ #if REACT_NATIVE_MINOR_VERSION >= 78
348
+ layoutAnimationIt->second.parentTag = movedViews.at(tag);
349
+ #endif // REACT_NATIVE_MINOR_VERSION >= 78
350
+ }
323
351
  continue;
324
352
  }
325
353
 
@@ -364,8 +392,23 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
364
392
  // store the oldChildShadowView, so that we can use this ShadowView when
365
393
  // the view is inserted
366
394
  oldShadowViewsForReparentings[tag] = mutation.oldChildShadowView;
367
- startLayoutAnimation(tag, mutation);
395
+ #if REACT_NATIVE_MINOR_VERSION >= 78
396
+ if (movedViews.contains(tag)) {
397
+ mutation.parentTag = movedViews.at(tag);
398
+ }
399
+ if (mutation.parentTag != -1) {
400
+ startLayoutAnimation(tag, mutation);
401
+ }
402
+ break;
403
+ #else
404
+ if (movedViews.contains(tag)) {
405
+ mutation.parentShadowView.tag = movedViews.at(tag);
406
+ }
407
+ if (mutation.parentShadowView.tag != -1) {
408
+ startLayoutAnimation(tag, mutation);
409
+ }
368
410
  break;
411
+ #endif // REACT_NATIVE_MINOR_VERSION >= 78
369
412
  }
370
413
 
371
414
  case ShadowViewMutation::Type::Remove:
@@ -449,6 +492,7 @@ void LayoutAnimationsProxy::maybeDropAncestors(
449
492
  nodeForTag_.erase(node->tag);
450
493
  cleanupMutations.push_back(node->mutation);
451
494
  maybeCancelAnimation(node->tag);
495
+ node->state = DELETED;
452
496
  #ifdef LAYOUT_ANIMATIONS_LOGS
453
497
  LOG(INFO) << "delete " << node->tag << std::endl;
454
498
  #endif
@@ -483,7 +527,8 @@ bool LayoutAnimationsProxy::startAnimationsRecursively(
483
527
  bool hasAnimatedChildren = false;
484
528
 
485
529
  shouldRemoveSubviewsWithoutAnimations =
486
- shouldRemoveSubviewsWithoutAnimations && !hasExitAnimation;
530
+ shouldRemoveSubviewsWithoutAnimations &&
531
+ (!hasExitAnimation || node->state == MOVED);
487
532
  std::vector<std::shared_ptr<MutationNode>> toBeRemoved;
488
533
 
489
534
  // iterate from the end, so that children
@@ -655,7 +700,7 @@ void LayoutAnimationsProxy::startEnteringAnimation(
655
700
  current,
656
701
  #if REACT_NATIVE_MINOR_VERSION < 78
657
702
  parent,
658
- #endif // RE
703
+ #endif // REACT_NATIVE_MINOR_VERSION < 78
659
704
  mutation,
660
705
  opacity,
661
706
  tag]() {
@@ -668,16 +713,14 @@ void LayoutAnimationsProxy::startEnteringAnimation(
668
713
  {
669
714
  auto &mutex = strongThis->mutex;
670
715
  auto lock = std::unique_lock<std::recursive_mutex>(mutex);
671
- strongThis->layoutAnimations_.insert_or_assign(
672
- tag, LayoutAnimation {
673
- finalView, current,
674
716
  #if REACT_NATIVE_MINOR_VERSION >= 78
675
- mutation.parentTag,
717
+ strongThis->layoutAnimations_.insert_or_assign(
718
+ tag,
719
+ LayoutAnimation{finalView, current, mutation.parentTag, opacity});
676
720
  #else
677
- parent,
721
+ strongThis->layoutAnimations_.insert_or_assign(
722
+ tag, LayoutAnimation{finalView, current, parent, opacity});
678
723
  #endif // REACT_NATIVE_MINOR_VERSION >= 78
679
- opacity
680
- });
681
724
  window = strongThis->surfaceManager.getWindow(
682
725
  mutation.newChildShadowView.surfaceId);
683
726
  }
@@ -865,6 +908,25 @@ void LayoutAnimationsProxy::maybeUpdateWindowDimensions(
865
908
  }
866
909
  }
867
910
 
911
+ // UIManagerAnimationDelegate
912
+
913
+ void LayoutAnimationsProxy::uiManagerDidConfigureNextLayoutAnimation(
914
+ jsi::Runtime &runtime,
915
+ const RawValue &config,
916
+ const jsi::Value &successCallbackValue,
917
+ const jsi::Value &failureCallbackValue) const {}
918
+
919
+ void LayoutAnimationsProxy::setComponentDescriptorRegistry(
920
+ const SharedComponentDescriptorRegistry &componentDescriptorRegistry) {}
921
+
922
+ bool LayoutAnimationsProxy::shouldAnimateFrame() const {
923
+ return false;
924
+ }
925
+
926
+ void LayoutAnimationsProxy::stopSurface(SurfaceId surfaceId) {
927
+ surfacesToRemove_.insert(surfaceId);
928
+ }
929
+
868
930
  } // namespace reanimated
869
931
 
870
932
  #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,
@@ -161,14 +169,20 @@ void ReanimatedModuleProxy::init(
161
169
  if (!surfaceId) {
162
170
  return;
163
171
  }
164
- strongThis->uiManager_->getShadowTreeRegistry().visit(
165
- *surfaceId, [](const ShadowTree &shadowTree) {
166
- shadowTree.notifyDelegatesOfUpdates();
167
- });
172
+ strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
168
173
  };
169
174
 
175
+ auto requestLayoutAnimationRender = [weakThis = weak_from_this()](double) {
176
+ auto strongThis = weakThis.lock();
177
+ if (!strongThis) {
178
+ return;
179
+ }
180
+ strongThis->layoutAnimationRenderRequested_ = false;
181
+ };
182
+
170
183
  EndLayoutAnimationFunction endLayoutAnimation =
171
- [weakThis = weak_from_this()](int tag, bool shouldRemove) {
184
+ [weakThis = weak_from_this(), requestLayoutAnimationRender](
185
+ int tag, bool shouldRemove) {
172
186
  auto strongThis = weakThis.lock();
173
187
  if (!strongThis) {
174
188
  return;
@@ -176,14 +190,19 @@ void ReanimatedModuleProxy::init(
176
190
 
177
191
  auto surfaceId = strongThis->layoutAnimationsProxy_->endLayoutAnimation(
178
192
  tag, shouldRemove);
193
+
194
+ if (!strongThis->layoutAnimationRenderRequested_) {
195
+ strongThis->layoutAnimationRenderRequested_ = true;
196
+ // if an animation has duration 0, performOperations would not get
197
+ // called for it so we call requestRender to have it called in the
198
+ // next frame
199
+ strongThis->requestRender_(requestLayoutAnimationRender);
200
+ }
201
+
179
202
  if (!surfaceId) {
180
203
  return;
181
204
  }
182
-
183
- strongThis->uiManager_->getShadowTreeRegistry().visit(
184
- *surfaceId, [](const ShadowTree &shadowTree) {
185
- shadowTree.notifyDelegatesOfUpdates();
186
- });
205
+ strongThis->layoutAnimationFlushRequests_.insert(*surfaceId);
187
206
  };
188
207
 
189
208
  auto obtainProp = [weakThis = weak_from_this()](
@@ -355,7 +374,7 @@ static inline std::string intColorToHex(const int val) {
355
374
  std::string ReanimatedModuleProxy::obtainPropFromShadowNode(
356
375
  jsi::Runtime &rt,
357
376
  const std::string &propName,
358
- const ShadowNode::Shared &shadowNode) {
377
+ const std::shared_ptr<const ShadowNode> &shadowNode) {
359
378
  auto newestCloneOfShadowNode =
360
379
  uiManager_->getNewestCloneOfShadowNode(*shadowNode);
361
380
 
@@ -700,13 +719,23 @@ void ReanimatedModuleProxy::updateProps(
700
719
  }
701
720
 
702
721
  void ReanimatedModuleProxy::performOperations() {
722
+ ReanimatedSystraceSection s("performOperations");
723
+
724
+ if (!layoutAnimationFlushRequests_.empty()) {
725
+ auto flushRequestsCopy = std::move(layoutAnimationFlushRequests_);
726
+ for (const auto surfaceId : flushRequestsCopy) {
727
+ uiManager_->getShadowTreeRegistry().visit(
728
+ surfaceId, [](const ShadowTree &shadowTree) {
729
+ shadowTree.notifyDelegatesOfUpdates();
730
+ });
731
+ }
732
+ }
733
+
703
734
  if (operationsInBatch_.empty() && tagsToRemove_.empty()) {
704
735
  // nothing to do
705
736
  return;
706
737
  }
707
738
 
708
- ReanimatedSystraceSection s("performOperations");
709
-
710
739
  auto copiedOperationsQueue = std::move(operationsInBatch_);
711
740
  operationsInBatch_.clear();
712
741
 
@@ -809,7 +838,7 @@ void ReanimatedModuleProxy::dispatchCommand(
809
838
  const jsi::Value &shadowNodeValue,
810
839
  const jsi::Value &commandNameValue,
811
840
  const jsi::Value &argsValue) {
812
- ShadowNode::Shared shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
841
+ const auto shadowNode = shadowNodeFromValue(rt, shadowNodeValue);
813
842
  std::string commandName = stringFromValue(rt, commandNameValue);
814
843
  folly::dynamic args = commandArgsFromValue(rt, argsValue);
815
844
  const auto &scheduler = static_cast<Scheduler *>(uiManager_->getDelegate());
@@ -911,6 +940,7 @@ void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
911
940
  scheduler->getContextContainer(),
912
941
  uiWorkletRuntime_->getJSIRuntime(),
913
942
  workletsModuleProxy_->getUIScheduler());
943
+ uiManager_->setAnimationDelegate(layoutAnimationsProxy_.get());
914
944
  }
915
945
  }
916
946
 
@@ -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
@@ -130,6 +130,6 @@ struct ReanimatedSystraceSection {
130
130
  };
131
131
 
132
132
  #endif // defined(__APPLE__) && OS_LOG_TARGET_HAS_10_15_FEATURES &&
133
- // defined(REANIMATED_PROFILING)
133
+ // defined(REANIMATED_PROFILING)
134
134
 
135
135
  } // namespace reanimated
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
  }