|
@@ -2,33 +2,29 @@
|
2
|
2
|
|
3
|
3
|
import React, { PureComponent } from 'react';
|
4
|
4
|
|
5
|
|
-import { Animated, Dimensions, StyleSheet, ViewPropTypes, WebView } from 'react-native';
|
|
5
|
+import { Animated, StyleSheet, ViewPropTypes, WebView } from 'react-native';
|
6
|
6
|
|
7
|
7
|
import PropTypes from 'prop-types';
|
8
|
8
|
|
9
|
|
-import { getScript, onHeightUpdated, onWidthUpdated, onHeightWidthUpdated, domMutationObserveScript } from './common.js';
|
10
|
|
-
|
11
|
|
-const screenWidth = Dimensions.get('window').width;
|
|
9
|
+import { getWidth, getScript, handleSizeUpdated, domMutationObserveScript } from './common.js';
|
12
|
10
|
|
13
|
11
|
export default class AutoHeightWebView extends PureComponent {
|
14
|
12
|
static propTypes = {
|
15
|
13
|
hasIframe: PropTypes.bool,
|
16
|
14
|
source: WebView.propTypes.source,
|
17
|
|
- onHeightUpdated: PropTypes.func,
|
18
|
|
- onWidthUpdated: PropTypes.func,
|
19
|
|
- onHeightWidthUpdated: PropTypes.func,
|
20
|
|
- shouldResizeWidth: PropTypes.bool,
|
21
|
15
|
customScript: PropTypes.string,
|
22
|
16
|
customStyle: PropTypes.string,
|
23
|
17
|
enableAnimation: PropTypes.bool,
|
|
18
|
+ style: ViewPropTypes.style,
|
|
19
|
+ scrollEnabled: PropTypes.bool,
|
|
20
|
+ // either height or width updated will trigger this
|
|
21
|
+ onSizeUpdated: PropTypes.func,
|
24
|
22
|
// if set to true may cause some layout issues (smaller font size)
|
25
|
23
|
scalesPageToFit: PropTypes.bool,
|
26
|
24
|
// only works on enable animation
|
27
|
25
|
animationDuration: PropTypes.number,
|
28
|
26
|
// offset of rn webview margin
|
29
|
|
- heightOffset: PropTypes.number,
|
30
|
|
- widthOffset: PropTypes.number,
|
31
|
|
- style: ViewPropTypes.style,
|
|
27
|
+ heightOffset: PropTypes.number,
|
32
|
28
|
// rn WebView callback
|
33
|
29
|
onError: PropTypes.func,
|
34
|
30
|
onLoad: PropTypes.func,
|
|
@@ -49,43 +45,57 @@ export default class AutoHeightWebView extends PureComponent {
|
49
|
45
|
scalesPageToFit: false,
|
50
|
46
|
enableAnimation: true,
|
51
|
47
|
animationDuration: 555,
|
52
|
|
- heightOffset: 12,
|
53
|
|
- widthOffset: 12,
|
54
|
|
- shouldResizeWidth: false
|
|
48
|
+ heightOffset: 12
|
55
|
49
|
};
|
56
|
50
|
|
57
|
51
|
constructor(props) {
|
58
|
52
|
super(props);
|
59
|
|
- props.enableAnimation && (this.opacityAnimatedValue = new Animated.Value(0));
|
|
53
|
+ const { enableAnimation, style } = props;
|
|
54
|
+ enableAnimation && (this.opacityAnimatedValue = new Animated.Value(0));
|
60
|
55
|
this.state = {
|
61
|
|
- height: 0,
|
62
|
|
- //heightOffset: 0, //?? I added this
|
63
|
|
- width: screenWidth,
|
64
|
|
- //widthOffset: 0,
|
65
|
|
- script: getScript(props, baseScript, iframeBaseScript)
|
|
56
|
+ width: getWidth(style),
|
|
57
|
+ height: style && style.height ? style.height : 0,
|
|
58
|
+ script: getScript(props, getBaseScript, getIframeBaseScript)
|
66
|
59
|
};
|
67
|
60
|
}
|
68
|
61
|
|
69
|
62
|
componentWillReceiveProps(nextProps) {
|
70
|
|
- this.setState({ script: getScript(nextProps, baseScript, iframeBaseScript) });
|
|
63
|
+ if (nextProps.style) {
|
|
64
|
+ const { width, height } = nextProps.style;
|
|
65
|
+ width && this.setState({ width });
|
|
66
|
+ height && this.setState({ height });
|
|
67
|
+ }
|
|
68
|
+ this.setState({ script: getScript(nextProps, getBaseScript, getIframeBaseScript) });
|
71
|
69
|
}
|
72
|
70
|
|
73
|
|
- handleNavigationStateChange = navState => {
|
74
|
|
- var [width, height] = navState.title.split(',');
|
75
|
|
- width = Number(width);
|
76
|
|
- height = Number(height);
|
77
|
|
- const { enableAnimation, animationDuration } = this.props;
|
78
|
|
- if (height && height !== this.state.height) { // ??? add to logic ??? width && width !== this.state.width
|
79
|
|
- enableAnimation && this.opacityAnimatedValue.setValue(0);
|
80
|
|
- this.setState({ height, width }, () => {
|
81
|
|
- enableAnimation
|
82
|
|
- ? Animated.timing(this.opacityAnimatedValue, {
|
83
|
|
- toValue: 1,
|
84
|
|
- duration: animationDuration
|
85
|
|
- }).start(() => onHeightWidthUpdated(height, width, this.props))
|
86
|
|
- : onHeightWidthUpdated(height, width, this.props);
|
87
|
|
- });
|
|
71
|
+ handleNavigationStateChange = navState => {
|
|
72
|
+ const { title } = navState;
|
|
73
|
+ if (!title) {
|
|
74
|
+ return;
|
|
75
|
+ }
|
|
76
|
+ const [heightValue, widthValue] = title.split(',');
|
|
77
|
+ const width = Number(widthValue);
|
|
78
|
+ const height = Number(heightValue);
|
|
79
|
+ const { height: oldHeight, width: oldWidth } = this.state;
|
|
80
|
+ if ((height && height !== oldHeight) || (width && width !== oldWidth)) {
|
|
81
|
+ // if ((height && height !== oldHeight)) {
|
|
82
|
+ const { enableAnimation, animationDuration, onSizeUpdated } = this.props;
|
|
83
|
+ enableAnimation && this.opacityAnimatedValue.setValue(0);
|
|
84
|
+ this.setState(
|
|
85
|
+ {
|
|
86
|
+ height,
|
|
87
|
+ width
|
|
88
|
+ },
|
|
89
|
+ () => {
|
|
90
|
+ enableAnimation
|
|
91
|
+ ? Animated.timing(this.opacityAnimatedValue, {
|
|
92
|
+ toValue: 1,
|
|
93
|
+ duration: animationDuration
|
|
94
|
+ }).start(() => handleSizeUpdated(height, width, onSizeUpdated))
|
|
95
|
+ : handleSizeUpdated(height, width, onSizeUpdated);
|
88
|
96
|
}
|
|
97
|
+ );
|
|
98
|
+ }
|
89
|
99
|
};
|
90
|
100
|
|
91
|
101
|
getWebView = webView => (this.webView = webView);
|
|
@@ -106,9 +116,9 @@ export default class AutoHeightWebView extends PureComponent {
|
106
|
116
|
enableAnimation,
|
107
|
117
|
source,
|
108
|
118
|
heightOffset,
|
109
|
|
- widthOffset,
|
110
|
119
|
customScript,
|
111
|
|
- style
|
|
120
|
+ style,
|
|
121
|
+ scrollEnabled
|
112
|
122
|
} = this.props;
|
113
|
123
|
const webViewSource = Object.assign({}, source, { baseUrl: 'web/' });
|
114
|
124
|
return (
|
|
@@ -117,8 +127,8 @@ export default class AutoHeightWebView extends PureComponent {
|
117
|
127
|
styles.container,
|
118
|
128
|
{
|
119
|
129
|
opacity: enableAnimation ? this.opacityAnimatedValue : 1,
|
120
|
|
- height: height + heightOffset,
|
121
|
|
- width: width + widthOffset
|
|
130
|
+ width,
|
|
131
|
+ height: height + heightOffset
|
122
|
132
|
},
|
123
|
133
|
style
|
124
|
134
|
]}
|
|
@@ -132,7 +142,7 @@ export default class AutoHeightWebView extends PureComponent {
|
132
|
142
|
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
133
|
143
|
style={styles.webView}
|
134
|
144
|
injectedJavaScript={script + customScript}
|
135
|
|
- scrollEnabled={false}
|
|
145
|
+ scrollEnabled={scrollEnabled}
|
136
|
146
|
scalesPageToFit={scalesPageToFit}
|
137
|
147
|
source={webViewSource}
|
138
|
148
|
onNavigationStateChange={this.handleNavigationStateChange}
|
|
@@ -158,41 +168,37 @@ const commonScript = `
|
158
|
168
|
window.addEventListener('resize', updateSize);
|
159
|
169
|
`;
|
160
|
170
|
|
161
|
|
-const _getter = `
|
162
|
|
- function getHeight(height) {
|
163
|
|
- if(height < 1) {
|
164
|
|
- return document.body.offsetHeight;
|
165
|
|
- }
|
166
|
|
- return height;
|
167
|
|
- }
|
168
|
|
- function getWidth(width) {
|
169
|
|
- if(width < 1) {
|
170
|
|
- return document.body.clientWidth; // maybe should be .offsetWidth ??
|
171
|
|
- }
|
172
|
|
- return width;
|
|
171
|
+const getSize = `
|
|
172
|
+ function getSize(container) {
|
|
173
|
+ var height = container.clientHeight || document.body.offsetHeight;
|
|
174
|
+ var width = container.clientWidth || document.body.offsetWidth;
|
|
175
|
+ return {
|
|
176
|
+ height,
|
|
177
|
+ width
|
|
178
|
+ };
|
173
|
179
|
}
|
174
|
180
|
`;
|
175
|
|
-const baseScript = `
|
|
181
|
+
|
|
182
|
+function getBaseScript(style) {
|
|
183
|
+ return `
|
176
|
184
|
;
|
177
|
|
- ${_getter}
|
|
185
|
+ ${getSize}
|
178
|
186
|
(function () {
|
179
|
187
|
var i = 0;
|
180
|
188
|
var height = 0;
|
181
|
|
- var width = ${screenWidth};
|
|
189
|
+ var width = ${getWidth(style)};
|
182
|
190
|
var wrapper = document.createElement('div');
|
183
|
|
- wrapper.id = 'height-wrapper';
|
|
191
|
+ wrapper.id = 'rnahw-wrapper';
|
184
|
192
|
while (document.body.firstChild instanceof Node) {
|
185
|
193
|
wrapper.appendChild(document.body.firstChild);
|
186
|
194
|
}
|
187
|
195
|
document.body.appendChild(wrapper);
|
188
|
196
|
function updateSize() {
|
189
|
|
- var rect = document.body.firstElementChild.getBoundingClientRect().toJSON();
|
190
|
|
- var newWidth = Math.round(rect.width);
|
191
|
|
- var newHeight = Math.round(rect.height);
|
192
|
|
- if(newHeight !== height) {
|
193
|
|
- //height = getHeight(wrapper.clientHeight);
|
194
|
|
- //width = getWidth(wrapper.clientWidth);
|
195
|
|
- document.title = newWidth + ',' + newHeight;
|
|
197
|
+ if(document.body.offsetHeight !== height || document.body.offsetWidth !== width) {
|
|
198
|
+ var size = getSize(wrapper);
|
|
199
|
+ height = size.height;
|
|
200
|
+ width = size.width;
|
|
201
|
+ document.title = height.toString() + ',' + width.toString();
|
196
|
202
|
window.location.hash = ++i;
|
197
|
203
|
}
|
198
|
204
|
}
|
|
@@ -200,22 +206,22 @@ const baseScript = `
|
200
|
206
|
${domMutationObserveScript}
|
201
|
207
|
} ());
|
202
|
208
|
`;
|
|
209
|
+}
|
203
|
210
|
|
204
|
|
-const iframeBaseScript = `
|
|
211
|
+function getIframeBaseScript(style) {
|
|
212
|
+ return `
|
205
|
213
|
;
|
206
|
|
- ${_getter}
|
|
214
|
+ ${getSize}
|
207
|
215
|
(function () {
|
208
|
216
|
var i = 0;
|
209
|
217
|
var height = 0;
|
210
|
|
- var width = ${screenWidth};
|
|
218
|
+ var width = ${getWidth(style)};
|
211
|
219
|
function updateSize() {
|
212
|
|
- var rect = document.body.firstElementChild.getBoundingClientRect().toJSON();
|
213
|
|
- var newWidth = Math.round(rect.width);
|
214
|
|
- var newHeight = Math.round(rect.height);
|
215
|
|
- if(newHeight !== height) {
|
216
|
|
- //height = getHeight(document.body.firstChild.clientHeight);
|
217
|
|
- //width = getWidth(document.body.firstChild.clientHeight);
|
218
|
|
- document.title = newWidth + ',' + newHeight;
|
|
220
|
+ if(document.body.offsetHeight !== height || document.body.offsetWidth !== width) {
|
|
221
|
+ var size = getSize(document.body.firstChild);
|
|
222
|
+ height = size.height;
|
|
223
|
+ width = size.width;
|
|
224
|
+ document.title = height.toString() + ',' + width.toString();
|
219
|
225
|
window.location.hash = ++i;
|
220
|
226
|
}
|
221
|
227
|
}
|
|
@@ -223,3 +229,4 @@ const iframeBaseScript = `
|
223
|
229
|
${domMutationObserveScript}
|
224
|
230
|
} ());
|
225
|
231
|
`;
|
|
232
|
+}
|