-
Notifications
You must be signed in to change notification settings - Fork 2.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1960 from Expensify/marcaaron-fixModalClosing
Fix modal closing animation on web/desktop
- Loading branch information
Showing
10 changed files
with
131 additions
and
156 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
26 changes: 26 additions & 0 deletions
26
src/libs/Navigation/AppNavigator/ClickAwayHandler/ClickAwayHandler.js
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,26 @@ | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import {Pressable} from 'react-native'; | ||
import Navigation from '../../Navigation'; | ||
import styles from '../../../../styles/styles'; | ||
|
||
const propTypes = { | ||
isDisplayingModal: PropTypes.bool.isRequired, | ||
}; | ||
|
||
const ClickAwayHandler = (props) => { | ||
if (!props.isDisplayingModal) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<Pressable | ||
style={styles.navigationModalOverlay} | ||
onPress={Navigation.dismissModal} | ||
/> | ||
); | ||
}; | ||
|
||
ClickAwayHandler.propTypes = propTypes; | ||
ClickAwayHandler.displayName = 'ClickAwayHandler'; | ||
export default ClickAwayHandler; |
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,3 @@ | ||
import ClickAwayHandler from './ClickAwayHandler'; | ||
|
||
export default ClickAwayHandler; |
20 changes: 20 additions & 0 deletions
20
src/libs/Navigation/AppNavigator/ClickAwayHandler/index.native.js
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,20 @@ | ||
import React from 'react'; | ||
import withWindowDimensions, {windowDimensionsPropTypes} from '../../../../components/withWindowDimensions'; | ||
import ClickAwayHandler from './ClickAwayHandler'; | ||
|
||
const propTypes = { | ||
...windowDimensionsPropTypes, | ||
}; | ||
|
||
const ClickAwayHandlerWithWindowDimensions = (props) => { | ||
if (props.isSmallScreenWidth) { | ||
return null; | ||
} | ||
|
||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
return <ClickAwayHandler {...props} />; | ||
}; | ||
|
||
ClickAwayHandlerWithWindowDimensions.propTypes = propTypes; | ||
ClickAwayHandlerWithWindowDimensions.displayName = 'ClickAwayHandlerWithWindowDimensions'; | ||
export default withWindowDimensions(ClickAwayHandlerWithWindowDimensions); |
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 was deleted.
Oops, something went wrong.
26 changes: 0 additions & 26 deletions
26
src/libs/Navigation/AppNavigator/ModalStacks/index.native.js
This file was deleted.
Oops, something went wrong.
118 changes: 22 additions & 96 deletions
118
src/libs/Navigation/AppNavigator/createCustomModalStackNavigator.js
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 |
---|---|---|
@@ -1,114 +1,40 @@ | ||
import _ from 'underscore'; | ||
import React from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import {withOnyx} from 'react-native-onyx'; | ||
import {createNavigatorFactory, useNavigationBuilder} from '@react-navigation/core'; | ||
import {StackRouter} from '@react-navigation/routers'; | ||
import withWindowDimensions from '../../../components/withWindowDimensions'; | ||
import Modal from '../../../components/Modal'; | ||
import themeColors from '../../../styles/themes/default'; | ||
import ONYXKEYS from '../../../ONYXKEYS'; | ||
import Navigation from '../Navigation'; | ||
import compose from '../../compose'; | ||
import CONST from '../../../CONST'; | ||
import {StackView} from '@react-navigation/stack'; | ||
import ClickAwayHandler from './ClickAwayHandler'; | ||
|
||
const propTypes = { | ||
// Navigation state for this navigator | ||
// See: https://reactnavigation.org/docs/navigation-state/ | ||
state: PropTypes.shape({ | ||
// Index of the focused route object in the routes array | ||
index: PropTypes.number, | ||
|
||
// List of route objects (screens) which are rendered in the navigator. It also represents the history in a | ||
// stack navigator. There should be at least one item present in this array. | ||
routes: PropTypes.arrayOf(PropTypes.shape({ | ||
|
||
// A unique key name for a screen. Created automatically by react-nav. | ||
key: PropTypes.string, | ||
})), | ||
}).isRequired, | ||
|
||
// Object containing descriptors for each route with the route keys as its properties | ||
// See: https://reactnavigation.org/docs/custom-navigators/#usenavigationbuilder | ||
// eslint-disable-next-line react/no-unused-prop-types | ||
descriptors: PropTypes.objectOf(PropTypes.shape({ | ||
|
||
// A function which can be used to render the actual screen. Calling descriptors[route.key].render() will return | ||
// a React element containing the screen content. | ||
render: PropTypes.func, | ||
})).isRequired, | ||
|
||
// Current url we are navigated to | ||
currentURL: PropTypes.string, | ||
|
||
// Path for the modal parent to match on | ||
path: PropTypes.string.isRequired, | ||
}; | ||
|
||
const defaultProps = { | ||
currentURL: '', | ||
}; | ||
|
||
/** | ||
* Returns the current descriptor for the focused screen in this navigators state. The descriptor has a function | ||
* called render() that we must call each time this navigator updates. It's important to use this method to render | ||
* a screen, otherwise any child navigators won't be connected to the navigation tree properly. | ||
* | ||
* @param {Object} props | ||
* @returns {Object} | ||
*/ | ||
function getCurrentViewDescriptor(props) { | ||
const currentRoute = props.state.routes[props.state.index]; | ||
const currentRouteKey = currentRoute.key; | ||
const currentDescriptor = props.descriptors[currentRouteKey]; | ||
return currentDescriptor; | ||
} | ||
|
||
const ResponsiveView = props => ( | ||
<Modal | ||
isVisible={props.currentURL | ||
&& props.currentURL.includes(props.path)} | ||
backgroundColor={themeColors.componentBG} | ||
type={CONST.MODAL.MODAL_TYPE.RIGHT_DOCKED} | ||
onClose={Navigation.dismissModal} | ||
> | ||
{getCurrentViewDescriptor(props).render()} | ||
</Modal> | ||
); | ||
|
||
ResponsiveView.propTypes = propTypes; | ||
ResponsiveView.defaultProps = defaultProps; | ||
ResponsiveView.displayName = 'ResponsiveView'; | ||
|
||
const ResponsiveViewWithHOCs = compose( | ||
withWindowDimensions, | ||
withOnyx({ | ||
currentURL: { | ||
key: ONYXKEYS.CURRENT_URL, | ||
}, | ||
}), | ||
)(ResponsiveView); | ||
|
||
const ResponsiveNavigator = ({ | ||
const CustomRootStackNavigator = ({ | ||
children, | ||
...rest | ||
}) => { | ||
const {state, navigation, descriptors} = useNavigationBuilder(StackRouter, { | ||
children, | ||
}); | ||
|
||
const isDisplayingModal = Boolean(_.find(descriptors, descriptor => descriptor.options.isModal)); | ||
return ( | ||
<ResponsiveViewWithHOCs | ||
state={state} | ||
navigation={navigation} | ||
descriptors={descriptors} | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
{...rest} | ||
/> | ||
<> | ||
<StackView | ||
state={state} | ||
navigation={navigation} | ||
descriptors={descriptors} | ||
// eslint-disable-next-line react/jsx-props-no-spreading | ||
{...rest} | ||
/> | ||
|
||
{/* We need to superimpose a clickaway handler when showing modals so that they can be dismissed. Capturing | ||
press events on the cardOverlay element in react-navigation is not yet supported on web */} | ||
<ClickAwayHandler | ||
isDisplayingModal={isDisplayingModal} | ||
/> | ||
</> | ||
); | ||
}; | ||
|
||
ResponsiveNavigator.propTypes = { | ||
CustomRootStackNavigator.propTypes = { | ||
children: PropTypes.node.isRequired, | ||
}; | ||
|
||
export default createNavigatorFactory(ResponsiveNavigator); | ||
export default createNavigatorFactory(CustomRootStackNavigator); |
31 changes: 31 additions & 0 deletions
31
src/libs/Navigation/AppNavigator/modalCardStyleInterpolator.js
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,31 @@ | ||
import {Animated} from 'react-native'; | ||
|
||
export default ({ | ||
current: {progress}, | ||
inverted, | ||
layouts: { | ||
screen, | ||
}, | ||
}) => { | ||
const translateX = Animated.multiply(progress.interpolate({ | ||
inputRange: [0, 1], | ||
outputRange: [screen.width, 0], | ||
extrapolate: 'clamp', | ||
}), inverted); | ||
|
||
return ({ | ||
containerStyle: { | ||
overflow: 'hidden', | ||
}, | ||
cardStyle: { | ||
transform: [{translateX}], | ||
}, | ||
overlayStyle: { | ||
opacity: progress.interpolate({ | ||
inputRange: [0, 1], | ||
outputRange: [0, 0.3], | ||
extrapolate: 'clamp', | ||
}), | ||
}, | ||
}); | ||
}; |
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