暫無描述

index.js 3.2KB

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