react-native-reanimated 4.4.1 → 4.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Common/cpp/reanimated/CSS/interpolation/transforms/TransformOperationInterpolator.cpp +12 -5
- package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.cpp +63 -36
- package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h +6 -8
- package/Common/cpp/reanimated/CSS/svg/values/SVGStrokeDashArray.cpp +5 -0
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +25 -12
- package/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +3 -0
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.cpp +6 -2
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +44 -1
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +125 -43
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +189 -102
- package/Common/cpp/reanimated/LayoutAnimations/SharedTransitions.cpp +8 -3
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +4 -16
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +0 -16
- package/android/CMakeLists.txt +6 -0
- package/android/build.gradle.kts +12 -1
- package/android/src/main/java/com/swmansion/reanimated/NativeProxy.kt +46 -2
- package/android/src/main/java/com/swmansion/reanimated/keyboard/KeyboardAnimationCallback.kt +8 -1
- package/apple/reanimated/apple/ReanimatedModule.mm +12 -1
- package/compatibility.json +1 -1
- package/lib/module/common/constants/platform.js +4 -4
- package/lib/module/common/constants/platform.js.map +1 -1
- package/lib/module/createAnimatedComponent/getViewInfo.js +3 -1
- package/lib/module/createAnimatedComponent/getViewInfo.js.map +1 -1
- package/lib/module/css/component/AnimatedComponent.js +0 -2
- package/lib/module/css/component/AnimatedComponent.js.map +1 -1
- package/lib/module/css/native/managers/CSSManager.js +5 -5
- package/lib/module/css/native/managers/CSSManager.js.map +1 -1
- package/lib/module/css/native/managers/CSSTransitionsManager.js +8 -1
- package/lib/module/css/native/managers/CSSTransitionsManager.js.map +1 -1
- package/lib/module/css/svg/native/processors/stroke.js +9 -5
- package/lib/module/css/svg/native/processors/stroke.js.map +1 -1
- package/lib/module/layoutReanimation/animationBuilder/ComplexAnimationBuilder.js +6 -3
- package/lib/module/layoutReanimation/animationBuilder/ComplexAnimationBuilder.js.map +1 -1
- package/lib/module/layoutReanimation/animationsManager.js +31 -6
- package/lib/module/layoutReanimation/animationsManager.js.map +1 -1
- package/lib/module/mappers.js +1 -1
- package/lib/module/mappers.js.map +1 -1
- package/lib/module/platform-specific/findHostInstance.js +8 -5
- package/lib/module/platform-specific/findHostInstance.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/module/updateProps/updateProps.js +3 -2
- package/lib/module/updateProps/updateProps.js.map +1 -1
- package/lib/module/valueSetter.js +6 -7
- package/lib/module/valueSetter.js.map +1 -1
- package/lib/typescript/common/constants/platform.d.ts.map +1 -1
- package/lib/typescript/createAnimatedComponent/commonTypes.d.ts +0 -1
- package/lib/typescript/createAnimatedComponent/commonTypes.d.ts.map +1 -1
- package/lib/typescript/createAnimatedComponent/getViewInfo.d.ts.map +1 -1
- package/lib/typescript/css/component/AnimatedComponent.d.ts +0 -1
- package/lib/typescript/css/component/AnimatedComponent.d.ts.map +1 -1
- package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts +5 -1
- package/lib/typescript/css/native/managers/CSSTransitionsManager.d.ts.map +1 -1
- package/lib/typescript/css/svg/native/processors/stroke.d.ts.map +1 -1
- package/lib/typescript/layoutReanimation/animationBuilder/ComplexAnimationBuilder.d.ts +17 -14
- package/lib/typescript/layoutReanimation/animationBuilder/ComplexAnimationBuilder.d.ts.map +1 -1
- package/lib/typescript/layoutReanimation/animationsManager.d.ts.map +1 -1
- package/lib/typescript/platform-specific/findHostInstance.d.ts.map +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/lib/typescript/platform-specific/types.d.ts +1 -0
- package/lib/typescript/platform-specific/types.d.ts.map +1 -1
- package/lib/typescript/updateProps/updateProps.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/common/constants/platform.ts +4 -4
- package/src/createAnimatedComponent/commonTypes.ts +0 -1
- package/src/createAnimatedComponent/getViewInfo.ts +3 -1
- package/src/css/component/AnimatedComponent.tsx +0 -2
- package/src/css/native/managers/CSSManager.ts +8 -8
- package/src/css/native/managers/CSSTransitionsManager.ts +9 -2
- package/src/css/svg/native/processors/stroke.ts +9 -6
- package/src/layoutReanimation/animationBuilder/ComplexAnimationBuilder.ts +39 -36
- package/src/layoutReanimation/animationsManager.ts +33 -5
- package/src/mappers.ts +1 -1
- package/src/platform-specific/findHostInstance.ts +7 -7
- package/src/platform-specific/jsVersion.ts +1 -1
- package/src/platform-specific/types.ts +2 -0
- package/src/updateProps/updateProps.ts +3 -2
- package/src/valueSetter.ts +7 -7
|
@@ -276,11 +276,10 @@ std::optional<SurfaceId> LayoutAnimationsProxy_Experimental::endLayoutAnimation(
|
|
|
276
276
|
// one after the other, so we need to keep count of how many
|
|
277
277
|
// were actually triggered, so that we don't cleanup necessary
|
|
278
278
|
// structures too early
|
|
279
|
-
if (layoutAnimation.count >
|
|
280
|
-
layoutAnimation.count--;
|
|
279
|
+
if (--layoutAnimation.count > 0) {
|
|
281
280
|
return {};
|
|
282
281
|
}
|
|
283
|
-
|
|
282
|
+
maybeSettledAnimationTags_.insert(tag);
|
|
284
283
|
auto surfaceId = layoutAnimation.finalView.surfaceId;
|
|
285
284
|
|
|
286
285
|
if (sharedTransitionManager_->tagToName_.contains(tag)) {
|
|
@@ -397,7 +396,7 @@ void LayoutAnimationsProxy_Experimental::addOngoingAnimations(SurfaceId surfaceI
|
|
|
397
396
|
|
|
398
397
|
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
399
398
|
|
|
400
|
-
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
399
|
+
if (layoutAnimationIt == layoutAnimations_.end() || layoutAnimationIt->second.isSettled()) {
|
|
401
400
|
continue;
|
|
402
401
|
}
|
|
403
402
|
|
|
@@ -516,11 +515,10 @@ bool LayoutAnimationsProxy_Experimental::startAnimationsRecursively(
|
|
|
516
515
|
|
|
517
516
|
if (hasExitAnimation) {
|
|
518
517
|
node->state = ANIMATING;
|
|
519
|
-
startExitingAnimation(node);
|
|
520
518
|
lightNodes_[node->current.tag] = node;
|
|
519
|
+
startExitingAnimation(node);
|
|
521
520
|
} else {
|
|
522
|
-
|
|
523
|
-
// layoutAnimationsManager_->clearLayoutAnimationConfig(node->tag);
|
|
521
|
+
layoutAnimationsManager_->clearLayoutAnimationConfig(node->current.tag);
|
|
524
522
|
}
|
|
525
523
|
|
|
526
524
|
return wantAnimateExit;
|
|
@@ -532,10 +530,22 @@ void LayoutAnimationsProxy_Experimental::updateOngoingAnimationTarget(const int
|
|
|
532
530
|
}
|
|
533
531
|
|
|
534
532
|
void LayoutAnimationsProxy_Experimental::maybeCancelAnimation(const int tag) const {
|
|
535
|
-
|
|
533
|
+
#ifdef ANDROID
|
|
534
|
+
// also invalidate animation starts that are scheduled but haven't run yet,
|
|
535
|
+
// so they don't re-create the animation after this cancellation
|
|
536
|
+
if (const auto it = pendingStarts_.find(tag); it != pendingStarts_.end()) {
|
|
537
|
+
it->second.handle++;
|
|
538
|
+
}
|
|
539
|
+
#endif
|
|
540
|
+
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
541
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
542
|
+
return;
|
|
543
|
+
}
|
|
544
|
+
if (layoutAnimationIt->second.isSettled()) {
|
|
545
|
+
// Already settled - cleanupAnimations will erase it together with its updateMap entry.
|
|
536
546
|
return;
|
|
537
547
|
}
|
|
538
|
-
layoutAnimations_.erase(
|
|
548
|
+
layoutAnimations_.erase(layoutAnimationIt);
|
|
539
549
|
scheduleOnUI(uiScheduler_, [weakThis = weak_from_this(), tag]() {
|
|
540
550
|
auto strongThis = weakThis.lock();
|
|
541
551
|
if (!strongThis) {
|
|
@@ -625,12 +635,17 @@ void LayoutAnimationsProxy_Experimental::cleanupAnimations(
|
|
|
625
635
|
#ifdef ANDROID
|
|
626
636
|
restoreOpacityInCaseOfFlakyEnteringAnimation(surfaceId);
|
|
627
637
|
#endif // ANDROID
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
638
|
+
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
639
|
+
for (const auto tag : maybeSettledAnimationTags_) {
|
|
640
|
+
// Skip tags re-animated since they settled (count back above 0).
|
|
641
|
+
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
642
|
+
if (layoutAnimationIt == layoutAnimations_.end() || !layoutAnimationIt->second.isSettled()) {
|
|
643
|
+
continue;
|
|
644
|
+
}
|
|
645
|
+
layoutAnimations_.erase(layoutAnimationIt);
|
|
631
646
|
updateMap.erase(tag);
|
|
632
647
|
}
|
|
633
|
-
|
|
648
|
+
maybeSettledAnimationTags_.clear();
|
|
634
649
|
}
|
|
635
650
|
|
|
636
651
|
// MARK: Start Animation
|
|
@@ -676,9 +691,24 @@ void LayoutAnimationsProxy_Experimental::startEnteringAnimation(const std::share
|
|
|
676
691
|
const auto &parent = node->parent.lock();
|
|
677
692
|
react_native_assert(parent && "Parent node is nullptr");
|
|
678
693
|
const auto parentTag = parent->current.tag;
|
|
694
|
+
#ifdef ANDROID
|
|
695
|
+
const auto handle = pendingStarts_[newChildShadowView.tag].handle;
|
|
696
|
+
pendingStarts_[newChildShadowView.tag].count++;
|
|
697
|
+
#endif
|
|
679
698
|
|
|
680
699
|
scheduleOnUI(
|
|
681
|
-
uiScheduler_,
|
|
700
|
+
uiScheduler_,
|
|
701
|
+
[weakThis = weak_from_this(),
|
|
702
|
+
finalView,
|
|
703
|
+
currentView,
|
|
704
|
+
newChildShadowView,
|
|
705
|
+
parentTag,
|
|
706
|
+
opacity
|
|
707
|
+
#ifdef ANDROID
|
|
708
|
+
,
|
|
709
|
+
handle
|
|
710
|
+
#endif
|
|
711
|
+
]() {
|
|
682
712
|
auto strongThis = weakThis.lock();
|
|
683
713
|
if (!strongThis) {
|
|
684
714
|
return;
|
|
@@ -688,6 +718,12 @@ void LayoutAnimationsProxy_Experimental::startEnteringAnimation(const std::share
|
|
|
688
718
|
const auto tag = newChildShadowView.tag;
|
|
689
719
|
{
|
|
690
720
|
auto lock = std::unique_lock<std::recursive_mutex>(strongThis->mutex);
|
|
721
|
+
#ifdef ANDROID
|
|
722
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
723
|
+
// the view was removed before this start could run
|
|
724
|
+
return;
|
|
725
|
+
}
|
|
726
|
+
#endif
|
|
691
727
|
strongThis->layoutAnimations_[tag] = {
|
|
692
728
|
.finalView = newChildShadowView,
|
|
693
729
|
.currentView = newChildShadowView,
|
|
@@ -721,38 +757,63 @@ void LayoutAnimationsProxy_Experimental::startExitingAnimation(const std::shared
|
|
|
721
757
|
const auto &parent = node->parent.lock();
|
|
722
758
|
react_native_assert(parent && "Parent node is nullptr");
|
|
723
759
|
const auto parentTag = parent->current.tag;
|
|
760
|
+
#ifdef ANDROID
|
|
761
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
762
|
+
pendingStarts_[tag].count++;
|
|
763
|
+
#endif
|
|
724
764
|
|
|
725
|
-
scheduleOnUI(
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
765
|
+
scheduleOnUI(
|
|
766
|
+
uiScheduler_,
|
|
767
|
+
[weakThis = weak_from_this(),
|
|
768
|
+
tag,
|
|
769
|
+
parentTag,
|
|
770
|
+
oldChildShadowView,
|
|
771
|
+
surfaceId
|
|
772
|
+
#ifdef ANDROID
|
|
773
|
+
,
|
|
774
|
+
handle
|
|
775
|
+
#endif
|
|
776
|
+
]() {
|
|
777
|
+
auto strongThis = weakThis.lock();
|
|
778
|
+
if (!strongThis) {
|
|
779
|
+
return;
|
|
780
|
+
}
|
|
730
781
|
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
782
|
+
auto oldView = oldChildShadowView;
|
|
783
|
+
Rect window{};
|
|
784
|
+
{
|
|
785
|
+
auto &mutex = strongThis->mutex;
|
|
786
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
787
|
+
#ifdef ANDROID
|
|
788
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
789
|
+
// the view was removed (e.g. its subtree was force-ended by a screen
|
|
790
|
+
// pop) before this start could run — its Remove+Delete are already on
|
|
791
|
+
// their way to the mounting layer, so starting the animation now
|
|
792
|
+
// would emit updates for a view that's about to be deleted
|
|
793
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
794
|
+
return;
|
|
795
|
+
}
|
|
796
|
+
#endif
|
|
797
|
+
oldView = strongThis->maybeCreateLayoutAnimation(oldView, oldView, parentTag);
|
|
798
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
799
|
+
}
|
|
739
800
|
|
|
740
|
-
|
|
801
|
+
const Snapshot values(oldView, window);
|
|
741
802
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
803
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
804
|
+
const jsi::Object yogaValues(uiRuntime);
|
|
805
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
|
|
806
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
|
|
807
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
|
|
808
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
|
|
809
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
|
|
810
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
|
|
811
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
812
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
813
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
814
|
+
uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
|
|
815
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
816
|
+
});
|
|
756
817
|
}
|
|
757
818
|
|
|
758
819
|
void LayoutAnimationsProxy_Experimental::startLayoutAnimation(const std::shared_ptr<LightNode> &node) const {
|
|
@@ -763,9 +824,24 @@ void LayoutAnimationsProxy_Experimental::startLayoutAnimation(const std::shared_
|
|
|
763
824
|
const auto &parent = node->parent.lock();
|
|
764
825
|
react_native_assert(parent && "Parent node is nullptr");
|
|
765
826
|
const auto parentTag = parent->current.tag;
|
|
827
|
+
#ifdef ANDROID
|
|
828
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
829
|
+
pendingStarts_[tag].count++;
|
|
830
|
+
#endif
|
|
766
831
|
|
|
767
832
|
scheduleOnUI(
|
|
768
|
-
uiScheduler_,
|
|
833
|
+
uiScheduler_,
|
|
834
|
+
[weakThis = weak_from_this(),
|
|
835
|
+
surfaceId,
|
|
836
|
+
oldChildShadowView,
|
|
837
|
+
newChildShadowView,
|
|
838
|
+
parentTag,
|
|
839
|
+
tag
|
|
840
|
+
#ifdef ANDROID
|
|
841
|
+
,
|
|
842
|
+
handle
|
|
843
|
+
#endif
|
|
844
|
+
]() {
|
|
769
845
|
auto strongThis = weakThis.lock();
|
|
770
846
|
if (!strongThis) {
|
|
771
847
|
return;
|
|
@@ -776,6 +852,12 @@ void LayoutAnimationsProxy_Experimental::startLayoutAnimation(const std::shared_
|
|
|
776
852
|
{
|
|
777
853
|
auto &mutex = strongThis->mutex;
|
|
778
854
|
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
855
|
+
#ifdef ANDROID
|
|
856
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
857
|
+
// the view was removed before this start could run
|
|
858
|
+
return;
|
|
859
|
+
}
|
|
860
|
+
#endif
|
|
779
861
|
oldView = strongThis->maybeCreateLayoutAnimation(oldView, newChildShadowView, parentTag);
|
|
780
862
|
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
781
863
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.h>
|
|
2
2
|
|
|
3
|
+
#include <react/debug/react_native_assert.h>
|
|
3
4
|
#include <react/renderer/mounting/ShadowViewMutation.h>
|
|
4
5
|
|
|
5
6
|
#include <memory>
|
|
@@ -42,12 +43,18 @@ std::optional<MountingTransaction> LayoutAnimationsProxy_Legacy::pullTransaction
|
|
|
42
43
|
#ifdef ANDROID
|
|
43
44
|
restoreOpacityInCaseOfFlakyEnteringAnimation(surfaceId);
|
|
44
45
|
#endif // ANDROID
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
layoutAnimations_.
|
|
46
|
+
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
47
|
+
for (const auto tag : maybeSettledAnimationTags_) {
|
|
48
|
+
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
49
|
+
if (layoutAnimationIt == layoutAnimations_.end() || !layoutAnimationIt->second.isSettled()) {
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
layoutAnimations_.erase(layoutAnimationIt);
|
|
48
53
|
updateMap.erase(tag);
|
|
49
54
|
}
|
|
50
|
-
|
|
55
|
+
maybeSettledAnimationTags_.clear();
|
|
56
|
+
// Past this point no animation can be settled - we hold the mutex for the whole
|
|
57
|
+
// transaction, so no end callback can run until we return.
|
|
51
58
|
|
|
52
59
|
parseRemoveMutations(movedViews, mutations, roots);
|
|
53
60
|
|
|
@@ -109,11 +116,10 @@ std::optional<SurfaceId> LayoutAnimationsProxy_Legacy::endLayoutAnimation(int ta
|
|
|
109
116
|
// one after the other, so we need to keep count of how many
|
|
110
117
|
// were actually triggered, so that we don't cleanup necessary
|
|
111
118
|
// structures too early
|
|
112
|
-
if (layoutAnimation.count >
|
|
113
|
-
layoutAnimation.count--;
|
|
119
|
+
if (--layoutAnimation.count > 0) {
|
|
114
120
|
return {};
|
|
115
121
|
}
|
|
116
|
-
|
|
122
|
+
maybeSettledAnimationTags_.insert(tag);
|
|
117
123
|
auto surfaceId = layoutAnimation.finalView.surfaceId;
|
|
118
124
|
|
|
119
125
|
if (!shouldRemove || !nodeForTag_.contains(tag)) {
|
|
@@ -121,6 +127,7 @@ std::optional<SurfaceId> LayoutAnimationsProxy_Legacy::endLayoutAnimation(int ta
|
|
|
121
127
|
}
|
|
122
128
|
|
|
123
129
|
auto node = nodeForTag_[tag];
|
|
130
|
+
react_native_assert(node->isMutationNode() && "exiting tag must map to a MutationNode");
|
|
124
131
|
auto mutationNode = std::static_pointer_cast<MutationNode>(node);
|
|
125
132
|
mutationNode->state = ExitingState_Legacy::DEAD;
|
|
126
133
|
auto &[deadNodes] = surfaceContext_[surfaceId];
|
|
@@ -406,7 +413,13 @@ void LayoutAnimationsProxy_Legacy::addOngoingAnimations(SurfaceId surfaceId, Sha
|
|
|
406
413
|
|
|
407
414
|
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
408
415
|
|
|
409
|
-
if (layoutAnimationIt == layoutAnimations_.end()
|
|
416
|
+
if (layoutAnimationIt == layoutAnimations_.end() ||
|
|
417
|
+
// A settled animation is normally cleaned up without applying further
|
|
418
|
+
// updates. The exception is a flaky entering animation whose opacity was
|
|
419
|
+
// never restored (the view wasn't mounted in time) - we still need to
|
|
420
|
+
// apply that pending opacity, otherwise the view stays invisible. Only
|
|
421
|
+
// entering animations carry an opacity value.
|
|
422
|
+
(layoutAnimationIt->second.isSettled() && !layoutAnimationIt->second.opacity.has_value())) {
|
|
410
423
|
continue;
|
|
411
424
|
}
|
|
412
425
|
|
|
@@ -633,38 +646,60 @@ void LayoutAnimationsProxy_Legacy::startEnteringAnimation(const int tag, ShadowV
|
|
|
633
646
|
|
|
634
647
|
auto &viewProps = static_cast<const ViewProps &>(*mutation.newChildShadowView.props);
|
|
635
648
|
auto opacity = viewProps.opacity;
|
|
649
|
+
#ifdef ANDROID
|
|
650
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
651
|
+
pendingStarts_[tag].count++;
|
|
652
|
+
#endif
|
|
636
653
|
|
|
637
|
-
scheduleOnUI(
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
654
|
+
scheduleOnUI(
|
|
655
|
+
uiScheduler_,
|
|
656
|
+
[weakThis = weak_from_this(),
|
|
657
|
+
finalView,
|
|
658
|
+
current,
|
|
659
|
+
mutation,
|
|
660
|
+
opacity,
|
|
661
|
+
tag
|
|
662
|
+
#ifdef ANDROID
|
|
663
|
+
,
|
|
664
|
+
handle
|
|
665
|
+
#endif
|
|
666
|
+
]() {
|
|
667
|
+
auto strongThis = weakThis.lock();
|
|
668
|
+
if (!strongThis) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
642
671
|
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
tag,
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
672
|
+
Rect window{};
|
|
673
|
+
{
|
|
674
|
+
auto &mutex = strongThis->mutex;
|
|
675
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
676
|
+
#ifdef ANDROID
|
|
677
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
678
|
+
// the view was removed before this start could run
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
#endif
|
|
682
|
+
strongThis->layoutAnimations_.insert_or_assign(
|
|
683
|
+
tag,
|
|
684
|
+
LayoutAnimation{
|
|
685
|
+
.finalView = finalView, .currentView = current, .parentTag = mutation.parentTag, .opacity = opacity});
|
|
686
|
+
window = strongThis->surfaceManager.getWindow(mutation.newChildShadowView.surfaceId);
|
|
687
|
+
}
|
|
653
688
|
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
689
|
+
Snapshot values(mutation.newChildShadowView, window);
|
|
690
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
691
|
+
jsi::Object yogaValues(uiRuntime);
|
|
692
|
+
yogaValues.setProperty(uiRuntime, "targetOriginX", values.x);
|
|
693
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", values.x);
|
|
694
|
+
yogaValues.setProperty(uiRuntime, "targetOriginY", values.y);
|
|
695
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", values.y);
|
|
696
|
+
yogaValues.setProperty(uiRuntime, "targetWidth", values.width);
|
|
697
|
+
yogaValues.setProperty(uiRuntime, "targetHeight", values.height);
|
|
698
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
699
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
700
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
701
|
+
uiRuntime, tag, LayoutAnimationType::ENTERING, yogaValues);
|
|
702
|
+
});
|
|
668
703
|
}
|
|
669
704
|
|
|
670
705
|
void LayoutAnimationsProxy_Legacy::startExitingAnimation(const int tag, ShadowViewMutation &mutation) const {
|
|
@@ -672,38 +707,62 @@ void LayoutAnimationsProxy_Legacy::startExitingAnimation(const int tag, ShadowVi
|
|
|
672
707
|
LOG(INFO) << "start exiting animation for tag " << tag << std::endl;
|
|
673
708
|
#endif
|
|
674
709
|
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
710
|
+
#ifdef ANDROID
|
|
711
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
712
|
+
pendingStarts_[tag].count++;
|
|
713
|
+
#endif
|
|
675
714
|
|
|
676
|
-
scheduleOnUI(
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
715
|
+
scheduleOnUI(
|
|
716
|
+
uiScheduler_,
|
|
717
|
+
[weakThis = weak_from_this(),
|
|
718
|
+
tag,
|
|
719
|
+
mutation,
|
|
720
|
+
surfaceId
|
|
721
|
+
#ifdef ANDROID
|
|
722
|
+
,
|
|
723
|
+
handle
|
|
724
|
+
#endif
|
|
725
|
+
]() {
|
|
726
|
+
auto strongThis = weakThis.lock();
|
|
727
|
+
if (!strongThis) {
|
|
728
|
+
return;
|
|
729
|
+
}
|
|
690
730
|
|
|
691
|
-
|
|
731
|
+
auto oldView = mutation.oldChildShadowView;
|
|
732
|
+
Rect window{};
|
|
733
|
+
{
|
|
734
|
+
auto &mutex = strongThis->mutex;
|
|
735
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
736
|
+
#ifdef ANDROID
|
|
737
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
738
|
+
// the view was removed (e.g. its subtree was force-ended by a screen
|
|
739
|
+
// pop) before this start could run — its Remove+Delete are already on
|
|
740
|
+
// their way to the mounting layer, so starting the animation now
|
|
741
|
+
// would emit updates for a view that's about to be deleted
|
|
742
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
743
|
+
return;
|
|
744
|
+
}
|
|
745
|
+
#endif
|
|
746
|
+
strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
747
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
748
|
+
}
|
|
692
749
|
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
uiRuntime,
|
|
705
|
-
|
|
706
|
-
|
|
750
|
+
Snapshot values(oldView, window);
|
|
751
|
+
|
|
752
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
753
|
+
jsi::Object yogaValues(uiRuntime);
|
|
754
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
|
|
755
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
|
|
756
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
|
|
757
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
|
|
758
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
|
|
759
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
|
|
760
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
761
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
762
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
763
|
+
uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
|
|
764
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
765
|
+
});
|
|
707
766
|
}
|
|
708
767
|
|
|
709
768
|
void LayoutAnimationsProxy_Legacy::startLayoutAnimation(const int tag, const ShadowViewMutation &mutation) const {
|
|
@@ -711,43 +770,64 @@ void LayoutAnimationsProxy_Legacy::startLayoutAnimation(const int tag, const Sha
|
|
|
711
770
|
LOG(INFO) << "start layout animation for tag " << tag << std::endl;
|
|
712
771
|
#endif
|
|
713
772
|
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
773
|
+
#ifdef ANDROID
|
|
774
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
775
|
+
pendingStarts_[tag].count++;
|
|
776
|
+
#endif
|
|
714
777
|
|
|
715
|
-
scheduleOnUI(
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
778
|
+
scheduleOnUI(
|
|
779
|
+
uiScheduler_,
|
|
780
|
+
[weakThis = weak_from_this(),
|
|
781
|
+
mutation,
|
|
782
|
+
surfaceId,
|
|
783
|
+
tag
|
|
784
|
+
#ifdef ANDROID
|
|
785
|
+
,
|
|
786
|
+
handle
|
|
787
|
+
#endif
|
|
788
|
+
]() {
|
|
789
|
+
auto strongThis = weakThis.lock();
|
|
790
|
+
if (!strongThis) {
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
729
793
|
|
|
730
|
-
|
|
731
|
-
|
|
794
|
+
auto oldView = mutation.oldChildShadowView;
|
|
795
|
+
Rect window{};
|
|
796
|
+
{
|
|
797
|
+
auto &mutex = strongThis->mutex;
|
|
798
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
799
|
+
#ifdef ANDROID
|
|
800
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
801
|
+
// the view was removed before this start could run
|
|
802
|
+
return;
|
|
803
|
+
}
|
|
804
|
+
#endif
|
|
805
|
+
strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
806
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
807
|
+
}
|
|
732
808
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
809
|
+
Snapshot currentValues(oldView, window);
|
|
810
|
+
Snapshot targetValues(mutation.newChildShadowView, window);
|
|
811
|
+
|
|
812
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
813
|
+
jsi::Object yogaValues(uiRuntime);
|
|
814
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", currentValues.x);
|
|
815
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", currentValues.x);
|
|
816
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", currentValues.y);
|
|
817
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", currentValues.y);
|
|
818
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", currentValues.width);
|
|
819
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", currentValues.height);
|
|
820
|
+
yogaValues.setProperty(uiRuntime, "targetOriginX", targetValues.x);
|
|
821
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", targetValues.x);
|
|
822
|
+
yogaValues.setProperty(uiRuntime, "targetOriginY", targetValues.y);
|
|
823
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", targetValues.y);
|
|
824
|
+
yogaValues.setProperty(uiRuntime, "targetWidth", targetValues.width);
|
|
825
|
+
yogaValues.setProperty(uiRuntime, "targetHeight", targetValues.height);
|
|
826
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", targetValues.windowWidth);
|
|
827
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", targetValues.windowHeight);
|
|
828
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
829
|
+
uiRuntime, tag, LayoutAnimationType::LAYOUT, yogaValues);
|
|
830
|
+
});
|
|
751
831
|
}
|
|
752
832
|
|
|
753
833
|
void LayoutAnimationsProxy_Legacy::updateOngoingAnimationTarget(const int tag, const ShadowViewMutation &mutation)
|
|
@@ -757,10 +837,17 @@ void LayoutAnimationsProxy_Legacy::updateOngoingAnimationTarget(const int tag, c
|
|
|
757
837
|
}
|
|
758
838
|
|
|
759
839
|
void LayoutAnimationsProxy_Legacy::maybeCancelAnimation(const int tag) const {
|
|
760
|
-
|
|
840
|
+
#ifdef ANDROID
|
|
841
|
+
// invalidate animation starts that are scheduled but haven't run yet
|
|
842
|
+
if (const auto it = pendingStarts_.find(tag); it != pendingStarts_.end()) {
|
|
843
|
+
it->second.handle++;
|
|
844
|
+
}
|
|
845
|
+
#endif
|
|
846
|
+
const auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
847
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
761
848
|
return;
|
|
762
849
|
}
|
|
763
|
-
layoutAnimations_.erase(
|
|
850
|
+
layoutAnimations_.erase(layoutAnimationIt);
|
|
764
851
|
scheduleOnUI(uiScheduler_, [weakThis = weak_from_this(), tag]() {
|
|
765
852
|
auto strongThis = weakThis.lock();
|
|
766
853
|
if (!strongThis) {
|
|
@@ -210,7 +210,11 @@ Tag LayoutAnimationsProxy_Experimental::getOrCreateContainer(
|
|
|
210
210
|
ShadowViewMutationList &filteredMutations,
|
|
211
211
|
SurfaceId surfaceId) const {
|
|
212
212
|
auto containerTag = sharedTransitionManager_->containerTags_[sharedTag];
|
|
213
|
-
auto shouldCreateContainer =
|
|
213
|
+
auto shouldCreateContainer = true;
|
|
214
|
+
if (containerTag != -1) {
|
|
215
|
+
const auto layoutAnimationIt = layoutAnimations_.find(containerTag);
|
|
216
|
+
shouldCreateContainer = layoutAnimationIt == layoutAnimations_.end() || layoutAnimationIt->second.isSettled();
|
|
217
|
+
}
|
|
214
218
|
|
|
215
219
|
if (shouldCreateContainer) {
|
|
216
220
|
containerTag = containerTag_;
|
|
@@ -264,11 +268,12 @@ void LayoutAnimationsProxy_Experimental::handleSharedTransitionsStart(
|
|
|
264
268
|
auto &[_, after] = transition.snapshot;
|
|
265
269
|
|
|
266
270
|
auto containerTag = sharedTransitionManager_->containerTags_[sharedTag];
|
|
267
|
-
|
|
271
|
+
const auto layoutAnimationIt = layoutAnimations_.find(containerTag);
|
|
272
|
+
if (layoutAnimationIt == layoutAnimations_.end() || layoutAnimationIt->second.isSettled()) {
|
|
268
273
|
continue;
|
|
269
274
|
}
|
|
270
275
|
after.tag = containerTag;
|
|
271
|
-
const auto &la =
|
|
276
|
+
const auto &la = layoutAnimationIt->second;
|
|
272
277
|
if (la.finalView.layoutMetrics != after.layoutMetrics) {
|
|
273
278
|
overrideTransform(after, transition.transform[AFTER], propsParserContext);
|
|
274
279
|
startSharedTransition(containerTag, la.currentView, after, surfaceId);
|