123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 |
- /**
- * Copyright (c) 2018-present, Infinite Red, Inc.
- *
- * This source code is licensed under the MIT license found in the
- * LICENSE file in the root directory of this source tree.
- *
- * @format
- * @flow
- */
-
- 'use strict';
-
- var React = require('react');
- var ReactNative = require('react-native');
- var {
- StyleSheet,
- Text,
- TextInput,
- TouchableWithoutFeedback,
- TouchableOpacity,
- View,
- WebView,
- } = ReactNative;
-
- 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';
- const FILE_SYSTEM_ORIGIN_WHITE_LIST = ['file://*', 'http://*', 'https://*'];
-
- class WebViewExample extends React.Component<{}, $FlowFixMeState> {
- state = {
- url: DEFAULT_URL,
- status: 'No Page Loaded',
- backButtonEnabled: false,
- forwardButtonEnabled: false,
- loading: true,
- scalesPageToFit: true,
- };
-
- inputText = '';
-
- handleTextInputChange = event => {
- var url = event.nativeEvent.text;
- if (!/^[a-zA-Z-_]+:/.test(url)) {
- url = 'http://' + url;
- }
- this.inputText = url;
- };
-
- render() {
- 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 = () => {
- this.refs[WEBVIEW_REF].goBack();
- };
-
- goForward = () => {
- this.refs[WEBVIEW_REF].goForward();
- };
-
- reload = () => {
- this.refs[WEBVIEW_REF].reload();
- };
-
- onShouldStartLoadWithRequest = event => {
- // Implement any custom loading logic here, don't forget to return!
- return true;
- };
-
- onNavigationStateChange = navState => {
- this.setState({
- backButtonEnabled: navState.canGoBack,
- forwardButtonEnabled: navState.canGoForward,
- url: navState.url,
- status: navState.title,
- loading: navState.loading,
- scalesPageToFit: true,
- });
- };
-
- onSubmitEditing = event => {
- this.pressGoButton();
- };
-
- pressGoButton = () => {
- 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();
- };
- }
-
- class Button extends React.Component<$FlowFixMeProps> {
- _handlePress = () => {
- if (this.props.enabled !== false && this.props.onPress) {
- this.props.onPress();
- }
- };
-
- render() {
- return (
- <TouchableWithoutFeedback onPress={this._handlePress}>
- <View style={styles.button}>
- <Text>{this.props.text}</Text>
- </View>
- </TouchableWithoutFeedback>
- );
- }
- }
-
- class ScaledWebView extends React.Component<{}, $FlowFixMeState> {
- state = {
- scalingEnabled: true,
- };
-
- render() {
- return (
- <View>
- <WebView
- style={{
- backgroundColor: BGWASH,
- height: 200,
- }}
- source={{ uri: 'https://facebook.github.io/react/' }}
- 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>
- );
- }
- }
-
- class MessagingTest extends React.Component<{}, $FlowFixMeState> {
- webview = null;
-
- state = {
- messagesReceivedFromWebView: 0,
- message: '',
- };
-
- onMessage = e =>
- this.setState({
- messagesReceivedFromWebView: this.state.messagesReceivedFromWebView + 1,
- message: e.nativeEvent.data,
- });
-
- postMessage = () => {
- if (this.webview) {
- this.webview.postMessage('"Hello" from React Native!');
- }
- };
-
- render(): React.Node {
- const { messagesReceivedFromWebView, message } = this.state;
-
- return (
- <View style={[styles.container, { height: 200 }]}>
- <View style={styles.container}>
- <Text>
- Messages received from web view: {messagesReceivedFromWebView}
- </Text>
- <Text>{message || '(No message)'}</Text>
- <View style={styles.buttons}>
- <Button
- text="Send Message to Web View"
- enabled
- onPress={this.postMessage}
- />
- </View>
- </View>
- <View style={styles.container}>
- <WebView
- ref={webview => {
- this.webview = webview;
- }}
- style={{
- backgroundColor: BGWASH,
- height: 100,
- }}
- originWhitelist={FILE_SYSTEM_ORIGIN_WHITE_LIST}
- source={require('./messagingtest.html')}
- onMessage={this.onMessage}
- />
- </View>
- </View>
- );
- }
- }
-
- class InjectJS extends React.Component<{}> {
- webview = null;
- injectJS = () => {
- const script = 'document.write("Injected JS ")';
- if (this.webview) {
- this.webview.injectJavaScript(script);
- }
- };
- render() {
- return (
- <View>
- <WebView
- ref={webview => {
- this.webview = webview;
- }}
- style={{
- backgroundColor: BGWASH,
- height: 300,
- }}
- source={{ uri: 'https://www.facebook.com' }}
- scalesPageToFit={true}
- />
- <View style={styles.buttons}>
- <Button text="Inject JS" enabled onPress={this.injectJS} />
- </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=320, 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(): React.Element<any> {
- return <WebViewExample />;
- },
- },
- {
- title: 'Scale Page to Fit',
- render(): React.Element<any> {
- return <ScaledWebView />;
- },
- },
- {
- title: 'Bundled HTML',
- render(): React.Element<any> {
- return (
- <WebView
- style={{
- backgroundColor: BGWASH,
- height: 100,
- }}
- originWhitelist={FILE_SYSTEM_ORIGIN_WHITE_LIST}
- source={require('./helloworld.html')}
- scalesPageToFit={true}
- />
- );
- },
- },
- {
- title: 'Static HTML',
- render(): React.Element<any> {
- return (
- <WebView
- style={{
- backgroundColor: BGWASH,
- height: 100,
- }}
- source={{ html: HTML }}
- scalesPageToFit={true}
- />
- );
- },
- },
- {
- title: 'POST Test',
- render(): React.Element<any> {
- return (
- <WebView
- style={{
- backgroundColor: BGWASH,
- height: 100,
- }}
- source={{
- uri: 'http://www.posttestserver.com/post.php',
- method: 'POST',
- body: 'foo=bar&bar=foo',
- }}
- scalesPageToFit={false}
- />
- );
- },
- },
- {
- title: 'Messaging Test',
- render(): React.Element<any> {
- return <MessagingTest />;
- },
- },
- {
- title: 'Inject JavaScript',
- render(): React.Element<any> {
- return <InjectJS />;
- },
- },
- ];
|