Skip to content

Commit e24e0b6

Browse files
zeyapfacebook-github-bot
authored andcommitted
keep old snapshot node position updated at applyViewTransitionName
Summary: ## Changelog: [Internal] [Changed] - keep old snapshot node position updated at applyViewTransitionName `createViewTransitionInstance` is only called once in a shadowNode's lifecycle but `applyViewTransitionName` will be called multiple times at each transition for the same shadowNode. Reviewed By: christophpurrer Differential Revision: D102226352
1 parent 6411611 commit e24e0b6

2 files changed

Lines changed: 39 additions & 6 deletions

File tree

packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.cpp

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,12 +97,40 @@ void ViewTransitionModule::applyViewTransitionName(
9797
// Find the pseudo element created from this specific source tag
9898
auto& pseudoElementsBySourceTag = it->second;
9999
auto innerIt = pseudoElementsBySourceTag.find(tag);
100+
100101
if (innerIt != pseudoElementsBySourceTag.end()) {
102+
// Only clone the pseudo-element if the layout metrics changed
103+
// since it was last created/refreshed (e.g. due to scrolling or
104+
// React updates).
105+
auto& cachedMetrics = innerIt->second.lastAppliedLayoutMetrics;
106+
if (cachedMetrics.originFromRoot.x !=
107+
keyframeMetrics.originFromRoot.x ||
108+
cachedMetrics.originFromRoot.y !=
109+
keyframeMetrics.originFromRoot.y ||
110+
cachedMetrics.size.width != keyframeMetrics.size.width ||
111+
cachedMetrics.size.height != keyframeMetrics.size.height) {
112+
auto updatedRawProps = RawProps(
113+
folly::dynamic::object("left", keyframeMetrics.originFromRoot.x)(
114+
"top", keyframeMetrics.originFromRoot.y)(
115+
"width", keyframeMetrics.size.width)(
116+
"height", keyframeMetrics.size.height)(
117+
"pointerEvents", "none")("opacity", 0)("collapsable", false)(
118+
"position", "absolute"));
119+
120+
auto updatedNode = uiManager_->cloneNode(
121+
*innerIt->second.node,
122+
nullptr /* children */,
123+
std::move(updatedRawProps));
124+
if (updatedNode != nullptr) {
125+
innerIt->second.node = updatedNode;
126+
cachedMetrics = keyframeMetrics;
127+
}
128+
}
101129
oldPseudoElementNodes_[name] = innerIt->second.node;
102-
} else if (!pseudoElementsBySourceTag.empty()) {
103-
// Fallback to first available entry for this name
104-
oldPseudoElementNodes_[name] =
105-
pseudoElementsBySourceTag.begin()->second.node;
130+
} else {
131+
LOG(WARNING)
132+
<< "applyViewTransitionName: old pseudo element shadow node doesn't exist for source tag "
133+
<< tag << " with name " << name;
106134
}
107135
} else {
108136
LOG(WARNING)
@@ -173,7 +201,9 @@ void ViewTransitionModule::createViewTransitionInstance(
173201
oldPseudoElementNodes_[name] = pseudoElementNode;
174202
}
175203
oldPseudoElementNodesRepository_[name][view.tag] = InactivePseudoElement{
176-
.node = pseudoElementNode, .sourceTag = view.tag};
204+
.node = pseudoElementNode,
205+
.sourceTag = view.tag,
206+
.lastAppliedLayoutMetrics = view.layoutMetrics};
177207
}
178208
}
179209
}

packages/react-native/ReactCommon/react/renderer/viewtransition/ViewTransitionModule.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,10 @@ class ViewTransitionModule : public UIManagerViewTransitionDelegate,
119119

120120
struct InactivePseudoElement {
121121
std::shared_ptr<const ShadowNode> node;
122-
Tag sourceTag{0}; // tag of the original view this was created from
122+
// tag of the original view this was created from
123+
Tag sourceTag{0};
124+
// Layout metrics last applied to the pseudo-element node's props.
125+
AnimationKeyFrameViewLayoutMetrics lastAppliedLayoutMetrics{};
123126
};
124127
// pseudo-element nodes created for entering nodes, to be copied into
125128
// oldPseudoElementNodes_ during the next applyViewTransitionName call.

0 commit comments

Comments
 (0)