react-native-reanimated 4.1.5 → 4.1.7
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/updates/UpdatesRegistry.cpp +12 -0
- package/Common/cpp/reanimated/Fabric/updates/UpdatesRegistry.h +1 -0
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +436 -366
- package/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +4 -0
- package/android/src/main/cpp/reanimated/android/NativeProxy.cpp +7 -0
- package/android/src/main/cpp/reanimated/android/NativeProxy.h +1 -0
- package/android/src/main/java/com/swmansion/reanimated/DrawPassDetector.java +82 -0
- package/android/src/main/java/com/swmansion/reanimated/NativeProxy.java +3 -1
- package/android/src/main/java/com/swmansion/reanimated/NodesManager.java +29 -1
- package/compatibility.json +1 -1
- package/lib/module/interpolation.js +2 -4
- package/lib/module/interpolation.js.map +1 -1
- package/lib/module/platform-specific/jsVersion.js +1 -1
- package/lib/typescript/platform-specific/jsVersion.d.ts +1 -1
- package/package.json +7 -7
- package/scripts/worklets-version.json +1 -4
- package/src/platform-specific/jsVersion.ts +1 -1
|
@@ -32,6 +32,18 @@ void UpdatesRegistry::flushUpdates(UpdatesBatch &updatesBatch) {
|
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
UpdatesBatch UpdatesRegistry::getPendingUpdates() {
|
|
36
|
+
auto lock = std::lock_guard<std::mutex>{mutex_};
|
|
37
|
+
flushUpdatesToRegistry(updatesBatch_);
|
|
38
|
+
|
|
39
|
+
UpdatesBatch updatesBatch;
|
|
40
|
+
for (const auto &[tag, pair] : updatesRegistry_) {
|
|
41
|
+
const auto &[shadowNode, props] = pair;
|
|
42
|
+
updatesBatch.emplace_back(shadowNode, props);
|
|
43
|
+
}
|
|
44
|
+
return updatesBatch;
|
|
45
|
+
}
|
|
46
|
+
|
|
35
47
|
void UpdatesRegistry::collectProps(PropsMap &propsMap) {
|
|
36
48
|
std::lock_guard<std::mutex> lock{mutex_};
|
|
37
49
|
|
|
@@ -35,6 +35,82 @@ static inline std::shared_ptr<const ShadowNode> shadowNodeFromValue(
|
|
|
35
35
|
}
|
|
36
36
|
#endif
|
|
37
37
|
|
|
38
|
+
namespace {
|
|
39
|
+
|
|
40
|
+
#ifdef ANDROID
|
|
41
|
+
constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
|
|
42
|
+
return StaticFeatureFlags::getFlag("ANDROID_SYNCHRONOUSLY_UPDATE_UI_PROPS");
|
|
43
|
+
}
|
|
44
|
+
#else
|
|
45
|
+
constexpr bool shouldUseSynchronousUpdatesInPerformOperations() {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
#endif
|
|
49
|
+
|
|
50
|
+
std::pair<UpdatesBatch, UpdatesBatch> partitionUpdates(
|
|
51
|
+
const UpdatesBatch &updatesBatch,
|
|
52
|
+
const std::unordered_set<std::string> &synchronousPropNames,
|
|
53
|
+
const bool shouldRequireIntegerColors = false,
|
|
54
|
+
const bool allowPartialViews = false) {
|
|
55
|
+
UpdatesBatch synchronousUpdatesBatch;
|
|
56
|
+
UpdatesBatch shadowTreeUpdatesBatch;
|
|
57
|
+
|
|
58
|
+
for (const auto &[shadowNode, props] : updatesBatch) {
|
|
59
|
+
if (allowPartialViews) {
|
|
60
|
+
folly::dynamic synchronousProps = folly::dynamic::object();
|
|
61
|
+
folly::dynamic shadowTreeProps = folly::dynamic::object();
|
|
62
|
+
|
|
63
|
+
for (const auto &[key, value] : props.items()) {
|
|
64
|
+
const auto keyStr = key.asString();
|
|
65
|
+
const bool isColorProp =
|
|
66
|
+
keyStr == "color" || keyStr.find("Color") != std::string::npos;
|
|
67
|
+
const bool isSynchronous = synchronousPropNames.contains(keyStr) &&
|
|
68
|
+
(!shouldRequireIntegerColors || !isColorProp || value.isInt());
|
|
69
|
+
if (isSynchronous) {
|
|
70
|
+
synchronousProps[keyStr] = value;
|
|
71
|
+
} else {
|
|
72
|
+
shadowTreeProps[keyStr] = value;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
if (!synchronousProps.empty()) {
|
|
77
|
+
synchronousUpdatesBatch.emplace_back(
|
|
78
|
+
shadowNode, std::move(synchronousProps));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!shadowTreeProps.empty()) {
|
|
82
|
+
shadowTreeUpdatesBatch.emplace_back(
|
|
83
|
+
shadowNode, std::move(shadowTreeProps));
|
|
84
|
+
}
|
|
85
|
+
} else {
|
|
86
|
+
bool hasOnlySynchronousProps = true;
|
|
87
|
+
|
|
88
|
+
for (const auto &[key, value] : props.items()) {
|
|
89
|
+
const auto keyStr = key.asString();
|
|
90
|
+
const bool isColorProp =
|
|
91
|
+
keyStr == "color" || keyStr.find("Color") != std::string::npos;
|
|
92
|
+
const bool isSynchronous = synchronousPropNames.contains(keyStr) &&
|
|
93
|
+
(!shouldRequireIntegerColors || !isColorProp || value.isInt());
|
|
94
|
+
if (!isSynchronous) {
|
|
95
|
+
hasOnlySynchronousProps = false;
|
|
96
|
+
break;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (hasOnlySynchronousProps) {
|
|
101
|
+
synchronousUpdatesBatch.emplace_back(shadowNode, props);
|
|
102
|
+
} else {
|
|
103
|
+
shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
std::move(synchronousUpdatesBatch), std::move(shadowTreeUpdatesBatch)};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
} // namespace
|
|
113
|
+
|
|
38
114
|
ReanimatedModuleProxy::ReanimatedModuleProxy(
|
|
39
115
|
const std::shared_ptr<WorkletsModuleProxy> &workletsModuleProxy,
|
|
40
116
|
jsi::Runtime &rnRuntime,
|
|
@@ -692,434 +768,428 @@ void ReanimatedModuleProxy::performOperations() {
|
|
|
692
768
|
|
|
693
769
|
shouldUpdateCssAnimations_ = false;
|
|
694
770
|
|
|
771
|
+
if constexpr (shouldUseSynchronousUpdatesInPerformOperations()) {
|
|
772
|
+
applySynchronousUpdates(updatesBatch);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
if ((updatesBatch.size() > 0) &&
|
|
776
|
+
updatesRegistryManager_->shouldReanimatedSkipCommit()) {
|
|
777
|
+
updatesRegistryManager_->pleaseCommitAfterPause();
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
|
|
782
|
+
// It may happen that `performOperations` is called on the UI thread
|
|
783
|
+
// while React Native tries to commit a new tree on the JS thread.
|
|
784
|
+
// In this case, we should skip the commit here and let React Native do
|
|
785
|
+
// it. The commit will include the current values from the updates manager
|
|
786
|
+
// which will be applied in ReanimatedCommitHook.
|
|
787
|
+
return;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
commitUpdates(rt, updatesBatch);
|
|
791
|
+
|
|
792
|
+
// Clear the entire cache after the commit
|
|
793
|
+
// (we don't know if the view is updated from outside of Reanimated
|
|
794
|
+
// so we have to clear the entire cache)
|
|
795
|
+
viewStylesRepository_->clearNodesCache();
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
void ReanimatedModuleProxy::performNonLayoutOperations() {
|
|
799
|
+
ReanimatedSystraceSection s(
|
|
800
|
+
"ReanimatedModuleProxy::performNonLayoutOperations");
|
|
801
|
+
|
|
802
|
+
UpdatesBatch updatesBatch = animatedPropsRegistry_->getPendingUpdates();
|
|
803
|
+
|
|
804
|
+
applySynchronousUpdates(updatesBatch, true);
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
void ReanimatedModuleProxy::applySynchronousUpdates(
|
|
808
|
+
UpdatesBatch &updatesBatch,
|
|
809
|
+
const bool allowPartialUpdates) {
|
|
695
810
|
#ifdef ANDROID
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
"transform",
|
|
728
|
-
};
|
|
811
|
+
static const std::unordered_set<std::string> synchronousProps = {
|
|
812
|
+
"opacity",
|
|
813
|
+
"elevation",
|
|
814
|
+
"zIndex",
|
|
815
|
+
// "shadowOpacity", // not supported on Android
|
|
816
|
+
// "shadowRadius", // not supported on Android
|
|
817
|
+
"backgroundColor",
|
|
818
|
+
// "color", // TODO: fix animating color of Animated.Text,
|
|
819
|
+
"tintColor",
|
|
820
|
+
"borderRadius",
|
|
821
|
+
"borderTopLeftRadius",
|
|
822
|
+
"borderTopRightRadius",
|
|
823
|
+
"borderTopStartRadius",
|
|
824
|
+
"borderTopEndRadius",
|
|
825
|
+
"borderBottomLeftRadius",
|
|
826
|
+
"borderBottomRightRadius",
|
|
827
|
+
"borderBottomStartRadius",
|
|
828
|
+
"borderBottomEndRadius",
|
|
829
|
+
"borderStartStartRadius",
|
|
830
|
+
"borderStartEndRadius",
|
|
831
|
+
"borderEndStartRadius",
|
|
832
|
+
"borderEndEndRadius",
|
|
833
|
+
"borderColor",
|
|
834
|
+
"borderTopColor",
|
|
835
|
+
"borderBottomColor",
|
|
836
|
+
"borderLeftColor",
|
|
837
|
+
"borderRightColor",
|
|
838
|
+
"borderStartColor",
|
|
839
|
+
"borderEndColor",
|
|
840
|
+
"transform",
|
|
841
|
+
};
|
|
729
842
|
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
843
|
+
// NOTE: Keep in sync with NativeProxy.java
|
|
844
|
+
static constexpr auto CMD_START_OF_VIEW = 1;
|
|
845
|
+
static constexpr auto CMD_START_OF_TRANSFORM = 2;
|
|
846
|
+
static constexpr auto CMD_END_OF_TRANSFORM = 3;
|
|
847
|
+
static constexpr auto CMD_END_OF_VIEW = 4;
|
|
848
|
+
|
|
849
|
+
static constexpr auto CMD_OPACITY = 10;
|
|
850
|
+
static constexpr auto CMD_ELEVATION = 11;
|
|
851
|
+
static constexpr auto CMD_Z_INDEX = 12;
|
|
852
|
+
static constexpr auto CMD_SHADOW_OPACITY = 13;
|
|
853
|
+
static constexpr auto CMD_SHADOW_RADIUS = 14;
|
|
854
|
+
static constexpr auto CMD_BACKGROUND_COLOR = 15;
|
|
855
|
+
static constexpr auto CMD_COLOR = 16;
|
|
856
|
+
static constexpr auto CMD_TINT_COLOR = 17;
|
|
857
|
+
|
|
858
|
+
static constexpr auto CMD_BORDER_RADIUS = 20;
|
|
859
|
+
static constexpr auto CMD_BORDER_TOP_LEFT_RADIUS = 21;
|
|
860
|
+
static constexpr auto CMD_BORDER_TOP_RIGHT_RADIUS = 22;
|
|
861
|
+
static constexpr auto CMD_BORDER_TOP_START_RADIUS = 23;
|
|
862
|
+
static constexpr auto CMD_BORDER_TOP_END_RADIUS = 24;
|
|
863
|
+
static constexpr auto CMD_BORDER_BOTTOM_LEFT_RADIUS = 25;
|
|
864
|
+
static constexpr auto CMD_BORDER_BOTTOM_RIGHT_RADIUS = 26;
|
|
865
|
+
static constexpr auto CMD_BORDER_BOTTOM_START_RADIUS = 27;
|
|
866
|
+
static constexpr auto CMD_BORDER_BOTTOM_END_RADIUS = 28;
|
|
867
|
+
static constexpr auto CMD_BORDER_START_START_RADIUS = 29;
|
|
868
|
+
static constexpr auto CMD_BORDER_START_END_RADIUS = 30;
|
|
869
|
+
static constexpr auto CMD_BORDER_END_START_RADIUS = 31;
|
|
870
|
+
static constexpr auto CMD_BORDER_END_END_RADIUS = 32;
|
|
871
|
+
|
|
872
|
+
static constexpr auto CMD_BORDER_COLOR = 40;
|
|
873
|
+
static constexpr auto CMD_BORDER_TOP_COLOR = 41;
|
|
874
|
+
static constexpr auto CMD_BORDER_BOTTOM_COLOR = 42;
|
|
875
|
+
static constexpr auto CMD_BORDER_LEFT_COLOR = 43;
|
|
876
|
+
static constexpr auto CMD_BORDER_RIGHT_COLOR = 44;
|
|
877
|
+
static constexpr auto CMD_BORDER_START_COLOR = 45;
|
|
878
|
+
static constexpr auto CMD_BORDER_END_COLOR = 46;
|
|
879
|
+
|
|
880
|
+
static constexpr auto CMD_TRANSFORM_TRANSLATE_X = 100;
|
|
881
|
+
static constexpr auto CMD_TRANSFORM_TRANSLATE_Y = 101;
|
|
882
|
+
static constexpr auto CMD_TRANSFORM_SCALE = 102;
|
|
883
|
+
static constexpr auto CMD_TRANSFORM_SCALE_X = 103;
|
|
884
|
+
static constexpr auto CMD_TRANSFORM_SCALE_Y = 104;
|
|
885
|
+
static constexpr auto CMD_TRANSFORM_ROTATE = 105;
|
|
886
|
+
static constexpr auto CMD_TRANSFORM_ROTATE_X = 106;
|
|
887
|
+
static constexpr auto CMD_TRANSFORM_ROTATE_Y = 107;
|
|
888
|
+
static constexpr auto CMD_TRANSFORM_ROTATE_Z = 108;
|
|
889
|
+
static constexpr auto CMD_TRANSFORM_SKEW_X = 109;
|
|
890
|
+
static constexpr auto CMD_TRANSFORM_SKEW_Y = 110;
|
|
891
|
+
static constexpr auto CMD_TRANSFORM_MATRIX = 111;
|
|
892
|
+
static constexpr auto CMD_TRANSFORM_PERSPECTIVE = 112;
|
|
780
893
|
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
894
|
+
static constexpr auto CMD_UNIT_DEG = 200;
|
|
895
|
+
static constexpr auto CMD_UNIT_RAD = 201;
|
|
896
|
+
static constexpr auto CMD_UNIT_PX = 202;
|
|
897
|
+
static constexpr auto CMD_UNIT_PERCENT = 203;
|
|
785
898
|
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
899
|
+
const auto propNameToCommand = [](const std::string &name) {
|
|
900
|
+
if (name == "opacity")
|
|
901
|
+
return CMD_OPACITY;
|
|
789
902
|
|
|
790
|
-
|
|
791
|
-
|
|
903
|
+
if (name == "elevation")
|
|
904
|
+
return CMD_ELEVATION;
|
|
792
905
|
|
|
793
|
-
|
|
794
|
-
|
|
906
|
+
if (name == "zIndex")
|
|
907
|
+
return CMD_Z_INDEX;
|
|
795
908
|
|
|
796
|
-
|
|
797
|
-
|
|
909
|
+
if (name == "shadowOpacity")
|
|
910
|
+
return CMD_SHADOW_OPACITY;
|
|
798
911
|
|
|
799
|
-
|
|
800
|
-
|
|
912
|
+
if (name == "shadowRadius")
|
|
913
|
+
return CMD_SHADOW_RADIUS;
|
|
801
914
|
|
|
802
|
-
|
|
803
|
-
|
|
915
|
+
if (name == "backgroundColor")
|
|
916
|
+
return CMD_BACKGROUND_COLOR;
|
|
804
917
|
|
|
805
|
-
|
|
806
|
-
|
|
918
|
+
if (name == "color")
|
|
919
|
+
return CMD_COLOR;
|
|
807
920
|
|
|
808
|
-
|
|
809
|
-
|
|
921
|
+
if (name == "tintColor")
|
|
922
|
+
return CMD_TINT_COLOR;
|
|
810
923
|
|
|
811
|
-
|
|
812
|
-
|
|
924
|
+
if (name == "borderRadius")
|
|
925
|
+
return CMD_BORDER_RADIUS;
|
|
813
926
|
|
|
814
|
-
|
|
815
|
-
|
|
927
|
+
if (name == "borderTopLeftRadius")
|
|
928
|
+
return CMD_BORDER_TOP_LEFT_RADIUS;
|
|
816
929
|
|
|
817
|
-
|
|
818
|
-
|
|
930
|
+
if (name == "borderTopRightRadius")
|
|
931
|
+
return CMD_BORDER_TOP_RIGHT_RADIUS;
|
|
819
932
|
|
|
820
|
-
|
|
821
|
-
|
|
933
|
+
if (name == "borderTopStartRadius")
|
|
934
|
+
return CMD_BORDER_TOP_START_RADIUS;
|
|
822
935
|
|
|
823
|
-
|
|
824
|
-
|
|
936
|
+
if (name == "borderTopEndRadius")
|
|
937
|
+
return CMD_BORDER_TOP_END_RADIUS;
|
|
825
938
|
|
|
826
|
-
|
|
827
|
-
|
|
939
|
+
if (name == "borderBottomLeftRadius")
|
|
940
|
+
return CMD_BORDER_BOTTOM_LEFT_RADIUS;
|
|
828
941
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
942
|
+
if (name == "borderBottomRightRadius")
|
|
943
|
+
return CMD_BORDER_BOTTOM_RIGHT_RADIUS;
|
|
944
|
+
|
|
945
|
+
if (name == "borderBottomStartRadius")
|
|
946
|
+
return CMD_BORDER_BOTTOM_START_RADIUS;
|
|
834
947
|
|
|
835
|
-
|
|
836
|
-
|
|
948
|
+
if (name == "borderBottomEndRadius")
|
|
949
|
+
return CMD_BORDER_BOTTOM_END_RADIUS;
|
|
837
950
|
|
|
838
|
-
|
|
839
|
-
|
|
951
|
+
if (name == "borderStartStartRadius")
|
|
952
|
+
return CMD_BORDER_START_START_RADIUS;
|
|
840
953
|
|
|
841
|
-
|
|
842
|
-
|
|
954
|
+
if (name == "borderStartEndRadius")
|
|
955
|
+
return CMD_BORDER_START_END_RADIUS;
|
|
843
956
|
|
|
844
|
-
|
|
845
|
-
|
|
957
|
+
if (name == "borderEndStartRadius")
|
|
958
|
+
return CMD_BORDER_END_START_RADIUS;
|
|
846
959
|
|
|
847
|
-
|
|
848
|
-
|
|
960
|
+
if (name == "borderEndEndRadius")
|
|
961
|
+
return CMD_BORDER_END_END_RADIUS;
|
|
849
962
|
|
|
850
|
-
|
|
851
|
-
|
|
963
|
+
if (name == "borderColor")
|
|
964
|
+
return CMD_BORDER_COLOR;
|
|
852
965
|
|
|
853
|
-
|
|
854
|
-
|
|
966
|
+
if (name == "borderTopColor")
|
|
967
|
+
return CMD_BORDER_TOP_COLOR;
|
|
855
968
|
|
|
856
|
-
|
|
857
|
-
|
|
969
|
+
if (name == "borderBottomColor")
|
|
970
|
+
return CMD_BORDER_BOTTOM_COLOR;
|
|
858
971
|
|
|
859
|
-
|
|
860
|
-
|
|
972
|
+
if (name == "borderLeftColor")
|
|
973
|
+
return CMD_BORDER_LEFT_COLOR;
|
|
861
974
|
|
|
862
|
-
|
|
863
|
-
|
|
975
|
+
if (name == "borderRightColor")
|
|
976
|
+
return CMD_BORDER_RIGHT_COLOR;
|
|
864
977
|
|
|
865
|
-
|
|
866
|
-
|
|
978
|
+
if (name == "borderStartColor")
|
|
979
|
+
return CMD_BORDER_START_COLOR;
|
|
867
980
|
|
|
868
|
-
|
|
869
|
-
|
|
981
|
+
if (name == "borderEndColor")
|
|
982
|
+
return CMD_BORDER_END_COLOR;
|
|
870
983
|
|
|
871
|
-
|
|
872
|
-
|
|
984
|
+
if (name == "transform")
|
|
985
|
+
return CMD_START_OF_TRANSFORM; // TODO: use CMD_TRANSFORM?
|
|
873
986
|
|
|
874
|
-
|
|
875
|
-
|
|
987
|
+
throw std::runtime_error("[Reanimated] Unsupported style: " + name);
|
|
988
|
+
};
|
|
876
989
|
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
990
|
+
const auto transformNameToCommand = [](const std::string &name) {
|
|
991
|
+
if (name == "translateX")
|
|
992
|
+
return CMD_TRANSFORM_TRANSLATE_X;
|
|
880
993
|
|
|
881
|
-
|
|
882
|
-
|
|
994
|
+
if (name == "translateY")
|
|
995
|
+
return CMD_TRANSFORM_TRANSLATE_Y;
|
|
883
996
|
|
|
884
|
-
|
|
885
|
-
|
|
997
|
+
if (name == "scale")
|
|
998
|
+
return CMD_TRANSFORM_SCALE;
|
|
886
999
|
|
|
887
|
-
|
|
888
|
-
|
|
1000
|
+
if (name == "scaleX")
|
|
1001
|
+
return CMD_TRANSFORM_SCALE_X;
|
|
889
1002
|
|
|
890
|
-
|
|
891
|
-
|
|
1003
|
+
if (name == "scaleY")
|
|
1004
|
+
return CMD_TRANSFORM_SCALE_Y;
|
|
892
1005
|
|
|
893
|
-
|
|
894
|
-
|
|
1006
|
+
if (name == "rotate")
|
|
1007
|
+
return CMD_TRANSFORM_ROTATE;
|
|
895
1008
|
|
|
896
|
-
|
|
897
|
-
|
|
1009
|
+
if (name == "rotateX")
|
|
1010
|
+
return CMD_TRANSFORM_ROTATE_X;
|
|
898
1011
|
|
|
899
|
-
|
|
900
|
-
|
|
1012
|
+
if (name == "rotateY")
|
|
1013
|
+
return CMD_TRANSFORM_ROTATE_Y;
|
|
901
1014
|
|
|
902
|
-
|
|
903
|
-
|
|
1015
|
+
if (name == "rotateZ")
|
|
1016
|
+
return CMD_TRANSFORM_ROTATE_Z;
|
|
904
1017
|
|
|
905
|
-
|
|
906
|
-
|
|
1018
|
+
if (name == "skewX")
|
|
1019
|
+
return CMD_TRANSFORM_SKEW_X;
|
|
907
1020
|
|
|
908
|
-
|
|
909
|
-
|
|
1021
|
+
if (name == "skewY")
|
|
1022
|
+
return CMD_TRANSFORM_SKEW_Y;
|
|
910
1023
|
|
|
911
|
-
|
|
912
|
-
|
|
1024
|
+
if (name == "matrix")
|
|
1025
|
+
return CMD_TRANSFORM_MATRIX;
|
|
913
1026
|
|
|
914
|
-
|
|
915
|
-
|
|
1027
|
+
if (name == "perspective")
|
|
1028
|
+
return CMD_TRANSFORM_PERSPECTIVE;
|
|
916
1029
|
|
|
917
|
-
|
|
918
|
-
|
|
1030
|
+
throw std::runtime_error("[Reanimated] Unsupported transform: " + name);
|
|
1031
|
+
};
|
|
919
1032
|
|
|
920
|
-
|
|
1033
|
+
auto [synchronousUpdatesBatch, shadowTreeUpdatesBatch] = partitionUpdates(
|
|
1034
|
+
updatesBatch, synchronousProps, true, allowPartialUpdates);
|
|
1035
|
+
|
|
1036
|
+
if (!synchronousUpdatesBatch.empty()) {
|
|
1037
|
+
std::vector<int> intBuffer;
|
|
1038
|
+
std::vector<double> doubleBuffer;
|
|
1039
|
+
intBuffer.reserve(1024);
|
|
1040
|
+
doubleBuffer.reserve(1024);
|
|
1041
|
+
|
|
1042
|
+
for (const auto &[shadowNode, props] : synchronousUpdatesBatch) {
|
|
1043
|
+
intBuffer.push_back(CMD_START_OF_VIEW);
|
|
1044
|
+
intBuffer.push_back(shadowNode->getTag());
|
|
1045
|
+
for (const auto &[key, value] : props.items()) {
|
|
1046
|
+
const auto command = propNameToCommand(key.getString());
|
|
1047
|
+
switch (command) {
|
|
1048
|
+
case CMD_OPACITY:
|
|
1049
|
+
case CMD_ELEVATION:
|
|
1050
|
+
case CMD_Z_INDEX:
|
|
1051
|
+
case CMD_SHADOW_OPACITY:
|
|
1052
|
+
case CMD_SHADOW_RADIUS:
|
|
1053
|
+
intBuffer.push_back(command);
|
|
1054
|
+
doubleBuffer.push_back(value.asDouble());
|
|
1055
|
+
break;
|
|
921
1056
|
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
1057
|
+
case CMD_BACKGROUND_COLOR:
|
|
1058
|
+
case CMD_COLOR:
|
|
1059
|
+
case CMD_TINT_COLOR:
|
|
1060
|
+
case CMD_BORDER_COLOR:
|
|
1061
|
+
case CMD_BORDER_TOP_COLOR:
|
|
1062
|
+
case CMD_BORDER_BOTTOM_COLOR:
|
|
1063
|
+
case CMD_BORDER_LEFT_COLOR:
|
|
1064
|
+
case CMD_BORDER_RIGHT_COLOR:
|
|
1065
|
+
case CMD_BORDER_START_COLOR:
|
|
1066
|
+
case CMD_BORDER_END_COLOR:
|
|
1067
|
+
intBuffer.push_back(command);
|
|
1068
|
+
intBuffer.push_back(value.asInt());
|
|
928
1069
|
break;
|
|
929
|
-
}
|
|
930
|
-
}
|
|
931
|
-
if (hasOnlySynchronousProps) {
|
|
932
|
-
synchronousUpdatesBatch.emplace_back(shadowNode, props);
|
|
933
|
-
} else {
|
|
934
|
-
shadowTreeUpdatesBatch.emplace_back(shadowNode, props);
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
1070
|
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
1071
|
+
case CMD_BORDER_RADIUS:
|
|
1072
|
+
case CMD_BORDER_TOP_LEFT_RADIUS:
|
|
1073
|
+
case CMD_BORDER_TOP_RIGHT_RADIUS:
|
|
1074
|
+
case CMD_BORDER_TOP_START_RADIUS:
|
|
1075
|
+
case CMD_BORDER_TOP_END_RADIUS:
|
|
1076
|
+
case CMD_BORDER_BOTTOM_LEFT_RADIUS:
|
|
1077
|
+
case CMD_BORDER_BOTTOM_RIGHT_RADIUS:
|
|
1078
|
+
case CMD_BORDER_BOTTOM_START_RADIUS:
|
|
1079
|
+
case CMD_BORDER_BOTTOM_END_RADIUS:
|
|
1080
|
+
case CMD_BORDER_START_START_RADIUS:
|
|
1081
|
+
case CMD_BORDER_START_END_RADIUS:
|
|
1082
|
+
case CMD_BORDER_END_START_RADIUS:
|
|
1083
|
+
case CMD_BORDER_END_END_RADIUS:
|
|
1084
|
+
intBuffer.push_back(command);
|
|
1085
|
+
if (value.isDouble()) {
|
|
1086
|
+
intBuffer.push_back(CMD_UNIT_PX);
|
|
1087
|
+
doubleBuffer.push_back(value.getDouble());
|
|
1088
|
+
} else if (value.isString()) {
|
|
1089
|
+
const auto &valueStr = value.getString();
|
|
1090
|
+
if (!valueStr.ends_with("%")) {
|
|
1091
|
+
throw std::runtime_error(
|
|
1092
|
+
"[Reanimated] Border radius string must be a percentage");
|
|
1093
|
+
}
|
|
1094
|
+
intBuffer.push_back(CMD_UNIT_PERCENT);
|
|
1095
|
+
doubleBuffer.push_back(std::stof(valueStr.substr(0, -1)));
|
|
1096
|
+
} else {
|
|
1097
|
+
throw std::runtime_error(
|
|
1098
|
+
"[Reanimated] Border radius value must be either a number or a string");
|
|
1099
|
+
}
|
|
1100
|
+
break;
|
|
1101
|
+
|
|
1102
|
+
case CMD_START_OF_TRANSFORM:
|
|
1103
|
+
intBuffer.push_back(command);
|
|
1104
|
+
react_native_assert(
|
|
1105
|
+
value.isArray() &&
|
|
1106
|
+
"[Reanimated] Transform value must be an array");
|
|
1107
|
+
for (const auto &item : value) {
|
|
1108
|
+
react_native_assert(
|
|
1109
|
+
item.isObject() &&
|
|
1110
|
+
"[Reanimated] Transform array item must be an object");
|
|
1111
|
+
react_native_assert(
|
|
1112
|
+
item.size() == 1 &&
|
|
1113
|
+
"[Reanimated] Transform array item must have exactly one key-value pair");
|
|
1114
|
+
const auto transformCommand =
|
|
1115
|
+
transformNameToCommand(item.keys().begin()->getString());
|
|
1116
|
+
const auto &transformValue = *item.values().begin();
|
|
1117
|
+
switch (transformCommand) {
|
|
1118
|
+
case CMD_TRANSFORM_SCALE:
|
|
1119
|
+
case CMD_TRANSFORM_SCALE_X:
|
|
1120
|
+
case CMD_TRANSFORM_SCALE_Y:
|
|
1121
|
+
case CMD_TRANSFORM_PERSPECTIVE: {
|
|
1122
|
+
intBuffer.push_back(transformCommand);
|
|
1123
|
+
doubleBuffer.push_back(transformValue.asDouble());
|
|
1124
|
+
break;
|
|
1125
|
+
}
|
|
1126
|
+
case CMD_TRANSFORM_TRANSLATE_X:
|
|
1127
|
+
case CMD_TRANSFORM_TRANSLATE_Y: {
|
|
1128
|
+
intBuffer.push_back(transformCommand);
|
|
1129
|
+
if (transformValue.isDouble()) {
|
|
1130
|
+
intBuffer.push_back(CMD_UNIT_PX);
|
|
1131
|
+
doubleBuffer.push_back(transformValue.getDouble());
|
|
1132
|
+
} else if (transformValue.isString()) {
|
|
1133
|
+
const auto &transformValueStr = transformValue.getString();
|
|
1134
|
+
if (!transformValueStr.ends_with("%")) {
|
|
1135
|
+
throw std::runtime_error(
|
|
1136
|
+
"[Reanimated] String translate must be a percentage");
|
|
1137
|
+
}
|
|
1138
|
+
intBuffer.push_back(CMD_UNIT_PERCENT);
|
|
1139
|
+
doubleBuffer.push_back(
|
|
1140
|
+
std::stof(transformValueStr.substr(0, -1)));
|
|
1141
|
+
} else {
|
|
993
1142
|
throw std::runtime_error(
|
|
994
|
-
"[Reanimated]
|
|
1143
|
+
"[Reanimated] Translate value must be either a number or a string");
|
|
995
1144
|
}
|
|
996
|
-
|
|
997
|
-
doubleBuffer.push_back(std::stof(valueStr.substr(0, -1)));
|
|
998
|
-
} else {
|
|
999
|
-
throw std::runtime_error(
|
|
1000
|
-
"[Reanimated] Border radius value must be either a number or a string");
|
|
1145
|
+
break;
|
|
1001
1146
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1147
|
+
case CMD_TRANSFORM_ROTATE:
|
|
1148
|
+
case CMD_TRANSFORM_ROTATE_X:
|
|
1149
|
+
case CMD_TRANSFORM_ROTATE_Y:
|
|
1150
|
+
case CMD_TRANSFORM_ROTATE_Z:
|
|
1151
|
+
case CMD_TRANSFORM_SKEW_X:
|
|
1152
|
+
case CMD_TRANSFORM_SKEW_Y: {
|
|
1153
|
+
const auto &transformValueStr = transformValue.getString();
|
|
1154
|
+
intBuffer.push_back(transformCommand);
|
|
1155
|
+
if (transformValueStr.ends_with("deg")) {
|
|
1156
|
+
intBuffer.push_back(CMD_UNIT_DEG);
|
|
1157
|
+
} else if (transformValueStr.ends_with("rad")) {
|
|
1158
|
+
intBuffer.push_back(CMD_UNIT_RAD);
|
|
1159
|
+
} else {
|
|
1160
|
+
throw std::runtime_error(
|
|
1161
|
+
"[Reanimated] Unsupported rotation unit: " +
|
|
1162
|
+
transformValueStr);
|
|
1163
|
+
}
|
|
1164
|
+
doubleBuffer.push_back(
|
|
1165
|
+
std::stof(transformValueStr.substr(0, -3)));
|
|
1166
|
+
break;
|
|
1167
|
+
}
|
|
1168
|
+
case CMD_TRANSFORM_MATRIX: {
|
|
1169
|
+
intBuffer.push_back(transformCommand);
|
|
1013
1170
|
react_native_assert(
|
|
1014
|
-
|
|
1015
|
-
"[Reanimated]
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
case CMD_TRANSFORM_SCALE:
|
|
1021
|
-
case CMD_TRANSFORM_SCALE_X:
|
|
1022
|
-
case CMD_TRANSFORM_SCALE_Y:
|
|
1023
|
-
case CMD_TRANSFORM_PERSPECTIVE: {
|
|
1024
|
-
intBuffer.push_back(transformCommand);
|
|
1025
|
-
doubleBuffer.push_back(transformValue.asDouble());
|
|
1026
|
-
break;
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
case CMD_TRANSFORM_TRANSLATE_X:
|
|
1030
|
-
case CMD_TRANSFORM_TRANSLATE_Y: {
|
|
1031
|
-
intBuffer.push_back(transformCommand);
|
|
1032
|
-
if (transformValue.isDouble()) {
|
|
1033
|
-
intBuffer.push_back(CMD_UNIT_PX);
|
|
1034
|
-
doubleBuffer.push_back(transformValue.getDouble());
|
|
1035
|
-
} else if (transformValue.isString()) {
|
|
1036
|
-
const auto &transformValueStr =
|
|
1037
|
-
transformValue.getString();
|
|
1038
|
-
if (!transformValueStr.ends_with("%")) {
|
|
1039
|
-
throw std::runtime_error(
|
|
1040
|
-
"[Reanimated] String translate must be a percentage");
|
|
1041
|
-
}
|
|
1042
|
-
intBuffer.push_back(CMD_UNIT_PERCENT);
|
|
1043
|
-
doubleBuffer.push_back(
|
|
1044
|
-
std::stof(transformValueStr.substr(0, -1)));
|
|
1045
|
-
} else {
|
|
1046
|
-
throw std::runtime_error(
|
|
1047
|
-
"[Reanimated] Translate value must be either a number or a string");
|
|
1048
|
-
}
|
|
1049
|
-
break;
|
|
1050
|
-
}
|
|
1051
|
-
|
|
1052
|
-
case CMD_TRANSFORM_ROTATE:
|
|
1053
|
-
case CMD_TRANSFORM_ROTATE_X:
|
|
1054
|
-
case CMD_TRANSFORM_ROTATE_Y:
|
|
1055
|
-
case CMD_TRANSFORM_ROTATE_Z:
|
|
1056
|
-
case CMD_TRANSFORM_SKEW_X:
|
|
1057
|
-
case CMD_TRANSFORM_SKEW_Y: {
|
|
1058
|
-
const auto &transformValueStr =
|
|
1059
|
-
transformValue.getString();
|
|
1060
|
-
intBuffer.push_back(transformCommand);
|
|
1061
|
-
if (transformValueStr.ends_with("deg")) {
|
|
1062
|
-
intBuffer.push_back(CMD_UNIT_DEG);
|
|
1063
|
-
} else if (transformValueStr.ends_with("rad")) {
|
|
1064
|
-
intBuffer.push_back(CMD_UNIT_RAD);
|
|
1065
|
-
} else {
|
|
1066
|
-
throw std::runtime_error(
|
|
1067
|
-
"[Reanimated] Unsupported rotation unit: " +
|
|
1068
|
-
transformValueStr);
|
|
1069
|
-
}
|
|
1070
|
-
doubleBuffer.push_back(
|
|
1071
|
-
std::stof(transformValueStr.substr(0, -3)));
|
|
1072
|
-
break;
|
|
1073
|
-
}
|
|
1074
|
-
|
|
1075
|
-
case CMD_TRANSFORM_MATRIX: {
|
|
1076
|
-
intBuffer.push_back(transformCommand);
|
|
1077
|
-
react_native_assert(
|
|
1078
|
-
transformValue.isArray() &&
|
|
1079
|
-
"[Reanimated] Matrix must be an array");
|
|
1080
|
-
int size = transformValue.size();
|
|
1081
|
-
intBuffer.push_back(size);
|
|
1082
|
-
for (int i = 0; i < size; i++) {
|
|
1083
|
-
doubleBuffer.push_back(transformValue[i].asDouble());
|
|
1084
|
-
}
|
|
1085
|
-
break;
|
|
1086
|
-
}
|
|
1171
|
+
transformValue.isArray() &&
|
|
1172
|
+
"[Reanimated] Matrix must be an array");
|
|
1173
|
+
int size = transformValue.size();
|
|
1174
|
+
intBuffer.push_back(size);
|
|
1175
|
+
for (int i = 0; i < size; i++) {
|
|
1176
|
+
doubleBuffer.push_back(transformValue[i].asDouble());
|
|
1087
1177
|
}
|
|
1178
|
+
break;
|
|
1088
1179
|
}
|
|
1089
|
-
|
|
1090
|
-
break;
|
|
1180
|
+
}
|
|
1091
1181
|
}
|
|
1092
|
-
|
|
1093
|
-
|
|
1182
|
+
intBuffer.push_back(CMD_END_OF_TRANSFORM);
|
|
1183
|
+
break;
|
|
1094
1184
|
}
|
|
1095
|
-
synchronouslyUpdateUIPropsFunction_(intBuffer, doubleBuffer);
|
|
1096
1185
|
}
|
|
1097
|
-
|
|
1098
|
-
updatesBatch = std::move(shadowTreeUpdatesBatch);
|
|
1186
|
+
intBuffer.push_back(CMD_END_OF_VIEW);
|
|
1099
1187
|
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
if ((updatesBatch.size() > 0) &&
|
|
1103
|
-
updatesRegistryManager_->shouldReanimatedSkipCommit()) {
|
|
1104
|
-
updatesRegistryManager_->pleaseCommitAfterPause();
|
|
1105
|
-
}
|
|
1106
|
-
}
|
|
1107
|
-
|
|
1108
|
-
if (updatesRegistryManager_->shouldReanimatedSkipCommit()) {
|
|
1109
|
-
// It may happen that `performOperations` is called on the UI thread
|
|
1110
|
-
// while React Native tries to commit a new tree on the JS thread.
|
|
1111
|
-
// In this case, we should skip the commit here and let React Native do
|
|
1112
|
-
// it. The commit will include the current values from the updates manager
|
|
1113
|
-
// which will be applied in ReanimatedCommitHook.
|
|
1114
|
-
return;
|
|
1188
|
+
synchronouslyUpdateUIPropsFunction_(intBuffer, doubleBuffer);
|
|
1115
1189
|
}
|
|
1116
1190
|
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
// Clear the entire cache after the commit
|
|
1120
|
-
// (we don't know if the view is updated from outside of Reanimated
|
|
1121
|
-
// so we have to clear the entire cache)
|
|
1122
|
-
viewStylesRepository_->clearNodesCache();
|
|
1191
|
+
updatesBatch = std::move(shadowTreeUpdatesBatch);
|
|
1192
|
+
#endif // ANDROID
|
|
1123
1193
|
}
|
|
1124
1194
|
|
|
1125
1195
|
void ReanimatedModuleProxy::requestFlushRegistry() {
|
|
@@ -118,6 +118,7 @@ class ReanimatedModuleProxy
|
|
|
118
118
|
double getCssTimestamp();
|
|
119
119
|
|
|
120
120
|
void performOperations();
|
|
121
|
+
void performNonLayoutOperations();
|
|
121
122
|
|
|
122
123
|
void setViewStyle(
|
|
123
124
|
jsi::Runtime &rt,
|
|
@@ -218,6 +219,9 @@ class ReanimatedModuleProxy
|
|
|
218
219
|
|
|
219
220
|
private:
|
|
220
221
|
void commitUpdates(jsi::Runtime &rt, const UpdatesBatch &updatesBatch);
|
|
222
|
+
void applySynchronousUpdates(
|
|
223
|
+
UpdatesBatch &updatesBatch,
|
|
224
|
+
bool allowPartialUpdates = false);
|
|
221
225
|
|
|
222
226
|
const bool isReducedMotion_;
|
|
223
227
|
bool shouldFlushRegistry_ = false;
|
|
@@ -131,6 +131,10 @@ void NativeProxy::performOperations() {
|
|
|
131
131
|
reanimatedModuleProxy_->performOperations();
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
+
void NativeProxy::performNonLayoutOperations() {
|
|
135
|
+
reanimatedModuleProxy_->performNonLayoutOperations();
|
|
136
|
+
}
|
|
137
|
+
|
|
134
138
|
bool NativeProxy::getIsReducedMotion() {
|
|
135
139
|
static const auto method = getJniMethod<jboolean()>("getIsReducedMotion");
|
|
136
140
|
return method(javaPart_.get());
|
|
@@ -144,6 +148,9 @@ void NativeProxy::registerNatives() {
|
|
|
144
148
|
"isAnyHandlerWaitingForEvent",
|
|
145
149
|
NativeProxy::isAnyHandlerWaitingForEvent),
|
|
146
150
|
makeNativeMethod("performOperations", NativeProxy::performOperations),
|
|
151
|
+
makeNativeMethod(
|
|
152
|
+
"performNonLayoutOperations",
|
|
153
|
+
NativeProxy::performNonLayoutOperations),
|
|
147
154
|
makeNativeMethod("invalidateCpp", NativeProxy::invalidateCpp)});
|
|
148
155
|
}
|
|
149
156
|
|
|
@@ -63,6 +63,7 @@ class NativeProxy : public jni::HybridClass<NativeProxy>,
|
|
|
63
63
|
const std::string &eventName,
|
|
64
64
|
const int emitterReactTag);
|
|
65
65
|
void performOperations();
|
|
66
|
+
void performNonLayoutOperations();
|
|
66
67
|
bool getIsReducedMotion();
|
|
67
68
|
void requestRender(std::function<void(double)> onRender);
|
|
68
69
|
void registerEventHandler();
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
package com.swmansion.reanimated;
|
|
2
|
+
|
|
3
|
+
import android.app.Activity;
|
|
4
|
+
import android.os.Handler;
|
|
5
|
+
import android.os.Looper;
|
|
6
|
+
import android.view.View;
|
|
7
|
+
import android.view.ViewTreeObserver;
|
|
8
|
+
import com.facebook.react.bridge.ReactApplicationContext;
|
|
9
|
+
import com.facebook.react.bridge.UiThreadUtil;
|
|
10
|
+
import javax.annotation.Nullable;
|
|
11
|
+
|
|
12
|
+
/** Tracks whether the current UI thread turn is inside a draw pass. */
|
|
13
|
+
class DrawPassDetector {
|
|
14
|
+
private final ReactApplicationContext mContext;
|
|
15
|
+
private final Handler mHandler = new Handler(Looper.getMainLooper());
|
|
16
|
+
private final Runnable mClearRunnable = () -> mIsInDrawPass = false;
|
|
17
|
+
private boolean mIsInDrawPass = false;
|
|
18
|
+
@Nullable private View mDecorView = null;
|
|
19
|
+
|
|
20
|
+
private final ViewTreeObserver.OnDrawListener mOnDrawListener =
|
|
21
|
+
() -> {
|
|
22
|
+
mIsInDrawPass = true;
|
|
23
|
+
mHandler.postAtFrontOfQueue(mClearRunnable);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
DrawPassDetector(ReactApplicationContext context) {
|
|
27
|
+
mContext = context;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
void initialize() {
|
|
31
|
+
Activity activity = mContext.getCurrentActivity();
|
|
32
|
+
if (activity == null) {
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
View decorView = activity.getWindow().getDecorView();
|
|
37
|
+
if (decorView == mDecorView) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Decor view has changed (e.g. Activity recreated) — detach from the old one first.
|
|
42
|
+
if (mDecorView != null) {
|
|
43
|
+
ViewTreeObserver oldObserver = mDecorView.getViewTreeObserver();
|
|
44
|
+
if (oldObserver.isAlive()) {
|
|
45
|
+
oldObserver.removeOnDrawListener(mOnDrawListener);
|
|
46
|
+
}
|
|
47
|
+
mDecorView = null;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
ViewTreeObserver observer = decorView.getViewTreeObserver();
|
|
51
|
+
if (!observer.isAlive()) {
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
mDecorView = decorView;
|
|
56
|
+
observer.addOnDrawListener(mOnDrawListener);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
boolean isInDrawPass() {
|
|
60
|
+
return mIsInDrawPass;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void invalidate() {
|
|
64
|
+
if (UiThreadUtil.isOnUiThread()) {
|
|
65
|
+
invalidateOnUiThread();
|
|
66
|
+
} else {
|
|
67
|
+
mHandler.post(this::invalidateOnUiThread);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
private void invalidateOnUiThread() {
|
|
72
|
+
if (mDecorView != null) {
|
|
73
|
+
ViewTreeObserver observer = mDecorView.getViewTreeObserver();
|
|
74
|
+
if (observer.isAlive()) {
|
|
75
|
+
observer.removeOnDrawListener(mOnDrawListener);
|
|
76
|
+
}
|
|
77
|
+
mDecorView = null;
|
|
78
|
+
}
|
|
79
|
+
mHandler.removeCallbacks(mClearRunnable);
|
|
80
|
+
mIsInDrawPass = false;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -112,6 +112,8 @@ public class NativeProxy {
|
|
|
112
112
|
|
|
113
113
|
public native void performOperations();
|
|
114
114
|
|
|
115
|
+
public native void performNonLayoutOperations();
|
|
116
|
+
|
|
115
117
|
protected native void installJSIBindings();
|
|
116
118
|
|
|
117
119
|
private native void invalidateCpp();
|
|
@@ -488,7 +490,7 @@ public class NativeProxy {
|
|
|
488
490
|
void maybeFlushUIUpdatesQueue() {
|
|
489
491
|
UiThreadUtil.assertOnUiThread();
|
|
490
492
|
if (!mNodesManager.isAnimationRunning()) {
|
|
491
|
-
mNodesManager.
|
|
493
|
+
mNodesManager.performOperationsRespectingDrawPass();
|
|
492
494
|
}
|
|
493
495
|
}
|
|
494
496
|
}
|
|
@@ -44,6 +44,7 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
44
44
|
private ConcurrentLinkedQueue<CopiedEvent> mEventQueue = new ConcurrentLinkedQueue<>();
|
|
45
45
|
private double lastFrameTimeMs;
|
|
46
46
|
private FabricUIManager mFabricUIManager;
|
|
47
|
+
private final DrawPassDetector mDrawPassDetector;
|
|
47
48
|
|
|
48
49
|
public NativeProxy getNativeProxy() {
|
|
49
50
|
return mNativeProxy;
|
|
@@ -57,6 +58,8 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
57
58
|
mNativeProxy = null;
|
|
58
59
|
}
|
|
59
60
|
|
|
61
|
+
mDrawPassDetector.invalidate();
|
|
62
|
+
|
|
60
63
|
if (mFabricUIManager != null) {
|
|
61
64
|
mFabricUIManager.getEventDispatcher().removeListener(this);
|
|
62
65
|
}
|
|
@@ -69,6 +72,7 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
69
72
|
assert uiManager != null;
|
|
70
73
|
mCustomEventNamesResolver = uiManager::resolveCustomDirectEventName;
|
|
71
74
|
mEventEmitter = context.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class);
|
|
75
|
+
mDrawPassDetector = new DrawPassDetector(context);
|
|
72
76
|
|
|
73
77
|
mReactChoreographer = ReactChoreographer.getInstance();
|
|
74
78
|
mChoreographerCallback =
|
|
@@ -122,6 +126,28 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
122
126
|
}
|
|
123
127
|
}
|
|
124
128
|
|
|
129
|
+
void performNonLayoutOperations() {
|
|
130
|
+
UiThreadUtil.assertOnUiThread();
|
|
131
|
+
if (mNativeProxy != null) {
|
|
132
|
+
mNativeProxy.performNonLayoutOperations();
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
void performOperationsRespectingDrawPass() {
|
|
137
|
+
mDrawPassDetector.initialize();
|
|
138
|
+
if (isInDrawPass()) {
|
|
139
|
+
performNonLayoutOperations();
|
|
140
|
+
startUpdatingOnAnimationFrame();
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
performOperations();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
boolean isInDrawPass() {
|
|
148
|
+
return mDrawPassDetector.isInDrawPass();
|
|
149
|
+
}
|
|
150
|
+
|
|
125
151
|
private void onAnimationFrame(long frameTimeNanos) {
|
|
126
152
|
UiThreadUtil.assertOnUiThread();
|
|
127
153
|
|
|
@@ -130,6 +156,8 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
130
156
|
Trace.beginSection("onAnimationFrame");
|
|
131
157
|
}
|
|
132
158
|
|
|
159
|
+
mDrawPassDetector.initialize();
|
|
160
|
+
|
|
133
161
|
double currentFrameTimeMs = frameTimeNanos / 1000000.;
|
|
134
162
|
if (mSlowAnimationsEnabled) {
|
|
135
163
|
currentFrameTimeMs =
|
|
@@ -189,7 +217,7 @@ public class NodesManager implements EventDispatcherListener {
|
|
|
189
217
|
// the UI thread.
|
|
190
218
|
if (UiThreadUtil.isOnUiThread()) {
|
|
191
219
|
handleEvent(event);
|
|
192
|
-
|
|
220
|
+
performOperationsRespectingDrawPass();
|
|
193
221
|
} else {
|
|
194
222
|
String eventName = mCustomEventNamesResolver.resolveCustomEventName(event.getEventName());
|
|
195
223
|
int viewTag = event.getViewTag();
|
package/compatibility.json
CHANGED
|
@@ -41,10 +41,8 @@ function getVal(type, coef, val, leftEdgeOutput, rightEdgeOutput, x) {
|
|
|
41
41
|
function isExtrapolate(value) {
|
|
42
42
|
'worklet';
|
|
43
43
|
|
|
44
|
-
return /* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */
|
|
45
|
-
|
|
46
|
-
/* eslint-enable @typescript-eslint/no-unsafe-enum-comparison */
|
|
47
|
-
);
|
|
44
|
+
return /* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */value === Extrapolation.EXTEND || value === Extrapolation.CLAMP || value === Extrapolation.IDENTITY
|
|
45
|
+
/* eslint-enable @typescript-eslint/no-unsafe-enum-comparison */;
|
|
48
46
|
}
|
|
49
47
|
|
|
50
48
|
// validates extrapolations type
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["ReanimatedError","Extrapolation","getVal","type","coef","val","leftEdgeOutput","rightEdgeOutput","x","IDENTITY","CLAMP","EXTEND","isExtrapolate","value","validateType","extrapolationConfig","extrapolateLeft","extrapolateRight","Object","assign","internalInterpolate","narrowedInput","leftEdgeInput","rightEdgeInput","progress","interpolate","inputRange","outputRange","length","i","clamp","min","max","Math"],"sourceRoot":"../../src","sources":["interpolation.ts"],"mappings":"AAAA,YAAY;;AAEZ,SAASA,eAAe,QAAQ,UAAU;;AAE1C;AACA;AACA;AACA;AACA;AACA;AACA;AACA,WAAYC,aAAa,0BAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAbA,aAAa;EAAA,OAAbA,aAAa;AAAA;;AAMzB;;AAUA;;AAWA;;AAOA,SAASC,MAAMA,CACbC,IAAmB,EACnBC,IAAY,EACZC,GAAW,EACXC,cAAsB,EACtBC,eAAuB,EACvBC,CAAS,EACD;EACR,SAAS;;EAET,QAAQL,IAAI;IACV,KAAKF,aAAa,CAACQ,QAAQ;MACzB,OAAOD,CAAC;IACV,KAAKP,aAAa,CAACS,KAAK;MACtB,IAAIN,IAAI,GAAGC,GAAG,GAAGD,IAAI,GAAGE,cAAc,EAAE;QACtC,OAAOA,cAAc;MACvB;MACA,OAAOC,eAAe;IACxB,KAAKN,aAAa,CAACU,MAAM;IACzB;MACE,OAAON,GAAG;EACd;AACF;AAEA,SAASO,aAAaA,CAACC,KAAa,EAA0B;EAC5D,SAAS;;EAET,OACE
|
|
1
|
+
{"version":3,"names":["ReanimatedError","Extrapolation","getVal","type","coef","val","leftEdgeOutput","rightEdgeOutput","x","IDENTITY","CLAMP","EXTEND","isExtrapolate","value","validateType","extrapolationConfig","extrapolateLeft","extrapolateRight","Object","assign","internalInterpolate","narrowedInput","leftEdgeInput","rightEdgeInput","progress","interpolate","inputRange","outputRange","length","i","clamp","min","max","Math"],"sourceRoot":"../../src","sources":["interpolation.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
* version used to build the native part of the library in runtime. Remember to
|
|
4
4
|
* keep this in sync with the version declared in `package.json`
|
|
5
5
|
*/
|
|
6
|
-
export declare const jsVersion = "4.1.
|
|
6
|
+
export declare const jsVersion = "4.1.7";
|
|
7
7
|
//# sourceMappingURL=jsVersion.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-reanimated",
|
|
3
|
-
"version": "4.1.
|
|
3
|
+
"version": "4.1.7",
|
|
4
4
|
"description": "More powerful alternative to Animated library for React Native.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -34,7 +34,8 @@
|
|
|
34
34
|
"circular-dependency-check": "yarn madge --extensions js,jsx --circular lib",
|
|
35
35
|
"use-strict-check": "node ../../scripts/validate-use-strict.js",
|
|
36
36
|
"prepack": "cp ../../README.md ./README.md",
|
|
37
|
-
"postpack": "rm ./README.md"
|
|
37
|
+
"postpack": "rm ./README.md",
|
|
38
|
+
"validate-peers": "node ../../scripts/validate-compatibility-peer-dependencies.js"
|
|
38
39
|
},
|
|
39
40
|
"main": "lib/module/index",
|
|
40
41
|
"module": "lib/module/index",
|
|
@@ -89,13 +90,12 @@
|
|
|
89
90
|
"homepage": "https://docs.swmansion.com/react-native-reanimated",
|
|
90
91
|
"dependencies": {
|
|
91
92
|
"react-native-is-edge-to-edge": "^1.2.1",
|
|
92
|
-
"semver": "7.7.2"
|
|
93
|
+
"semver": "^7.7.2"
|
|
93
94
|
},
|
|
94
95
|
"peerDependencies": {
|
|
95
|
-
"@babel/core": "^7.0.0-0",
|
|
96
96
|
"react": "*",
|
|
97
|
-
"react-native": "
|
|
98
|
-
"react-native-worklets": "
|
|
97
|
+
"react-native": "0.78 - 0.82",
|
|
98
|
+
"react-native-worklets": "0.5 - 0.8"
|
|
99
99
|
},
|
|
100
100
|
"devDependencies": {
|
|
101
101
|
"@babel/cli": "^7.20.0",
|
|
@@ -148,7 +148,7 @@
|
|
|
148
148
|
"react-native-builder-bob": "0.40.13",
|
|
149
149
|
"react-native-gesture-handler": "2.28.0",
|
|
150
150
|
"react-native-svg": "15.12.1",
|
|
151
|
-
"react-native-worklets": "
|
|
151
|
+
"react-native-worklets": "0.8.0",
|
|
152
152
|
"react-test-renderer": "19.1.0",
|
|
153
153
|
"shelljs": "^0.8.5",
|
|
154
154
|
"typescript": "5.8.3"
|