@react-native-ohos/react-native-reanimated 3.18.2-rc.2 → 3.18.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/LICENSE +21 -21
- package/README.OpenSource +10 -10
- package/README.md +10 -10
- package/harmony/reanimated/BuildProfile.ets +1 -1
- package/harmony/reanimated/build-profile.json5 +11 -11
- package/harmony/reanimated/oh-package.json5 +11 -11
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.cpp +86 -86
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/AnimatedSensor/AnimatedSensorModule.h +47 -47
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/PropsRegistry.cpp +68 -68
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/PropsRegistry.h +68 -68
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.cpp +101 -101
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitHook.h +51 -51
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedCommitShadowNode.h +49 -49
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedMountHook.cpp +96 -96
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ReanimatedMountHook.h +33 -33
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ShadowTreeCloner.cpp +95 -95
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Fabric/ShadowTreeCloner.h +29 -29
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationType.h +9 -9
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.cpp +232 -232
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsManager.h +90 -90
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.cpp +870 -870
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsProxy.h +147 -147
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.cpp +91 -91
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/LayoutAnimations/LayoutAnimationsUtils.h +176 -176
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.cpp +971 -971
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxy.h +254 -252
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.cpp +231 -231
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/NativeModules/ReanimatedModuleProxySpec.h +109 -109
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.cpp +56 -56
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/RNRuntimeDecorator.h +20 -20
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.cpp +70 -70
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/RuntimeDecorators/UIRuntimeDecorator.h +35 -35
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/CollectionUtils.h +14 -14
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/FeaturesConfig.cpp +5 -5
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/FeaturesConfig.h +19 -19
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/PlatformDepMethodsHolder.h +98 -98
- package/harmony/reanimated/src/main/cpp/Common/cpp/reanimated/Tools/ReanimatedSystraceSection.h +135 -135
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.cpp +47 -47
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/NativeModules/WorkletsModuleProxy.h +59 -59
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.cpp +27 -27
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/NativeModules/WorkletsModuleProxySpec.h +25 -25
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Registries/EventHandlerRegistry.cpp +94 -94
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Registries/EventHandlerRegistry.h +49 -49
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.cpp +8 -8
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Registries/WorkletRuntimeRegistry.h +39 -39
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/SharedItems/Shareables.cpp +326 -326
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/SharedItems/Shareables.h +345 -345
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/AsyncQueue.cpp +52 -52
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/AsyncQueue.h +35 -35
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/Defs.h +10 -10
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/JSISerializer.cpp +342 -342
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/JSISerializer.h +47 -47
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/JSLogger.cpp +16 -16
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/JSLogger.h +20 -20
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/JSScheduler.cpp +20 -20
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/JSScheduler.h +29 -29
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/PlatformLogger.h +16 -16
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/ReanimatedJSIUtils.cpp +26 -26
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/ReanimatedJSIUtils.h +199 -199
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/ReanimatedVersion.cpp +95 -95
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/ReanimatedVersion.h +19 -19
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/SingleInstanceChecker.h +72 -72
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/ThreadSafeQueue.h +49 -49
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/UIScheduler.cpp +20 -20
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/UIScheduler.h +22 -22
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/WorkletEventHandler.cpp +29 -29
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/Tools/WorkletEventHandler.h +41 -41
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.cpp +16 -16
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/RNRuntimeWorkletDecorator.h +19 -19
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.cpp +112 -112
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/ReanimatedHermesRuntime.h +127 -127
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.cpp +53 -53
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/ReanimatedRuntime.h +22 -22
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/RuntimeInitialization.md +191 -191
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.cpp +173 -173
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/WorkletRuntime.h +90 -90
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeCollector.h +36 -36
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.cpp +189 -189
- package/harmony/reanimated/src/main/cpp/Common/cpp/worklets/WorkletRuntime/WorkletRuntimeDecorator.h +22 -22
- package/harmony/reanimated/src/main/cpp/ReanimatedModule.cpp +3 -0
- package/harmony/reanimated/src/main/cpp/WorkletsModule.cpp +60 -60
- package/harmony/reanimated/src/main/cpp/patches/AnimatedSensor/AnimatedSensorModule.cpp +89 -89
- package/harmony/reanimated/src/main/cpp/patches/NativeModules/ReanimatedModuleProxy.cpp +4 -0
- package/harmony/reanimated/src/main/module.json5 +12 -12
- package/harmony/reanimated/src/main/resources/base/element/color.json +7 -7
- package/harmony/reanimated/src/main/resources/base/element/string.json +15 -15
- package/harmony/reanimated/src/main/resources/base/profile/main_pages.json +5 -5
- package/harmony/reanimated/src/main/resources/en_US/element/string.json +15 -15
- package/harmony/reanimated/src/main/resources/zh_CN/element/string.json +15 -15
- package/harmony/reanimated/ts.ts +6 -6
- package/harmony/reanimated.har +0 -0
- package/package.json +50 -50
|
@@ -1,870 +1,870 @@
|
|
|
1
|
-
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
-
|
|
3
|
-
#include <reanimated/LayoutAnimations/LayoutAnimationsProxy.h>
|
|
4
|
-
#include <reanimated/NativeModules/ReanimatedModuleProxy.h>
|
|
5
|
-
|
|
6
|
-
#include <react/renderer/animations/utils.h>
|
|
7
|
-
#include <react/renderer/mounting/ShadowViewMutation.h>
|
|
8
|
-
|
|
9
|
-
#include <set>
|
|
10
|
-
#include <utility>
|
|
11
|
-
|
|
12
|
-
namespace reanimated {
|
|
13
|
-
|
|
14
|
-
// We never modify the Shadow Tree, we just send some additional
|
|
15
|
-
// mutations to the mounting layer.
|
|
16
|
-
// When animations finish, the Host Tree will represent the most recent Shadow
|
|
17
|
-
// Tree
|
|
18
|
-
// On android this code will be sometimes executed on the JS thread.
|
|
19
|
-
// That's why we have to schedule some of animation manager function on the UI
|
|
20
|
-
// thread
|
|
21
|
-
std::optional<MountingTransaction> LayoutAnimationsProxy::pullTransaction(
|
|
22
|
-
SurfaceId surfaceId,
|
|
23
|
-
MountingTransaction::Number transactionNumber,
|
|
24
|
-
const TransactionTelemetry &telemetry,
|
|
25
|
-
ShadowViewMutationList mutations) const {
|
|
26
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
27
|
-
LOG(INFO) << std::endl;
|
|
28
|
-
LOG(INFO) << "pullTransaction " << std::this_thread::get_id() << " "
|
|
29
|
-
<< surfaceId << std::endl;
|
|
30
|
-
#endif
|
|
31
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
32
|
-
PropsParserContext propsParserContext{surfaceId, *contextContainer_};
|
|
33
|
-
ShadowViewMutationList filteredMutations;
|
|
34
|
-
|
|
35
|
-
std::vector<std::shared_ptr<MutationNode>> roots;
|
|
36
|
-
std::unordered_map<Tag, ShadowView> movedViews;
|
|
37
|
-
|
|
38
|
-
parseRemoveMutations(movedViews, mutations, roots);
|
|
39
|
-
|
|
40
|
-
handleRemovals(filteredMutations, roots);
|
|
41
|
-
|
|
42
|
-
handleUpdatesAndEnterings(
|
|
43
|
-
filteredMutations, movedViews, mutations, propsParserContext, surfaceId);
|
|
44
|
-
|
|
45
|
-
addOngoingAnimations(surfaceId, filteredMutations);
|
|
46
|
-
|
|
47
|
-
return MountingTransaction{
|
|
48
|
-
surfaceId, transactionNumber, std::move(filteredMutations), telemetry};
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
std::optional<SurfaceId> LayoutAnimationsProxy::progressLayoutAnimation(
|
|
52
|
-
int tag,
|
|
53
|
-
const jsi::Object &newStyle) {
|
|
54
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
55
|
-
LOG(INFO) << "progress layout animation for tag " << tag << std::endl;
|
|
56
|
-
#endif
|
|
57
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
58
|
-
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
59
|
-
|
|
60
|
-
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
61
|
-
return {};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
auto &layoutAnimation = layoutAnimationIt->second;
|
|
65
|
-
|
|
66
|
-
maybeRestoreOpacity(layoutAnimation, newStyle);
|
|
67
|
-
|
|
68
|
-
auto rawProps =
|
|
69
|
-
std::make_shared<RawProps>(uiRuntime_, jsi::Value(uiRuntime_, newStyle));
|
|
70
|
-
|
|
71
|
-
PropsParserContext propsParserContext{
|
|
72
|
-
layoutAnimation.finalView->surfaceId, *contextContainer_};
|
|
73
|
-
#ifdef ANDROID
|
|
74
|
-
rawProps = std::make_shared<RawProps>(folly::dynamic::merge(
|
|
75
|
-
layoutAnimation.finalView->props->rawProps, (folly::dynamic)*rawProps));
|
|
76
|
-
#endif
|
|
77
|
-
auto newProps =
|
|
78
|
-
getComponentDescriptorForShadowView(*layoutAnimation.finalView)
|
|
79
|
-
.cloneProps(
|
|
80
|
-
propsParserContext,
|
|
81
|
-
layoutAnimation.finalView->props,
|
|
82
|
-
std::move(*rawProps));
|
|
83
|
-
auto &updateMap =
|
|
84
|
-
surfaceManager.getUpdateMap(layoutAnimation.finalView->surfaceId);
|
|
85
|
-
updateMap.insert_or_assign(
|
|
86
|
-
tag, UpdateValues{newProps, Frame(uiRuntime_, newStyle)});
|
|
87
|
-
|
|
88
|
-
return layoutAnimation.finalView->surfaceId;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
std::optional<SurfaceId> LayoutAnimationsProxy::endLayoutAnimation(
|
|
92
|
-
int tag,
|
|
93
|
-
bool shouldRemove) {
|
|
94
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
95
|
-
LOG(INFO) << "end layout animation for " << tag << " - should remove "
|
|
96
|
-
<< shouldRemove << std::endl;
|
|
97
|
-
#endif
|
|
98
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
99
|
-
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
100
|
-
|
|
101
|
-
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
102
|
-
return {};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
auto &layoutAnimation = layoutAnimationIt->second;
|
|
106
|
-
|
|
107
|
-
// multiple layout animations can be triggered for a view
|
|
108
|
-
// one after the other, so we need to keep count of how many
|
|
109
|
-
// were actually triggered, so that we don't cleanup necessary
|
|
110
|
-
// structures too early
|
|
111
|
-
if (layoutAnimation.count > 1) {
|
|
112
|
-
layoutAnimation.count--;
|
|
113
|
-
return {};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
auto surfaceId = layoutAnimation.finalView->surfaceId;
|
|
117
|
-
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
118
|
-
layoutAnimations_.erase(tag);
|
|
119
|
-
updateMap.erase(tag);
|
|
120
|
-
|
|
121
|
-
if (!shouldRemove || !nodeForTag_.contains(tag)) {
|
|
122
|
-
return {};
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
auto node = nodeForTag_[tag];
|
|
126
|
-
auto mutationNode = std::static_pointer_cast<MutationNode>(node);
|
|
127
|
-
mutationNode->state = DEAD;
|
|
128
|
-
deadNodes.insert(mutationNode);
|
|
129
|
-
|
|
130
|
-
return surfaceId;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
/**
|
|
134
|
-
Organizes removed views into a tree structure, allowing for convenient
|
|
135
|
-
traversals and index maintenance
|
|
136
|
-
*/
|
|
137
|
-
void LayoutAnimationsProxy::parseRemoveMutations(
|
|
138
|
-
std::unordered_map<Tag, ShadowView> &movedViews,
|
|
139
|
-
ShadowViewMutationList &mutations,
|
|
140
|
-
std::vector<std::shared_ptr<MutationNode>> &roots) const {
|
|
141
|
-
std::set<Tag> deletedViews;
|
|
142
|
-
std::unordered_map<Tag, std::vector<std::shared_ptr<MutationNode>>>
|
|
143
|
-
childrenForTag, unflattenedChildrenForTag;
|
|
144
|
-
|
|
145
|
-
std::vector<std::shared_ptr<MutationNode>> mutationNodes;
|
|
146
|
-
|
|
147
|
-
// iterate from the end, so that parents appear before children
|
|
148
|
-
for (auto it = mutations.rbegin(); it != mutations.rend(); it++) {
|
|
149
|
-
auto &mutation = *it;
|
|
150
|
-
if (mutation.type == ShadowViewMutation::Delete) {
|
|
151
|
-
deletedViews.insert(mutation.oldChildShadowView.tag);
|
|
152
|
-
}
|
|
153
|
-
if (mutation.type == ShadowViewMutation::Remove) {
|
|
154
|
-
updateIndexForMutation(mutation);
|
|
155
|
-
auto tag = mutation.oldChildShadowView.tag;
|
|
156
|
-
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
157
|
-
auto parentTag = mutation.parentTag;
|
|
158
|
-
#else
|
|
159
|
-
auto parentTag = mutation.parentShadowView.tag;
|
|
160
|
-
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
161
|
-
auto unflattenedParentTag = parentTag; // temporary
|
|
162
|
-
|
|
163
|
-
std::shared_ptr<MutationNode> mutationNode;
|
|
164
|
-
std::shared_ptr<Node> node = nodeForTag_[tag],
|
|
165
|
-
parent = nodeForTag_[parentTag],
|
|
166
|
-
unflattenedParent =
|
|
167
|
-
nodeForTag_[unflattenedParentTag];
|
|
168
|
-
|
|
169
|
-
if (!node) {
|
|
170
|
-
mutationNode = std::make_shared<MutationNode>(mutation);
|
|
171
|
-
} else {
|
|
172
|
-
mutationNode =
|
|
173
|
-
std::make_shared<MutationNode>(mutation, std::move(*node));
|
|
174
|
-
for (auto &subNode : mutationNode->children) {
|
|
175
|
-
subNode->parent = mutationNode;
|
|
176
|
-
}
|
|
177
|
-
for (auto &subNode : mutationNode->unflattenedChildren) {
|
|
178
|
-
subNode->unflattenedParent = mutationNode;
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
if (!deletedViews.contains(mutation.oldChildShadowView.tag)) {
|
|
182
|
-
mutationNode->state = MOVED;
|
|
183
|
-
movedViews.insert_or_assign(
|
|
184
|
-
mutation.oldChildShadowView.tag, mutation.oldChildShadowView);
|
|
185
|
-
}
|
|
186
|
-
nodeForTag_[tag] = mutationNode;
|
|
187
|
-
|
|
188
|
-
if (!parent) {
|
|
189
|
-
parent = std::make_shared<Node>(parentTag);
|
|
190
|
-
nodeForTag_[parentTag] = parent;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (!unflattenedParent) {
|
|
194
|
-
if (parentTag == unflattenedParentTag) {
|
|
195
|
-
unflattenedParent = parent;
|
|
196
|
-
} else {
|
|
197
|
-
unflattenedParent = std::make_shared<Node>(unflattenedParentTag);
|
|
198
|
-
nodeForTag_[unflattenedParentTag] = unflattenedParent;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
mutationNodes.push_back(mutationNode);
|
|
203
|
-
|
|
204
|
-
childrenForTag[parentTag].push_back(mutationNode);
|
|
205
|
-
unflattenedChildrenForTag[unflattenedParentTag].push_back(mutationNode);
|
|
206
|
-
mutationNode->parent = parent;
|
|
207
|
-
mutationNode->unflattenedParent = unflattenedParent;
|
|
208
|
-
}
|
|
209
|
-
if (mutation.type == ShadowViewMutation::Update &&
|
|
210
|
-
movedViews.contains(mutation.newChildShadowView.tag)) {
|
|
211
|
-
auto node = nodeForTag_[mutation.newChildShadowView.tag];
|
|
212
|
-
auto mutationNode = std::static_pointer_cast<MutationNode>(node);
|
|
213
|
-
mutationNode->mutation.oldChildShadowView = mutation.oldChildShadowView;
|
|
214
|
-
movedViews[mutation.newChildShadowView.tag] = mutation.oldChildShadowView;
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
for (auto &[parentTag, children] : childrenForTag) {
|
|
219
|
-
auto &parent = nodeForTag_[parentTag];
|
|
220
|
-
parent->insertChildren(children);
|
|
221
|
-
for (auto &child : children) {
|
|
222
|
-
child->parent = parent;
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
for (auto &[unflattenedParentTag, children] : unflattenedChildrenForTag) {
|
|
226
|
-
auto &unflattenedParent = nodeForTag_[unflattenedParentTag];
|
|
227
|
-
unflattenedParent->insertUnflattenedChildren(children);
|
|
228
|
-
for (auto &child : children) {
|
|
229
|
-
child->unflattenedParent = unflattenedParent;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
for (auto &mutationNode : mutationNodes) {
|
|
234
|
-
if (!mutationNode->unflattenedParent->isMutationMode()) {
|
|
235
|
-
roots.push_back(mutationNode);
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
void LayoutAnimationsProxy::handleRemovals(
|
|
241
|
-
ShadowViewMutationList &filteredMutations,
|
|
242
|
-
std::vector<std::shared_ptr<MutationNode>> &roots) const {
|
|
243
|
-
// iterate from the end, so that children
|
|
244
|
-
// with higher indices appear first in the mutations list
|
|
245
|
-
for (auto it = roots.rbegin(); it != roots.rend(); it++) {
|
|
246
|
-
auto &node = *it;
|
|
247
|
-
if (!startAnimationsRecursively(
|
|
248
|
-
node, true, true, false, filteredMutations)) {
|
|
249
|
-
filteredMutations.push_back(node->mutation);
|
|
250
|
-
node->unflattenedParent->removeChildFromUnflattenedTree(node); //???
|
|
251
|
-
if (node->state != MOVED) {
|
|
252
|
-
maybeCancelAnimation(node->tag);
|
|
253
|
-
filteredMutations.push_back(ShadowViewMutation::DeleteMutation(
|
|
254
|
-
node->mutation.oldChildShadowView));
|
|
255
|
-
nodeForTag_.erase(node->tag);
|
|
256
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
257
|
-
LOG(INFO) << "delete " << node->tag << std::endl;
|
|
258
|
-
#endif
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
for (auto node : deadNodes) {
|
|
264
|
-
if (node->state != DELETED) {
|
|
265
|
-
endAnimationsRecursively(node, filteredMutations);
|
|
266
|
-
maybeDropAncestors(node->unflattenedParent, node, filteredMutations);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
deadNodes.clear();
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
void LayoutAnimationsProxy::handleUpdatesAndEnterings(
|
|
273
|
-
ShadowViewMutationList &filteredMutations,
|
|
274
|
-
const std::unordered_map<Tag, ShadowView> &movedViews,
|
|
275
|
-
ShadowViewMutationList &mutations,
|
|
276
|
-
const PropsParserContext &propsParserContext,
|
|
277
|
-
SurfaceId surfaceId) const {
|
|
278
|
-
std::unordered_map<Tag, ShadowView> oldShadowViewsForReparentings;
|
|
279
|
-
for (auto &mutation : mutations) {
|
|
280
|
-
maybeUpdateWindowDimensions(mutation, surfaceId);
|
|
281
|
-
|
|
282
|
-
Tag tag = mutation.type == ShadowViewMutation::Type::Create ||
|
|
283
|
-
mutation.type == ShadowViewMutation::Type::Insert
|
|
284
|
-
? mutation.newChildShadowView.tag
|
|
285
|
-
: mutation.oldChildShadowView.tag;
|
|
286
|
-
|
|
287
|
-
switch (mutation.type) {
|
|
288
|
-
case ShadowViewMutation::Type::Create: {
|
|
289
|
-
filteredMutations.push_back(mutation);
|
|
290
|
-
break;
|
|
291
|
-
}
|
|
292
|
-
case ShadowViewMutation::Type::Insert: {
|
|
293
|
-
updateIndexForMutation(mutation);
|
|
294
|
-
|
|
295
|
-
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
296
|
-
const auto parentTag = mutation.parentTag;
|
|
297
|
-
const auto mutationParent = parentTag;
|
|
298
|
-
#else
|
|
299
|
-
const auto parentTag = mutation.parentShadowView.tag;
|
|
300
|
-
const auto mutationParent = mutation.parentShadowView;
|
|
301
|
-
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
302
|
-
if (nodeForTag_.contains(parentTag)) {
|
|
303
|
-
nodeForTag_[parentTag]->applyMutationToIndices(mutation);
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
if (movedViews.contains(tag)) {
|
|
307
|
-
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
308
|
-
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
309
|
-
if (oldShadowViewsForReparentings.contains(tag)) {
|
|
310
|
-
filteredMutations.push_back(ShadowViewMutation::InsertMutation(
|
|
311
|
-
mutationParent,
|
|
312
|
-
oldShadowViewsForReparentings[tag],
|
|
313
|
-
mutation.index));
|
|
314
|
-
} else {
|
|
315
|
-
filteredMutations.push_back(mutation);
|
|
316
|
-
}
|
|
317
|
-
continue;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
auto oldView = *layoutAnimationIt->second.currentView;
|
|
321
|
-
filteredMutations.push_back(ShadowViewMutation::InsertMutation(
|
|
322
|
-
mutationParent, oldView, mutation.index));
|
|
323
|
-
continue;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
transferConfigFromNativeID(
|
|
327
|
-
mutation.newChildShadowView.props->nativeId,
|
|
328
|
-
mutation.newChildShadowView.tag);
|
|
329
|
-
if (!layoutAnimationsManager_->hasLayoutAnimation(tag, ENTERING)) {
|
|
330
|
-
filteredMutations.push_back(mutation);
|
|
331
|
-
continue;
|
|
332
|
-
}
|
|
333
|
-
|
|
334
|
-
startEnteringAnimation(tag, mutation);
|
|
335
|
-
filteredMutations.push_back(mutation);
|
|
336
|
-
|
|
337
|
-
// temporarily set opacity to 0 to prevent flickering on android
|
|
338
|
-
std::shared_ptr<ShadowView> newView =
|
|
339
|
-
cloneViewWithoutOpacity(mutation, propsParserContext);
|
|
340
|
-
|
|
341
|
-
filteredMutations.push_back(ShadowViewMutation::UpdateMutation(
|
|
342
|
-
mutation.newChildShadowView, *newView, mutationParent));
|
|
343
|
-
break;
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
case ShadowViewMutation::Type::Update: {
|
|
347
|
-
auto shouldAnimate = hasLayoutChanged(mutation);
|
|
348
|
-
if (!layoutAnimationsManager_->hasLayoutAnimation(tag, LAYOUT) ||
|
|
349
|
-
(!shouldAnimate && !layoutAnimations_.contains(tag))) {
|
|
350
|
-
// We should cancel any ongoing animation here to ensure that the
|
|
351
|
-
// proper final state is reached for this view However, due to how
|
|
352
|
-
// RNSScreens handle adding headers (a second commit is triggered to
|
|
353
|
-
// offset all the elements by the header height) this would lead to
|
|
354
|
-
// all entering animations being cancelled when a screen with a header
|
|
355
|
-
// is pushed onto a stack
|
|
356
|
-
// TODO: find a better solution for this problem
|
|
357
|
-
filteredMutations.push_back(mutation);
|
|
358
|
-
continue;
|
|
359
|
-
} else if (!shouldAnimate) {
|
|
360
|
-
updateOngoingAnimationTarget(tag, mutation);
|
|
361
|
-
continue;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// store the oldChildShadowView, so that we can use this ShadowView when
|
|
365
|
-
// the view is inserted
|
|
366
|
-
oldShadowViewsForReparentings[tag] = mutation.oldChildShadowView;
|
|
367
|
-
startLayoutAnimation(tag, mutation);
|
|
368
|
-
break;
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
case ShadowViewMutation::Type::Remove:
|
|
372
|
-
case ShadowViewMutation::Type::Delete: {
|
|
373
|
-
break;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
default:
|
|
377
|
-
filteredMutations.push_back(mutation);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
void LayoutAnimationsProxy::addOngoingAnimations(
|
|
383
|
-
SurfaceId surfaceId,
|
|
384
|
-
ShadowViewMutationList &mutations) const {
|
|
385
|
-
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
386
|
-
for (auto &[tag, updateValues] : updateMap) {
|
|
387
|
-
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
388
|
-
|
|
389
|
-
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
390
|
-
continue;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
auto &layoutAnimation = layoutAnimationIt->second;
|
|
394
|
-
|
|
395
|
-
auto newView = std::make_shared<ShadowView>(*layoutAnimation.finalView);
|
|
396
|
-
newView->props = updateValues.newProps;
|
|
397
|
-
updateLayoutMetrics(newView->layoutMetrics, updateValues.frame);
|
|
398
|
-
|
|
399
|
-
mutations.push_back(ShadowViewMutation::UpdateMutation(
|
|
400
|
-
*layoutAnimation.currentView,
|
|
401
|
-
*newView,
|
|
402
|
-
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
403
|
-
layoutAnimation.parentTag
|
|
404
|
-
#else
|
|
405
|
-
*layoutAnimation.parentView
|
|
406
|
-
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
407
|
-
));
|
|
408
|
-
layoutAnimation.currentView = newView;
|
|
409
|
-
}
|
|
410
|
-
updateMap.clear();
|
|
411
|
-
}
|
|
412
|
-
|
|
413
|
-
void LayoutAnimationsProxy::endAnimationsRecursively(
|
|
414
|
-
std::shared_ptr<MutationNode> node,
|
|
415
|
-
ShadowViewMutationList &mutations) const {
|
|
416
|
-
maybeCancelAnimation(node->tag);
|
|
417
|
-
node->state = DELETED;
|
|
418
|
-
// iterate from the end, so that children
|
|
419
|
-
// with higher indices appear first in the mutations list
|
|
420
|
-
for (auto it = node->unflattenedChildren.rbegin();
|
|
421
|
-
it != node->unflattenedChildren.rend();
|
|
422
|
-
it++) {
|
|
423
|
-
auto &subNode = *it;
|
|
424
|
-
if (subNode->state != DELETED) {
|
|
425
|
-
endAnimationsRecursively(subNode, mutations);
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
mutations.push_back(node->mutation);
|
|
429
|
-
nodeForTag_.erase(node->tag);
|
|
430
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
431
|
-
LOG(INFO) << "delete " << node->tag << std::endl;
|
|
432
|
-
#endif
|
|
433
|
-
mutations.push_back(
|
|
434
|
-
ShadowViewMutation::DeleteMutation(node->mutation.oldChildShadowView));
|
|
435
|
-
}
|
|
436
|
-
|
|
437
|
-
void LayoutAnimationsProxy::maybeDropAncestors(
|
|
438
|
-
std::shared_ptr<Node> parent,
|
|
439
|
-
std::shared_ptr<MutationNode> child,
|
|
440
|
-
ShadowViewMutationList &cleanupMutations) const {
|
|
441
|
-
parent->removeChildFromUnflattenedTree(child);
|
|
442
|
-
if (!parent->isMutationMode()) {
|
|
443
|
-
return;
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
auto node = std::static_pointer_cast<MutationNode>(parent);
|
|
447
|
-
|
|
448
|
-
if (node->children.size() == 0 && node->state != ANIMATING) {
|
|
449
|
-
nodeForTag_.erase(node->tag);
|
|
450
|
-
cleanupMutations.push_back(node->mutation);
|
|
451
|
-
maybeCancelAnimation(node->tag);
|
|
452
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
453
|
-
LOG(INFO) << "delete " << node->tag << std::endl;
|
|
454
|
-
#endif
|
|
455
|
-
cleanupMutations.push_back(
|
|
456
|
-
ShadowViewMutation::DeleteMutation(node->mutation.oldChildShadowView));
|
|
457
|
-
maybeDropAncestors(node->unflattenedParent, node, cleanupMutations);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
const ComponentDescriptor &
|
|
462
|
-
LayoutAnimationsProxy::getComponentDescriptorForShadowView(
|
|
463
|
-
const ShadowView &shadowView) const {
|
|
464
|
-
return componentDescriptorRegistry_->at(shadowView.componentHandle);
|
|
465
|
-
}
|
|
466
|
-
|
|
467
|
-
bool LayoutAnimationsProxy::startAnimationsRecursively(
|
|
468
|
-
std::shared_ptr<MutationNode> node,
|
|
469
|
-
bool shouldRemoveSubviewsWithoutAnimations,
|
|
470
|
-
bool shouldAnimate,
|
|
471
|
-
bool isScreenPop,
|
|
472
|
-
ShadowViewMutationList &mutations) const {
|
|
473
|
-
if (isRNSScreen(node)) {
|
|
474
|
-
isScreenPop = true;
|
|
475
|
-
}
|
|
476
|
-
|
|
477
|
-
shouldAnimate = !isScreenPop &&
|
|
478
|
-
layoutAnimationsManager_->shouldAnimateExiting(node->tag, shouldAnimate);
|
|
479
|
-
|
|
480
|
-
bool hasExitAnimation = shouldAnimate &&
|
|
481
|
-
layoutAnimationsManager_->hasLayoutAnimation(
|
|
482
|
-
node->tag, LayoutAnimationType::EXITING);
|
|
483
|
-
bool hasAnimatedChildren = false;
|
|
484
|
-
|
|
485
|
-
shouldRemoveSubviewsWithoutAnimations =
|
|
486
|
-
shouldRemoveSubviewsWithoutAnimations && !hasExitAnimation;
|
|
487
|
-
std::vector<std::shared_ptr<MutationNode>> toBeRemoved;
|
|
488
|
-
|
|
489
|
-
// iterate from the end, so that children
|
|
490
|
-
// with higher indices appear first in the mutations list
|
|
491
|
-
for (auto it = node->unflattenedChildren.rbegin();
|
|
492
|
-
it != node->unflattenedChildren.rend();
|
|
493
|
-
it++) {
|
|
494
|
-
auto &subNode = *it;
|
|
495
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
496
|
-
LOG(INFO) << "child " << subNode->tag << " "
|
|
497
|
-
<< " " << shouldAnimate << " "
|
|
498
|
-
<< shouldRemoveSubviewsWithoutAnimations << std::endl;
|
|
499
|
-
#endif
|
|
500
|
-
if (subNode->state != UNDEFINED && subNode->state != MOVED) {
|
|
501
|
-
if (shouldAnimate && subNode->state != DEAD) {
|
|
502
|
-
hasAnimatedChildren = true;
|
|
503
|
-
} else {
|
|
504
|
-
endAnimationsRecursively(subNode, mutations);
|
|
505
|
-
toBeRemoved.push_back(subNode);
|
|
506
|
-
}
|
|
507
|
-
} else if (startAnimationsRecursively(
|
|
508
|
-
subNode,
|
|
509
|
-
shouldRemoveSubviewsWithoutAnimations,
|
|
510
|
-
shouldAnimate,
|
|
511
|
-
isScreenPop,
|
|
512
|
-
mutations)) {
|
|
513
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
514
|
-
LOG(INFO) << "child " << subNode->tag
|
|
515
|
-
<< " start animations returned true " << std::endl;
|
|
516
|
-
#endif
|
|
517
|
-
hasAnimatedChildren = true;
|
|
518
|
-
} else if (subNode->state == MOVED) {
|
|
519
|
-
mutations.push_back(subNode->mutation);
|
|
520
|
-
toBeRemoved.push_back(subNode);
|
|
521
|
-
} else if (shouldRemoveSubviewsWithoutAnimations) {
|
|
522
|
-
maybeCancelAnimation(subNode->tag);
|
|
523
|
-
mutations.push_back(subNode->mutation);
|
|
524
|
-
toBeRemoved.push_back(subNode);
|
|
525
|
-
subNode->state = DELETED;
|
|
526
|
-
nodeForTag_.erase(subNode->tag);
|
|
527
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
528
|
-
LOG(INFO) << "delete " << subNode->tag << std::endl;
|
|
529
|
-
#endif
|
|
530
|
-
mutations.push_back(ShadowViewMutation::DeleteMutation(
|
|
531
|
-
subNode->mutation.oldChildShadowView));
|
|
532
|
-
} else {
|
|
533
|
-
subNode->state = WAITING;
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
|
|
537
|
-
for (auto &subNode : toBeRemoved) {
|
|
538
|
-
node->removeChildFromUnflattenedTree(subNode);
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
if (node->state == MOVED) {
|
|
542
|
-
auto replacement = std::make_shared<Node>(*node);
|
|
543
|
-
for (auto subNode : node->children) {
|
|
544
|
-
subNode->parent = replacement;
|
|
545
|
-
}
|
|
546
|
-
for (auto subNode : node->unflattenedChildren) {
|
|
547
|
-
subNode->unflattenedParent = replacement;
|
|
548
|
-
}
|
|
549
|
-
nodeForTag_[replacement->tag] = replacement;
|
|
550
|
-
return false;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
bool wantAnimateExit = hasExitAnimation || hasAnimatedChildren;
|
|
554
|
-
|
|
555
|
-
if (hasExitAnimation) {
|
|
556
|
-
node->state = ANIMATING;
|
|
557
|
-
startExitingAnimation(node->tag, node->mutation);
|
|
558
|
-
} else {
|
|
559
|
-
layoutAnimationsManager_->clearLayoutAnimationConfig(node->tag);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
return wantAnimateExit;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
void LayoutAnimationsProxy::updateIndexForMutation(
|
|
566
|
-
ShadowViewMutation &mutation) const {
|
|
567
|
-
if (mutation.index == -1) {
|
|
568
|
-
return;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
572
|
-
const auto parentTag = mutation.parentTag;
|
|
573
|
-
#else
|
|
574
|
-
const auto parentTag = mutation.parentShadowView.tag;
|
|
575
|
-
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
576
|
-
|
|
577
|
-
if (!nodeForTag_.contains(parentTag)) {
|
|
578
|
-
return;
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
auto parent = nodeForTag_[parentTag];
|
|
582
|
-
int size = 0, prevIndex = -1, offset = 0;
|
|
583
|
-
|
|
584
|
-
for (auto &subNode : parent->children) {
|
|
585
|
-
size += subNode->mutation.index - prevIndex - 1;
|
|
586
|
-
if (mutation.index < size) {
|
|
587
|
-
break;
|
|
588
|
-
}
|
|
589
|
-
offset++;
|
|
590
|
-
prevIndex = subNode->mutation.index;
|
|
591
|
-
}
|
|
592
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
593
|
-
int tag = mutation.type == ShadowViewMutation::Insert
|
|
594
|
-
? mutation.newChildShadowView.tag
|
|
595
|
-
: mutation.oldChildShadowView.tag;
|
|
596
|
-
LOG(INFO) << "update index for " << tag << " in " << parentTag << ": "
|
|
597
|
-
<< mutation.index << " -> " << mutation.index + offset << std::endl;
|
|
598
|
-
#endif
|
|
599
|
-
mutation.index += offset;
|
|
600
|
-
}
|
|
601
|
-
|
|
602
|
-
bool LayoutAnimationsProxy::shouldOverridePullTransaction() const {
|
|
603
|
-
return true;
|
|
604
|
-
}
|
|
605
|
-
|
|
606
|
-
void LayoutAnimationsProxy::createLayoutAnimation(
|
|
607
|
-
const ShadowViewMutation &mutation,
|
|
608
|
-
ShadowView &oldView,
|
|
609
|
-
const SurfaceId &surfaceId,
|
|
610
|
-
const int tag) const {
|
|
611
|
-
int count = 1;
|
|
612
|
-
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
613
|
-
|
|
614
|
-
if (layoutAnimationIt != layoutAnimations_.end()) {
|
|
615
|
-
auto &layoutAnimation = layoutAnimationIt->second;
|
|
616
|
-
oldView = *layoutAnimation.currentView;
|
|
617
|
-
count = layoutAnimation.count + 1;
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
auto finalView = std::make_shared<ShadowView>(
|
|
621
|
-
mutation.type == ShadowViewMutation::Remove
|
|
622
|
-
? mutation.oldChildShadowView
|
|
623
|
-
: mutation.newChildShadowView);
|
|
624
|
-
auto currentView = std::make_shared<ShadowView>(oldView);
|
|
625
|
-
|
|
626
|
-
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
627
|
-
layoutAnimations_.insert_or_assign(
|
|
628
|
-
tag,
|
|
629
|
-
LayoutAnimation{finalView, currentView, mutation.parentTag, {}, count});
|
|
630
|
-
#else
|
|
631
|
-
auto parentView = std::make_shared<ShadowView>(mutation.parentShadowView);
|
|
632
|
-
layoutAnimations_.insert_or_assign(
|
|
633
|
-
tag, LayoutAnimation{finalView, currentView, parentView, {}, count});
|
|
634
|
-
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
635
|
-
}
|
|
636
|
-
|
|
637
|
-
void LayoutAnimationsProxy::startEnteringAnimation(
|
|
638
|
-
const int tag,
|
|
639
|
-
ShadowViewMutation &mutation) const {
|
|
640
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
641
|
-
LOG(INFO) << "start entering animation for tag " << tag << std::endl;
|
|
642
|
-
#endif
|
|
643
|
-
auto finalView = std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
644
|
-
auto current = std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
645
|
-
#if REACT_NATIVE_MINOR_VERSION < 78
|
|
646
|
-
auto parent = std::make_shared<ShadowView>(mutation.parentShadowView);
|
|
647
|
-
#endif
|
|
648
|
-
|
|
649
|
-
auto &viewProps =
|
|
650
|
-
static_cast<const ViewProps &>(*mutation.newChildShadowView.props);
|
|
651
|
-
auto opacity = viewProps.opacity;
|
|
652
|
-
|
|
653
|
-
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(),
|
|
654
|
-
finalView,
|
|
655
|
-
current,
|
|
656
|
-
#if REACT_NATIVE_MINOR_VERSION < 78
|
|
657
|
-
parent,
|
|
658
|
-
#endif // RE
|
|
659
|
-
mutation,
|
|
660
|
-
opacity,
|
|
661
|
-
tag]() {
|
|
662
|
-
auto strongThis = weakThis.lock();
|
|
663
|
-
if (!strongThis) {
|
|
664
|
-
return;
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
Rect window{};
|
|
668
|
-
{
|
|
669
|
-
auto &mutex = strongThis->mutex;
|
|
670
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
671
|
-
strongThis->layoutAnimations_.insert_or_assign(
|
|
672
|
-
tag, LayoutAnimation {
|
|
673
|
-
finalView, current,
|
|
674
|
-
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
675
|
-
mutation.parentTag,
|
|
676
|
-
#else
|
|
677
|
-
parent,
|
|
678
|
-
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
679
|
-
opacity
|
|
680
|
-
});
|
|
681
|
-
window = strongThis->surfaceManager.getWindow(
|
|
682
|
-
mutation.newChildShadowView.surfaceId);
|
|
683
|
-
}
|
|
684
|
-
|
|
685
|
-
Snapshot values(mutation.newChildShadowView, window);
|
|
686
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
687
|
-
jsi::Object yogaValues(uiRuntime);
|
|
688
|
-
yogaValues.setProperty(uiRuntime, "targetOriginX", values.x);
|
|
689
|
-
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", values.x);
|
|
690
|
-
yogaValues.setProperty(uiRuntime, "targetOriginY", values.y);
|
|
691
|
-
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", values.y);
|
|
692
|
-
yogaValues.setProperty(uiRuntime, "targetWidth", values.width);
|
|
693
|
-
yogaValues.setProperty(uiRuntime, "targetHeight", values.height);
|
|
694
|
-
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
695
|
-
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
696
|
-
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
697
|
-
uiRuntime, tag, LayoutAnimationType::ENTERING, yogaValues);
|
|
698
|
-
});
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
void LayoutAnimationsProxy::startExitingAnimation(
|
|
702
|
-
const int tag,
|
|
703
|
-
ShadowViewMutation &mutation) const {
|
|
704
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
705
|
-
LOG(INFO) << "start exiting animation for tag " << tag << std::endl;
|
|
706
|
-
#endif
|
|
707
|
-
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
708
|
-
|
|
709
|
-
uiScheduler_->scheduleOnUI(
|
|
710
|
-
[weakThis = weak_from_this(), tag, mutation, surfaceId]() {
|
|
711
|
-
auto strongThis = weakThis.lock();
|
|
712
|
-
if (!strongThis) {
|
|
713
|
-
return;
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
auto oldView = mutation.oldChildShadowView;
|
|
717
|
-
Rect window{};
|
|
718
|
-
{
|
|
719
|
-
auto &mutex = strongThis->mutex;
|
|
720
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
721
|
-
strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
722
|
-
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
723
|
-
}
|
|
724
|
-
|
|
725
|
-
Snapshot values(oldView, window);
|
|
726
|
-
|
|
727
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
728
|
-
jsi::Object yogaValues(uiRuntime);
|
|
729
|
-
yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
|
|
730
|
-
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
|
|
731
|
-
yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
|
|
732
|
-
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
|
|
733
|
-
yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
|
|
734
|
-
yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
|
|
735
|
-
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
736
|
-
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
737
|
-
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
738
|
-
uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
|
|
739
|
-
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
740
|
-
});
|
|
741
|
-
}
|
|
742
|
-
|
|
743
|
-
void LayoutAnimationsProxy::startLayoutAnimation(
|
|
744
|
-
const int tag,
|
|
745
|
-
const ShadowViewMutation &mutation) const {
|
|
746
|
-
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
747
|
-
LOG(INFO) << "start layout animation for tag " << tag << std::endl;
|
|
748
|
-
#endif
|
|
749
|
-
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
750
|
-
|
|
751
|
-
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(),
|
|
752
|
-
mutation,
|
|
753
|
-
surfaceId,
|
|
754
|
-
tag]() {
|
|
755
|
-
auto strongThis = weakThis.lock();
|
|
756
|
-
if (!strongThis) {
|
|
757
|
-
return;
|
|
758
|
-
}
|
|
759
|
-
|
|
760
|
-
auto oldView = mutation.oldChildShadowView;
|
|
761
|
-
Rect window{};
|
|
762
|
-
{
|
|
763
|
-
auto &mutex = strongThis->mutex;
|
|
764
|
-
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
765
|
-
strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
766
|
-
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
Snapshot currentValues(oldView, window);
|
|
770
|
-
Snapshot targetValues(mutation.newChildShadowView, window);
|
|
771
|
-
|
|
772
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
773
|
-
jsi::Object yogaValues(uiRuntime);
|
|
774
|
-
yogaValues.setProperty(uiRuntime, "currentOriginX", currentValues.x);
|
|
775
|
-
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", currentValues.x);
|
|
776
|
-
yogaValues.setProperty(uiRuntime, "currentOriginY", currentValues.y);
|
|
777
|
-
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", currentValues.y);
|
|
778
|
-
yogaValues.setProperty(uiRuntime, "currentWidth", currentValues.width);
|
|
779
|
-
yogaValues.setProperty(uiRuntime, "currentHeight", currentValues.height);
|
|
780
|
-
yogaValues.setProperty(uiRuntime, "targetOriginX", targetValues.x);
|
|
781
|
-
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", targetValues.x);
|
|
782
|
-
yogaValues.setProperty(uiRuntime, "targetOriginY", targetValues.y);
|
|
783
|
-
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", targetValues.y);
|
|
784
|
-
yogaValues.setProperty(uiRuntime, "targetWidth", targetValues.width);
|
|
785
|
-
yogaValues.setProperty(uiRuntime, "targetHeight", targetValues.height);
|
|
786
|
-
yogaValues.setProperty(uiRuntime, "windowWidth", targetValues.windowWidth);
|
|
787
|
-
yogaValues.setProperty(
|
|
788
|
-
uiRuntime, "windowHeight", targetValues.windowHeight);
|
|
789
|
-
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
790
|
-
uiRuntime, tag, LayoutAnimationType::LAYOUT, yogaValues);
|
|
791
|
-
});
|
|
792
|
-
}
|
|
793
|
-
|
|
794
|
-
void LayoutAnimationsProxy::updateOngoingAnimationTarget(
|
|
795
|
-
const int tag,
|
|
796
|
-
const ShadowViewMutation &mutation) const {
|
|
797
|
-
layoutAnimations_[tag].finalView =
|
|
798
|
-
std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
799
|
-
}
|
|
800
|
-
|
|
801
|
-
void LayoutAnimationsProxy::maybeCancelAnimation(const int tag) const {
|
|
802
|
-
if (!layoutAnimations_.contains(tag)) {
|
|
803
|
-
return;
|
|
804
|
-
}
|
|
805
|
-
layoutAnimations_.erase(tag);
|
|
806
|
-
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), tag]() {
|
|
807
|
-
auto strongThis = weakThis.lock();
|
|
808
|
-
if (!strongThis) {
|
|
809
|
-
return;
|
|
810
|
-
}
|
|
811
|
-
|
|
812
|
-
auto &uiRuntime = strongThis->uiRuntime_;
|
|
813
|
-
strongThis->layoutAnimationsManager_->cancelLayoutAnimation(uiRuntime, tag);
|
|
814
|
-
});
|
|
815
|
-
}
|
|
816
|
-
|
|
817
|
-
void LayoutAnimationsProxy::transferConfigFromNativeID(
|
|
818
|
-
const std::string nativeIdString,
|
|
819
|
-
const int tag) const {
|
|
820
|
-
if (nativeIdString.empty()) {
|
|
821
|
-
return;
|
|
822
|
-
}
|
|
823
|
-
try {
|
|
824
|
-
auto nativeId = stoi(nativeIdString);
|
|
825
|
-
layoutAnimationsManager_->transferConfigFromNativeID(nativeId, tag);
|
|
826
|
-
} catch (std::invalid_argument) {
|
|
827
|
-
} catch (std::out_of_range) {
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
// When entering animations start, we temporarily set opacity to 0
|
|
832
|
-
// so that we can immediately insert the view at the right position
|
|
833
|
-
// and schedule the animation on the UI thread
|
|
834
|
-
std::shared_ptr<ShadowView> LayoutAnimationsProxy::cloneViewWithoutOpacity(
|
|
835
|
-
facebook::react::ShadowViewMutation &mutation,
|
|
836
|
-
const PropsParserContext &propsParserContext) const {
|
|
837
|
-
auto newView = std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
838
|
-
folly::dynamic opacity = folly::dynamic::object("opacity", 0);
|
|
839
|
-
auto newProps = getComponentDescriptorForShadowView(*newView).cloneProps(
|
|
840
|
-
propsParserContext, newView->props, RawProps(opacity));
|
|
841
|
-
newView->props = newProps;
|
|
842
|
-
return newView;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
void LayoutAnimationsProxy::maybeRestoreOpacity(
|
|
846
|
-
LayoutAnimation &layoutAnimation,
|
|
847
|
-
const jsi::Object &newStyle) const {
|
|
848
|
-
if (layoutAnimation.opacity && !newStyle.hasProperty(uiRuntime_, "opacity")) {
|
|
849
|
-
newStyle.setProperty(
|
|
850
|
-
uiRuntime_, "opacity", jsi::Value(*layoutAnimation.opacity));
|
|
851
|
-
layoutAnimation.opacity.reset();
|
|
852
|
-
}
|
|
853
|
-
}
|
|
854
|
-
|
|
855
|
-
void LayoutAnimationsProxy::maybeUpdateWindowDimensions(
|
|
856
|
-
facebook::react::ShadowViewMutation &mutation,
|
|
857
|
-
SurfaceId surfaceId) const {
|
|
858
|
-
if (mutation.type == ShadowViewMutation::Update &&
|
|
859
|
-
!std::strcmp(
|
|
860
|
-
mutation.oldChildShadowView.componentName, RootComponentName)) {
|
|
861
|
-
surfaceManager.updateWindow(
|
|
862
|
-
surfaceId,
|
|
863
|
-
mutation.newChildShadowView.layoutMetrics.frame.size.width,
|
|
864
|
-
mutation.newChildShadowView.layoutMetrics.frame.size.height);
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
|
|
868
|
-
} // namespace reanimated
|
|
869
|
-
|
|
870
|
-
#endif // RCT_NEW_ARCH_ENABLED
|
|
1
|
+
#ifdef RCT_NEW_ARCH_ENABLED
|
|
2
|
+
|
|
3
|
+
#include <reanimated/LayoutAnimations/LayoutAnimationsProxy.h>
|
|
4
|
+
#include <reanimated/NativeModules/ReanimatedModuleProxy.h>
|
|
5
|
+
|
|
6
|
+
#include <react/renderer/animations/utils.h>
|
|
7
|
+
#include <react/renderer/mounting/ShadowViewMutation.h>
|
|
8
|
+
|
|
9
|
+
#include <set>
|
|
10
|
+
#include <utility>
|
|
11
|
+
|
|
12
|
+
namespace reanimated {
|
|
13
|
+
|
|
14
|
+
// We never modify the Shadow Tree, we just send some additional
|
|
15
|
+
// mutations to the mounting layer.
|
|
16
|
+
// When animations finish, the Host Tree will represent the most recent Shadow
|
|
17
|
+
// Tree
|
|
18
|
+
// On android this code will be sometimes executed on the JS thread.
|
|
19
|
+
// That's why we have to schedule some of animation manager function on the UI
|
|
20
|
+
// thread
|
|
21
|
+
std::optional<MountingTransaction> LayoutAnimationsProxy::pullTransaction(
|
|
22
|
+
SurfaceId surfaceId,
|
|
23
|
+
MountingTransaction::Number transactionNumber,
|
|
24
|
+
const TransactionTelemetry &telemetry,
|
|
25
|
+
ShadowViewMutationList mutations) const {
|
|
26
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
27
|
+
LOG(INFO) << std::endl;
|
|
28
|
+
LOG(INFO) << "pullTransaction " << std::this_thread::get_id() << " "
|
|
29
|
+
<< surfaceId << std::endl;
|
|
30
|
+
#endif
|
|
31
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
32
|
+
PropsParserContext propsParserContext{surfaceId, *contextContainer_};
|
|
33
|
+
ShadowViewMutationList filteredMutations;
|
|
34
|
+
|
|
35
|
+
std::vector<std::shared_ptr<MutationNode>> roots;
|
|
36
|
+
std::unordered_map<Tag, ShadowView> movedViews;
|
|
37
|
+
|
|
38
|
+
parseRemoveMutations(movedViews, mutations, roots);
|
|
39
|
+
|
|
40
|
+
handleRemovals(filteredMutations, roots);
|
|
41
|
+
|
|
42
|
+
handleUpdatesAndEnterings(
|
|
43
|
+
filteredMutations, movedViews, mutations, propsParserContext, surfaceId);
|
|
44
|
+
|
|
45
|
+
addOngoingAnimations(surfaceId, filteredMutations);
|
|
46
|
+
|
|
47
|
+
return MountingTransaction{
|
|
48
|
+
surfaceId, transactionNumber, std::move(filteredMutations), telemetry};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
std::optional<SurfaceId> LayoutAnimationsProxy::progressLayoutAnimation(
|
|
52
|
+
int tag,
|
|
53
|
+
const jsi::Object &newStyle) {
|
|
54
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
55
|
+
LOG(INFO) << "progress layout animation for tag " << tag << std::endl;
|
|
56
|
+
#endif
|
|
57
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
58
|
+
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
59
|
+
|
|
60
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
61
|
+
return {};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
auto &layoutAnimation = layoutAnimationIt->second;
|
|
65
|
+
|
|
66
|
+
maybeRestoreOpacity(layoutAnimation, newStyle);
|
|
67
|
+
|
|
68
|
+
auto rawProps =
|
|
69
|
+
std::make_shared<RawProps>(uiRuntime_, jsi::Value(uiRuntime_, newStyle));
|
|
70
|
+
|
|
71
|
+
PropsParserContext propsParserContext{
|
|
72
|
+
layoutAnimation.finalView->surfaceId, *contextContainer_};
|
|
73
|
+
#ifdef ANDROID
|
|
74
|
+
rawProps = std::make_shared<RawProps>(folly::dynamic::merge(
|
|
75
|
+
layoutAnimation.finalView->props->rawProps, (folly::dynamic)*rawProps));
|
|
76
|
+
#endif
|
|
77
|
+
auto newProps =
|
|
78
|
+
getComponentDescriptorForShadowView(*layoutAnimation.finalView)
|
|
79
|
+
.cloneProps(
|
|
80
|
+
propsParserContext,
|
|
81
|
+
layoutAnimation.finalView->props,
|
|
82
|
+
std::move(*rawProps));
|
|
83
|
+
auto &updateMap =
|
|
84
|
+
surfaceManager.getUpdateMap(layoutAnimation.finalView->surfaceId);
|
|
85
|
+
updateMap.insert_or_assign(
|
|
86
|
+
tag, UpdateValues{newProps, Frame(uiRuntime_, newStyle)});
|
|
87
|
+
|
|
88
|
+
return layoutAnimation.finalView->surfaceId;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
std::optional<SurfaceId> LayoutAnimationsProxy::endLayoutAnimation(
|
|
92
|
+
int tag,
|
|
93
|
+
bool shouldRemove) {
|
|
94
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
95
|
+
LOG(INFO) << "end layout animation for " << tag << " - should remove "
|
|
96
|
+
<< shouldRemove << std::endl;
|
|
97
|
+
#endif
|
|
98
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
99
|
+
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
100
|
+
|
|
101
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
102
|
+
return {};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
auto &layoutAnimation = layoutAnimationIt->second;
|
|
106
|
+
|
|
107
|
+
// multiple layout animations can be triggered for a view
|
|
108
|
+
// one after the other, so we need to keep count of how many
|
|
109
|
+
// were actually triggered, so that we don't cleanup necessary
|
|
110
|
+
// structures too early
|
|
111
|
+
if (layoutAnimation.count > 1) {
|
|
112
|
+
layoutAnimation.count--;
|
|
113
|
+
return {};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
auto surfaceId = layoutAnimation.finalView->surfaceId;
|
|
117
|
+
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
118
|
+
layoutAnimations_.erase(tag);
|
|
119
|
+
updateMap.erase(tag);
|
|
120
|
+
|
|
121
|
+
if (!shouldRemove || !nodeForTag_.contains(tag)) {
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
auto node = nodeForTag_[tag];
|
|
126
|
+
auto mutationNode = std::static_pointer_cast<MutationNode>(node);
|
|
127
|
+
mutationNode->state = DEAD;
|
|
128
|
+
deadNodes.insert(mutationNode);
|
|
129
|
+
|
|
130
|
+
return surfaceId;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
Organizes removed views into a tree structure, allowing for convenient
|
|
135
|
+
traversals and index maintenance
|
|
136
|
+
*/
|
|
137
|
+
void LayoutAnimationsProxy::parseRemoveMutations(
|
|
138
|
+
std::unordered_map<Tag, ShadowView> &movedViews,
|
|
139
|
+
ShadowViewMutationList &mutations,
|
|
140
|
+
std::vector<std::shared_ptr<MutationNode>> &roots) const {
|
|
141
|
+
std::set<Tag> deletedViews;
|
|
142
|
+
std::unordered_map<Tag, std::vector<std::shared_ptr<MutationNode>>>
|
|
143
|
+
childrenForTag, unflattenedChildrenForTag;
|
|
144
|
+
|
|
145
|
+
std::vector<std::shared_ptr<MutationNode>> mutationNodes;
|
|
146
|
+
|
|
147
|
+
// iterate from the end, so that parents appear before children
|
|
148
|
+
for (auto it = mutations.rbegin(); it != mutations.rend(); it++) {
|
|
149
|
+
auto &mutation = *it;
|
|
150
|
+
if (mutation.type == ShadowViewMutation::Delete) {
|
|
151
|
+
deletedViews.insert(mutation.oldChildShadowView.tag);
|
|
152
|
+
}
|
|
153
|
+
if (mutation.type == ShadowViewMutation::Remove) {
|
|
154
|
+
updateIndexForMutation(mutation);
|
|
155
|
+
auto tag = mutation.oldChildShadowView.tag;
|
|
156
|
+
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
157
|
+
auto parentTag = mutation.parentTag;
|
|
158
|
+
#else
|
|
159
|
+
auto parentTag = mutation.parentShadowView.tag;
|
|
160
|
+
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
161
|
+
auto unflattenedParentTag = parentTag; // temporary
|
|
162
|
+
|
|
163
|
+
std::shared_ptr<MutationNode> mutationNode;
|
|
164
|
+
std::shared_ptr<Node> node = nodeForTag_[tag],
|
|
165
|
+
parent = nodeForTag_[parentTag],
|
|
166
|
+
unflattenedParent =
|
|
167
|
+
nodeForTag_[unflattenedParentTag];
|
|
168
|
+
|
|
169
|
+
if (!node) {
|
|
170
|
+
mutationNode = std::make_shared<MutationNode>(mutation);
|
|
171
|
+
} else {
|
|
172
|
+
mutationNode =
|
|
173
|
+
std::make_shared<MutationNode>(mutation, std::move(*node));
|
|
174
|
+
for (auto &subNode : mutationNode->children) {
|
|
175
|
+
subNode->parent = mutationNode;
|
|
176
|
+
}
|
|
177
|
+
for (auto &subNode : mutationNode->unflattenedChildren) {
|
|
178
|
+
subNode->unflattenedParent = mutationNode;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
if (!deletedViews.contains(mutation.oldChildShadowView.tag)) {
|
|
182
|
+
mutationNode->state = MOVED;
|
|
183
|
+
movedViews.insert_or_assign(
|
|
184
|
+
mutation.oldChildShadowView.tag, mutation.oldChildShadowView);
|
|
185
|
+
}
|
|
186
|
+
nodeForTag_[tag] = mutationNode;
|
|
187
|
+
|
|
188
|
+
if (!parent) {
|
|
189
|
+
parent = std::make_shared<Node>(parentTag);
|
|
190
|
+
nodeForTag_[parentTag] = parent;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
if (!unflattenedParent) {
|
|
194
|
+
if (parentTag == unflattenedParentTag) {
|
|
195
|
+
unflattenedParent = parent;
|
|
196
|
+
} else {
|
|
197
|
+
unflattenedParent = std::make_shared<Node>(unflattenedParentTag);
|
|
198
|
+
nodeForTag_[unflattenedParentTag] = unflattenedParent;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
mutationNodes.push_back(mutationNode);
|
|
203
|
+
|
|
204
|
+
childrenForTag[parentTag].push_back(mutationNode);
|
|
205
|
+
unflattenedChildrenForTag[unflattenedParentTag].push_back(mutationNode);
|
|
206
|
+
mutationNode->parent = parent;
|
|
207
|
+
mutationNode->unflattenedParent = unflattenedParent;
|
|
208
|
+
}
|
|
209
|
+
if (mutation.type == ShadowViewMutation::Update &&
|
|
210
|
+
movedViews.contains(mutation.newChildShadowView.tag)) {
|
|
211
|
+
auto node = nodeForTag_[mutation.newChildShadowView.tag];
|
|
212
|
+
auto mutationNode = std::static_pointer_cast<MutationNode>(node);
|
|
213
|
+
mutationNode->mutation.oldChildShadowView = mutation.oldChildShadowView;
|
|
214
|
+
movedViews[mutation.newChildShadowView.tag] = mutation.oldChildShadowView;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
for (auto &[parentTag, children] : childrenForTag) {
|
|
219
|
+
auto &parent = nodeForTag_[parentTag];
|
|
220
|
+
parent->insertChildren(children);
|
|
221
|
+
for (auto &child : children) {
|
|
222
|
+
child->parent = parent;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
for (auto &[unflattenedParentTag, children] : unflattenedChildrenForTag) {
|
|
226
|
+
auto &unflattenedParent = nodeForTag_[unflattenedParentTag];
|
|
227
|
+
unflattenedParent->insertUnflattenedChildren(children);
|
|
228
|
+
for (auto &child : children) {
|
|
229
|
+
child->unflattenedParent = unflattenedParent;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
for (auto &mutationNode : mutationNodes) {
|
|
234
|
+
if (!mutationNode->unflattenedParent->isMutationMode()) {
|
|
235
|
+
roots.push_back(mutationNode);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
void LayoutAnimationsProxy::handleRemovals(
|
|
241
|
+
ShadowViewMutationList &filteredMutations,
|
|
242
|
+
std::vector<std::shared_ptr<MutationNode>> &roots) const {
|
|
243
|
+
// iterate from the end, so that children
|
|
244
|
+
// with higher indices appear first in the mutations list
|
|
245
|
+
for (auto it = roots.rbegin(); it != roots.rend(); it++) {
|
|
246
|
+
auto &node = *it;
|
|
247
|
+
if (!startAnimationsRecursively(
|
|
248
|
+
node, true, true, false, filteredMutations)) {
|
|
249
|
+
filteredMutations.push_back(node->mutation);
|
|
250
|
+
node->unflattenedParent->removeChildFromUnflattenedTree(node); //???
|
|
251
|
+
if (node->state != MOVED) {
|
|
252
|
+
maybeCancelAnimation(node->tag);
|
|
253
|
+
filteredMutations.push_back(ShadowViewMutation::DeleteMutation(
|
|
254
|
+
node->mutation.oldChildShadowView));
|
|
255
|
+
nodeForTag_.erase(node->tag);
|
|
256
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
257
|
+
LOG(INFO) << "delete " << node->tag << std::endl;
|
|
258
|
+
#endif
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
for (auto node : deadNodes) {
|
|
264
|
+
if (node->state != DELETED) {
|
|
265
|
+
endAnimationsRecursively(node, filteredMutations);
|
|
266
|
+
maybeDropAncestors(node->unflattenedParent, node, filteredMutations);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
deadNodes.clear();
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
void LayoutAnimationsProxy::handleUpdatesAndEnterings(
|
|
273
|
+
ShadowViewMutationList &filteredMutations,
|
|
274
|
+
const std::unordered_map<Tag, ShadowView> &movedViews,
|
|
275
|
+
ShadowViewMutationList &mutations,
|
|
276
|
+
const PropsParserContext &propsParserContext,
|
|
277
|
+
SurfaceId surfaceId) const {
|
|
278
|
+
std::unordered_map<Tag, ShadowView> oldShadowViewsForReparentings;
|
|
279
|
+
for (auto &mutation : mutations) {
|
|
280
|
+
maybeUpdateWindowDimensions(mutation, surfaceId);
|
|
281
|
+
|
|
282
|
+
Tag tag = mutation.type == ShadowViewMutation::Type::Create ||
|
|
283
|
+
mutation.type == ShadowViewMutation::Type::Insert
|
|
284
|
+
? mutation.newChildShadowView.tag
|
|
285
|
+
: mutation.oldChildShadowView.tag;
|
|
286
|
+
|
|
287
|
+
switch (mutation.type) {
|
|
288
|
+
case ShadowViewMutation::Type::Create: {
|
|
289
|
+
filteredMutations.push_back(mutation);
|
|
290
|
+
break;
|
|
291
|
+
}
|
|
292
|
+
case ShadowViewMutation::Type::Insert: {
|
|
293
|
+
updateIndexForMutation(mutation);
|
|
294
|
+
|
|
295
|
+
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
296
|
+
const auto parentTag = mutation.parentTag;
|
|
297
|
+
const auto mutationParent = parentTag;
|
|
298
|
+
#else
|
|
299
|
+
const auto parentTag = mutation.parentShadowView.tag;
|
|
300
|
+
const auto mutationParent = mutation.parentShadowView;
|
|
301
|
+
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
302
|
+
if (nodeForTag_.contains(parentTag)) {
|
|
303
|
+
nodeForTag_[parentTag]->applyMutationToIndices(mutation);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
if (movedViews.contains(tag)) {
|
|
307
|
+
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
308
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
309
|
+
if (oldShadowViewsForReparentings.contains(tag)) {
|
|
310
|
+
filteredMutations.push_back(ShadowViewMutation::InsertMutation(
|
|
311
|
+
mutationParent,
|
|
312
|
+
oldShadowViewsForReparentings[tag],
|
|
313
|
+
mutation.index));
|
|
314
|
+
} else {
|
|
315
|
+
filteredMutations.push_back(mutation);
|
|
316
|
+
}
|
|
317
|
+
continue;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
auto oldView = *layoutAnimationIt->second.currentView;
|
|
321
|
+
filteredMutations.push_back(ShadowViewMutation::InsertMutation(
|
|
322
|
+
mutationParent, oldView, mutation.index));
|
|
323
|
+
continue;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
transferConfigFromNativeID(
|
|
327
|
+
mutation.newChildShadowView.props->nativeId,
|
|
328
|
+
mutation.newChildShadowView.tag);
|
|
329
|
+
if (!layoutAnimationsManager_->hasLayoutAnimation(tag, ENTERING)) {
|
|
330
|
+
filteredMutations.push_back(mutation);
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
startEnteringAnimation(tag, mutation);
|
|
335
|
+
filteredMutations.push_back(mutation);
|
|
336
|
+
|
|
337
|
+
// temporarily set opacity to 0 to prevent flickering on android
|
|
338
|
+
std::shared_ptr<ShadowView> newView =
|
|
339
|
+
cloneViewWithoutOpacity(mutation, propsParserContext);
|
|
340
|
+
|
|
341
|
+
filteredMutations.push_back(ShadowViewMutation::UpdateMutation(
|
|
342
|
+
mutation.newChildShadowView, *newView, mutationParent));
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
case ShadowViewMutation::Type::Update: {
|
|
347
|
+
auto shouldAnimate = hasLayoutChanged(mutation);
|
|
348
|
+
if (!layoutAnimationsManager_->hasLayoutAnimation(tag, LAYOUT) ||
|
|
349
|
+
(!shouldAnimate && !layoutAnimations_.contains(tag))) {
|
|
350
|
+
// We should cancel any ongoing animation here to ensure that the
|
|
351
|
+
// proper final state is reached for this view However, due to how
|
|
352
|
+
// RNSScreens handle adding headers (a second commit is triggered to
|
|
353
|
+
// offset all the elements by the header height) this would lead to
|
|
354
|
+
// all entering animations being cancelled when a screen with a header
|
|
355
|
+
// is pushed onto a stack
|
|
356
|
+
// TODO: find a better solution for this problem
|
|
357
|
+
filteredMutations.push_back(mutation);
|
|
358
|
+
continue;
|
|
359
|
+
} else if (!shouldAnimate) {
|
|
360
|
+
updateOngoingAnimationTarget(tag, mutation);
|
|
361
|
+
continue;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
// store the oldChildShadowView, so that we can use this ShadowView when
|
|
365
|
+
// the view is inserted
|
|
366
|
+
oldShadowViewsForReparentings[tag] = mutation.oldChildShadowView;
|
|
367
|
+
startLayoutAnimation(tag, mutation);
|
|
368
|
+
break;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
case ShadowViewMutation::Type::Remove:
|
|
372
|
+
case ShadowViewMutation::Type::Delete: {
|
|
373
|
+
break;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
default:
|
|
377
|
+
filteredMutations.push_back(mutation);
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
void LayoutAnimationsProxy::addOngoingAnimations(
|
|
383
|
+
SurfaceId surfaceId,
|
|
384
|
+
ShadowViewMutationList &mutations) const {
|
|
385
|
+
auto &updateMap = surfaceManager.getUpdateMap(surfaceId);
|
|
386
|
+
for (auto &[tag, updateValues] : updateMap) {
|
|
387
|
+
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
388
|
+
|
|
389
|
+
if (layoutAnimationIt == layoutAnimations_.end()) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
auto &layoutAnimation = layoutAnimationIt->second;
|
|
394
|
+
|
|
395
|
+
auto newView = std::make_shared<ShadowView>(*layoutAnimation.finalView);
|
|
396
|
+
newView->props = updateValues.newProps;
|
|
397
|
+
updateLayoutMetrics(newView->layoutMetrics, updateValues.frame);
|
|
398
|
+
|
|
399
|
+
mutations.push_back(ShadowViewMutation::UpdateMutation(
|
|
400
|
+
*layoutAnimation.currentView,
|
|
401
|
+
*newView,
|
|
402
|
+
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
403
|
+
layoutAnimation.parentTag
|
|
404
|
+
#else
|
|
405
|
+
*layoutAnimation.parentView
|
|
406
|
+
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
407
|
+
));
|
|
408
|
+
layoutAnimation.currentView = newView;
|
|
409
|
+
}
|
|
410
|
+
updateMap.clear();
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
void LayoutAnimationsProxy::endAnimationsRecursively(
|
|
414
|
+
std::shared_ptr<MutationNode> node,
|
|
415
|
+
ShadowViewMutationList &mutations) const {
|
|
416
|
+
maybeCancelAnimation(node->tag);
|
|
417
|
+
node->state = DELETED;
|
|
418
|
+
// iterate from the end, so that children
|
|
419
|
+
// with higher indices appear first in the mutations list
|
|
420
|
+
for (auto it = node->unflattenedChildren.rbegin();
|
|
421
|
+
it != node->unflattenedChildren.rend();
|
|
422
|
+
it++) {
|
|
423
|
+
auto &subNode = *it;
|
|
424
|
+
if (subNode->state != DELETED) {
|
|
425
|
+
endAnimationsRecursively(subNode, mutations);
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
mutations.push_back(node->mutation);
|
|
429
|
+
nodeForTag_.erase(node->tag);
|
|
430
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
431
|
+
LOG(INFO) << "delete " << node->tag << std::endl;
|
|
432
|
+
#endif
|
|
433
|
+
mutations.push_back(
|
|
434
|
+
ShadowViewMutation::DeleteMutation(node->mutation.oldChildShadowView));
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
void LayoutAnimationsProxy::maybeDropAncestors(
|
|
438
|
+
std::shared_ptr<Node> parent,
|
|
439
|
+
std::shared_ptr<MutationNode> child,
|
|
440
|
+
ShadowViewMutationList &cleanupMutations) const {
|
|
441
|
+
parent->removeChildFromUnflattenedTree(child);
|
|
442
|
+
if (!parent->isMutationMode()) {
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
auto node = std::static_pointer_cast<MutationNode>(parent);
|
|
447
|
+
|
|
448
|
+
if (node->children.size() == 0 && node->state != ANIMATING) {
|
|
449
|
+
nodeForTag_.erase(node->tag);
|
|
450
|
+
cleanupMutations.push_back(node->mutation);
|
|
451
|
+
maybeCancelAnimation(node->tag);
|
|
452
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
453
|
+
LOG(INFO) << "delete " << node->tag << std::endl;
|
|
454
|
+
#endif
|
|
455
|
+
cleanupMutations.push_back(
|
|
456
|
+
ShadowViewMutation::DeleteMutation(node->mutation.oldChildShadowView));
|
|
457
|
+
maybeDropAncestors(node->unflattenedParent, node, cleanupMutations);
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
const ComponentDescriptor &
|
|
462
|
+
LayoutAnimationsProxy::getComponentDescriptorForShadowView(
|
|
463
|
+
const ShadowView &shadowView) const {
|
|
464
|
+
return componentDescriptorRegistry_->at(shadowView.componentHandle);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
bool LayoutAnimationsProxy::startAnimationsRecursively(
|
|
468
|
+
std::shared_ptr<MutationNode> node,
|
|
469
|
+
bool shouldRemoveSubviewsWithoutAnimations,
|
|
470
|
+
bool shouldAnimate,
|
|
471
|
+
bool isScreenPop,
|
|
472
|
+
ShadowViewMutationList &mutations) const {
|
|
473
|
+
if (isRNSScreen(node)) {
|
|
474
|
+
isScreenPop = true;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
shouldAnimate = !isScreenPop &&
|
|
478
|
+
layoutAnimationsManager_->shouldAnimateExiting(node->tag, shouldAnimate);
|
|
479
|
+
|
|
480
|
+
bool hasExitAnimation = shouldAnimate &&
|
|
481
|
+
layoutAnimationsManager_->hasLayoutAnimation(
|
|
482
|
+
node->tag, LayoutAnimationType::EXITING);
|
|
483
|
+
bool hasAnimatedChildren = false;
|
|
484
|
+
|
|
485
|
+
shouldRemoveSubviewsWithoutAnimations =
|
|
486
|
+
shouldRemoveSubviewsWithoutAnimations && !hasExitAnimation;
|
|
487
|
+
std::vector<std::shared_ptr<MutationNode>> toBeRemoved;
|
|
488
|
+
|
|
489
|
+
// iterate from the end, so that children
|
|
490
|
+
// with higher indices appear first in the mutations list
|
|
491
|
+
for (auto it = node->unflattenedChildren.rbegin();
|
|
492
|
+
it != node->unflattenedChildren.rend();
|
|
493
|
+
it++) {
|
|
494
|
+
auto &subNode = *it;
|
|
495
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
496
|
+
LOG(INFO) << "child " << subNode->tag << " "
|
|
497
|
+
<< " " << shouldAnimate << " "
|
|
498
|
+
<< shouldRemoveSubviewsWithoutAnimations << std::endl;
|
|
499
|
+
#endif
|
|
500
|
+
if (subNode->state != UNDEFINED && subNode->state != MOVED) {
|
|
501
|
+
if (shouldAnimate && subNode->state != DEAD) {
|
|
502
|
+
hasAnimatedChildren = true;
|
|
503
|
+
} else {
|
|
504
|
+
endAnimationsRecursively(subNode, mutations);
|
|
505
|
+
toBeRemoved.push_back(subNode);
|
|
506
|
+
}
|
|
507
|
+
} else if (startAnimationsRecursively(
|
|
508
|
+
subNode,
|
|
509
|
+
shouldRemoveSubviewsWithoutAnimations,
|
|
510
|
+
shouldAnimate,
|
|
511
|
+
isScreenPop,
|
|
512
|
+
mutations)) {
|
|
513
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
514
|
+
LOG(INFO) << "child " << subNode->tag
|
|
515
|
+
<< " start animations returned true " << std::endl;
|
|
516
|
+
#endif
|
|
517
|
+
hasAnimatedChildren = true;
|
|
518
|
+
} else if (subNode->state == MOVED) {
|
|
519
|
+
mutations.push_back(subNode->mutation);
|
|
520
|
+
toBeRemoved.push_back(subNode);
|
|
521
|
+
} else if (shouldRemoveSubviewsWithoutAnimations) {
|
|
522
|
+
maybeCancelAnimation(subNode->tag);
|
|
523
|
+
mutations.push_back(subNode->mutation);
|
|
524
|
+
toBeRemoved.push_back(subNode);
|
|
525
|
+
subNode->state = DELETED;
|
|
526
|
+
nodeForTag_.erase(subNode->tag);
|
|
527
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
528
|
+
LOG(INFO) << "delete " << subNode->tag << std::endl;
|
|
529
|
+
#endif
|
|
530
|
+
mutations.push_back(ShadowViewMutation::DeleteMutation(
|
|
531
|
+
subNode->mutation.oldChildShadowView));
|
|
532
|
+
} else {
|
|
533
|
+
subNode->state = WAITING;
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
for (auto &subNode : toBeRemoved) {
|
|
538
|
+
node->removeChildFromUnflattenedTree(subNode);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
if (node->state == MOVED) {
|
|
542
|
+
auto replacement = std::make_shared<Node>(*node);
|
|
543
|
+
for (auto subNode : node->children) {
|
|
544
|
+
subNode->parent = replacement;
|
|
545
|
+
}
|
|
546
|
+
for (auto subNode : node->unflattenedChildren) {
|
|
547
|
+
subNode->unflattenedParent = replacement;
|
|
548
|
+
}
|
|
549
|
+
nodeForTag_[replacement->tag] = replacement;
|
|
550
|
+
return false;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
bool wantAnimateExit = hasExitAnimation || hasAnimatedChildren;
|
|
554
|
+
|
|
555
|
+
if (hasExitAnimation) {
|
|
556
|
+
node->state = ANIMATING;
|
|
557
|
+
startExitingAnimation(node->tag, node->mutation);
|
|
558
|
+
} else {
|
|
559
|
+
layoutAnimationsManager_->clearLayoutAnimationConfig(node->tag);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
return wantAnimateExit;
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
void LayoutAnimationsProxy::updateIndexForMutation(
|
|
566
|
+
ShadowViewMutation &mutation) const {
|
|
567
|
+
if (mutation.index == -1) {
|
|
568
|
+
return;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
572
|
+
const auto parentTag = mutation.parentTag;
|
|
573
|
+
#else
|
|
574
|
+
const auto parentTag = mutation.parentShadowView.tag;
|
|
575
|
+
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
576
|
+
|
|
577
|
+
if (!nodeForTag_.contains(parentTag)) {
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
auto parent = nodeForTag_[parentTag];
|
|
582
|
+
int size = 0, prevIndex = -1, offset = 0;
|
|
583
|
+
|
|
584
|
+
for (auto &subNode : parent->children) {
|
|
585
|
+
size += subNode->mutation.index - prevIndex - 1;
|
|
586
|
+
if (mutation.index < size) {
|
|
587
|
+
break;
|
|
588
|
+
}
|
|
589
|
+
offset++;
|
|
590
|
+
prevIndex = subNode->mutation.index;
|
|
591
|
+
}
|
|
592
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
593
|
+
int tag = mutation.type == ShadowViewMutation::Insert
|
|
594
|
+
? mutation.newChildShadowView.tag
|
|
595
|
+
: mutation.oldChildShadowView.tag;
|
|
596
|
+
LOG(INFO) << "update index for " << tag << " in " << parentTag << ": "
|
|
597
|
+
<< mutation.index << " -> " << mutation.index + offset << std::endl;
|
|
598
|
+
#endif
|
|
599
|
+
mutation.index += offset;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
bool LayoutAnimationsProxy::shouldOverridePullTransaction() const {
|
|
603
|
+
return true;
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
void LayoutAnimationsProxy::createLayoutAnimation(
|
|
607
|
+
const ShadowViewMutation &mutation,
|
|
608
|
+
ShadowView &oldView,
|
|
609
|
+
const SurfaceId &surfaceId,
|
|
610
|
+
const int tag) const {
|
|
611
|
+
int count = 1;
|
|
612
|
+
auto layoutAnimationIt = layoutAnimations_.find(tag);
|
|
613
|
+
|
|
614
|
+
if (layoutAnimationIt != layoutAnimations_.end()) {
|
|
615
|
+
auto &layoutAnimation = layoutAnimationIt->second;
|
|
616
|
+
oldView = *layoutAnimation.currentView;
|
|
617
|
+
count = layoutAnimation.count + 1;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
auto finalView = std::make_shared<ShadowView>(
|
|
621
|
+
mutation.type == ShadowViewMutation::Remove
|
|
622
|
+
? mutation.oldChildShadowView
|
|
623
|
+
: mutation.newChildShadowView);
|
|
624
|
+
auto currentView = std::make_shared<ShadowView>(oldView);
|
|
625
|
+
|
|
626
|
+
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
627
|
+
layoutAnimations_.insert_or_assign(
|
|
628
|
+
tag,
|
|
629
|
+
LayoutAnimation{finalView, currentView, mutation.parentTag, {}, count});
|
|
630
|
+
#else
|
|
631
|
+
auto parentView = std::make_shared<ShadowView>(mutation.parentShadowView);
|
|
632
|
+
layoutAnimations_.insert_or_assign(
|
|
633
|
+
tag, LayoutAnimation{finalView, currentView, parentView, {}, count});
|
|
634
|
+
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
void LayoutAnimationsProxy::startEnteringAnimation(
|
|
638
|
+
const int tag,
|
|
639
|
+
ShadowViewMutation &mutation) const {
|
|
640
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
641
|
+
LOG(INFO) << "start entering animation for tag " << tag << std::endl;
|
|
642
|
+
#endif
|
|
643
|
+
auto finalView = std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
644
|
+
auto current = std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
645
|
+
#if REACT_NATIVE_MINOR_VERSION < 78
|
|
646
|
+
auto parent = std::make_shared<ShadowView>(mutation.parentShadowView);
|
|
647
|
+
#endif
|
|
648
|
+
|
|
649
|
+
auto &viewProps =
|
|
650
|
+
static_cast<const ViewProps &>(*mutation.newChildShadowView.props);
|
|
651
|
+
auto opacity = viewProps.opacity;
|
|
652
|
+
|
|
653
|
+
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(),
|
|
654
|
+
finalView,
|
|
655
|
+
current,
|
|
656
|
+
#if REACT_NATIVE_MINOR_VERSION < 78
|
|
657
|
+
parent,
|
|
658
|
+
#endif // RE
|
|
659
|
+
mutation,
|
|
660
|
+
opacity,
|
|
661
|
+
tag]() {
|
|
662
|
+
auto strongThis = weakThis.lock();
|
|
663
|
+
if (!strongThis) {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
Rect window{};
|
|
668
|
+
{
|
|
669
|
+
auto &mutex = strongThis->mutex;
|
|
670
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
671
|
+
strongThis->layoutAnimations_.insert_or_assign(
|
|
672
|
+
tag, LayoutAnimation {
|
|
673
|
+
finalView, current,
|
|
674
|
+
#if REACT_NATIVE_MINOR_VERSION >= 78
|
|
675
|
+
mutation.parentTag,
|
|
676
|
+
#else
|
|
677
|
+
parent,
|
|
678
|
+
#endif // REACT_NATIVE_MINOR_VERSION >= 78
|
|
679
|
+
opacity
|
|
680
|
+
});
|
|
681
|
+
window = strongThis->surfaceManager.getWindow(
|
|
682
|
+
mutation.newChildShadowView.surfaceId);
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
Snapshot values(mutation.newChildShadowView, window);
|
|
686
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
687
|
+
jsi::Object yogaValues(uiRuntime);
|
|
688
|
+
yogaValues.setProperty(uiRuntime, "targetOriginX", values.x);
|
|
689
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", values.x);
|
|
690
|
+
yogaValues.setProperty(uiRuntime, "targetOriginY", values.y);
|
|
691
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", values.y);
|
|
692
|
+
yogaValues.setProperty(uiRuntime, "targetWidth", values.width);
|
|
693
|
+
yogaValues.setProperty(uiRuntime, "targetHeight", values.height);
|
|
694
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
695
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
696
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
697
|
+
uiRuntime, tag, LayoutAnimationType::ENTERING, yogaValues);
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
void LayoutAnimationsProxy::startExitingAnimation(
|
|
702
|
+
const int tag,
|
|
703
|
+
ShadowViewMutation &mutation) const {
|
|
704
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
705
|
+
LOG(INFO) << "start exiting animation for tag " << tag << std::endl;
|
|
706
|
+
#endif
|
|
707
|
+
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
708
|
+
|
|
709
|
+
uiScheduler_->scheduleOnUI(
|
|
710
|
+
[weakThis = weak_from_this(), tag, mutation, surfaceId]() {
|
|
711
|
+
auto strongThis = weakThis.lock();
|
|
712
|
+
if (!strongThis) {
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
auto oldView = mutation.oldChildShadowView;
|
|
717
|
+
Rect window{};
|
|
718
|
+
{
|
|
719
|
+
auto &mutex = strongThis->mutex;
|
|
720
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
721
|
+
strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
722
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
Snapshot values(oldView, window);
|
|
726
|
+
|
|
727
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
728
|
+
jsi::Object yogaValues(uiRuntime);
|
|
729
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", values.x);
|
|
730
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", values.x);
|
|
731
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", values.y);
|
|
732
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", values.y);
|
|
733
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", values.width);
|
|
734
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", values.height);
|
|
735
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", values.windowWidth);
|
|
736
|
+
yogaValues.setProperty(uiRuntime, "windowHeight", values.windowHeight);
|
|
737
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
738
|
+
uiRuntime, tag, LayoutAnimationType::EXITING, yogaValues);
|
|
739
|
+
strongThis->layoutAnimationsManager_->clearLayoutAnimationConfig(tag);
|
|
740
|
+
});
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
void LayoutAnimationsProxy::startLayoutAnimation(
|
|
744
|
+
const int tag,
|
|
745
|
+
const ShadowViewMutation &mutation) const {
|
|
746
|
+
#ifdef LAYOUT_ANIMATIONS_LOGS
|
|
747
|
+
LOG(INFO) << "start layout animation for tag " << tag << std::endl;
|
|
748
|
+
#endif
|
|
749
|
+
auto surfaceId = mutation.oldChildShadowView.surfaceId;
|
|
750
|
+
|
|
751
|
+
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(),
|
|
752
|
+
mutation,
|
|
753
|
+
surfaceId,
|
|
754
|
+
tag]() {
|
|
755
|
+
auto strongThis = weakThis.lock();
|
|
756
|
+
if (!strongThis) {
|
|
757
|
+
return;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
auto oldView = mutation.oldChildShadowView;
|
|
761
|
+
Rect window{};
|
|
762
|
+
{
|
|
763
|
+
auto &mutex = strongThis->mutex;
|
|
764
|
+
auto lock = std::unique_lock<std::recursive_mutex>(mutex);
|
|
765
|
+
strongThis->createLayoutAnimation(mutation, oldView, surfaceId, tag);
|
|
766
|
+
window = strongThis->surfaceManager.getWindow(surfaceId);
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
Snapshot currentValues(oldView, window);
|
|
770
|
+
Snapshot targetValues(mutation.newChildShadowView, window);
|
|
771
|
+
|
|
772
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
773
|
+
jsi::Object yogaValues(uiRuntime);
|
|
774
|
+
yogaValues.setProperty(uiRuntime, "currentOriginX", currentValues.x);
|
|
775
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginX", currentValues.x);
|
|
776
|
+
yogaValues.setProperty(uiRuntime, "currentOriginY", currentValues.y);
|
|
777
|
+
yogaValues.setProperty(uiRuntime, "currentGlobalOriginY", currentValues.y);
|
|
778
|
+
yogaValues.setProperty(uiRuntime, "currentWidth", currentValues.width);
|
|
779
|
+
yogaValues.setProperty(uiRuntime, "currentHeight", currentValues.height);
|
|
780
|
+
yogaValues.setProperty(uiRuntime, "targetOriginX", targetValues.x);
|
|
781
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginX", targetValues.x);
|
|
782
|
+
yogaValues.setProperty(uiRuntime, "targetOriginY", targetValues.y);
|
|
783
|
+
yogaValues.setProperty(uiRuntime, "targetGlobalOriginY", targetValues.y);
|
|
784
|
+
yogaValues.setProperty(uiRuntime, "targetWidth", targetValues.width);
|
|
785
|
+
yogaValues.setProperty(uiRuntime, "targetHeight", targetValues.height);
|
|
786
|
+
yogaValues.setProperty(uiRuntime, "windowWidth", targetValues.windowWidth);
|
|
787
|
+
yogaValues.setProperty(
|
|
788
|
+
uiRuntime, "windowHeight", targetValues.windowHeight);
|
|
789
|
+
strongThis->layoutAnimationsManager_->startLayoutAnimation(
|
|
790
|
+
uiRuntime, tag, LayoutAnimationType::LAYOUT, yogaValues);
|
|
791
|
+
});
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
void LayoutAnimationsProxy::updateOngoingAnimationTarget(
|
|
795
|
+
const int tag,
|
|
796
|
+
const ShadowViewMutation &mutation) const {
|
|
797
|
+
layoutAnimations_[tag].finalView =
|
|
798
|
+
std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
799
|
+
}
|
|
800
|
+
|
|
801
|
+
void LayoutAnimationsProxy::maybeCancelAnimation(const int tag) const {
|
|
802
|
+
if (!layoutAnimations_.contains(tag)) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
805
|
+
layoutAnimations_.erase(tag);
|
|
806
|
+
uiScheduler_->scheduleOnUI([weakThis = weak_from_this(), tag]() {
|
|
807
|
+
auto strongThis = weakThis.lock();
|
|
808
|
+
if (!strongThis) {
|
|
809
|
+
return;
|
|
810
|
+
}
|
|
811
|
+
|
|
812
|
+
auto &uiRuntime = strongThis->uiRuntime_;
|
|
813
|
+
strongThis->layoutAnimationsManager_->cancelLayoutAnimation(uiRuntime, tag);
|
|
814
|
+
});
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
void LayoutAnimationsProxy::transferConfigFromNativeID(
|
|
818
|
+
const std::string nativeIdString,
|
|
819
|
+
const int tag) const {
|
|
820
|
+
if (nativeIdString.empty()) {
|
|
821
|
+
return;
|
|
822
|
+
}
|
|
823
|
+
try {
|
|
824
|
+
auto nativeId = stoi(nativeIdString);
|
|
825
|
+
layoutAnimationsManager_->transferConfigFromNativeID(nativeId, tag);
|
|
826
|
+
} catch (std::invalid_argument) {
|
|
827
|
+
} catch (std::out_of_range) {
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
// When entering animations start, we temporarily set opacity to 0
|
|
832
|
+
// so that we can immediately insert the view at the right position
|
|
833
|
+
// and schedule the animation on the UI thread
|
|
834
|
+
std::shared_ptr<ShadowView> LayoutAnimationsProxy::cloneViewWithoutOpacity(
|
|
835
|
+
facebook::react::ShadowViewMutation &mutation,
|
|
836
|
+
const PropsParserContext &propsParserContext) const {
|
|
837
|
+
auto newView = std::make_shared<ShadowView>(mutation.newChildShadowView);
|
|
838
|
+
folly::dynamic opacity = folly::dynamic::object("opacity", 0);
|
|
839
|
+
auto newProps = getComponentDescriptorForShadowView(*newView).cloneProps(
|
|
840
|
+
propsParserContext, newView->props, RawProps(opacity));
|
|
841
|
+
newView->props = newProps;
|
|
842
|
+
return newView;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
void LayoutAnimationsProxy::maybeRestoreOpacity(
|
|
846
|
+
LayoutAnimation &layoutAnimation,
|
|
847
|
+
const jsi::Object &newStyle) const {
|
|
848
|
+
if (layoutAnimation.opacity && !newStyle.hasProperty(uiRuntime_, "opacity")) {
|
|
849
|
+
newStyle.setProperty(
|
|
850
|
+
uiRuntime_, "opacity", jsi::Value(*layoutAnimation.opacity));
|
|
851
|
+
layoutAnimation.opacity.reset();
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
|
|
855
|
+
void LayoutAnimationsProxy::maybeUpdateWindowDimensions(
|
|
856
|
+
facebook::react::ShadowViewMutation &mutation,
|
|
857
|
+
SurfaceId surfaceId) const {
|
|
858
|
+
if (mutation.type == ShadowViewMutation::Update &&
|
|
859
|
+
!std::strcmp(
|
|
860
|
+
mutation.oldChildShadowView.componentName, RootComponentName)) {
|
|
861
|
+
surfaceManager.updateWindow(
|
|
862
|
+
surfaceId,
|
|
863
|
+
mutation.newChildShadowView.layoutMetrics.frame.size.width,
|
|
864
|
+
mutation.newChildShadowView.layoutMetrics.frame.size.height);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
} // namespace reanimated
|
|
869
|
+
|
|
870
|
+
#endif // RCT_NEW_ARCH_ENABLED
|