mirror of
https://github.com/status-im/react-native-webview.git
synced 2025-02-22 16:58:34 +00:00
feat(Android Webview): Support onShouldStartLoadWithRequest on Android (#107)
This PR adds support for `onShouldStartLoadWithRequest` on android. The initial PR was #59 The issue for this PR is: #106 fixes #106
This commit is contained in:
parent
48230e4dcf
commit
b1b662628e
@ -48,6 +48,7 @@ android {
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
jcenter()
|
||||
maven {
|
||||
url 'https://maven.google.com/'
|
||||
name 'Google'
|
||||
|
@ -30,6 +30,7 @@ import android.webkit.GeolocationPermissions;
|
||||
import android.webkit.JavascriptInterface;
|
||||
import android.webkit.ValueCallback;
|
||||
import android.webkit.WebChromeClient;
|
||||
import android.webkit.WebResourceRequest;
|
||||
import android.webkit.WebSettings;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
@ -51,11 +52,19 @@ import com.facebook.react.uimanager.annotations.ReactProp;
|
||||
import com.facebook.react.uimanager.events.ContentSizeChangeEvent;
|
||||
import com.facebook.react.uimanager.events.Event;
|
||||
import com.facebook.react.uimanager.events.EventDispatcher;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
import com.reactnativecommunity.webview.events.TopLoadingErrorEvent;
|
||||
import com.reactnativecommunity.webview.events.TopLoadingFinishEvent;
|
||||
import com.reactnativecommunity.webview.events.TopLoadingStartEvent;
|
||||
import com.reactnativecommunity.webview.events.TopMessageEvent;
|
||||
import com.reactnativecommunity.webview.events.TopLoadingProgressEvent;
|
||||
import com.reactnativecommunity.webview.events.TopShouldStartLoadWithRequestEvent;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@ -66,12 +75,14 @@ import org.json.JSONObject;
|
||||
* - GO_BACK
|
||||
* - GO_FORWARD
|
||||
* - RELOAD
|
||||
* - LOAD_URL
|
||||
*
|
||||
* {@link WebView} instances could emit following direct events:
|
||||
* - topLoadingFinish
|
||||
* - topLoadingStart
|
||||
* - topLoadingStart
|
||||
* - topLoadingProgress
|
||||
* - topShouldStartLoadWithRequest
|
||||
*
|
||||
* Each event will carry the following properties:
|
||||
* - target - view's react tag
|
||||
@ -99,6 +110,7 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||
public static final int COMMAND_STOP_LOADING = 4;
|
||||
public static final int COMMAND_POST_MESSAGE = 5;
|
||||
public static final int COMMAND_INJECT_JAVASCRIPT = 6;
|
||||
public static final int COMMAND_LOAD_URL = 7;
|
||||
|
||||
// Use `webView.loadUrl("about:blank")` to reliably reset the view
|
||||
// state and release page resources (including any running JavaScript).
|
||||
@ -111,7 +123,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||
|
||||
protected boolean mLastLoadFailed = false;
|
||||
protected @Nullable ReadableArray mUrlPrefixesForDefaultIntent;
|
||||
protected @Nullable List<Pattern> mOriginWhitelist;
|
||||
|
||||
@Override
|
||||
public void onPageFinished(WebView webView, String url) {
|
||||
@ -139,50 +150,16 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, String url) {
|
||||
if (url.equals(BLANK_URL)) return false;
|
||||
|
||||
// url blacklisting
|
||||
if (mUrlPrefixesForDefaultIntent != null && mUrlPrefixesForDefaultIntent.size() > 0) {
|
||||
ArrayList<Object> urlPrefixesForDefaultIntent =
|
||||
mUrlPrefixesForDefaultIntent.toArrayList();
|
||||
for (Object urlPrefix : urlPrefixesForDefaultIntent) {
|
||||
if (url.startsWith((String) urlPrefix)) {
|
||||
launchIntent(view.getContext(), url);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mOriginWhitelist != null && shouldHandleURL(mOriginWhitelist, url)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
launchIntent(view.getContext(), url);
|
||||
dispatchEvent(view, new TopShouldStartLoadWithRequestEvent(view.getId(), url));
|
||||
return true;
|
||||
}
|
||||
|
||||
private void launchIntent(Context context, String url) {
|
||||
try {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.addCategory(Intent.CATEGORY_BROWSABLE);
|
||||
context.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
FLog.w(ReactConstants.TAG, "activity not found to handle uri scheme for: " + url, e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldHandleURL(List<Pattern> originWhitelist, String url) {
|
||||
Uri uri = Uri.parse(url);
|
||||
String scheme = uri.getScheme() != null ? uri.getScheme() : "";
|
||||
String authority = uri.getAuthority() != null ? uri.getAuthority() : "";
|
||||
String urlToCheck = scheme + "://" + authority;
|
||||
for (Pattern pattern : originWhitelist) {
|
||||
if (pattern.matcher(urlToCheck).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@TargetApi(Build.VERSION_CODES.N)
|
||||
@Override
|
||||
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
|
||||
dispatchEvent(view, new TopShouldStartLoadWithRequestEvent(view.getId(), request.getUrl().toString()));
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -231,10 +208,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||
public void setUrlPrefixesForDefaultIntent(ReadableArray specialUrls) {
|
||||
mUrlPrefixesForDefaultIntent = specialUrls;
|
||||
}
|
||||
|
||||
public void setOriginWhitelist(List<Pattern> originWhitelist) {
|
||||
mOriginWhitelist = originWhitelist;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -656,20 +629,6 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||
view.getSettings().setGeolocationEnabled(isGeolocationEnabled != null && isGeolocationEnabled);
|
||||
}
|
||||
|
||||
@ReactProp(name = "originWhitelist")
|
||||
public void setOriginWhitelist(
|
||||
WebView view,
|
||||
@Nullable ReadableArray originWhitelist) {
|
||||
RNCWebViewClient client = ((RNCWebView) view).getRNCWebViewClient();
|
||||
if (client != null && originWhitelist != null) {
|
||||
List<Pattern> whiteList = new LinkedList<>();
|
||||
for (int i = 0 ; i < originWhitelist.size() ; i++) {
|
||||
whiteList.add(Pattern.compile(originWhitelist.getString(i)));
|
||||
}
|
||||
client.setOriginWhitelist(whiteList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addEventEmitters(ThemedReactContext reactContext, WebView view) {
|
||||
// Do not register default touch emitter and let WebView implementation handle touches
|
||||
@ -678,9 +637,13 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||
|
||||
@Override
|
||||
public Map getExportedCustomDirectEventTypeConstants() {
|
||||
MapBuilder.Builder builder = MapBuilder.builder();
|
||||
builder.put("topLoadingProgress", MapBuilder.of("registrationName", "onLoadingProgress"));
|
||||
return builder.build();
|
||||
Map export = super.getExportedCustomDirectEventTypeConstants();
|
||||
if (export == null) {
|
||||
export = MapBuilder.newHashMap();
|
||||
}
|
||||
export.put(TopLoadingProgressEvent.EVENT_NAME, MapBuilder.of("registrationName", "onLoadingProgress"));
|
||||
export.put(TopShouldStartLoadWithRequestEvent.EVENT_NAME, MapBuilder.of("registrationName", "onShouldStartLoadWithRequest"));
|
||||
return export;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -691,7 +654,8 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||
"reload", COMMAND_RELOAD,
|
||||
"stopLoading", COMMAND_STOP_LOADING,
|
||||
"postMessage", COMMAND_POST_MESSAGE,
|
||||
"injectJavaScript", COMMAND_INJECT_JAVASCRIPT
|
||||
"injectJavaScript", COMMAND_INJECT_JAVASCRIPT,
|
||||
"loadUrl", COMMAND_LOAD_URL
|
||||
);
|
||||
}
|
||||
|
||||
@ -734,6 +698,12 @@ public class RNCWebViewManager extends SimpleViewManager<WebView> {
|
||||
RNCWebView reactWebView = (RNCWebView) root;
|
||||
reactWebView.evaluateJavascriptWithFallback(args.getString(0));
|
||||
break;
|
||||
case COMMAND_LOAD_URL:
|
||||
if (args == null) {
|
||||
throw new RuntimeException("Arguments for loading an url are null!");
|
||||
}
|
||||
root.loadUrl(args.getString(0));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
package com.reactnativecommunity.webview.events;
|
||||
|
||||
import com.facebook.react.bridge.Arguments;
|
||||
import com.facebook.react.bridge.WritableMap;
|
||||
import com.facebook.react.uimanager.events.Event;
|
||||
import com.facebook.react.uimanager.events.RCTEventEmitter;
|
||||
|
||||
public class TopShouldStartLoadWithRequestEvent extends Event<TopMessageEvent> {
|
||||
public static final String EVENT_NAME = "topShouldStartLoadWithRequest";
|
||||
private final String mUrl;
|
||||
|
||||
public TopShouldStartLoadWithRequestEvent(int viewId, String url) {
|
||||
super(viewId);
|
||||
mUrl = url;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEventName() {
|
||||
return EVENT_NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canCoalesce() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public short getCoalescingKey() {
|
||||
// All events for a given view can be coalesced.
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispatch(RCTEventEmitter rctEventEmitter) {
|
||||
WritableMap data = Arguments.createMap();
|
||||
data.putString("url", mUrl);
|
||||
data.putString("navigationType", "other");
|
||||
rctEventEmitter.receiveEvent(getViewTag(), EVENT_NAME, data);
|
||||
}
|
||||
}
|
@ -8,35 +8,33 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
|
||||
import ReactNative from 'react-native';
|
||||
import {
|
||||
import ReactNative, {
|
||||
ActivityIndicator,
|
||||
Image,
|
||||
requireNativeComponent,
|
||||
StyleSheet,
|
||||
UIManager,
|
||||
View,
|
||||
Image,
|
||||
requireNativeComponent,
|
||||
NativeModules
|
||||
} from 'react-native';
|
||||
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import keyMirror from 'fbjs/lib/keyMirror';
|
||||
|
||||
import WebViewShared from './WebViewShared';
|
||||
import {
|
||||
defaultOriginWhitelist,
|
||||
createOnShouldStartLoadWithRequest,
|
||||
} from './WebViewShared';
|
||||
import type {
|
||||
WebViewEvent,
|
||||
WebViewError,
|
||||
WebViewErrorEvent,
|
||||
WebViewMessageEvent,
|
||||
WebViewNavigation,
|
||||
WebViewNavigationEvent,
|
||||
WebViewProgressEvent,
|
||||
WebViewSharedProps,
|
||||
WebViewSource,
|
||||
WebViewProgressEvent,
|
||||
} from './WebViewTypes';
|
||||
|
||||
const resolveAssetSource = Image.resolveAssetSource;
|
||||
@ -69,7 +67,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
scalesPageToFit: true,
|
||||
allowFileAccess: false,
|
||||
saveFormDataDisabled: false,
|
||||
originWhitelist: WebViewShared.defaultOriginWhitelist,
|
||||
originWhitelist: defaultOriginWhitelist,
|
||||
};
|
||||
|
||||
static isFileUploadSupported = async () => {
|
||||
@ -78,7 +76,9 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
}
|
||||
|
||||
state = {
|
||||
viewState: this.props.startInLoadingState ? WebViewState.LOADING : WebViewState.IDLE,
|
||||
viewState: this.props.startInLoadingState
|
||||
? WebViewState.LOADING
|
||||
: WebViewState.IDLE,
|
||||
lastErrorEvent: null,
|
||||
};
|
||||
|
||||
@ -131,12 +131,14 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
|
||||
const nativeConfig = this.props.nativeConfig || {};
|
||||
|
||||
const originWhitelist = (this.props.originWhitelist || []).map(
|
||||
WebViewShared.originWhitelistToRegex,
|
||||
);
|
||||
|
||||
let NativeWebView = nativeConfig.component || RNCWebView;
|
||||
|
||||
const onShouldStartLoadWithRequest = createOnShouldStartLoadWithRequest(
|
||||
this.onShouldStartLoadWithRequestCallback,
|
||||
this.props.originWhitelist,
|
||||
this.props.onShouldStartLoadWithRequest,
|
||||
);
|
||||
|
||||
const webView = (
|
||||
<NativeWebView
|
||||
ref={this.webViewRef}
|
||||
@ -157,6 +159,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
automaticallyAdjustContentInsets={
|
||||
this.props.automaticallyAdjustContentInsets
|
||||
}
|
||||
onShouldStartLoadWithRequest={onShouldStartLoadWithRequest}
|
||||
onContentSizeChange={this.props.onContentSizeChange}
|
||||
onLoadingStart={this.onLoadingStart}
|
||||
onLoadingFinish={this.onLoadingFinish}
|
||||
@ -170,7 +173,6 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
allowUniversalAccessFromFileURLs={
|
||||
this.props.allowUniversalAccessFromFileURLs
|
||||
}
|
||||
originWhitelist={originWhitelist}
|
||||
mixedContentMode={this.props.mixedContentMode}
|
||||
saveFormDataDisabled={this.props.saveFormDataDisabled}
|
||||
urlPrefixesForDefaultIntent={this.props.urlPrefixesForDefaultIntent}
|
||||
@ -290,11 +292,24 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
const { onMessage } = this.props;
|
||||
onMessage && onMessage(event);
|
||||
};
|
||||
|
||||
|
||||
onLoadingProgress = (event: WebViewProgressEvent) => {
|
||||
const { onLoadProgress} = this.props;
|
||||
const { onLoadProgress } = this.props;
|
||||
onLoadProgress && onLoadProgress(event);
|
||||
}
|
||||
};
|
||||
|
||||
onShouldStartLoadWithRequestCallback = (
|
||||
shouldStart: boolean,
|
||||
url: string,
|
||||
) => {
|
||||
if (shouldStart) {
|
||||
UIManager.dispatchViewManagerCommand(
|
||||
this.getWebViewHandle(),
|
||||
UIManager.RNCWebView.Commands.loadUrl,
|
||||
[String(url)],
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
const RNCWebView = requireNativeComponent('RNCWebView');
|
||||
|
@ -25,7 +25,10 @@ import {
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
import keyMirror from 'fbjs/lib/keyMirror';
|
||||
|
||||
import WebViewShared from './WebViewShared';
|
||||
import {
|
||||
defaultOriginWhitelist,
|
||||
createOnShouldStartLoadWithRequest,
|
||||
} from './WebViewShared';
|
||||
import type {
|
||||
WebViewEvent,
|
||||
WebViewError,
|
||||
@ -130,7 +133,7 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
|
||||
static defaultProps = {
|
||||
useWebKit: true,
|
||||
originWhitelist: WebViewShared.defaultOriginWhitelist,
|
||||
originWhitelist: defaultOriginWhitelist,
|
||||
};
|
||||
|
||||
static isFileUploadSupported = async () => {
|
||||
@ -204,40 +207,11 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
|
||||
const nativeConfig = this.props.nativeConfig || {};
|
||||
|
||||
let viewManager = nativeConfig.viewManager;
|
||||
|
||||
if (this.props.useWebKit) {
|
||||
viewManager = viewManager || RNCWKWebViewManager;
|
||||
} else {
|
||||
viewManager = viewManager || RNCUIWebViewManager;
|
||||
}
|
||||
|
||||
const compiledWhitelist = [
|
||||
'about:blank',
|
||||
...(this.props.originWhitelist || []),
|
||||
].map(WebViewShared.originWhitelistToRegex);
|
||||
const onShouldStartLoadWithRequest = event => {
|
||||
let shouldStart = true;
|
||||
const { url } = event.nativeEvent;
|
||||
const origin = WebViewShared.extractOrigin(url);
|
||||
const passesWhitelist = compiledWhitelist.some(x =>
|
||||
new RegExp(x).test(origin),
|
||||
);
|
||||
shouldStart = shouldStart && passesWhitelist;
|
||||
if (!passesWhitelist) {
|
||||
Linking.openURL(url);
|
||||
}
|
||||
if (this.props.onShouldStartLoadWithRequest) {
|
||||
shouldStart =
|
||||
shouldStart &&
|
||||
this.props.onShouldStartLoadWithRequest(event.nativeEvent);
|
||||
}
|
||||
invariant(viewManager != null, 'viewManager expected to be non-null');
|
||||
viewManager.startLoadWithResult(
|
||||
!!shouldStart,
|
||||
event.nativeEvent.lockIdentifier,
|
||||
);
|
||||
};
|
||||
const onShouldStartLoadWithRequest = createOnShouldStartLoadWithRequest(
|
||||
this.onShouldStartLoadWithRequestCallback,
|
||||
this.props.originWhitelist,
|
||||
this.props.onShouldStartLoadWithRequest,
|
||||
);
|
||||
|
||||
const decelerationRate = processDecelerationRate(
|
||||
this.props.decelerationRate,
|
||||
@ -441,9 +415,25 @@ class WebView extends React.Component<WebViewSharedProps, State> {
|
||||
};
|
||||
|
||||
_onLoadingProgress = (event: WebViewProgressEvent) => {
|
||||
const {onLoadProgress} = this.props;
|
||||
const { onLoadProgress } = this.props;
|
||||
onLoadProgress && onLoadProgress(event);
|
||||
}
|
||||
};
|
||||
|
||||
onShouldStartLoadWithRequestCallback = (
|
||||
shouldStart: boolean,
|
||||
url: string,
|
||||
lockIdentifier: number,
|
||||
) => {
|
||||
let viewManager = (this.props.nativeConfig || {}).viewManager;
|
||||
|
||||
if (this.props.useWebKit) {
|
||||
viewManager = viewManager || RNCWKWebViewManager;
|
||||
} else {
|
||||
viewManager = viewManager || RNCUIWebViewManager;
|
||||
}
|
||||
invariant(viewManager != null, 'viewManager expected to be non-null');
|
||||
viewManager.startLoadWithResult(!!shouldStart, lockIdentifier);
|
||||
};
|
||||
|
||||
componentDidUpdate(prevProps: WebViewSharedProps) {
|
||||
if (!(prevProps.useWebKit && this.props.useWebKit)) {
|
||||
|
@ -8,19 +8,58 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
import escapeStringRegexp from 'escape-string-regexp';
|
||||
import { Linking } from 'react-native';
|
||||
import type {
|
||||
WebViewNavigationEvent,
|
||||
WebViewNavigation,
|
||||
OnShouldStartLoadWithRequest,
|
||||
} from './WebViewTypes';
|
||||
|
||||
const escapeStringRegexp = require('escape-string-regexp');
|
||||
const defaultOriginWhitelist = ['http://*', 'https://*'];
|
||||
|
||||
const WebViewShared = {
|
||||
defaultOriginWhitelist: ['http://*', 'https://*'],
|
||||
extractOrigin: (url: string): string => {
|
||||
const result = /^[A-Za-z0-9]+:(\/\/)?[^/]*/.exec(url);
|
||||
return result === null ? '' : result[0];
|
||||
},
|
||||
originWhitelistToRegex: (originWhitelist: string): string => {
|
||||
return escapeStringRegexp(originWhitelist).replace(/\\\*/g, '.*');
|
||||
},
|
||||
const extractOrigin = (url: string): string => {
|
||||
const result = /^[A-Za-z0-9]+:(\/\/)?[^/]*/.exec(url);
|
||||
return result === null ? '' : result[0];
|
||||
};
|
||||
|
||||
module.exports = WebViewShared;
|
||||
const originWhitelistToRegex = (originWhitelist: string): string =>
|
||||
escapeStringRegexp(originWhitelist).replace(/\\\*/g, '.*');
|
||||
|
||||
const passesWhitelist = (compiledWhitelist: Array<string>, url: string) => {
|
||||
const origin = extractOrigin(url);
|
||||
return compiledWhitelist.some(x => new RegExp(x).test(origin));
|
||||
};
|
||||
|
||||
const compileWhitelist = (
|
||||
originWhitelist: ?$ReadOnlyArray<string>,
|
||||
): Array<string> =>
|
||||
['about:blank', ...(originWhitelist || [])].map(originWhitelistToRegex);
|
||||
|
||||
const createOnShouldStartLoadWithRequest = (
|
||||
loadRequest: (
|
||||
shouldStart: boolean,
|
||||
url: string,
|
||||
lockIdentifier: number,
|
||||
) => void,
|
||||
originWhitelist: ?$ReadOnlyArray<string>,
|
||||
onShouldStartLoadWithRequest: ?OnShouldStartLoadWithRequest,
|
||||
) => {
|
||||
return ({ nativeEvent }: WebViewNavigationEvent) => {
|
||||
let shouldStart = true;
|
||||
const { url, lockIdentifier } = nativeEvent;
|
||||
|
||||
if (!passesWhitelist(compileWhitelist(originWhitelist), url)) {
|
||||
Linking.openURL(url);
|
||||
shouldStart = false
|
||||
}
|
||||
|
||||
if (onShouldStartLoadWithRequest) {
|
||||
shouldStart = onShouldStartLoadWithRequest(nativeEvent);
|
||||
}
|
||||
|
||||
loadRequest(shouldStart, url, lockIdentifier);
|
||||
};
|
||||
};
|
||||
|
||||
export { defaultOriginWhitelist, createOnShouldStartLoadWithRequest };
|
||||
|
@ -10,12 +10,12 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
import type {Node, Element, ComponentType} from 'react';
|
||||
import type { Node, Element, ComponentType } from 'react';
|
||||
|
||||
import type {SyntheticEvent} from 'CoreEventTypes';
|
||||
import type {EdgeInsetsProp} from 'EdgeInsetsPropType';
|
||||
import type {ViewStyleProp} from 'StyleSheet';
|
||||
import type {ViewProps} from 'ViewPropTypes';
|
||||
import type { SyntheticEvent } from 'CoreEventTypes';
|
||||
import type { EdgeInsetsProp } from 'EdgeInsetsPropType';
|
||||
import type { ViewStyleProp } from 'StyleSheet';
|
||||
import type { ViewProps } from 'ViewPropTypes';
|
||||
|
||||
export type WebViewNativeEvent = $ReadOnly<{|
|
||||
url: string,
|
||||
@ -23,12 +23,13 @@ export type WebViewNativeEvent = $ReadOnly<{|
|
||||
title: string,
|
||||
canGoBack: boolean,
|
||||
canGoForward: boolean,
|
||||
lockIdentifier: number,
|
||||
|}>;
|
||||
|
||||
export type WebViewProgressEvent = $ReadOnly<{|
|
||||
...WebViewNativeEvent,
|
||||
progress: number,
|
||||
|}>
|
||||
...WebViewNativeEvent,
|
||||
progress: number,
|
||||
|}>;
|
||||
|
||||
export type WebViewNavigation = $ReadOnly<{|
|
||||
...WebViewNativeEvent,
|
||||
@ -118,22 +119,26 @@ export type WebViewSourceHtml = $ReadOnly<{|
|
||||
export type WebViewSource = WebViewSourceUri | WebViewSourceHtml;
|
||||
|
||||
export type WebViewNativeConfig = $ReadOnly<{|
|
||||
/*
|
||||
/**
|
||||
* The native component used to render the WebView.
|
||||
*/
|
||||
component?: ComponentType<WebViewSharedProps>,
|
||||
/*
|
||||
/**
|
||||
* Set props directly on the native component WebView. Enables custom props which the
|
||||
* original WebView doesn't pass through.
|
||||
*/
|
||||
props?: ?Object,
|
||||
/*
|
||||
/**
|
||||
* Set the ViewManager to use for communication with the native side.
|
||||
* @platform ios
|
||||
*/
|
||||
viewManager?: ?Object,
|
||||
|}>;
|
||||
|
||||
export type OnShouldStartLoadWithRequest = (
|
||||
event: WebViewNavigation,
|
||||
) => boolean;
|
||||
|
||||
export type IOSWebViewProps = $ReadOnly<{|
|
||||
/**
|
||||
* If true, use WKWebView instead of UIWebView.
|
||||
@ -205,17 +210,7 @@ export type IOSWebViewProps = $ReadOnly<{|
|
||||
*
|
||||
* @platform ios
|
||||
*/
|
||||
dataDetectorTypes?:
|
||||
| ?DataDetectorTypes
|
||||
| $ReadOnlyArray<DataDetectorTypes>,
|
||||
|
||||
/**
|
||||
* Function that allows custom handling of any web view requests. Return
|
||||
* `true` from the function to continue loading the request and `false`
|
||||
* to stop loading.
|
||||
* @platform ios
|
||||
*/
|
||||
onShouldStartLoadWithRequest?: (event: WebViewEvent) => mixed,
|
||||
dataDetectorTypes?: ?DataDetectorTypes | $ReadOnlyArray<DataDetectorTypes>,
|
||||
|
||||
/**
|
||||
* Boolean that determines whether HTML5 videos play inline or use the
|
||||
@ -295,7 +290,7 @@ export type AndroidWebViewProps = $ReadOnly<{|
|
||||
*/
|
||||
saveFormDataDisabled?: ?boolean,
|
||||
|
||||
/*
|
||||
/**
|
||||
* Used on Android only, controls whether the given list of URL prefixes should
|
||||
* make {@link com.facebook.react.views.webview.ReactWebViewClient} to launch a
|
||||
* default activity intent for those URL instead of loading it within the webview.
|
||||
@ -345,7 +340,7 @@ export type AndroidWebViewProps = $ReadOnly<{|
|
||||
mixedContentMode?: ?('never' | 'always' | 'compatibility'),
|
||||
|}>;
|
||||
|
||||
export type WebViewSharedProps = $ReadOnly<{|
|
||||
export type WebViewSharedProps = $ReadOnly<{|
|
||||
...ViewProps,
|
||||
...IOSWebViewProps,
|
||||
...AndroidWebViewProps,
|
||||
@ -366,7 +361,11 @@ export type WebViewSharedProps = $ReadOnly<{|
|
||||
/**
|
||||
* Function that returns a view to show if there's an error.
|
||||
*/
|
||||
renderError: (errorDomain: ?string, errorCode: number, errorDesc: string) => Element<any>, // view to show if there's an error
|
||||
renderError: (
|
||||
errorDomain: ?string,
|
||||
errorCode: number,
|
||||
errorDesc: string,
|
||||
) => Element<any>, // view to show if there's an error
|
||||
|
||||
/**
|
||||
* Function that returns a loading indicator.
|
||||
@ -457,6 +456,13 @@ export type WebViewSharedProps = $ReadOnly<{|
|
||||
*/
|
||||
originWhitelist?: $ReadOnlyArray<string>,
|
||||
|
||||
/**
|
||||
* Function that allows custom handling of any web view requests. Return
|
||||
* `true` from the function to continue loading the request and `false`
|
||||
* to stop loading. The `navigationType` is always `other` on android.
|
||||
*/
|
||||
onShouldStartLoadWithRequest?: OnShouldStartLoadWithRequest,
|
||||
|
||||
/**
|
||||
* Override the native component used to render the WebView. Enables a custom native
|
||||
* WebView which uses the same JavaScript as the original WebView.
|
||||
|
Loading…
x
Reference in New Issue
Block a user