123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- 'use strict';
-
- import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react';
-
- import { StyleSheet, Platform, ViewPropTypes } from 'react-native';
-
- import PropTypes from 'prop-types';
-
- import { WebView } from 'react-native-webview';
-
- import { reduceData, getWidth, isSizeChanged, shouldUpdate } from './utils';
-
- const AutoHeightWebView = React.memo(
- forwardRef((props, ref) => {
- const { style, onMessage, onSizeUpdated, scrollEnabledWithZoomedin, scrollEnabled, source } = props;
-
- if (!source) {
- return null;
- }
-
- let webView = useRef();
- useImperativeHandle(ref, () => ({
- stopLoading: () => webView.current.stopLoading(),
- goForward: () => webView.current.goForward(),
- goBack: () => webView.current.goBack(),
- reload: () => webView.current.reload(),
- injectJavaScript: script => webView.current.injectJavaScript(script)
- }));
-
- const [size, setSize] = useState({
- height: style && style.height ? style.height : 0,
- width: getWidth(style)
- });
- const [scrollable, setScrollable] = useState(false);
- const handleMessage = event => {
- onMessage && onMessage(event);
- if (!event.nativeEvent) {
- return;
- }
- let data = {};
- // Sometimes the message is invalid JSON, so we ignore that case
- try {
- data = JSON.parse(event.nativeEvent.data);
- } catch (error) {
- console.error(error);
- return;
- }
- const { height, width, zoomedin } = data;
- !scrollEnabled && scrollEnabledWithZoomedin && setScrollable(!!zoomedin);
- const { height: previousHeight, width: previousWidth } = size;
- !zoomedin && webView.current.zoomedin === zoomedin && isSizeChanged({ height, previousHeight, width, previousWidth }) &&
- setSize({
- height,
- width
- });
- webView.current.zoomedin = zoomedin;
- };
-
- const currentScrollEnabled = scrollEnabled === false && scrollEnabledWithZoomedin ? scrollable : scrollEnabled;
-
- const { currentSource, script } = reduceData(props);
-
- const { width, height } = size;
- useEffect(
- () =>
- onSizeUpdated &&
- onSizeUpdated({
- height,
- width
- }),
- [width, height, onSizeUpdated]
- );
-
- return (
- <WebView
- {...props}
- ref={webView}
- onMessage={handleMessage}
- style={[
- styles.webView,
- {
- width,
- height
- },
- style
- ]}
- injectedJavaScript={script}
- source={currentSource}
- scrollEnabled={currentScrollEnabled}
- />
- );
- }),
- (prevProps, nextProps) => !shouldUpdate({ prevProps, nextProps })
- );
-
- AutoHeightWebView.propTypes = {
- onSizeUpdated: PropTypes.func,
- files: PropTypes.arrayOf(
- PropTypes.shape({
- href: PropTypes.string,
- type: PropTypes.string,
- rel: PropTypes.string
- })
- ),
- style: ViewPropTypes.style,
- customScript: PropTypes.string,
- customStyle: PropTypes.string,
- viewportContent: PropTypes.string,
- scrollEnabledWithZoomedin: PropTypes.bool,
- // webview props
- originWhitelist: PropTypes.arrayOf(PropTypes.string),
- onMessage: PropTypes.func,
- scalesPageToFit: PropTypes.bool,
- source: PropTypes.object
- };
-
- let defaultProps = {
- showsVerticalScrollIndicator: false,
- showsHorizontalScrollIndicator: false,
- originWhitelist: ['*']
- };
-
- Platform.OS === 'android' &&
- Object.assign(defaultProps, {
- scalesPageToFit: false
- });
-
- Platform.OS === 'ios' &&
- Object.assign(defaultProps, {
- viewportContent: 'width=device-width'
- });
-
- AutoHeightWebView.defaultProps = defaultProps;
-
- const styles = StyleSheet.create({
- webView: {
- backgroundColor: 'transparent'
- }
- });
-
- export default AutoHeightWebView;
|