-
-
Notifications
You must be signed in to change notification settings - Fork 545
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(iOS,Fabric): fix invalid position of FullWindowOverlay in certain…
… scenarios (#2641) ## Description Fixes #2631 I've given extensive description of both the issue ~and potential solution~ in #2631 issue discussion * #2631 In particular important parts are: * #2631 (comment) * #2631 (comment) I settled down on zeroing origin of the `FullWindowOverlay` frame in HostTree & setting `ShadowNodeTraits::RootNodeKind` for the custom shadow node of `FullWindowOverlay` component in the ShadowTree. This is much cleaner than managing the state & content offset manually. ## Changes `FullWindowOverlay` has now custom component descriptor, shadow node & shadow node state (its empty). The shadow node has `ShadowNodeTraits::RootNodeKind` set allowing it to be the reference point when computing position of any descendant view in shadow tree - this is fine, because we always expect `FullWindowOverlay` to have origin at `(0, 0)` in window coordinate space. In the HostTree we now ensure that `FWO` origin is at `(0, 0)` by overriding frame received during mounting stage. ## Test code and steps to reproduce Test2631 should now work not as in recording from issue description but correctly. ## Checklist - [x] Included code example that can be used to test this change - [x] Ensured that CI passes
- Loading branch information
Showing
11 changed files
with
242 additions
and
72 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
import React from 'react'; | ||
import { ForwardedRef } from 'react'; | ||
import { GestureResponderEvent, Pressable, PressableProps, StyleSheet, View } from 'react-native'; | ||
|
||
export type PressableState = 'pressed-in' | 'pressed' | 'pressed-out' | ||
|
||
const PressableWithFeedback = React.forwardRef((props: PressableProps, ref: ForwardedRef<View>): React.JSX.Element => { | ||
const [pressedState, setPressedState] = React.useState<PressableState>('pressed-out'); | ||
|
||
const onPressInCallback = React.useCallback((e: GestureResponderEvent) => { | ||
console.log('Pressable onPressIn', { | ||
locationX: e.nativeEvent.locationX, | ||
locationY: e.nativeEvent.locationY, | ||
pageX: e.nativeEvent.pageX, | ||
pageY: e.nativeEvent.pageY, | ||
}); | ||
setPressedState('pressed-in'); | ||
props.onPressIn?.(e); | ||
}, [props]); | ||
|
||
const onPressCallback = React.useCallback((e: GestureResponderEvent) => { | ||
console.log('Pressable onPress'); | ||
setPressedState('pressed'); | ||
props.onPress?.(e); | ||
}, [props]); | ||
|
||
const onPressOutCallback = React.useCallback((e: GestureResponderEvent) => { | ||
console.log('Pressable onPressOut'); | ||
setPressedState('pressed-out'); | ||
props.onPressOut?.(e); | ||
}, [props]); | ||
|
||
const onResponderMoveCallback = React.useCallback((e: GestureResponderEvent) => { | ||
console.log('Pressable onResponderMove'); | ||
props.onResponderMove?.(e); | ||
}, [props]); | ||
|
||
const contentsStyle = pressedState === 'pressed-out' | ||
? styles.pressablePressedOut | ||
: (pressedState === 'pressed' | ||
? styles.pressablePressed | ||
: styles.pressablePressedIn); | ||
|
||
return ( | ||
<View ref={ref} style={[contentsStyle]}> | ||
<Pressable | ||
onPressIn={onPressInCallback} | ||
onPress={onPressCallback} | ||
onPressOut={onPressOutCallback} | ||
onResponderMove={onResponderMoveCallback} | ||
> | ||
{props.children} | ||
</Pressable> | ||
</View> | ||
|
||
); | ||
}); | ||
|
||
const styles = StyleSheet.create({ | ||
pressablePressedIn: { | ||
backgroundColor: 'lightsalmon', | ||
}, | ||
pressablePressed: { | ||
backgroundColor: 'crimson', | ||
}, | ||
pressablePressedOut: { | ||
backgroundColor: 'lightseagreen', | ||
}, | ||
}); | ||
|
||
export default PressableWithFeedback; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import * as React from 'react'; | ||
|
||
import {Button, Pressable, StyleSheet, Text, View} from 'react-native'; | ||
import {FullWindowOverlay} from 'react-native-screens'; | ||
import PressableWithFeedback from '../shared/PressableWithFeedback'; | ||
|
||
function SharedPressable() { | ||
return ( | ||
<PressableWithFeedback> | ||
<View style={{ width: '100%', height: 32 }}> | ||
<Text>Pressable</Text> | ||
</View> | ||
</PressableWithFeedback> | ||
); | ||
} | ||
|
||
function HomeScreen() { | ||
const [overlayShown, setOverlayShown] = React.useState(false); | ||
return ( | ||
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}} collapsable={true}> | ||
<Text>Home Screen</Text> | ||
<Button title="Show Overlay" onPress={() => setOverlayShown(true)} /> | ||
<SharedPressable /> | ||
{overlayShown && ( | ||
<FullWindowOverlay> | ||
<View style={{flex: 1}}> | ||
<Pressable | ||
style={{ | ||
flex: 1, | ||
alignItems: 'center', | ||
justifyContent: 'center', | ||
backgroundColor: 'rgba(130, 200, 120, 0.8)', | ||
}} | ||
onPress={() => setOverlayShown(false)}> | ||
<Text>Overlay</Text> | ||
<SharedPressable /> | ||
</Pressable> | ||
</View> | ||
</FullWindowOverlay> | ||
)} | ||
</View> | ||
); | ||
} | ||
|
||
function Header() { | ||
return ( | ||
<View pointerEvents='box-none' style={{ height: 100.6666 }}> | ||
<View style={[StyleSheet.absoluteFill, { }]}> | ||
<View style={{ flex: 1, backgroundColor: 'white', opacity: 0.6}} /> | ||
</View> | ||
</View> | ||
); | ||
} | ||
|
||
export default function App() { | ||
return ( | ||
<View style={{flex: 1, backgroundColor: 'lightsalmon' }}> | ||
<Header /> | ||
<HomeScreen /> | ||
</View> | ||
); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayComponentDescriptor.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#pragma once | ||
|
||
#ifdef ANDROID | ||
#include <fbjni/fbjni.h> | ||
#endif // ANDROID | ||
#include <react/renderer/core/ConcreteComponentDescriptor.h> | ||
#include "RNSFullWindowOverlayShadowNode.h" | ||
|
||
namespace facebook::react { | ||
|
||
class RNSFullWindowOverlayComponentDescriptor final | ||
: public ConcreteComponentDescriptor<RNSFullWindowOverlayShadowNode> { | ||
public: | ||
using ConcreteComponentDescriptor::ConcreteComponentDescriptor; | ||
}; | ||
|
||
} // namespace facebook::react |
7 changes: 7 additions & 0 deletions
7
common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayShadowNode.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#include "RNSFullWindowOverlayShadowNode.h" | ||
|
||
namespace facebook::react { | ||
|
||
extern const char RNSFullWindowOverlayComponentName[] = "RNSFullWindowOverlay"; | ||
|
||
} // namespace facebook::react |
35 changes: 35 additions & 0 deletions
35
common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayShadowNode.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
#pragma once | ||
|
||
#include <jsi/jsi.h> | ||
#include <react/renderer/components/rnscreens/EventEmitters.h> | ||
#include <react/renderer/components/rnscreens/Props.h> | ||
#include <react/renderer/components/view/ConcreteViewShadowNode.h> | ||
#include <react/renderer/core/LayoutContext.h> | ||
#include "RNSFullWindowOverlayState.h" | ||
|
||
namespace facebook::react { | ||
|
||
JSI_EXPORT extern const char RNSFullWindowOverlayComponentName[]; | ||
|
||
using ConcreteViewShadowNodeSuperType = ConcreteViewShadowNode< | ||
RNSFullWindowOverlayComponentName, | ||
RNSFullWindowOverlayProps, | ||
RNSFullWindowOverlayEventEmitter, | ||
RNSFullWindowOverlayState>; | ||
|
||
class JSI_EXPORT RNSFullWindowOverlayShadowNode final | ||
: public ConcreteViewShadowNodeSuperType { | ||
public: | ||
using ConcreteViewShadowNode::ConcreteViewShadowNode; | ||
using StateData = ConcreteViewShadowNode::ConcreteStateData; | ||
|
||
#if !defined(ANDROID) | ||
static ShadowNodeTraits BaseTraits() { | ||
auto traits = ConcreteViewShadowNodeSuperType::BaseTraits(); | ||
traits.set(ShadowNodeTraits::Trait::RootNodeKind); | ||
return traits; | ||
} | ||
#endif | ||
}; | ||
|
||
} // namespace facebook::react |
30 changes: 30 additions & 0 deletions
30
common/cpp/react/renderer/components/rnscreens/RNSFullWindowOverlayState.h
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#pragma once | ||
|
||
#if defined(ANDROID) | ||
#include <folly/dynamic.h> | ||
#include <react/renderer/mapbuffer/MapBuffer.h> | ||
#include <react/renderer/mapbuffer/MapBufferBuilder.h> | ||
#endif // ANDROID | ||
|
||
#include <react/renderer/core/graphicsConversions.h> | ||
#include <react/renderer/graphics/Float.h> | ||
|
||
namespace facebook::react { | ||
|
||
class JSI_EXPORT RNSFullWindowOverlayState final { | ||
public: | ||
using Shared = std::shared_ptr<const RNSFullWindowOverlayState>; | ||
|
||
RNSFullWindowOverlayState() = default; | ||
|
||
#if defined(ANDROID) | ||
RNSFullWindowOverlayState( | ||
const RNSFullWindowOverlayState &previousState, | ||
folly::dynamic data) {} | ||
folly::dynamic getDynamic() const { | ||
return {}; | ||
} | ||
#endif | ||
}; | ||
|
||
} // namespace facebook::react |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters