/** * Copyright (c) Facebook, Inc. and its affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * Portions copyright for react-native-windows: * * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ import React, { forwardRef, useCallback, useImperativeHandle, useRef } from 'react'; import { View, Image, ImageSourcePropType, NativeModules, } from 'react-native'; import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands'; import invariant from 'invariant'; import {RCTWebView, RCTWebView2} from "./WebViewNativeComponent.windows"; import { useWebViewLogic, defaultOriginWhitelist, defaultRenderError, defaultRenderLoading, } from './WebViewShared'; import { NativeWebViewWindows, WindowsWebViewProps, } from './WebViewTypes'; import styles from './WebView.styles'; const Commands = codegenNativeCommands({ supportedCommands: ['goBack', 'goForward', 'reload', 'stopLoading', 'injectJavaScript', 'requestFocus', 'clearCache', 'postMessage', 'loadUrl'], }); const { resolveAssetSource } = Image; const WebViewComponent = forwardRef<{}, WindowsWebViewProps>(({ cacheEnabled = true, originWhitelist = defaultOriginWhitelist, startInLoadingState, onNavigationStateChange, onLoadStart, onError, onLoad, onLoadEnd, onLoadProgress, onOpenWindow: onOpenWindowProp, onSourceChanged, onHttpError: onHttpErrorProp, onMessage: onMessageProp, renderLoading, renderError, style, containerStyle, source, nativeConfig, onShouldStartLoadWithRequest: onShouldStartLoadWithRequestProp, useWebView2, ...otherProps }, ref) => { const webViewRef = useRef(null); const RCTWebViewString = useWebView2 ? 'RCTWebView2' : 'RCTWebView'; const onShouldStartLoadWithRequestCallback = useCallback((shouldStart: boolean, url: string, lockIdentifier?: number) => { if (lockIdentifier) { if (RCTWebViewString === 'RCTWebView'){ NativeModules.RCTWebView.onShouldStartLoadWithRequestCallback(shouldStart, lockIdentifier); }else{ NativeModules.RCTWebView2.onShouldStartLoadWithRequestCallback(shouldStart, lockIdentifier); } } else if (shouldStart) { Commands.loadUrl(webViewRef, url); } }, [RCTWebViewString]); const { onLoadingStart, onShouldStartLoadWithRequest, onMessage, viewState, setViewState, lastErrorEvent, onHttpError, onLoadingError, onLoadingFinish, onLoadingProgress, onOpenWindow } = useWebViewLogic({ onNavigationStateChange, onLoad, onError, onHttpErrorProp, onLoadEnd, onLoadProgress, onLoadStart, onMessageProp, startInLoadingState, originWhitelist, onShouldStartLoadWithRequestProp, onShouldStartLoadWithRequestCallback, onOpenWindowProp, }) useImperativeHandle(ref, () => ({ goForward: () => Commands.goForward(webViewRef.current), goBack: () => Commands.goBack(webViewRef.current), reload: () => { setViewState( 'LOADING', ); Commands.reload(webViewRef.current) }, stopLoading: () => Commands.stopLoading(webViewRef.current), postMessage: (data: string) => Commands.postMessage(webViewRef.current, data), injectJavaScript: (data: string) => Commands.injectJavaScript(webViewRef.current, data), requestFocus: () => Commands.requestFocus(webViewRef.current), clearCache: () => Commands.clearCache(webViewRef.current), loadUrl: (url: string) => Commands.loadUrl(webViewRef.current, url), }), [setViewState, webViewRef]); let otherView = null; if (viewState === 'LOADING') { otherView = (renderLoading || defaultRenderLoading)(); } else if (viewState === 'ERROR') { invariant(lastErrorEvent != null, 'lastErrorEvent expected to be non-null'); otherView = (renderError || defaultRenderError)( lastErrorEvent.domain, lastErrorEvent.code, lastErrorEvent.description, ); } else if (viewState !== 'IDLE') { console.error(`RNCWebView invalid state encountered: ${viewState}`); } const webViewStyles = [styles.container, styles.webView, style]; const webViewContainerStyle = [styles.container, containerStyle]; const NativeWebView = useWebView2 ? RCTWebView2 : RCTWebView; const webView = return ( {webView} {otherView} ); }); // native implementation should return "true" only for Android 5+ const isFileUploadSupported: () => Promise = async () => false; const WebView = Object.assign(WebViewComponent, {isFileUploadSupported}); export default WebView;