No Description

index.js 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. 'use strict';
  2. import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react';
  3. import { StyleSheet, Platform, ViewPropTypes } from 'react-native';
  4. import PropTypes from 'prop-types';
  5. import { WebView } from 'react-native-webview';
  6. import { reduceData, getWidth, isSizeChanged, shouldUpdate } from './utils';
  7. const AutoHeightWebView = React.memo(
  8. forwardRef((props, ref) => {
  9. const { style, onMessage, onSizeUpdated, scrollEnabledWithZoomedin, scrollEnabled } = props;
  10. let webView = useRef();
  11. useImperativeHandle(ref, () => ({
  12. stopLoading: () => webView.current.stopLoading(),
  13. goForward: () => webView.current.goForward(),
  14. goBack: () => webView.current.goBack(),
  15. reload: () => webView.current.reload(),
  16. injectJavaScript: script => webView.current.injectJavaScript(script)
  17. }));
  18. const [size, setSize] = useState({
  19. height: style && style.height ? style.height : 0,
  20. width: getWidth(style)
  21. });
  22. const [scrollable, setScrollable] = useState(false);
  23. const handleMessage = event => {
  24. onMessage && onMessage(event);
  25. if (!event.nativeEvent) {
  26. return;
  27. }
  28. let data = {};
  29. // Sometimes the message is invalid JSON, so we ignore that case
  30. try {
  31. data = JSON.parse(event.nativeEvent.data);
  32. } catch (error) {
  33. console.error(error);
  34. return;
  35. }
  36. const { height, width, zoomedin } = data;
  37. !scrollEnabled && scrollEnabledWithZoomedin && setScrollable(!!zoomedin);
  38. const { height: previousHeight, width: previousWidth } = size;
  39. isSizeChanged({ height, previousHeight, width, previousWidth }) &&
  40. setSize({
  41. height,
  42. width
  43. });
  44. };
  45. const currentScrollEnabled = scrollEnabled === false && scrollEnabledWithZoomedin ? scrollable : scrollEnabled;
  46. const { currentSource, script } = reduceData(props);
  47. const { width, height } = size;
  48. useEffect(
  49. () =>
  50. onSizeUpdated &&
  51. onSizeUpdated({
  52. height,
  53. width
  54. }),
  55. [width, height, onSizeUpdated]
  56. );
  57. return (
  58. <WebView
  59. {...props}
  60. ref={webView}
  61. onMessage={handleMessage}
  62. style={[
  63. styles.webView,
  64. {
  65. width,
  66. height
  67. },
  68. style
  69. ]}
  70. injectedJavaScript={script}
  71. source={currentSource}
  72. scrollEnabled={currentScrollEnabled}
  73. />
  74. );
  75. }),
  76. (prevProps, nextProps) => !shouldUpdate({ prevProps, nextProps })
  77. );
  78. AutoHeightWebView.propTypes = {
  79. onSizeUpdated: PropTypes.func,
  80. files: PropTypes.arrayOf(
  81. PropTypes.shape({
  82. href: PropTypes.string,
  83. type: PropTypes.string,
  84. rel: PropTypes.string
  85. })
  86. ),
  87. style: ViewPropTypes.style,
  88. customScript: PropTypes.string,
  89. customStyle: PropTypes.string,
  90. viewportContent: PropTypes.string,
  91. scrollEnabledWithZoomedin: PropTypes.bool,
  92. // webview props
  93. originWhitelist: PropTypes.arrayOf(PropTypes.string),
  94. onMessage: PropTypes.func,
  95. scalesPageToFit: PropTypes.bool,
  96. source: PropTypes.object
  97. };
  98. let defaultProps = {
  99. showsVerticalScrollIndicator: false,
  100. showsHorizontalScrollIndicator: false,
  101. originWhitelist: ['*']
  102. };
  103. Platform.OS === 'android' &&
  104. Object.assign(defaultProps, {
  105. scalesPageToFit: false
  106. });
  107. Platform.OS === 'ios' &&
  108. Object.assign(defaultProps, {
  109. viewportContent: 'width=device-width'
  110. });
  111. AutoHeightWebView.defaultProps = defaultProps;
  112. const styles = StyleSheet.create({
  113. webView: {
  114. backgroundColor: 'transparent'
  115. }
  116. });
  117. export default AutoHeightWebView;