-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Shared Element Transition on the New Architecture (feature flag) #7466
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
|
Hey 👋 Just backlinking to the PR announcement tweet for demos and community comments: https://x.com/BBloniarz_/status/1919390653856829566 |
|
Hi @bartlomiejbloniarz nice work you are doing. Is there a way we can get a code demo of it in new Arch? Currently, I am unable to get it to work with the code sample provide in the docs. Thanks ❤️ |
|
@elozino-eryk you can see the set of examples by run |
tomekzaw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Please use
const auto &instead ofautoorauto &wherever possible. - Please address leftover TODOs – are they "for now" or "for later"?
- Please remove leftover comments with code snippets if they are no longer needed
- Please add some spacing between switch
cases for better readability.
| function HomeScreen({ navigation }: HomeScreenProps) { | ||
| const [search, setSearch] = React.useState(''); | ||
| const [wasClicked, setWasClicked] = React.useState<string[]>([]); | ||
| const platform = Platform.OS as 'ios' | 'android'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about web and other platforms?
| fontSize: 16, | ||
| color: 'black', | ||
| }, | ||
| marker: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| marker: { | |
| shouldWorkEmoji: { |
| type SharedTransitionProps = { | ||
| sharedTransitionTag?: string; | ||
| sharedTransitionStyle?: SharedTransition; | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have an unique chance to consider some breaking changes in the API, for instance:
- renaming
SharedTransitiontoSharedElementTransition - renaming
sharedTransitionTagtosharedElementTransitionTagorsharedTag - renaming
sharedTransitionStyleto something else withoutstyle
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think a more descriptive name would be cool, but it just is too long. Maybe just drop the style and have sharedTransiton like with layout animations? It would be confusing though with the tag being a separate thing
| extends ComplexAnimationBuilder | ||
| implements ILayoutAnimationBuilder | ||
| { | ||
| static presetName = 'LinearTransition'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| static presetName = 'LinearTransition'; | |
| static presetName = 'SharedTransition'; |
| build = (): LayoutAnimationFunction => { | ||
| const delayFunction = this.getDelayFunction(); | ||
| if (!this.durationV) { | ||
| this.durationV = 500; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's double check if the default config looks good.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think I inherit too much here from layout animations
| ShadowView finalView, currentView, startView; | ||
| Tag parentTag; | ||
| std::optional<double> opacity; | ||
| int count = 1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
count of what?
|
|
||
| const ShadowNode *LayoutAnimationsProxy_Experimental::findInShadowTreeByTag(const ShadowNode &node, Tag tag) const { | ||
| if (node.getTag() == tag) { | ||
| return const_cast<const ShadowNode *>(&node); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can't it be done simpler?
| if (node.getTag() == tag) { | ||
| return const_cast<const ShadowNode *>(&node); | ||
| } | ||
| for (auto &child : node.getChildren()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| for (auto &child : node.getChildren()) { | |
| for (const auto &child : node.getChildren()) { |
| } | ||
|
|
||
| auto oldView = oldChildShadowView; | ||
| Rect window{}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| Rect window{}; | |
| Rect window; |
| auto &mutex = strongThis->mutex; | ||
| auto lock = std::unique_lock<std::recursive_mutex>(mutex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| auto &mutex = strongThis->mutex; | |
| auto lock = std::unique_lock<std::recursive_mutex>(mutex); | |
| auto lock = std::unique_lock<std::recursive_mutex>(strongThis->mutex); |
| "USE_SYNCHRONIZABLE_FOR_MUTABLES": true, | ||
| "USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS": true | ||
| "USE_COMMIT_HOOK_ONLY_FOR_REACT_COMMITS": true, | ||
| "SHARED_ELEMENT_TRANSITIONS": true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "SHARED_ELEMENT_TRANSITIONS": true | |
| "ENABLE_SHARED_ELEMENT_TRANSITIONS": true |
As was described in the las point of https://docs.swmansion.com/react-native-reanimated/docs/guides/feature-flags/#remarks-for-contributors
| EXITING = 2, | ||
| LAYOUT = 3, | ||
| SHARED_ELEMENT_TRANSITION = 4, | ||
| SHARED_ELEMENT_TRANSITION_NATIVE_ID = 5, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks a bit sus that NATIVE_ID is a type of layout animation 🤔
| build = (): LayoutAnimationFunction => { | ||
| const delayFunction = this.getDelayFunction(); | ||
| if (!this.durationV) { | ||
| this.durationV = 500; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe let's make it a bit faster, 300 would be better
| animations[key] = target.map( | ||
| (item: Record<string, number | string>) => { | ||
| key = Object.keys(item)[0]; | ||
| return { | ||
| [key]: animationFactory(item[key]), | ||
| }; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that this is a simple implementation from previous version, but we should keep in mind or note somewhere that this is not the correct way of doing matrix interpolation. Since we have higher priorities, let's keep it as it is for now.
| if (!getStaticFeatureFlag('SHARED_ELEMENT_TRANSITIONS')) { | ||
| return; | ||
| } | ||
| if (this.props.sharedTransitionTag) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will probably prevent the removal of a shared transition from a component when someone assigns null or undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know that SET and LayoutAnimation are close features, but it think we need to split implementation of Layout animation proxy to maintain readability.
| auto transform = parseParentTransforms(node, absolutePositions); | ||
| transition.transform[index] = std::move(transform); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| auto transform = parseParentTransforms(node, absolutePositions); | |
| transition.transform[index] = std::move(transform); | |
| transition.transform[index] = parseParentTransforms(node, absolutePositions); |
| overrideTransform(transition.snapshot[1], transition.transform[1], propsParserContext); | ||
| transitions_.emplace_back(sharedTag, transition); | ||
| } else if (transition.parentTag[1]) { | ||
| // TODO: this is too eager |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you explain this case?
| } | ||
|
|
||
| void LayoutAnimationsProxy_Experimental::hideTransitioningViews( | ||
| int index, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can replace this index with enum
| lightNodes_[myTag] = std::move(node); | ||
|
|
||
| sharedTransitionManager_->containerTags_[sharedTag] = containerTag; | ||
| myTag += 2; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not the best name 😅
Summary
This PR brings back the Shared Element Transition feature to reanimated (within a limited scope and behind a feature flag).
Current limitations:
[SET] Modals) exampleTest plan