|
@@ -6,11 +6,14 @@ import { Animated, StyleSheet, ViewPropTypes, WebView } from 'react-native';
|
6
|
6
|
|
7
|
7
|
import PropTypes from 'prop-types';
|
8
|
8
|
|
9
|
|
-import { isScriptChanged, getSize, getWidth, getScript, handleSizeUpdated, domMutationObserveScript } from './common.js';
|
|
9
|
+import { getSize, isEqual, setState, getWidth, handleSizeUpdated, domMutationObserveScript } from './common.js';
|
|
10
|
+
|
|
11
|
+import momoize from './momoize';
|
10
|
12
|
|
11
|
13
|
export default class AutoHeightWebView extends PureComponent {
|
12
|
14
|
static propTypes = {
|
13
|
15
|
hasIframe: PropTypes.bool,
|
|
16
|
+ onMessage: PropTypes.func,
|
14
|
17
|
source: WebView.propTypes.source,
|
15
|
18
|
customScript: PropTypes.string,
|
16
|
19
|
customStyle: PropTypes.string,
|
|
@@ -52,20 +55,14 @@ export default class AutoHeightWebView extends PureComponent {
|
52
|
55
|
super(props);
|
53
|
56
|
const { enableAnimation, style } = props;
|
54
|
57
|
enableAnimation && (this.opacityAnimatedValue = new Animated.Value(0));
|
|
58
|
+ this.webView = React.createRef();
|
55
|
59
|
this.state = {
|
56
|
|
- isScriptChanged: false,
|
57
|
60
|
width: getWidth(style),
|
58
|
|
- height: style && style.height ? style.height : 0,
|
59
|
|
- script: getScript(props, getBaseScript, getIframeBaseScript)
|
|
61
|
+ height: style && style.height ? style.height : 0
|
60
|
62
|
};
|
61
|
63
|
}
|
62
|
64
|
|
63
|
|
- componentWillReceiveProps(nextProps) {
|
64
|
|
- const size = getSize(nextProps, this.props);
|
65
|
|
- size && this.setState(size);
|
66
|
|
- this.isScriptChanged = isScriptChanged(nextProps, this.props);
|
67
|
|
- this.isScriptChanged && this.setState({ script: getScript(nextProps, getBaseScript, getIframeBaseScript) });
|
68
|
|
- }
|
|
65
|
+ getUpdatedState = momoize(setState, isEqual);
|
69
|
66
|
|
70
|
67
|
handleNavigationStateChange = navState => {
|
71
|
68
|
const { title } = navState;
|
|
@@ -77,35 +74,40 @@ export default class AutoHeightWebView extends PureComponent {
|
77
|
74
|
const height = Number(heightValue);
|
78
|
75
|
const { height: oldHeight, width: oldWidth } = this.state;
|
79
|
76
|
if ((height && height !== oldHeight) || (width && width !== oldWidth)) {
|
80
|
|
- // if ((height && height !== oldHeight)) {
|
81
|
77
|
const { enableAnimation, animationDuration, onSizeUpdated } = this.props;
|
82
|
78
|
enableAnimation && this.opacityAnimatedValue.setValue(0);
|
|
79
|
+ this.updatingSize = true;
|
83
|
80
|
this.setState(
|
84
|
81
|
{
|
85
|
82
|
height,
|
86
|
83
|
width
|
87
|
84
|
},
|
88
|
85
|
() => {
|
89
|
|
- enableAnimation
|
90
|
|
- ? Animated.timing(this.opacityAnimatedValue, {
|
91
|
|
- toValue: 1,
|
92
|
|
- duration: animationDuration
|
93
|
|
- }).start(() => handleSizeUpdated(height, width, onSizeUpdated))
|
94
|
|
- : handleSizeUpdated(height, width, onSizeUpdated);
|
|
86
|
+ if (enableAnimation) {
|
|
87
|
+ Animated.timing(this.opacityAnimatedValue, {
|
|
88
|
+ toValue: 1,
|
|
89
|
+ duration: animationDuration
|
|
90
|
+ }).start(() => {
|
|
91
|
+ handleSizeUpdated(height, width, onSizeUpdated);
|
|
92
|
+ this.updatingSize = false;
|
|
93
|
+ });
|
|
94
|
+ } else {
|
|
95
|
+ handleSizeUpdated(height, width, onSizeUpdated);
|
|
96
|
+ this.updatingSize = false;
|
|
97
|
+ }
|
95
|
98
|
}
|
96
|
99
|
);
|
97
|
100
|
}
|
98
|
101
|
};
|
99
|
102
|
|
100
|
|
- getWebView = webView => (this.webView = webView);
|
101
|
|
-
|
102
|
103
|
stopLoading() {
|
103
|
104
|
this.webView.stopLoading();
|
104
|
105
|
}
|
105
|
106
|
|
106
|
107
|
render() {
|
107
|
|
- const { height, width, script } = this.state;
|
|
108
|
+ const { height, width } = this.state;
|
108
|
109
|
const {
|
|
110
|
+ onMessage,
|
109
|
111
|
onError,
|
110
|
112
|
onLoad,
|
111
|
113
|
onLoadStart,
|
|
@@ -113,41 +115,43 @@ export default class AutoHeightWebView extends PureComponent {
|
113
|
115
|
onShouldStartLoadWithRequest,
|
114
|
116
|
scalesPageToFit,
|
115
|
117
|
enableAnimation,
|
116
|
|
- source,
|
117
|
118
|
heightOffset,
|
118
|
119
|
style,
|
119
|
120
|
scrollEnabled
|
120
|
121
|
} = this.props;
|
121
|
|
- let webViewSource = Object.assign({}, source, { baseUrl: 'web/' });
|
122
|
|
- if (this.isScriptChanged) {
|
123
|
|
- this.changeSourceFlag = !this.changeSourceFlag;
|
124
|
|
- webViewSource = Object.assign(webViewSource, { changeSourceFlag: this.changeSourceFlag });
|
125
|
|
- }
|
|
122
|
+ const { height: newHeight, width: newWidth, source, script } = this.getUpdatedState(
|
|
123
|
+ this.props,
|
|
124
|
+ getBaseScript,
|
|
125
|
+ getIframeBaseScript
|
|
126
|
+ );
|
|
127
|
+ const { w, h } = getSize(newHeight, newWidth, height, width, this.updatingSize, this.calledOnce);
|
|
128
|
+ this.calledOnce = true;
|
126
|
129
|
return (
|
127
|
130
|
<Animated.View
|
128
|
131
|
style={[
|
129
|
132
|
styles.container,
|
130
|
133
|
{
|
131
|
134
|
opacity: enableAnimation ? this.opacityAnimatedValue : 1,
|
132
|
|
- width,
|
133
|
|
- height: height + heightOffset
|
|
135
|
+ width: w,
|
|
136
|
+ height: h + heightOffset
|
134
|
137
|
},
|
135
|
138
|
style
|
136
|
139
|
]}
|
137
|
140
|
>
|
138
|
141
|
<WebView
|
139
|
142
|
originWhitelist={['*']}
|
140
|
|
- ref={this.getWebView}
|
|
143
|
+ ref={this.webView}
|
|
144
|
+ onMessage={onMessage}
|
141
|
145
|
onError={onError}
|
142
|
146
|
onLoad={onLoad}
|
143
|
147
|
onLoadStart={onLoadStart}
|
144
|
148
|
onLoadEnd={onLoadEnd}
|
145
|
149
|
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
146
|
150
|
style={styles.webView}
|
147
|
|
- injectedJavaScript={script}
|
148
|
151
|
scrollEnabled={!!scrollEnabled}
|
149
|
152
|
scalesPageToFit={scalesPageToFit}
|
150
|
|
- source={webViewSource}
|
|
153
|
+ injectedJavaScript={script}
|
|
154
|
+ source={source}
|
151
|
155
|
onNavigationStateChange={this.handleNavigationStateChange}
|
152
|
156
|
/>
|
153
|
157
|
</Animated.View>
|