mirror of
https://github.com/status-im/react-native.git
synced 2025-01-10 01:25:39 +00:00
0a290e22da
Summary: public Original github title: Exported a callback for native webview delegate method shouldStartLoadWithRequest We have a requirement in our app, to open in mobile Safari, any http:// and https:// links displayed in a web view. Our web view is not full screen and is loaded with an HTML string from the backend. Displaying external content in that web view is outside of the scope of our app, so we open them in mobile Safari. I've forked the WebView component and added a callback property, shouldStartLoadWithRequest, and modified the RCTWebView implementation of `webView:shouldStartLoadWithRequest:navigationType:` to check if the shouldStartLoadWithRequest property is set. If the property is set, `webView:shouldStartLoadWithRequest:navigationType:` passes the URL & navigationType to the callback. The callback is then able to ignore the request, redirect it, open a full screen web view to display the URL content, or even deep link to another app with LinkingIOS.openURL(). Original author: PJ Cabrera <pj.cabrera@gmail.com> Closes https://github.com/facebook/react-native/pull/3643 Reviewed By: nicklockwood Differential Revision: D2600371 fb-gh-sync-id: 14dfdb3df442d899d9f2af831bbc8d695faefa33
237 lines
5.6 KiB
JavaScript
237 lines
5.6 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,
|
|
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) {
|
|
this.inputText = event.nativeEvent.text;
|
|
},
|
|
|
|
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}
|
|
url={this.state.url}
|
|
javaScriptEnabledAndroid={true}
|
|
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 keyoard
|
|
this.refs[TEXT_INPUT_REF].blur();
|
|
},
|
|
|
|
});
|
|
|
|
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,
|
|
},
|
|
});
|
|
|
|
exports.displayName = (undefined: ?string);
|
|
exports.title = '<WebView>';
|
|
exports.description = 'Base component to display web content';
|
|
exports.examples = [
|
|
{
|
|
title: 'WebView',
|
|
render(): ReactElement { return <WebViewExample />; }
|
|
}
|
|
];
|