349989153 / 349989153.github.io

My personal blog.
0 stars 0 forks source link

react-native-autoheight-webview #6

Open 349989153 opened 4 years ago

349989153 commented 4 years ago

'use strict';

import React, { useState, useEffect, 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, initialHeight } = props; const innerRef = React.useRef(ref)

const [size, setSize] = useState({
  height: style && style.height ? style.height : initialHeight,
  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;
  isSizeChanged({ height, previousHeight, width, previousWidth }) &&
    setSize({
      height,
      width
    });
};

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={innerRef}
    onMessage={handleMessage}
    style={[
      styles.webView,
      {
        width,
        height
      },
      style
    ]}

    source={currentSource}
    onLoadProgress={({ nativeEvent }) => {
      console.log(nativeEvent.progress);
      console.log(innerRef);
      if (nativeEvent.progress === 1 && innerRef.current) {
        innerRef.current.injectJavaScript(script);
      }
    }}
    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, initialHeight: PropTypes.number, // webview props originWhitelist: PropTypes.arrayOf(PropTypes.string), onMessage: PropTypes.func, scalesPageToFit: PropTypes.bool, source: PropTypes.object };

let defaultProps = { showsVerticalScrollIndicator: false, showsHorizontalScrollIndicator: false, initialHeight: 0, 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;