-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
Copy pathScreenWrapper.js
119 lines (103 loc) · 3.87 KB
/
ScreenWrapper.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
import _ from 'underscore';
import React from 'react';
import PropTypes from 'prop-types';
import {View} from 'react-native';
import {withNavigation} from '@react-navigation/compat';
import {SafeAreaInsetsContext} from 'react-native-safe-area-context';
import styles, {getSafeAreaPadding} from '../styles/styles';
import HeaderGap from './HeaderGap';
import KeyboardShortcut from '../libs/KeyboardShortcut';
import onScreenTransitionEnd from '../libs/onScreenTransitionEnd';
import Navigation from '../libs/Navigation/Navigation';
const propTypes = {
/** Array of additional styles to add */
style: PropTypes.arrayOf(PropTypes.object),
/** Returns a function as a child to pass insets to or a node to render without insets */
children: PropTypes.oneOfType([
PropTypes.node,
PropTypes.func,
]).isRequired,
/** Whether to include padding bottom */
includePaddingBottom: PropTypes.bool,
/** Whether to include padding top */
includePaddingTop: PropTypes.bool,
// Called when navigated Screen's transition is finished.
onTransitionEnd: PropTypes.func,
// react-navigation navigation object available to screen components
navigation: PropTypes.shape({
// Method to attach listener to Navigation state.
addListener: PropTypes.func.isRequired,
}),
};
const defaultProps = {
style: [],
includePaddingBottom: true,
includePaddingTop: true,
onTransitionEnd: () => {},
navigation: {
addListener: () => {},
},
};
class ScreenWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
didScreenTransitionEnd: false,
};
}
componentDidMount() {
this.unsubscribeEscapeKey = KeyboardShortcut.subscribe('Escape', () => {
Navigation.dismissModal();
}, [], true);
this.unsubscribeTransitionEnd = onScreenTransitionEnd(this.props.navigation, () => {
this.setState({didScreenTransitionEnd: true});
this.props.onTransitionEnd();
});
}
componentWillUnmount() {
if (this.unsubscribeEscapeKey) {
this.unsubscribeEscapeKey();
}
if (this.unsubscribeTransitionEnd) {
this.unsubscribeTransitionEnd();
}
}
render() {
return (
<SafeAreaInsetsContext.Consumer>
{(insets) => {
const {paddingTop, paddingBottom} = getSafeAreaPadding(insets);
const paddingStyle = {};
if (this.props.includePaddingTop) {
paddingStyle.paddingTop = paddingTop;
}
if (this.props.includePaddingBottom) {
paddingStyle.paddingBottom = paddingBottom;
}
return (
<View style={[
...this.props.style,
styles.flex1,
paddingStyle,
]}
>
<HeaderGap />
{// If props.children is a function, call it to provide the insets to the children.
_.isFunction(this.props.children)
? this.props.children({
insets,
didScreenTransitionEnd: this.state.didScreenTransitionEnd,
})
: this.props.children
}
</View>
);
}}
</SafeAreaInsetsContext.Consumer>
);
}
}
ScreenWrapper.propTypes = propTypes;
ScreenWrapper.defaultProps = defaultProps;
ScreenWrapper.displayName = 'ScreenWrapper';
export default withNavigation(ScreenWrapper);