react-native-reanimated 4.3.0 → 4.3.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 +59 -37
- package/Common/cpp/reanimated/CSS/misc/ViewStylesRepository.h +11 -8
- package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.cpp +11 -3
- package/Common/cpp/reanimated/CSS/registries/CSSAnimationsRegistry.h +9 -2
- package/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.cpp +6 -2
- package/Common/cpp/reanimated/CSS/registries/CSSTransitionsRegistry.h +8 -2
- package/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.cpp +17 -4
- package/Common/cpp/reanimated/CSS/registries/StaticPropsRegistry.h +5 -0
- 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/Fabric/updates/AnimatedPropsRegistry.cpp +12 -5
- package/Common/cpp/reanimated/Fabric/updates/AnimatedPropsRegistry.h +6 -3
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.cpp +4 -6
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +25 -7
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxyCommon.h +38 -0
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Experimental.cpp +106 -33
- package/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy_Legacy.cpp +165 -92
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +12 -34
- package/README.md +1 -1
- package/android/CMakeLists.txt +4 -1
- package/android/build.gradle +2 -0
- package/android/generate-stub-pch.gradle.kts +84 -0
- package/android/src/main/cpp/ReanimatedPCH.h +46 -0
- package/android/src/main/java/com/swmansion/reanimated/NativeProxy.java +14 -1
- package/android/src/main/java/com/swmansion/reanimated/keyboard/KeyboardAnimationCallback.java +9 -1
- package/apple/reanimated/apple/ReanimatedModule.mm +12 -1
- package/lib/module/common/constants/platform.js +5 -5
- package/lib/module/common/constants/platform.js.map +1 -1
- package/lib/module/createAnimatedComponent/AnimatedComponent.js +1 -7
- package/lib/module/createAnimatedComponent/AnimatedComponent.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 +16 -7
- 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/css/utils/props.js +6 -0
- package/lib/module/css/utils/props.js.map +1 -1
- package/lib/module/hook/useAnimatedRef.js +2 -2
- package/lib/module/hook/useAnimatedRef.js.map +1 -1
- package/lib/module/mutables.js +5 -1
- package/lib/module/mutables.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 +1 -1
- package/lib/module/valueSetter.js.map +1 -1
- package/lib/typescript/common/constants/platform.d.ts.map +1 -1
- package/lib/typescript/createAnimatedComponent/AnimatedComponent.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/CSSManager.d.ts +7 -0
- package/lib/typescript/css/native/managers/CSSManager.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/css/utils/props.d.ts.map +1 -1
- package/lib/typescript/mutables.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/lib/typescript/valueSetter.d.ts.map +1 -1
- package/package.json +5 -3
- package/src/common/constants/platform.ts +6 -5
- package/src/createAnimatedComponent/AnimatedComponent.tsx +1 -7
- 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 +33 -12
- package/src/css/native/managers/CSSTransitionsManager.ts +9 -2
- package/src/css/svg/native/processors/stroke.ts +9 -6
- package/src/css/utils/props.ts +7 -0
- package/src/hook/useAnimatedRef.ts +2 -2
- package/src/mutables.ts +5 -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 +2 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
|
-
#include <
|
|
4
|
-
|
|
3
|
+
#include <jsi/jsi.h>
|
|
5
4
|
#include <react/renderer/core/ShadowNode.h>
|
|
5
|
+
#include <reanimated/Fabric/ShadowTreeCloner.h>
|
|
6
6
|
|
|
7
|
-
#include <jsi/jsi.h>
|
|
8
7
|
#include <memory>
|
|
8
|
+
#include <mutex>
|
|
9
9
|
#include <string>
|
|
10
10
|
#include <unordered_map>
|
|
11
11
|
#include <unordered_set>
|
|
@@ -33,18 +33,23 @@ class UpdatesRegistry {
|
|
|
33
33
|
public:
|
|
34
34
|
virtual ~UpdatesRegistry() {}
|
|
35
35
|
|
|
36
|
-
std::lock_guard<std::mutex> lock() const;
|
|
37
|
-
|
|
38
36
|
virtual bool isEmpty() const;
|
|
39
37
|
folly::dynamic get(Tag tag) const;
|
|
40
|
-
|
|
38
|
+
void remove(Tag tag) {
|
|
39
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
40
|
+
removeTag(tag);
|
|
41
|
+
}
|
|
41
42
|
|
|
42
43
|
#ifdef ANDROID
|
|
43
44
|
bool hasPropsToRevert() const;
|
|
44
45
|
void collectPropsToRevert(PropsToRevertMap &propsToRevertMap);
|
|
45
46
|
#endif
|
|
46
47
|
|
|
47
|
-
void flushUpdates(UpdatesBatch &updatesBatch)
|
|
48
|
+
void flushUpdates(UpdatesBatch &updatesBatch) {
|
|
49
|
+
std::lock_guard<std::mutex> lock{mutex_};
|
|
50
|
+
flush(updatesBatch);
|
|
51
|
+
}
|
|
52
|
+
|
|
48
53
|
void collectProps(PropsMap &propsMap);
|
|
49
54
|
UpdatesBatch getPendingUpdates();
|
|
50
55
|
|
|
@@ -52,9 +57,22 @@ class UpdatesRegistry {
|
|
|
52
57
|
mutable std::mutex mutex_;
|
|
53
58
|
RegistryMap updatesRegistry_;
|
|
54
59
|
|
|
60
|
+
/// Assumes the caller already locked the registry.
|
|
61
|
+
void flush(UpdatesBatch &updatesBatch);
|
|
62
|
+
|
|
63
|
+
/// Assumes the caller already locked the registry.
|
|
64
|
+
virtual void removeTag(Tag tag) = 0;
|
|
65
|
+
|
|
66
|
+
/// Assumes the caller already locked the registry.
|
|
55
67
|
void addUpdatesToBatch(const std::shared_ptr<const ShadowNode> &shadowNode, const folly::dynamic &props);
|
|
68
|
+
|
|
69
|
+
/// Assumes the caller already locked the registry.
|
|
56
70
|
folly::dynamic getUpdatesFromRegistry(const Tag tag) const;
|
|
71
|
+
|
|
72
|
+
/// Assumes the caller already locked the registry.
|
|
57
73
|
void setInUpdatesRegistry(const std::shared_ptr<const ShadowNode> &shadowNode, const folly::dynamic &props);
|
|
74
|
+
|
|
75
|
+
/// Assumes the caller already locked the registry.
|
|
58
76
|
void removeFromUpdatesRegistry(Tag tag);
|
|
59
77
|
|
|
60
78
|
private:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#pragma once
|
|
2
2
|
|
|
3
3
|
#include <jsi/jsi.h>
|
|
4
|
+
#include <react/debug/react_native_assert.h>
|
|
4
5
|
#include <react/renderer/componentregistry/ComponentDescriptorFactory.h>
|
|
5
6
|
#include <react/renderer/mounting/MountingOverrideDelegate.h>
|
|
6
7
|
#include <react/renderer/uimanager/UIManager.h>
|
|
@@ -24,6 +25,31 @@ struct LayoutAnimation {
|
|
|
24
25
|
LayoutAnimation &operator=(const LayoutAnimation &other) = default;
|
|
25
26
|
};
|
|
26
27
|
|
|
28
|
+
#ifdef ANDROID
|
|
29
|
+
// Bookkeeping for animation starts that were scheduled onto the UI thread but
|
|
30
|
+
// haven't run yet — see `pendingStarts_` below.
|
|
31
|
+
struct PendingStart {
|
|
32
|
+
int count = 0;
|
|
33
|
+
uint64_t handle = 0;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Removes one pending start for the given tag and returns whether it was
|
|
37
|
+
// cancelled since it was scheduled (i.e. its handle is no longer current).
|
|
38
|
+
// Call under the proxy mutex.
|
|
39
|
+
inline bool
|
|
40
|
+
consumeIsCancelled(std::unordered_map<Tag, PendingStart> &pendingStarts, const Tag tag, const uint64_t handle) {
|
|
41
|
+
const auto it = pendingStarts.find(tag);
|
|
42
|
+
// every scheduled start keeps its entry alive until it is consumed —
|
|
43
|
+
// cancellations only bump the handle, they never erase
|
|
44
|
+
react_native_assert(it != pendingStarts.end() && "PendingStart not found");
|
|
45
|
+
const bool isCancelled = it->second.handle != handle;
|
|
46
|
+
if (--it->second.count == 0) {
|
|
47
|
+
pendingStarts.erase(it);
|
|
48
|
+
}
|
|
49
|
+
return isCancelled;
|
|
50
|
+
}
|
|
51
|
+
#endif
|
|
52
|
+
|
|
27
53
|
class LayoutAnimationsProxyCommon : public facebook::react::MountingOverrideDelegate {
|
|
28
54
|
public:
|
|
29
55
|
LayoutAnimationsProxyCommon(
|
|
@@ -75,6 +101,18 @@ class LayoutAnimationsProxyCommon : public facebook::react::MountingOverrideDele
|
|
|
75
101
|
|
|
76
102
|
void restoreOpacityInCaseOfFlakyEnteringAnimation(SurfaceId surfaceId) const;
|
|
77
103
|
|
|
104
|
+
// On Android pullTransaction can run on the JS thread, so animation starts
|
|
105
|
+
// are scheduled onto the UI thread. If `maybeCancelAnimation` is called between the
|
|
106
|
+
// start was scheduled and the lambda runs, it
|
|
107
|
+
// finds no `layoutAnimations_` entry to erase (the start lambda hasn't created it
|
|
108
|
+
// yet) and the cancellation is lost — the stale start would later
|
|
109
|
+
// "resurrect" the animation for a view whose Remove+Delete are already on
|
|
110
|
+
// their way to the mounting layer
|
|
111
|
+
// (https://github.com/software-mansion/react-native-reanimated/issues/7493).
|
|
112
|
+
|
|
113
|
+
// To work around this, we keep a separate `pendingStarts_` map that tracks scheduled starts by tag,
|
|
114
|
+
// with a generation counter to detect cancellations.
|
|
115
|
+
mutable std::unordered_map<Tag, PendingStart> pendingStarts_;
|
|
78
116
|
#endif
|
|
79
117
|
};
|
|
80
118
|
|
|
@@ -518,11 +518,10 @@ bool LayoutAnimationsProxy_Experimental::startAnimationsRecursively(
|
|
|
518
518
|
|
|
519
519
|
if (hasExitAnimation) {
|
|
520
520
|
node->state = ANIMATING;
|
|
521
|
-
startExitingAnimation(node);
|
|
522
521
|
lightNodes_[node->current.tag] = node;
|
|
522
|
+
startExitingAnimation(node);
|
|
523
523
|
} else {
|
|
524
|
-
|
|
525
|
-
// layoutAnimationsManager_->clearLayoutAnimationConfig(node->tag);
|
|
524
|
+
layoutAnimationsManager_->clearLayoutAnimationConfig(node->current.tag);
|
|
526
525
|
}
|
|
527
526
|
|
|
528
527
|
return wantAnimateExit;
|
|
@@ -534,6 +533,13 @@ void LayoutAnimationsProxy_Experimental::updateOngoingAnimationTarget(const int
|
|
|
534
533
|
}
|
|
535
534
|
|
|
536
535
|
void LayoutAnimationsProxy_Experimental::maybeCancelAnimation(const int tag) const {
|
|
536
|
+
#ifdef ANDROID
|
|
537
|
+
// also invalidate animation starts that are scheduled but haven't run yet,
|
|
538
|
+
// so they don't re-create the animation after this cancellation
|
|
539
|
+
if (const auto it = pendingStarts_.find(tag); it != pendingStarts_.end()) {
|
|
540
|
+
it->second.handle++;
|
|
541
|
+
}
|
|
542
|
+
#endif
|
|
537
543
|
if (!layoutAnimations_.contains(tag)) {
|
|
538
544
|
return;
|
|
539
545
|
}
|
|
@@ -678,9 +684,24 @@ void LayoutAnimationsProxy_Experimental::startEnteringAnimation(const std::share
|
|
|
678
684
|
const auto &parent = node->parent.lock();
|
|
679
685
|
react_native_assert(parent && "Parent node is nullptr");
|
|
680
686
|
const auto parentTag = parent->current.tag;
|
|
687
|
+
#ifdef ANDROID
|
|
688
|
+
const auto handle = pendingStarts_[newChildShadowView.tag].handle;
|
|
689
|
+
pendingStarts_[newChildShadowView.tag].count++;
|
|
690
|
+
#endif
|
|
681
691
|
|
|
682
692
|
scheduleOnUI(
|
|
683
|
-
uiScheduler_,
|
|
693
|
+
uiScheduler_,
|
|
694
|
+
[weakThis = weak_from_this(),
|
|
695
|
+
finalView,
|
|
696
|
+
currentView,
|
|
697
|
+
newChildShadowView,
|
|
698
|
+
parentTag,
|
|
699
|
+
opacity
|
|
700
|
+
#ifdef ANDROID
|
|
701
|
+
,
|
|
702
|
+
handle
|
|
703
|
+
#endif
|
|
704
|
+
]() {
|
|
684
705
|
auto strongThis = weakThis.lock();
|
|
685
706
|
if (!strongThis) {
|
|
686
707
|
return;
|
|
@@ -690,6 +711,12 @@ void LayoutAnimationsProxy_Experimental::startEnteringAnimation(const std::share
|
|
|
690
711
|
const auto tag = newChildShadowView.tag;
|
|
691
712
|
{
|
|
692
713
|
auto lock = std::unique_lock<std::recursive_mutex>(strongThis->mutex);
|
|
714
|
+
#ifdef ANDROID
|
|
715
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
716
|
+
// the view was removed before this start could run
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
#endif
|
|
693
720
|
strongThis->layoutAnimations_[tag] = {
|
|
694
721
|
.finalView = newChildShadowView,
|
|
695
722
|
.currentView = newChildShadowView,
|
|
@@ -723,38 +750,63 @@ void LayoutAnimationsProxy_Experimental::startExitingAnimation(const std::shared
|
|
|
723
750
|
const auto &parent = node->parent.lock();
|
|
724
751
|
react_native_assert(parent && "Parent node is nullptr");
|
|
725
752
|
const auto parentTag = parent->current.tag;
|
|
753
|
+
#ifdef ANDROID
|
|
754
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
755
|
+
pendingStarts_[tag].count++;
|
|
756
|
+
#endif
|
|
726
757
|
|
|
727
|
-
scheduleOnUI(
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
758
|
+
scheduleOnUI(
|
|
759
|
+
uiScheduler_,
|
|
760
|
+
[weakThis = weak_from_this(),
|
|
761
|
+
tag,
|
|
762
|
+
parentTag,
|
|
763
|
+
oldChildShadowView,
|
|
764
|
+
surfaceId
|
|
765
|
+
#ifdef ANDROID
|
|
766
|
+
,
|
|
767
|
+
handle
|
|
768
|
+
#endif
|
|
769
|
+
]() {
|
|
770
|
+
auto strongThis = weakThis.lock();
|
|
771
|
+
if (!strongThis) {
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
732
774
|
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
775
|
+
auto oldView = oldChildShadowView;
|
|
776
|
+
Rect window{};
|
|
777
|
+
{
|
|
778
|
+
auto &mutex = strongThis->mutex;
|
|
779
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
780
|
+
#ifdef ANDROID
|
|
781
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
782
|
+
// the view was removed (e.g. its subtree was force-ended by a screen
|
|
783
|
+
// pop) before this start could run — its Remove+Delete are already on
|
|
784
|
+
// their way to the mounting layer, so starting the animation now
|
|
785
|
+
// would emit updates for a view that's about to be deleted
|
|
786
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
#endif
|
|
790
|
+
oldView = strongThis->maybeCreateLayoutAnimation(oldView, oldView, parentTag);
|
|
791
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
792
|
+
}
|
|
741
793
|
|
|
742
|
-
|
|
794
|
+
const Snapshot values(oldView, window);
|
|
743
795
|
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
796
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
797
|
+
const jsi::Object yogaValues(uiRuntime);
|
|
798
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
|
|
799
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
|
|
800
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
|
|
801
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
|
|
802
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
|
|
803
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
|
|
804
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
805
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
806
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
807
|
+
uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
|
|
808
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
809
|
+
});
|
|
758
810
|
}
|
|
759
811
|
|
|
760
812
|
void LayoutAnimationsProxy_Experimental::startLayoutAnimation(const std::shared_ptr<LightNode> &node) const {
|
|
@@ -765,9 +817,24 @@ void LayoutAnimationsProxy_Experimental::startLayoutAnimation(const std::shared_
|
|
|
765
817
|
const auto &parent = node->parent.lock();
|
|
766
818
|
react_native_assert(parent && "Parent node is nullptr");
|
|
767
819
|
const auto parentTag = parent->current.tag;
|
|
820
|
+
#ifdef ANDROID
|
|
821
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
822
|
+
pendingStarts_[tag].count++;
|
|
823
|
+
#endif
|
|
768
824
|
|
|
769
825
|
scheduleOnUI(
|
|
770
|
-
uiScheduler_,
|
|
826
|
+
uiScheduler_,
|
|
827
|
+
[weakThis = weak_from_this(),
|
|
828
|
+
surfaceId,
|
|
829
|
+
oldChildShadowView,
|
|
830
|
+
newChildShadowView,
|
|
831
|
+
parentTag,
|
|
832
|
+
tag
|
|
833
|
+
#ifdef ANDROID
|
|
834
|
+
,
|
|
835
|
+
handle
|
|
836
|
+
#endif
|
|
837
|
+
]() {
|
|
771
838
|
auto strongThis = weakThis.lock();
|
|
772
839
|
if (!strongThis) {
|
|
773
840
|
return;
|
|
@@ -778,6 +845,12 @@ void LayoutAnimationsProxy_Experimental::startLayoutAnimation(const std::shared_
|
|
|
778
845
|
{
|
|
779
846
|
auto &mutex = strongThis->mutex;
|
|
780
847
|
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
848
|
+
#ifdef ANDROID
|
|
849
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
850
|
+
// the view was removed before this start could run
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
#endif
|
|
781
854
|
oldView = strongThis->maybeCreateLayoutAnimation(oldView, newChildShadowView, parentTag);
|
|
782
855
|
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
783
856
|
}
|
|
@@ -635,38 +635,60 @@ void LayoutAnimationsProxy_Legacy::startEnteringAnimation(const int tag, ShadowV
|
|
|
635
635
|
|
|
636
636
|
auto &viewProps = static_cast<const ViewProps &>(*mutation.newChildShadowView.props);
|
|
637
637
|
auto opacity = viewProps.opacity;
|
|
638
|
+
#ifdef ANDROID
|
|
639
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
640
|
+
pendingStarts_[tag].count++;
|
|
641
|
+
#endif
|
|
638
642
|
|
|
639
|
-
scheduleOnUI(
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
643
|
+
scheduleOnUI(
|
|
644
|
+
uiScheduler_,
|
|
645
|
+
[weakThis = weak_from_this(),
|
|
646
|
+
finalView,
|
|
647
|
+
current,
|
|
648
|
+
mutation,
|
|
649
|
+
opacity,
|
|
650
|
+
tag
|
|
651
|
+
#ifdef ANDROID
|
|
652
|
+
,
|
|
653
|
+
handle
|
|
654
|
+
#endif
|
|
655
|
+
]() {
|
|
656
|
+
auto strongThis = weakThis.lock();
|
|
657
|
+
if (!strongThis) {
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
644
660
|
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
tag,
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
661
|
+
Rect window{};
|
|
662
|
+
{
|
|
663
|
+
auto &mutex = strongThis->mutex;
|
|
664
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
665
|
+
#ifdef ANDROID
|
|
666
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
667
|
+
// the view was removed before this start could run
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
#endif
|
|
671
|
+
strongThis->layoutAnimations_.insert_or_assign(
|
|
672
|
+
tag,
|
|
673
|
+
LayoutAnimation{
|
|
674
|
+
.finalView = finalView, .currentView = current, .parentTag = mutation.parentTag, .opacity = opacity});
|
|
675
|
+
window = strongThis->surfaceManager.getWindow(mutation.newChildShadowView.surfaceId);
|
|
676
|
+
}
|
|
655
677
|
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
678
|
+
Snapshot values(mutation.newChildShadowView, window);
|
|
679
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
680
|
+
jsi::Object yogaValues(uiRuntime);
|
|
681
|
+
yogaValues.setProperty(uiRuntime, "targetOriginX", values.x);
|
|
682
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", values.x);
|
|
683
|
+
yogaValues.setProperty(uiRuntime, "targetOriginY", values.y);
|
|
684
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", values.y);
|
|
685
|
+
yogaValues.setProperty(uiRuntime, "targetWidth", values.width);
|
|
686
|
+
yogaValues.setProperty(uiRuntime, "targetHeight", values.height);
|
|
687
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
688
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
689
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
690
|
+
uiRuntime, tag, LayoutAnimationType::ENTERING, yogaValues);
|
|
691
|
+
});
|
|
670
692
|
}
|
|
671
693
|
|
|
672
694
|
void LayoutAnimationsProxy_Legacy::startExitingAnimation(const int tag, ShadowViewMutation &mutation) const {
|
|
@@ -674,38 +696,62 @@ void LayoutAnimationsProxy_Legacy::startExitingAnimation(const int tag, ShadowVi
|
|
|
674
696
|
LOG(INFO) << "start exiting animation for tag " << tag << std::endl;
|
|
675
697
|
#endif
|
|
676
698
|
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
699
|
+
#ifdef ANDROID
|
|
700
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
701
|
+
pendingStarts_[tag].count++;
|
|
702
|
+
#endif
|
|
677
703
|
|
|
678
|
-
scheduleOnUI(
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
704
|
+
scheduleOnUI(
|
|
705
|
+
uiScheduler_,
|
|
706
|
+
[weakThis = weak_from_this(),
|
|
707
|
+
tag,
|
|
708
|
+
mutation,
|
|
709
|
+
surfaceId
|
|
710
|
+
#ifdef ANDROID
|
|
711
|
+
,
|
|
712
|
+
handle
|
|
713
|
+
#endif
|
|
714
|
+
]() {
|
|
715
|
+
auto strongThis = weakThis.lock();
|
|
716
|
+
if (!strongThis) {
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
692
719
|
|
|
693
|
-
|
|
720
|
+
auto oldView = mutation.oldChildShadowView;
|
|
721
|
+
Rect window{};
|
|
722
|
+
{
|
|
723
|
+
auto &mutex = strongThis->mutex;
|
|
724
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
725
|
+
#ifdef ANDROID
|
|
726
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
727
|
+
// the view was removed (e.g. its subtree was force-ended by a screen
|
|
728
|
+
// pop) before this start could run — its Remove+Delete are already on
|
|
729
|
+
// their way to the mounting layer, so starting the animation now
|
|
730
|
+
// would emit updates for a view that's about to be deleted
|
|
731
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
734
|
+
#endif
|
|
735
|
+
strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
736
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
737
|
+
}
|
|
694
738
|
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
uiRuntime,
|
|
707
|
-
|
|
708
|
-
|
|
739
|
+
Snapshot values(oldView, window);
|
|
740
|
+
|
|
741
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
742
|
+
jsi::Object yogaValues(uiRuntime);
|
|
743
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
|
|
744
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
|
|
745
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
|
|
746
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
|
|
747
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
|
|
748
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
|
|
749
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
750
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
751
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
752
|
+
uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
|
|
753
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
754
|
+
});
|
|
709
755
|
}
|
|
710
756
|
|
|
711
757
|
void LayoutAnimationsProxy_Legacy::startLayoutAnimation(const int tag, const ShadowViewMutation &mutation) const {
|
|
@@ -713,43 +759,64 @@ void LayoutAnimationsProxy_Legacy::startLayoutAnimation(const int tag, const Sha
|
|
|
713
759
|
LOG(INFO) << "start layout animation for tag " << tag << std::endl;
|
|
714
760
|
#endif
|
|
715
761
|
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
762
|
+
#ifdef ANDROID
|
|
763
|
+
const auto handle = pendingStarts_[tag].handle;
|
|
764
|
+
pendingStarts_[tag].count++;
|
|
765
|
+
#endif
|
|
716
766
|
|
|
717
|
-
scheduleOnUI(
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
767
|
+
scheduleOnUI(
|
|
768
|
+
uiScheduler_,
|
|
769
|
+
[weakThis = weak_from_this(),
|
|
770
|
+
mutation,
|
|
771
|
+
surfaceId,
|
|
772
|
+
tag
|
|
773
|
+
#ifdef ANDROID
|
|
774
|
+
,
|
|
775
|
+
handle
|
|
776
|
+
#endif
|
|
777
|
+
]() {
|
|
778
|
+
auto strongThis = weakThis.lock();
|
|
779
|
+
if (!strongThis) {
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
731
782
|
|
|
732
|
-
|
|
733
|
-
|
|
783
|
+
auto oldView = mutation.oldChildShadowView;
|
|
784
|
+
Rect window{};
|
|
785
|
+
{
|
|
786
|
+
auto &mutex = strongThis->mutex;
|
|
787
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
788
|
+
#ifdef ANDROID
|
|
789
|
+
if (consumeIsCancelled(strongThis->pendingStarts_, tag, handle)) {
|
|
790
|
+
// the view was removed before this start could run
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
#endif
|
|
794
|
+
strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
795
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
796
|
+
}
|
|
734
797
|
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
798
|
+
Snapshot currentValues(oldView, window);
|
|
799
|
+
Snapshot targetValues(mutation.newChildShadowView, window);
|
|
800
|
+
|
|
801
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
802
|
+
jsi::Object yogaValues(uiRuntime);
|
|
803
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", currentValues.x);
|
|
804
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", currentValues.x);
|
|
805
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", currentValues.y);
|
|
806
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", currentValues.y);
|
|
807
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", currentValues.width);
|
|
808
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", currentValues.height);
|
|
809
|
+
yogaValues.setProperty(uiRuntime, "targetOriginX", targetValues.x);
|
|
810
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", targetValues.x);
|
|
811
|
+
yogaValues.setProperty(uiRuntime, "targetOriginY", targetValues.y);
|
|
812
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", targetValues.y);
|
|
813
|
+
yogaValues.setProperty(uiRuntime, "targetWidth", targetValues.width);
|
|
814
|
+
yogaValues.setProperty(uiRuntime, "targetHeight", targetValues.height);
|
|
815
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", targetValues.windowWidth);
|
|
816
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", targetValues.windowHeight);
|
|
817
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
818
|
+
uiRuntime, tag, LayoutAnimationType::LAYOUT, yogaValues);
|
|
819
|
+
});
|
|
753
820
|
}
|
|
754
821
|
|
|
755
822
|
void LayoutAnimationsProxy_Legacy::updateOngoingAnimationTarget(const int tag, const ShadowViewMutation &mutation)
|
|
@@ -759,6 +826,12 @@ void LayoutAnimationsProxy_Legacy::updateOngoingAnimationTarget(const int tag, c
|
|
|
759
826
|
}
|
|
760
827
|
|
|
761
828
|
void LayoutAnimationsProxy_Legacy::maybeCancelAnimation(const int tag) const {
|
|
829
|
+
#ifdef ANDROID
|
|
830
|
+
// invalidate animation starts that are scheduled but haven't run yet
|
|
831
|
+
if (const auto it = pendingStarts_.find(tag); it != pendingStarts_.end()) {
|
|
832
|
+
it->second.handle++;
|
|
833
|
+
}
|
|
834
|
+
#endif
|
|
762
835
|
if (!layoutAnimations_.contains(tag)) {
|
|
763
836
|
return;
|
|
764
837
|
}
|