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.
- package/Common/cpp/reanimated/Fabric/PropsRegistry.cpp +13 -15
- package/Common/cpp/reanimated/Fabric/PropsRegistry.h +8 -6
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +138 -34
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h +32 -3
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +27 -14
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +3 -0
- package/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +9 -1
- package/android/CMakeLists.txt +10 -3
- package/android/build.gradle +3 -3
- package/android/src/fabric/java/com/swmansion/reanimated/NativeProxy.java +19 -0
- package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +37 -12
- package/android/src/main/cpp/reanimated/android/NativeProxy.h +8 -2
- package/android/src/main/java/com/swmansion/worklets/WorkletsMessageQueueThreadBase.java +1 -2
- package/lib/module/ViewDescriptorsSet.js +5 -1
- package/lib/module/ViewDescriptorsSet.js.map +1 -1
- package/lib/module/animation/util.js +5 -3
- package/lib/module/animation/util.js.map +1 -1
- package/lib/module/component/ReducedMotionConfig.js +1 -1
- package/lib/module/createAnimatedComponent/NativeEventsManager.js +1 -1
- package/lib/module/createAnimatedComponent/NativeEventsManager.js.map +1 -1
- package/lib/module/createAnimatedComponent/createAnimatedComponent.js +28 -11
- package/lib/module/createAnimatedComponent/createAnimatedComponent.js.map +1 -1
- package/lib/module/layoutReanimation/web/Easing.web.js +14 -0
- package/lib/module/layoutReanimation/web/Easing.web.js.map +1 -1
- package/lib/module/layoutReanimation/web/animationParser.js.map +1 -1
- package/lib/module/layoutReanimation/web/componentUtils.js +52 -14
- package/lib/module/layoutReanimation/web/componentUtils.js.map +1 -1
- package/lib/module/layoutReanimation/web/config.js.map +1 -1
- package/lib/module/layoutReanimation/web/createAnimation.js +12 -0
- package/lib/module/layoutReanimation/web/createAnimation.js.map +1 -1
- package/lib/module/layoutReanimation/web/domUtils.js +1 -1
- package/lib/module/layoutReanimation/web/domUtils.js.map +1 -1
- package/lib/module/layoutReanimation/web/transition/Curved.web.js +1 -0
- package/lib/module/layoutReanimation/web/transition/Curved.web.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/module/platformFunctions/dispatchCommand.js +10 -0
- package/lib/module/platformFunctions/dispatchCommand.js.map +1 -1
- package/lib/module/platformFunctions/scrollTo.web.js +11 -7
- package/lib/module/platformFunctions/scrollTo.web.js.map +1 -1
- package/lib/module/runtimes.js +1 -1
- package/lib/module/threads.js +5 -5
- package/lib/typescript/ViewDescriptorsSet.d.ts +1 -0
- package/lib/typescript/ViewDescriptorsSet.d.ts.map +1 -1
- package/lib/typescript/animation/util.d.ts.map +1 -1
- package/lib/typescript/component/ReducedMotionConfig.d.ts +1 -1
- package/lib/typescript/createAnimatedComponent/createAnimatedComponent.d.ts.map +1 -1
- package/lib/typescript/helperTypes.d.ts +4 -1
- package/lib/typescript/helperTypes.d.ts.map +1 -1
- package/lib/typescript/layoutReanimation/web/Easing.web.d.ts +2 -0
- package/lib/typescript/layoutReanimation/web/Easing.web.d.ts.map +1 -1
- package/lib/typescript/layoutReanimation/web/animationParser.d.ts +3 -0
- package/lib/typescript/layoutReanimation/web/animationParser.d.ts.map +1 -1
- package/lib/typescript/layoutReanimation/web/componentUtils.d.ts.map +1 -1
- package/lib/typescript/layoutReanimation/web/config.d.ts +4 -4
- package/lib/typescript/layoutReanimation/web/config.d.ts.map +1 -1
- package/lib/typescript/layoutReanimation/web/createAnimation.d.ts.map +1 -1
- package/lib/typescript/layoutReanimation/web/transition/Curved.web.d.ts.map +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/lib/typescript/platformFunctions/scrollTo.web.d.ts.map +1 -1
- package/lib/typescript/runtimes.d.ts +1 -1
- package/lib/typescript/threads.d.ts +5 -5
- package/package.json +1 -1
- package/scripts/reanimated_utils.rb +1 -1
- package/src/ViewDescriptorsSet.ts +9 -0
- package/src/animation/util.ts +6 -4
- package/src/component/ReducedMotionConfig.tsx +1 -1
- package/src/createAnimatedComponent/NativeEventsManager.ts +1 -1
- package/src/createAnimatedComponent/createAnimatedComponent.tsx +35 -24
- package/src/helperTypes.ts +5 -1
- package/src/layoutReanimation/web/Easing.web.ts +32 -0
- package/src/layoutReanimation/web/animationParser.ts +3 -0
- package/src/layoutReanimation/web/componentUtils.ts +69 -16
- package/src/layoutReanimation/web/config.ts +7 -3
- package/src/layoutReanimation/web/createAnimation.ts +15 -0
- package/src/layoutReanimation/web/domUtils.ts +1 -1
- package/src/layoutReanimation/web/transition/Curved.web.ts +1 -0
- package/src/platform-specific/jsVersion.ts +1 -1
- package/src/platformFunctions/dispatchCommand.ts +23 -2
- package/src/platformFunctions/scrollTo.web.ts +9 -3
- package/src/runtimes.ts +1 -1
- 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
|
-
|
|
29
|
-
|
|
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
|
-
|
|
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
|
-
|
|
53
|
-
if (!
|
|
54
|
-
++it;
|
|
47
|
+
for (const auto &[tag, shadowNode] : removableShadowNodes_) {
|
|
48
|
+
if (!shadowNode) {
|
|
55
49
|
continue;
|
|
56
50
|
}
|
|
57
51
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
26
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
325
|
-
|
|
326
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
425
|
-
|
|
426
|
-
*newView,
|
|
451
|
+
mutations.push_back(ShadowViewMutation::UpdateMutation(
|
|
452
|
+
*layoutAnimation.currentView,
|
|
453
|
+
*newView,
|
|
427
454
|
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
428
|
-
|
|
455
|
+
layoutAnimation.parentTag
|
|
429
456
|
#else
|
|
430
|
-
|
|
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
|
-
|
|
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{
|
|
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,
|
|
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
|
-
|
|
702
|
-
finalView,
|
|
703
|
-
current,
|
|
728
|
+
tag, LayoutAnimation {
|
|
729
|
+
finalView, current,
|
|
704
730
|
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
705
|
-
|
|
731
|
+
mutation.parentTag,
|
|
706
732
|
#else
|
|
707
733
|
parent,
|
|
708
734
|
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
709
|
-
|
|
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.
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
-
|
|
415
|
-
|
|
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
|
-
|
|
84
|
+
#ifdef ANDROID
|
|
85
|
+
PreserveMountedTagsFunction filterUnmountedTagsFunction;
|
|
86
|
+
#endif // ANDROID
|
|
79
87
|
#else
|
|
80
88
|
UpdatePropsFunction updatePropsFunction;
|
|
81
89
|
ScrollToFunction scrollToFunction;
|
package/android/CMakeLists.txt
CHANGED
|
@@ -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
|
-
|
|
20
|
-
|
|
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")
|
package/android/build.gradle
CHANGED
|
@@ -332,8 +332,8 @@ android {
|
|
|
332
332
|
extractSO
|
|
333
333
|
}
|
|
334
334
|
compileOptions {
|
|
335
|
-
sourceCompatibility JavaVersion.
|
|
336
|
-
targetCompatibility JavaVersion.
|
|
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 =
|
|
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;
|