react-native-reanimated 3.19.0 → 3.19.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 (81) hide show
  1. package/Common/cpp/reanimated/Fabric/PropsRegistry.cpp +13 -15
  2. package/Common/cpp/reanimated/Fabric/PropsRegistry.h +8 -6
  3. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +138 -34
  4. package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h +32 -3
  5. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +27 -14
  6. package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +3 -0
  7. package/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +9 -1
  8. package/android/CMakeLists.txt +10 -3
  9. package/android/build.gradle +3 -3
  10. package/android/src/fabric/java/com/swmansion/reanimated/NativeProxy.java +19 -0
  11. package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +37 -12
  12. package/android/src/main/cpp/reanimated/android/NativeProxy.h +8 -2
  13. package/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java +1 -2
  14. package/lib/module/ViewDescriptorsSet.js +5 -1
  15. package/lib/module/ViewDescriptorsSet.js.map +1 -1
  16. package/lib/module/animation/util.js +5 -3
  17. package/lib/module/animation/util.js.map +1 -1
  18. package/lib/module/component/ReducedMotionConfig.js +1 -1
  19. package/lib/module/createAnimatedComponent/NativeEventsManager.js +1 -1
  20. package/lib/module/createAnimatedComponent/NativeEventsManager.js.map +1 -1
  21. package/lib/module/createAnimatedComponent/createAnimatedComponent.js +28 -11
  22. package/lib/module/createAnimatedComponent/createAnimatedComponent.js.map +1 -1
  23. package/lib/module/layoutReanimation/web/Easing.web.js +14 -0
  24. package/lib/module/layoutReanimation/web/Easing.web.js.map +1 -1
  25. package/lib/module/layoutReanimation/web/animationParser.js.map +1 -1
  26. package/lib/module/layoutReanimation/web/componentUtils.js +52 -14
  27. package/lib/module/layoutReanimation/web/componentUtils.js.map +1 -1
  28. package/lib/module/layoutReanimation/web/config.js.map +1 -1
  29. package/lib/module/layoutReanimation/web/createAnimation.js +12 -0
  30. package/lib/module/layoutReanimation/web/createAnimation.js.map +1 -1
  31. package/lib/module/layoutReanimation/web/domUtils.js +1 -1
  32. package/lib/module/layoutReanimation/web/domUtils.js.map +1 -1
  33. package/lib/module/layoutReanimation/web/transition/Curved.web.js +1 -0
  34. package/lib/module/layoutReanimation/web/transition/Curved.web.js.map +1 -1
  35. package/lib/module/platform-specific/jsVersion.js +1 -1
  36. package/lib/module/platformFunctions/dispatchCommand.js +10 -0
  37. package/lib/module/platformFunctions/dispatchCommand.js.map +1 -1
  38. package/lib/module/platformFunctions/scrollTo.web.js +11 -7
  39. package/lib/module/platformFunctions/scrollTo.web.js.map +1 -1
  40. package/lib/module/runtimes.js +1 -1
  41. package/lib/module/threads.js +5 -5
  42. package/lib/typescript/ViewDescriptorsSet.d.ts +1 -0
  43. package/lib/typescript/ViewDescriptorsSet.d.ts.map +1 -1
  44. package/lib/typescript/animation/util.d.ts.map +1 -1
  45. package/lib/typescript/component/ReducedMotionConfig.d.ts +1 -1
  46. package/lib/typescript/createAnimatedComponent/createAnimatedComponent.d.ts.map +1 -1
  47. package/lib/typescript/helperTypes.d.ts +4 -1
  48. package/lib/typescript/helperTypes.d.ts.map +1 -1
  49. package/lib/typescript/layoutReanimation/web/Easing.web.d.ts +2 -0
  50. package/lib/typescript/layoutReanimation/web/Easing.web.d.ts.map +1 -1
  51. package/lib/typescript/layoutReanimation/web/animationParser.d.ts +3 -0
  52. package/lib/typescript/layoutReanimation/web/animationParser.d.ts.map +1 -1
  53. package/lib/typescript/layoutReanimation/web/componentUtils.d.ts.map +1 -1
  54. package/lib/typescript/layoutReanimation/web/config.d.ts +4 -4
  55. package/lib/typescript/layoutReanimation/web/config.d.ts.map +1 -1
  56. package/lib/typescript/layoutReanimation/web/createAnimation.d.ts.map +1 -1
  57. package/lib/typescript/layoutReanimation/web/transition/Curved.web.d.ts.map +1 -1
  58. package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
  59. package/lib/typescript/platformFunctions/scrollTo.web.d.ts.map +1 -1
  60. package/lib/typescript/runtimes.d.ts +1 -1
  61. package/lib/typescript/threads.d.ts +5 -5
  62. package/package.json +1 -1
  63. package/scripts/reanimated_utils.rb +1 -1
  64. package/src/ViewDescriptorsSet.ts +9 -0
  65. package/src/animation/util.ts +6 -4
  66. package/src/component/ReducedMotionConfig.tsx +1 -1
  67. package/src/createAnimatedComponent/NativeEventsManager.ts +1 -1
  68. package/src/createAnimatedComponent/createAnimatedComponent.tsx +35 -24
  69. package/src/helperTypes.ts +5 -1
  70. package/src/layoutReanimation/web/Easing.web.ts +32 -0
  71. package/src/layoutReanimation/web/animationParser.ts +3 -0
  72. package/src/layoutReanimation/web/componentUtils.ts +69 -16
  73. package/src/layoutReanimation/web/config.ts +7 -3
  74. package/src/layoutReanimation/web/createAnimation.ts +15 -0
  75. package/src/layoutReanimation/web/domUtils.ts +1 -1
  76. package/src/layoutReanimation/web/transition/Curved.web.ts +1 -0
  77. package/src/platform-specific/jsVersion.ts +1 -1
  78. package/src/platformFunctions/dispatchCommand.ts +23 -2
  79. package/src/platformFunctions/scrollTo.web.ts +9 -3
  80. package/src/runtimes.ts +1 -1
  81. package/src/threads.ts +5 -5
@@ -24,10 +24,9 @@ void PropsRegistry::update(
24
24
  }
25
25
  }
26
26
 
27
- void PropsRegistry::for_each(
28
- std::function<
29
- void(const ShadowNodeFamily &family, const folly::dynamic &props)>
30
- callback) const {
27
+ void PropsRegistry::for_each(std::function<void(
28
+ const ShadowNodeFamily &family,
29
+ const folly::dynamic &props)> callback) const {
31
30
  for (const auto &[_, value] : map_) {
32
31
  callback(value.first->getFamily(), value.second);
33
32
  }
@@ -43,22 +42,21 @@ void PropsRegistry::unmarkNodeAsRemovable(Tag viewTag) {
43
42
  }
44
43
 
45
44
  void PropsRegistry::handleNodeRemovals(const RootShadowNode &rootShadowNode) {
46
- for (auto it = removableShadowNodes_.begin();
47
- it != removableShadowNodes_.end();) {
48
- const auto &shadowNode = it->second;
49
- const auto &family = shadowNode->getFamily();
50
- const auto &ancestors = family.getAncestors(rootShadowNode);
45
+ RemovableShadowNodes remainingShadowNodes;
51
46
 
52
- // Skip if the node hasn't been removed
53
- if (!ancestors.empty()) {
54
- ++it;
47
+ for (const auto &[tag, shadowNode] : removableShadowNodes_) {
48
+ if (!shadowNode) {
55
49
  continue;
56
50
  }
57
51
 
58
- const auto tag = shadowNode->getTag();
59
- map_.erase(tag);
60
- it = removableShadowNodes_.erase(it);
52
+ if (shadowNode->getFamily().getAncestors(rootShadowNode).empty()) {
53
+ map_.erase(tag);
54
+ } else {
55
+ remainingShadowNodes.emplace(tag, shadowNode);
56
+ }
61
57
  }
58
+
59
+ removableShadowNodes_ = std::move(remainingShadowNodes);
62
60
  }
63
61
 
64
62
  void PropsRegistry::remove(const Tag tag) {
@@ -4,6 +4,7 @@
4
4
  #include <react/renderer/components/root/RootShadowNode.h>
5
5
  #include <react/renderer/core/ShadowNode.h>
6
6
 
7
+ #include <memory>
7
8
  #include <unordered_map>
8
9
  #include <utility>
9
10
 
@@ -21,10 +22,9 @@ class PropsRegistry {
21
22
  const std::shared_ptr<const ShadowNode> &shadowNode,
22
23
  folly::dynamic &&props);
23
24
 
24
- void for_each(
25
- std::function<
26
- void(const ShadowNodeFamily &family, const folly::dynamic &props)>
27
- callback) const;
25
+ void for_each(std::function<void(
26
+ const ShadowNodeFamily &family,
27
+ const folly::dynamic &props)> callback) const;
28
28
 
29
29
  void remove(const Tag tag);
30
30
 
@@ -57,12 +57,14 @@ class PropsRegistry {
57
57
  void handleNodeRemovals(const RootShadowNode &rootShadowNode);
58
58
 
59
59
  private:
60
+ using RemovableShadowNodes =
61
+ std::unordered_map<Tag, std::shared_ptr<const ShadowNode>>;
62
+
60
63
  std::unordered_map<
61
64
  Tag,
62
65
  std::pair<std::shared_ptr<const ShadowNode>, folly::dynamic>>
63
66
  map_;
64
- std::unordered_map<Tag, std::shared_ptr<const ShadowNode>>
65
- removableShadowNodes_;
67
+ RemovableShadowNodes removableShadowNodes_;
66
68
 
67
69
  mutable std::mutex mutex_; // Protects `map_`.
68
70
 
@@ -37,6 +37,9 @@ std::optional<MountingTransaction> LayoutAnimationsProxy::pullTransaction(
37
37
 
38
38
  addOngoingAnimations(surfaceId, filteredMutations);
39
39
 
40
+ #ifdef ANDROID
41
+ restoreOpacityInCaseOfFlakyEnteringAnimation(surfaceId);
42
+ #endif // ANDROID
40
43
  for (const auto tag : finishedAnimationTags_) {
41
44
  auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
42
45
  layoutAnimations_.erase(tag);
@@ -261,9 +264,8 @@ void LayoutAnimationsProxy::handleRemovals(
261
264
  node->unflattenedParent->removeChildFromUnflattenedTree(node); //???
262
265
  if (node->state != MOVED) {
263
266
  maybeCancelAnimation(node->tag);
264
- filteredMutations.push_back(
265
- ShadowViewMutation::DeleteMutation(
266
- node->mutation.oldChildShadowView));
267
+ filteredMutations.push_back(ShadowViewMutation::DeleteMutation(
268
+ node->mutation.oldChildShadowView));
267
269
  nodeForTag_.erase(node->tag);
268
270
  node->state = DELETED;
269
271
  #ifdef LAYOUT_ANIMATIONS_LOGS
@@ -320,11 +322,10 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
320
322
  auto layoutAnimationIt = layoutAnimations_.find(tag);
321
323
  if (layoutAnimationIt == layoutAnimations_.end()) {
322
324
  if (oldShadowViewsForReparentings.contains(tag)) {
323
- filteredMutations.push_back(
324
- ShadowViewMutation::InsertMutation(
325
- mutationParent,
326
- oldShadowViewsForReparentings[tag],
327
- mutation.index));
325
+ filteredMutations.push_back(ShadowViewMutation::InsertMutation(
326
+ mutationParent,
327
+ oldShadowViewsForReparentings[tag],
328
+ mutation.index));
328
329
  } else {
329
330
  filteredMutations.push_back(mutation);
330
331
  }
@@ -332,9 +333,8 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
332
333
  }
333
334
 
334
335
  auto oldView = *layoutAnimationIt->second.currentView;
335
- filteredMutations.push_back(
336
- ShadowViewMutation::InsertMutation(
337
- mutationParent, oldView, mutation.index));
336
+ filteredMutations.push_back(ShadowViewMutation::InsertMutation(
337
+ mutationParent, oldView, mutation.index));
338
338
  if (movedViews.contains(tag)) {
339
339
  layoutAnimationIt->second.parentTag = movedViews.at(tag);
340
340
  }
@@ -356,9 +356,8 @@ void LayoutAnimationsProxy::handleUpdatesAndEnterings(
356
356
  std::shared_ptr<ShadowView> newView =
357
357
  cloneViewWithoutOpacity(mutation, propsParserContext);
358
358
 
359
- filteredMutations.push_back(
360
- ShadowViewMutation::UpdateMutation(
361
- mutation.newChildShadowView, *newView, mutationParent));
359
+ filteredMutations.push_back(ShadowViewMutation::UpdateMutation(
360
+ mutation.newChildShadowView, *newView, mutationParent));
362
361
  break;
363
362
  }
364
363
 
@@ -407,7 +406,36 @@ void LayoutAnimationsProxy::addOngoingAnimations(
407
406
  SurfaceId surfaceId,
408
407
  ShadowViewMutationList &mutations) const {
409
408
  auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
409
+ #ifdef ANDROID
410
+ std::vector<int> tagsToUpdate;
410
411
  for (auto &[tag, updateValues] : updateMap) {
412
+ tagsToUpdate.push_back(tag);
413
+ }
414
+
415
+ auto maybeCorrectedTags = preserveMountedTags_(tagsToUpdate);
416
+ if (!maybeCorrectedTags.has_value()) {
417
+ return;
418
+ }
419
+
420
+ auto correctedTags = maybeCorrectedTags->get();
421
+
422
+ // since the map is not updated, we can assume that the ordering of tags in
423
+ // correctedTags matches the iterator
424
+ int i = -1;
425
+ #endif
426
+ for (auto &[tag, updateValues] : updateMap) {
427
+ #ifdef ANDROID
428
+ i++;
429
+ if (correctedTags[i] == -1) {
430
+ // skip views that have not been mounted yet
431
+ // on Android we start entering animations from the JS thread
432
+ // so it might happen, that the first frame of the animation goes through
433
+ // before the view is first mounted
434
+ // https://github.com/software-mansion/react-native-reanimated/issues/7493
435
+ continue;
436
+ }
437
+ #endif
438
+
411
439
  auto layoutAnimationIt = layoutAnimations_.find(tag);
412
440
 
413
441
  if (layoutAnimationIt == layoutAnimations_.end()) {
@@ -415,21 +443,20 @@ void LayoutAnimationsProxy::addOngoingAnimations(
415
443
  }
416
444
 
417
445
  auto &layoutAnimation = layoutAnimationIt->second;
418
-
446
+ layoutAnimation.isViewAlreadyMounted = true;
419
447
  auto newView = std::make_shared<ShadowView>(*layoutAnimation.finalView);
420
448
  newView->props = updateValues.newProps;
421
449
  updateLayoutMetrics(newView->layoutMetrics, updateValues.frame);
422
450
 
423
- mutations.push_back(
424
- ShadowViewMutation::UpdateMutation(
425
- *layoutAnimation.currentView,
426
- *newView,
451
+ mutations.push_back(ShadowViewMutation::UpdateMutation(
452
+ *layoutAnimation.currentView,
453
+ *newView,
427
454
  #if REACT_NATIVE_MINOR_VERSION >= 78
428
- layoutAnimation.parentTag
455
+ layoutAnimation.parentTag
429
456
  #else
430
- *layoutAnimation.parentView
457
+ *layoutAnimation.parentView
431
458
  #endif // REACT_NATIVE_MINOR_VERSION >= 78
432
- ));
459
+ ));
433
460
  layoutAnimation.currentView = newView;
434
461
  }
435
462
  updateMap.clear();
@@ -554,9 +581,8 @@ bool LayoutAnimationsProxy::startAnimationsRecursively(
554
581
  #ifdef LAYOUT_ANIMATIONS_LOGS
555
582
  LOG(INFO) << "delete " << subNode->tag << std::endl;
556
583
  #endif
557
- mutations.push_back(
558
- ShadowViewMutation::DeleteMutation(
559
- subNode->mutation.oldChildShadowView));
584
+ mutations.push_back(ShadowViewMutation::DeleteMutation(
585
+ subNode->mutation.oldChildShadowView));
560
586
  } else {
561
587
  subNode->state = WAITING;
562
588
  }
@@ -654,11 +680,13 @@ void LayoutAnimationsProxy::createLayoutAnimation(
654
680
  #if REACT_NATIVE_MINOR_VERSION >= 78
655
681
  layoutAnimations_.insert_or_assign(
656
682
  tag,
657
- LayoutAnimation{finalView, currentView, mutation.parentTag, {}, count});
683
+ LayoutAnimation{
684
+ finalView, currentView, mutation.parentTag, {}, false, count});
658
685
  #else
659
686
  auto parentView = std::make_shared<ShadowView>(mutation.parentShadowView);
660
687
  layoutAnimations_.insert_or_assign(
661
- tag, LayoutAnimation{finalView, currentView, parentView, {}, count});
688
+ tag,
689
+ LayoutAnimation{finalView, currentView, parentView, {}, false, count});
662
690
  #endif // REACT_NATIVE_MINOR_VERSION >= 78
663
691
  }
664
692
 
@@ -697,16 +725,15 @@ void LayoutAnimationsProxy::startEnteringAnimation(
697
725
  auto &mutex = strongThis->mutex;
698
726
  auto lock = std::unique_lock<std::recursive_mutex>(mutex);
699
727
  strongThis->layoutAnimations_.insert_or_assign(
700
- tag,
701
- LayoutAnimation{
702
- finalView,
703
- current,
728
+ tag, LayoutAnimation {
729
+ finalView, current,
704
730
  #if REACT_NATIVE_MINOR_VERSION >= 78
705
- mutation.parentTag,
731
+ mutation.parentTag,
706
732
  #else
707
733
  parent,
708
734
  #endif // REACT_NATIVE_MINOR_VERSION >= 78
709
- opacity});
735
+ opacity
736
+ });
710
737
  window = strongThis->surfaceManager.getWindow(
711
738
  mutation.newChildShadowView.surfaceId);
712
739
  }
@@ -877,7 +904,12 @@ void LayoutAnimationsProxy::maybeRestoreOpacity(
877
904
  if (layoutAnimation.opacity && !newStyle.hasProperty(uiRuntime_, "opacity")) {
878
905
  newStyle.setProperty(
879
906
  uiRuntime_, "opacity", jsi::Value(*layoutAnimation.opacity));
880
- layoutAnimation.opacity.reset();
907
+ if (layoutAnimation.isViewAlreadyMounted) {
908
+ // We want to reset opacity only when we are sure that this update will be
909
+ // applied to the native view. Otherwise, we want to update opacity using
910
+ // the `restoreOpacityInCaseOfFlakyEnteringAnimation` method.
911
+ layoutAnimation.opacity.reset();
912
+ }
881
913
  }
882
914
  }
883
915
 
@@ -894,6 +926,78 @@ void LayoutAnimationsProxy::maybeUpdateWindowDimensions(
894
926
  }
895
927
  }
896
928
 
929
+ #ifdef ANDROID
930
+ /*
931
+ * It is possible that we may finish the layout animation before the native view
932
+ * is mounted. If the view wasn't mounted, we wouldn't be able to restore the
933
+ * opacity of the view. To fix this, we need to schedule a React update that
934
+ * will restore the view's opacity. This is safe because we'll use the same
935
+ * queue where React has already scheduled (but not yet executed) the view
936
+ * mounting, so the opacity update will execute after the view is mounted.
937
+ */
938
+ void LayoutAnimationsProxy::restoreOpacityInCaseOfFlakyEnteringAnimation(
939
+ SurfaceId surfaceId) const {
940
+ std::vector<std::pair<double, Tag>> opacityToRestore;
941
+ for (const auto tag : finishedAnimationTags_) {
942
+ const auto &opacity = layoutAnimations_[tag].opacity;
943
+ if (opacity.has_value()) {
944
+ opacityToRestore.emplace_back(
945
+ std::pair<double, Tag>{opacity.value(), tag});
946
+ }
947
+ }
948
+ if (opacityToRestore.empty()) {
949
+ // Animation was successfully finished, and the opacity was restored, so we
950
+ // don't need to do anything. Only the Entering animation has a set opacity
951
+ // value.
952
+ return;
953
+ }
954
+ const auto weakThis = weak_from_this();
955
+ jsInvoker_->invokeAsync([=](jsi::Runtime &runtime) {
956
+ const auto self = weakThis.lock();
957
+ if (!self) {
958
+ return;
959
+ }
960
+ self->uiManager_->getShadowTreeRegistry().visit(
961
+ surfaceId, [=](ShadowTree const &shadowTree) {
962
+ shadowTree.commit(
963
+ [=](RootShadowNode const &oldRootShadowNode) {
964
+ const auto self = weakThis.lock();
965
+ if (!self) {
966
+ return cloneShadowTreeWithNewProps(oldRootShadowNode, {});
967
+ }
968
+ const auto &rootShadowNode =
969
+ static_cast<const ShadowNode &>(oldRootShadowNode);
970
+ PropsMap propsMap;
971
+ for (const auto &[opacity, tag] : opacityToRestore) {
972
+ const auto *targetShadowNode =
973
+ self->findInShadowTreeByTag(rootShadowNode, tag);
974
+ if (targetShadowNode != nullptr) {
975
+ propsMap[&targetShadowNode->getFamily()].emplace_back(
976
+ folly::dynamic::object("opacity", opacity));
977
+ }
978
+ }
979
+ return cloneShadowTreeWithNewProps(oldRootShadowNode, propsMap);
980
+ },
981
+ {});
982
+ });
983
+ });
984
+ }
985
+
986
+ const ShadowNode *LayoutAnimationsProxy::findInShadowTreeByTag(
987
+ const ShadowNode &node,
988
+ Tag tag) const {
989
+ if (node.getTag() == tag) {
990
+ return const_cast<const ShadowNode *>(&node);
991
+ }
992
+ for (auto &child : node.getChildren()) {
993
+ if (const auto result = findInShadowTreeByTag(*child, tag)) {
994
+ return result;
995
+ }
996
+ }
997
+ return nullptr;
998
+ }
999
+ #endif // ANDROID
1000
+
897
1001
  } // namespace reanimated
898
1002
 
899
1003
  #endif // RCT_NEW_ARCH_ENABLED
@@ -4,12 +4,15 @@
4
4
  #include <reanimated/Fabric/PropsRegistry.h>
5
5
  #include <reanimated/LayoutAnimations/LayoutAnimationsManager.h>
6
6
  #include <reanimated/LayoutAnimations/LayoutAnimationsUtils.h>
7
+ #include <reanimated/Tools/PlatformDepMethodsHolder.h>
7
8
 
8
9
  #include <worklets/Tools/UIScheduler.h>
9
10
 
10
11
  #include <react/renderer/componentregistry/ComponentDescriptorFactory.h>
11
12
  #include <react/renderer/mounting/MountingOverrideDelegate.h>
12
13
  #include <react/renderer/mounting/ShadowView.h>
14
+ #include <react/renderer/scheduler/Scheduler.h>
15
+ #include <react/renderer/uimanager/UIManagerBinding.h>
13
16
 
14
17
  #include <memory>
15
18
  #include <string>
@@ -31,6 +34,7 @@ struct LayoutAnimation {
31
34
  std::shared_ptr<ShadowView> finalView, currentView, parentView;
32
35
  #endif // REACT_NATIVE_MINOR_VERSION >= 78
33
36
  std::optional<double> opacity;
37
+ bool isViewAlreadyMounted = false;
34
38
  int count = 1;
35
39
  LayoutAnimation &operator=(const LayoutAnimation &other) = default;
36
40
  };
@@ -50,17 +54,38 @@ struct LayoutAnimationsProxy
50
54
  SharedComponentDescriptorRegistry componentDescriptorRegistry_;
51
55
  jsi::Runtime &uiRuntime_;
52
56
  const std::shared_ptr<UIScheduler> uiScheduler_;
57
+ #ifdef ANDROID
58
+ PreserveMountedTagsFunction preserveMountedTags_;
59
+ std::shared_ptr<UIManager> uiManager_;
60
+ std::shared_ptr<CallInvoker> jsInvoker_;
61
+ #endif
62
+
53
63
  LayoutAnimationsProxy(
54
64
  std::shared_ptr<LayoutAnimationsManager> layoutAnimationsManager,
55
65
  SharedComponentDescriptorRegistry componentDescriptorRegistry,
56
66
  ContextContainer::Shared contextContainer,
57
67
  jsi::Runtime &uiRuntime,
58
- const std::shared_ptr<UIScheduler> uiScheduler)
68
+ const std::shared_ptr<UIScheduler> uiScheduler
69
+ #ifdef ANDROID
70
+ ,
71
+ PreserveMountedTagsFunction filterUnmountedTagsFunction,
72
+ std::shared_ptr<UIManager> uiManager,
73
+ std::shared_ptr<CallInvoker> jsInvoker
74
+ #endif
75
+ )
59
76
  : layoutAnimationsManager_(layoutAnimationsManager),
60
77
  contextContainer_(contextContainer),
61
78
  componentDescriptorRegistry_(componentDescriptorRegistry),
62
79
  uiRuntime_(uiRuntime),
63
- uiScheduler_(uiScheduler) {}
80
+ uiScheduler_(uiScheduler)
81
+ #ifdef ANDROID
82
+ ,
83
+ preserveMountedTags_(filterUnmountedTagsFunction),
84
+ uiManager_(uiManager),
85
+ jsInvoker_(jsInvoker)
86
+ #endif // ANDROID
87
+ {
88
+ }
64
89
 
65
90
  void startEnteringAnimation(const int tag, ShadowViewMutation &mutation)
66
91
  const;
@@ -132,7 +157,11 @@ struct LayoutAnimationsProxy
132
157
 
133
158
  const ComponentDescriptor &getComponentDescriptorForShadowView(
134
159
  const ShadowView &shadowView) const;
135
-
160
+ #ifdef ANDROID
161
+ void restoreOpacityInCaseOfFlakyEnteringAnimation(SurfaceId surfaceId) const;
162
+ const ShadowNode *findInShadowTreeByTag(const ShadowNode &node, Tag tag)
163
+ const;
164
+ #endif // ANDROID
136
165
  // MountingOverrideDelegate
137
166
 
138
167
  bool shouldOverridePullTransaction() const override;
@@ -36,6 +36,7 @@
36
36
 
37
37
  namespace reanimated {
38
38
 
39
+ #ifdef RCT_NEW_ARCH_ENABLED
39
40
  #if REACT_NATIVE_MINOR_VERSION >= 81
40
41
  static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
41
42
  jsi::Runtime &rt,
@@ -43,7 +44,8 @@ static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
43
44
  return Bridging<std::shared_ptr<const ShadowNode>>::fromJs(
44
45
  rt, shadowNodeWrapper);
45
46
  }
46
- #endif
47
+ #endif // REACT_NATIVE_MINOR_VERSION >= 81
48
+ #endif // RCT_NEW_ARCH_ENABLED
47
49
 
48
50
  ReanimatedModuleProxy::ReanimatedModuleProxy(
49
51
  const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
@@ -57,14 +59,13 @@ ReanimatedModuleProxy::ReanimatedModuleProxy(
57
59
  isReducedMotion_(isReducedMotion),
58
60
  workletsModuleProxy_(workletsModuleProxy),
59
61
  valueUnpackerCode_(workletsModuleProxy->getValueUnpackerCode()),
60
- uiWorkletRuntime_(
61
- std::make_shared<WorkletRuntime>(
62
- rnRuntime,
63
- workletsModuleProxy->getJSQueue(),
64
- workletsModuleProxy->getJSScheduler(),
65
- "Reanimated UI runtime",
66
- true /* supportsLocking */,
67
- valueUnpackerCode_)),
62
+ uiWorkletRuntime_(std::make_shared<WorkletRuntime>(
63
+ rnRuntime,
64
+ workletsModuleProxy->getJSQueue(),
65
+ workletsModuleProxy->getJSScheduler(),
66
+ "Reanimated UI runtime",
67
+ true /* supportsLocking */,
68
+ valueUnpackerCode_)),
68
69
  eventHandlerRegistry_(std::make_unique<EventHandlerRegistry>()),
69
70
  requestRender_(platformDepMethodsHolder.requestRender),
70
71
  animatedSensorModule_(platformDepMethodsHolder),
@@ -73,6 +74,10 @@ ReanimatedModuleProxy::ReanimatedModuleProxy(
73
74
  layoutAnimationsManager_(
74
75
  std::make_shared<LayoutAnimationsManager>(jsLogger_)),
75
76
  #ifdef RCT_NEW_ARCH_ENABLED
77
+ #ifdef ANDROID
78
+ filterUnmountedTagsFunction_(
79
+ platformDepMethodsHolder.filterUnmountedTagsFunction),
80
+ #endif // ANDROID
76
81
  propsRegistry_(std::make_shared<PropsRegistry>()),
77
82
  #else
78
83
  obtainPropFunction_(platformDepMethodsHolder.obtainPropFunction),
@@ -410,10 +415,9 @@ std::string ReanimatedModuleProxy::obtainPropFromShadowNode(
410
415
  }
411
416
  }
412
417
 
413
- throw std::runtime_error(
414
- std::string(
415
- "Getting property `" + propName +
416
- "` with function `getViewProp` is not supported"));
418
+ throw std::runtime_error(std::string(
419
+ "Getting property `" + propName +
420
+ "` with function `getViewProp` is not supported"));
417
421
  }
418
422
 
419
423
  jsi::Value ReanimatedModuleProxy::getViewProp(
@@ -621,6 +625,7 @@ void ReanimatedModuleProxy::cleanupSensors() {
621
625
  void ReanimatedModuleProxy::markNodeAsRemovable(
622
626
  jsi::Runtime &rt,
623
627
  const jsi::Value &shadowNodeWrapper) {
628
+ auto lock = propsRegistry_->createLock();
624
629
  auto shadowNode = shadowNodeFromValue(rt, shadowNodeWrapper);
625
630
  propsRegistry_->markNodeAsRemovable(shadowNode);
626
631
  }
@@ -628,6 +633,7 @@ void ReanimatedModuleProxy::markNodeAsRemovable(
628
633
  void ReanimatedModuleProxy::unmarkNodeAsRemovable(
629
634
  jsi::Runtime &rt,
630
635
  const jsi::Value &viewTag) {
636
+ auto lock = propsRegistry_->createLock();
631
637
  propsRegistry_->unmarkNodeAsRemovable(viewTag.asNumber());
632
638
  }
633
639
 
@@ -941,7 +947,14 @@ void ReanimatedModuleProxy::initializeLayoutAnimationsProxy() {
941
947
  componentDescriptorRegistry,
942
948
  scheduler->getContextContainer(),
943
949
  uiWorkletRuntime_->getJSIRuntime(),
944
- workletsModuleProxy_->getUIScheduler());
950
+ workletsModuleProxy_->getUIScheduler()
951
+ #ifdef ANDROID
952
+ ,
953
+ filterUnmountedTagsFunction_,
954
+ uiManager_,
955
+ jsInvoker_
956
+ #endif
957
+ );
945
958
  }
946
959
  }
947
960
 
@@ -223,6 +223,9 @@ class ReanimatedModuleProxy
223
223
  std::shared_ptr<LayoutAnimationsManager> layoutAnimationsManager_;
224
224
 
225
225
  #ifdef RCT_NEW_ARCH_ENABLED
226
+ #ifdef ANDROID
227
+ const PreserveMountedTagsFunction filterUnmountedTagsFunction_;
228
+ #endif // ANDROID
226
229
  std::unordered_set<std::string>
227
230
  animatablePropNames_; // filled by configureProps
228
231
  std::shared_ptr<UIManager> uiManager_;
@@ -6,6 +6,8 @@
6
6
  #include <react/renderer/core/ReactPrimitives.h>
7
7
  #endif
8
8
 
9
+ #include <memory>
10
+ #include <optional>
9
11
  #include <string>
10
12
  #include <utility>
11
13
  #include <vector>
@@ -53,6 +55,10 @@ using ObtainPropFunction =
53
55
 
54
56
  using RequestRenderFunction =
55
57
  std::function<void(std::function<void(const double)>)>;
58
+ #ifdef ANDROID
59
+ using PreserveMountedTagsFunction =
60
+ std::function<std::optional<std::unique_ptr<int[]>>(std::vector<int> &)>;
61
+ #endif // ANDROID
56
62
  using GetAnimationTimestampFunction = std::function<double(void)>;
57
63
 
58
64
  using ProgressLayoutAnimationFunction =
@@ -75,7 +81,9 @@ using MaybeFlushUIUpdatesQueueFunction = std::function<void()>;
75
81
  struct PlatformDepMethodsHolder {
76
82
  RequestRenderFunction requestRender;
77
83
  #ifdef RCT_NEW_ARCH_ENABLED
78
- // nothing
84
+ #ifdef ANDROID
85
+ PreserveMountedTagsFunction filterUnmountedTagsFunction;
86
+ #endif // ANDROID
79
87
  #else
80
88
  UpdatePropsFunction updatePropsFunction;
81
89
  ScrollToFunction scrollToFunction;
@@ -15,9 +15,16 @@ string(APPEND CMAKE_CXX_FLAGS
15
15
  " -DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}\
16
16
  -DREANIMATED_VERSION=${REANIMATED_VERSION}")
17
17
 
18
- string(APPEND CMAKE_CXX_FLAGS
19
- " -fexceptions -fno-omit-frame-pointer -frtti -fstack-protector-all\
20
- -std=c++${CMAKE_CXX_STANDARD} -Wall -Werror")
18
+ string(APPEND CMAKE_CXX_FLAGS " -fno-omit-frame-pointer -fstack-protector-all")
19
+
20
+ if(ReactAndroid_VERSION_MINOR GREATER_EQUAL 80)
21
+ include("${REACT_NATIVE_DIR}/ReactCommon/cmake-utils/\
22
+ react-native-flags.cmake")
23
+ target_compile_reactnative_options(reanimated PUBLIC)
24
+ else()
25
+ string(APPEND CMAKE_CXX_FLAGS
26
+ " -fexceptions -frtti -std=c++${CMAKE_CXX_STANDARD} -Wall -Werror")
27
+ endif()
21
28
 
22
29
  if(${IS_NEW_ARCHITECTURE_ENABLED})
23
30
  string(APPEND CMAKE_CXX_FLAGS " -DRCT_NEW_ARCH_ENABLED")
@@ -332,8 +332,8 @@ android {
332
332
  extractSO
333
333
  }
334
334
  compileOptions {
335
- sourceCompatibility JavaVersion.VERSION_1_8
336
- targetCompatibility JavaVersion.VERSION_1_8
335
+ sourceCompatibility JavaVersion.VERSION_17
336
+ targetCompatibility JavaVersion.VERSION_17
337
337
  }
338
338
  sourceSets.main {
339
339
  java {
@@ -380,7 +380,7 @@ android {
380
380
 
381
381
  def assertMinimalReactNativeVersion = task assertMinimalReactNativeVersionTask {
382
382
  // If you change the minimal React Native version remember to update Compatibility Table in docs
383
- def minimalReactNativeVersion = 75
383
+ def minimalReactNativeVersion = 78
384
384
  onlyIf { REACT_NATIVE_MINOR_VERSION < minimalReactNativeVersion }
385
385
  doFirst {
386
386
  throw new GradleException("[Reanimated] Unsupported React Native version. Please use $minimalReactNativeVersion. or newer.")
@@ -4,6 +4,7 @@ import androidx.annotation.OptIn;
4
4
  import com.facebook.jni.HybridData;
5
5
  import com.facebook.proguard.annotations.DoNotStrip;
6
6
  import com.facebook.react.bridge.ReactApplicationContext;
7
+ import com.facebook.react.bridge.UiThreadUtil;
7
8
  import com.facebook.react.common.annotations.FrameworkAPI;
8
9
  import com.facebook.react.fabric.FabricUIManager;
9
10
  import com.facebook.react.turbomodule.core.CallInvokerHolderImpl;
@@ -32,6 +33,8 @@ public class NativeProxy extends NativeProxyCommon {
32
33
  */
33
34
  private final AtomicBoolean mInvalidated = new AtomicBoolean(false);
34
35
 
36
+ private final FabricUIManager mFabricUIManager;
37
+
35
38
  public @OptIn(markerClass = FrameworkAPI.class) NativeProxy(
36
39
  ReactApplicationContext context, WorkletsModule workletsModule) {
37
40
  super(context);
@@ -39,6 +42,7 @@ public class NativeProxy extends NativeProxyCommon {
39
42
 
40
43
  FabricUIManager fabricUIManager =
41
44
  (FabricUIManager) UIManagerHelper.getUIManager(context, UIManagerType.FABRIC);
45
+ mFabricUIManager = fabricUIManager;
42
46
 
43
47
  LayoutAnimations LayoutAnimations = new LayoutAnimations(context);
44
48
 
@@ -72,6 +76,21 @@ public class NativeProxy extends NativeProxyCommon {
72
76
 
73
77
  public native void performOperations();
74
78
 
79
+ @DoNotStrip
80
+ public boolean preserveMountedTags(int[] tags) {
81
+ if (!UiThreadUtil.isOnUiThread()) {
82
+ return false;
83
+ }
84
+
85
+ for (int i = 0; i < tags.length; i++) {
86
+ if (mFabricUIManager.resolveView(tags[i]) == null) {
87
+ tags[i] = -1;
88
+ }
89
+ }
90
+
91
+ return true;
92
+ }
93
+
75
94
  @Override
76
95
  protected HybridData getHybridData() {
77
96
  return mHybridData;