mirror of
https://github.com/status-im/react-native.git
synced 2025-01-10 01:25:39 +00:00
4b97137eee
Summary:PR for https://github.com/facebook/react-native/issues/5958. The viewport meta tags if present, are overridden from the page and it is rendered according to the screen size. An example has been added in the Web View section of UIExplorer demo app. Closes https://github.com/facebook/react-native/pull/6013 Differential Revision: D2953940 Pulled By: nicklockwood fb-gh-sync-id: 012769f3a2a3f7dc942b60de02a9d1b80a27236e shipit-source-id: 012769f3a2a3f7dc942b60de02a9d1b80a27236e
394 lines
9.0 KiB
JavaScript
394 lines
9.0 KiB
JavaScript
/**
|
|
* The examples provided by Facebook are for non-commercial testing and
|
|
* evaluation purposes only.
|
|
*
|
|
* Facebook reserves all rights not expressly granted.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
|
|
* FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* @flow
|
|
*/
|
|
'use strict';
|
|
|
|
var React = require('react-native');
|
|
var {
|
|
StyleSheet,
|
|
Text,
|
|
TextInput,
|
|
TouchableWithoutFeedback,
|
|
TouchableOpacity,
|
|
View,
|
|
WebView
|
|
} = React;
|
|
|
|
var HEADER = '#3b5998';
|
|
var BGWASH = 'rgba(255,255,255,0.8)';
|
|
var DISABLED_WASH = 'rgba(255,255,255,0.25)';
|
|
|
|
var TEXT_INPUT_REF = 'urlInput';
|
|
var WEBVIEW_REF = 'webview';
|
|
var DEFAULT_URL = 'https://m.facebook.com';
|
|
|
|
var WebViewExample = React.createClass({
|
|
|
|
getInitialState: function() {
|
|
return {
|
|
url: DEFAULT_URL,
|
|
status: 'No Page Loaded',
|
|
backButtonEnabled: false,
|
|
forwardButtonEnabled: false,
|
|
loading: true,
|
|
scalesPageToFit: true,
|
|
};
|
|
},
|
|
|
|
inputText: '',
|
|
|
|
handleTextInputChange: function(event) {
|
|
var url = event.nativeEvent.text;
|
|
if (!/^[a-zA-Z-_]+:/.test(url)) {
|
|
url = 'http://' + url;
|
|
}
|
|
this.inputText = url;
|
|
},
|
|
|
|
render: function() {
|
|
this.inputText = this.state.url;
|
|
|
|
return (
|
|
<View style={[styles.container]}>
|
|
<View style={[styles.addressBarRow]}>
|
|
<TouchableOpacity
|
|
onPress={this.goBack}
|
|
style={this.state.backButtonEnabled ? styles.navButton : styles.disabledButton}>
|
|
<Text>
|
|
{'<'}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
<TouchableOpacity
|
|
onPress={this.goForward}
|
|
style={this.state.forwardButtonEnabled ? styles.navButton : styles.disabledButton}>
|
|
<Text>
|
|
{'>'}
|
|
</Text>
|
|
</TouchableOpacity>
|
|
<TextInput
|
|
ref={TEXT_INPUT_REF}
|
|
autoCapitalize="none"
|
|
defaultValue={this.state.url}
|
|
onSubmitEditing={this.onSubmitEditing}
|
|
onChange={this.handleTextInputChange}
|
|
clearButtonMode="while-editing"
|
|
style={styles.addressBarTextInput}
|
|
/>
|
|
<TouchableOpacity onPress={this.pressGoButton}>
|
|
<View style={styles.goButton}>
|
|
<Text>
|
|
Go!
|
|
</Text>
|
|
</View>
|
|
</TouchableOpacity>
|
|
</View>
|
|
<WebView
|
|
ref={WEBVIEW_REF}
|
|
automaticallyAdjustContentInsets={false}
|
|
style={styles.webView}
|
|
source={{uri: this.state.url}}
|
|
javaScriptEnabled={true}
|
|
domStorageEnabled={true}
|
|
decelerationRate="normal"
|
|
onNavigationStateChange={this.onNavigationStateChange}
|
|
onShouldStartLoadWithRequest={this.onShouldStartLoadWithRequest}
|
|
startInLoadingState={true}
|
|
scalesPageToFit={this.state.scalesPageToFit}
|
|
/>
|
|
<View style={styles.statusBar}>
|
|
<Text style={styles.statusBarText}>{this.state.status}</Text>
|
|
</View>
|
|
</View>
|
|
);
|
|
},
|
|
|
|
goBack: function() {
|
|
this.refs[WEBVIEW_REF].goBack();
|
|
},
|
|
|
|
goForward: function() {
|
|
this.refs[WEBVIEW_REF].goForward();
|
|
},
|
|
|
|
reload: function() {
|
|
this.refs[WEBVIEW_REF].reload();
|
|
},
|
|
|
|
onShouldStartLoadWithRequest: function(event) {
|
|
// Implement any custom loading logic here, don't forget to return!
|
|
return true;
|
|
},
|
|
|
|
onNavigationStateChange: function(navState) {
|
|
this.setState({
|
|
backButtonEnabled: navState.canGoBack,
|
|
forwardButtonEnabled: navState.canGoForward,
|
|
url: navState.url,
|
|
status: navState.title,
|
|
loading: navState.loading,
|
|
scalesPageToFit: true
|
|
});
|
|
},
|
|
|
|
onSubmitEditing: function(event) {
|
|
this.pressGoButton();
|
|
},
|
|
|
|
pressGoButton: function() {
|
|
var url = this.inputText.toLowerCase();
|
|
if (url === this.state.url) {
|
|
this.reload();
|
|
} else {
|
|
this.setState({
|
|
url: url,
|
|
});
|
|
}
|
|
// dismiss keyboard
|
|
this.refs[TEXT_INPUT_REF].blur();
|
|
},
|
|
|
|
});
|
|
|
|
var Button = React.createClass({
|
|
_handlePress: function() {
|
|
if (this.props.enabled && this.props.onPress) {
|
|
this.props.onPress();
|
|
}
|
|
},
|
|
render: function() {
|
|
return (
|
|
<TouchableWithoutFeedback onPress={this._handlePress}>
|
|
<View style={[styles.button, this.props.enabled ? {} : styles.buttonDisabled]}>
|
|
<Text style={styles.buttonText}>{this.props.text}</Text>
|
|
</View>
|
|
</TouchableWithoutFeedback>
|
|
);
|
|
}
|
|
});
|
|
|
|
var ScaledWebView = React.createClass({
|
|
|
|
getInitialState: function() {
|
|
return {
|
|
scalingEnabled: true
|
|
}
|
|
},
|
|
|
|
render: function() {
|
|
return (
|
|
<View style={{height:120}}>
|
|
<WebView
|
|
style={{
|
|
backgroundColor: BGWASH,
|
|
height: 100,
|
|
}}
|
|
source={{html: HTML}}
|
|
scalesPageToFit={this.state.scalingEnabled}
|
|
/>
|
|
<View style={styles.buttons}>
|
|
{ this.state.scalingEnabled ?
|
|
<Button
|
|
text="Scaling:ON"
|
|
enabled={true}
|
|
onPress={() => this.setState({scalingEnabled: false})}
|
|
/> :
|
|
<Button
|
|
text="Scaling:OFF"
|
|
enabled={true}
|
|
onPress={() => this.setState({scalingEnabled: true})}
|
|
/> }
|
|
</View>
|
|
</View>
|
|
);
|
|
},
|
|
})
|
|
|
|
var styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
backgroundColor: HEADER,
|
|
},
|
|
addressBarRow: {
|
|
flexDirection: 'row',
|
|
padding: 8,
|
|
},
|
|
webView: {
|
|
backgroundColor: BGWASH,
|
|
height: 350,
|
|
},
|
|
addressBarTextInput: {
|
|
backgroundColor: BGWASH,
|
|
borderColor: 'transparent',
|
|
borderRadius: 3,
|
|
borderWidth: 1,
|
|
height: 24,
|
|
paddingLeft: 10,
|
|
paddingTop: 3,
|
|
paddingBottom: 3,
|
|
flex: 1,
|
|
fontSize: 14,
|
|
},
|
|
navButton: {
|
|
width: 20,
|
|
padding: 3,
|
|
marginRight: 3,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
backgroundColor: BGWASH,
|
|
borderColor: 'transparent',
|
|
borderRadius: 3,
|
|
},
|
|
disabledButton: {
|
|
width: 20,
|
|
padding: 3,
|
|
marginRight: 3,
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
backgroundColor: DISABLED_WASH,
|
|
borderColor: 'transparent',
|
|
borderRadius: 3,
|
|
},
|
|
goButton: {
|
|
height: 24,
|
|
padding: 3,
|
|
marginLeft: 8,
|
|
alignItems: 'center',
|
|
backgroundColor: BGWASH,
|
|
borderColor: 'transparent',
|
|
borderRadius: 3,
|
|
alignSelf: 'stretch',
|
|
},
|
|
statusBar: {
|
|
flexDirection: 'row',
|
|
alignItems: 'center',
|
|
paddingLeft: 5,
|
|
height: 22,
|
|
},
|
|
statusBarText: {
|
|
color: 'white',
|
|
fontSize: 13,
|
|
},
|
|
spinner: {
|
|
width: 20,
|
|
marginRight: 6,
|
|
},
|
|
buttons: {
|
|
flexDirection: 'row',
|
|
height: 30,
|
|
backgroundColor: 'black',
|
|
alignItems: 'center',
|
|
justifyContent: 'space-between',
|
|
},
|
|
button: {
|
|
flex: 0.5,
|
|
width: 0,
|
|
margin: 5,
|
|
borderColor: 'gray',
|
|
borderWidth: 1,
|
|
backgroundColor: 'gray',
|
|
},
|
|
});
|
|
|
|
const HTML = `
|
|
<!DOCTYPE html>\n
|
|
<html>
|
|
<head>
|
|
<title>Hello Static World</title>
|
|
<meta http-equiv="content-type" content="text/html; charset=utf-8">
|
|
<meta name="viewport" content="width=640, user-scalable=no">
|
|
<style type="text/css">
|
|
body {
|
|
margin: 0;
|
|
padding: 0;
|
|
font: 62.5% arial, sans-serif;
|
|
background: #ccc;
|
|
}
|
|
h1 {
|
|
padding: 45px;
|
|
margin: 0;
|
|
text-align: center;
|
|
color: #33f;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<h1>Hello Static World</h1>
|
|
</body>
|
|
</html>
|
|
`;
|
|
|
|
exports.displayName = (undefined: ?string);
|
|
exports.title = '<WebView>';
|
|
exports.description = 'Base component to display web content';
|
|
exports.examples = [
|
|
{
|
|
title: 'Simple Browser',
|
|
render(): ReactElement { return <WebViewExample />; }
|
|
},
|
|
{
|
|
title: 'Bundled HTML',
|
|
render(): ReactElement {
|
|
return (
|
|
<WebView
|
|
style={{
|
|
backgroundColor: BGWASH,
|
|
height: 100,
|
|
}}
|
|
source={require('./helloworld.html')}
|
|
scalesPageToFit={true}
|
|
/>
|
|
);
|
|
}
|
|
},
|
|
{
|
|
title: 'Static HTML',
|
|
render(): ReactElement {
|
|
return (
|
|
<WebView
|
|
style={{
|
|
backgroundColor: BGWASH,
|
|
height: 100,
|
|
}}
|
|
source={{html: HTML}}
|
|
scalesPageToFit={true}
|
|
/>
|
|
);
|
|
}
|
|
},
|
|
{
|
|
title: 'Scale Page to Fit',
|
|
render(): ReactElement { return <ScaledWebView/>; }
|
|
},
|
|
{
|
|
title: 'POST Test',
|
|
render(): ReactElement {
|
|
return (
|
|
<WebView
|
|
style={{
|
|
backgroundColor: BGWASH,
|
|
height: 100,
|
|
}}
|
|
source={{
|
|
uri: 'http://www.posttestserver.com/post.php',
|
|
method: 'POST',
|
|
body: 'foo=bar&bar=foo'
|
|
}}
|
|
scalesPageToFit={false}
|
|
/>
|
|
);
|
|
}
|
|
}
|
|
];
|