Skip to content

Commit 4df6957

Browse files
zeyapfacebook-github-bot
authored andcommitted
support multiple old pseudo elements for same name but different source node
Summary: ## Changelog: [General] [Fixed] - support multiple old pseudo elements for same name but different source node We will need to track multiple old pseudo elements for same name but different source node when doing a series of shared transitions: 1. go from component A to component B (A stays hidden with Activity but not unmounted) 2. go back to A (B unmounted) 3. hide A and show B again A will lose its old pseudo element node, because at facebook#1, B's old pseudo element node overrides A's (since they have the same vt name), and at facebook#2, B's old node gets cleaned up. At facebook#3, since createViewTransitionInstance won't be called for A again (react reconciler assumes the instance is only created once until a component is unmounted), there's no valid old node for A anymore. Differential Revision: D101237889
1 parent 84ade57 commit 4df6957

2 files changed

Lines changed: 24 additions & 4 deletions

File tree

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "ViewTransitionModule.h"
99

10+
#include <glog/logging.h>
1011
#include <react/renderer/components/root/RootShadowNode.h>
1112
#include <react/renderer/core/LayoutableShadowNode.h>
1213
#include <react/renderer/core/RawProps.h>
@@ -93,7 +94,20 @@ void ViewTransitionModule::applyViewTransitionName(
9394

9495
if (auto it = oldPseudoElementNodesRepository_.find(name);
9596
it != oldPseudoElementNodesRepository_.end()) {
96-
oldPseudoElementNodes_[name] = it->second.node;
97+
// Find the pseudo element created from this specific source tag
98+
auto& pseudoElementsBySourceTag = it->second;
99+
auto innerIt = pseudoElementsBySourceTag.find(tag);
100+
if (innerIt != pseudoElementsBySourceTag.end()) {
101+
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;
106+
}
107+
} else {
108+
LOG(ERROR)
109+
<< "applyViewTransitionName: old pseudo element shadow node doesn't exist for name "
110+
<< name;
97111
}
98112

99113
} else {
@@ -158,7 +172,7 @@ void ViewTransitionModule::createViewTransitionInstance(
158172
if (!forNextTransition) {
159173
oldPseudoElementNodes_[name] = pseudoElementNode;
160174
}
161-
oldPseudoElementNodesRepository_[name] = InactivePseudoElement{
175+
oldPseudoElementNodesRepository_[name][view.tag] = InactivePseudoElement{
162176
.node = pseudoElementNode, .sourceTag = view.tag};
163177
}
164178
}
@@ -222,7 +236,12 @@ std::optional<MountingTransaction> ViewTransitionModule::pullTransaction(
222236
auto tag = mutation.oldChildShadowView.tag;
223237
for (auto it = oldPseudoElementNodesRepository_.begin();
224238
it != oldPseudoElementNodesRepository_.end();) {
225-
if (it->second.sourceTag == tag) {
239+
auto& pseudoElementsBySourceTag = it->second;
240+
if (auto innerIt = pseudoElementsBySourceTag.find(tag);
241+
innerIt != pseudoElementsBySourceTag.end()) {
242+
pseudoElementsBySourceTag.erase(innerIt);
243+
}
244+
if (pseudoElementsBySourceTag.empty()) {
226245
it = oldPseudoElementNodesRepository_.erase(it);
227246
} else {
228247
++it;

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,8 @@ class ViewTransitionModule : public UIManagerViewTransitionDelegate,
124124
// pseudo-element nodes created for entering nodes, to be copied into
125125
// oldPseudoElementNodes_ during the next applyViewTransitionName call.
126126
// Mutable because pullTransaction (const) needs to erase unmounted entries.
127-
mutable std::unordered_map<std::string, InactivePseudoElement> oldPseudoElementNodesRepository_{};
127+
mutable std::unordered_map<std::string, std::unordered_map<Tag /* sourceTag */, InactivePseudoElement>>
128+
oldPseudoElementNodesRepository_{};
128129

129130
LayoutMetrics captureLayoutMetricsFromRoot(const ShadowNode &shadowNode);
130131

0 commit comments

Comments
 (0)