| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184 | 'use strict';
import { Dimensions, Platform } from 'react-native';
import Immutable from 'immutable';
function appendFilesToHead(files, script) {
  return files.reduceRight((combinedScript, file) => {
    const { rel, type, href } = file;
    return `
            var link  = document.createElement('link');
            link.rel  = '${rel}';
            link.type = '${type}';
            link.href = '${href}';
            document.head.appendChild(link);
            ${combinedScript}
          `;
  }, script);
}
const screenWidth = Dimensions.get('window').width;
const bodyStyle = `
body {
  margin: 0;
  padding: 0;
}
`;
function appendStylesToHead(styles, script) {
  const currentStyles = styles ? bodyStyle + styles : bodyStyle;
  // Escape any single quotes or newlines in the CSS with .replace()
  const escaped = currentStyles.replace(/\'/g, "\\'").replace(/\n/g, '\\n');
  return `
          var styleElement = document.createElement('style');
          styleElement.innerHTML = '${escaped}';
          document.head.appendChild(styleElement);
          ${script}
        `;
}
function getReloadRelatedData(props) {
  const { files, customStyle, customScript, style, source } = props;
  return {
    source,
    files,
    customStyle,
    customScript,
    style
  };
}
function isChanged(newValue, oldValue) {
  return !Immutable.is(Immutable.fromJS(newValue), Immutable.fromJS(oldValue));
}
function getInjectedSource(html, script) {
  return `
    ${html}
    <script>
    ${script}
    </script>
    `;
}
function getScript(props, getScript) {
  const { files, customStyle, customScript, style } = getReloadRelatedData(props);
  let script = getScript(style);
  script = files && files.length > 0 ? appendFilesToHead(files, script) : script;
  script = appendStylesToHead(customStyle, script);
  customScript && (script = customScript + script);
  return script;
}
export function getWidth(style) {
  return style && style.width ? style.width : screenWidth;
}
export function isEqual(newProps, oldProps) {
  return isChanged(getReloadRelatedData(newProps), getReloadRelatedData(oldProps));
}
export function setState(props, getBaseScript) {
  const { source, baseUrl } = props;
  const script = getScript(props, getBaseScript);
  let state = {};
  if (source.html) {
    let currentSource = { html: getInjectedSource(source.html, script) };
    baseUrl && Object.assign(currentSource, { baseUrl });
    Object.assign(state, { source: currentSource });
  } else {
    let currentSource = Object.assign({}, source);
    baseUrl && Object.assign(currentSource, { baseUrl });
    Object.assign(state, {
      source: currentSource,
      script
    });
  }
  return state;
}
export function handleSizeUpdated(height, width, onSizeUpdated) {
  onSizeUpdated &&
    onSizeUpdated({
      height,
      width
    });
}
export function isSizeChanged(height, oldHeight, width, oldWidth) {
  if (!height || !width) {
    return;
  }
  return height !== oldHeight || width !== oldWidth;
}
export const domMutationObserveScript = `
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
var observer = new MutationObserver(updateSize);
observer.observe(document, {
    subtree: true,
    attributes: true
});
`;
export function updateSizeWithMessage(element) {
  return `
  var updateSizeInterval = null;
  var height = 0;
  function updateSize(event) {
    if (!window.hasOwnProperty('ReactNativeWebView') || !window.ReactNativeWebView.hasOwnProperty('postMessage')) {
      !updateSizeInterval && (updateSizeInterval = setInterval(updateSize, 200));
      return;
    }
    clearInterval(updateSizeInterval)
    height = ${element}.offsetHeight || window.innerHeight;
    width = ${element}.offsetWidth || window.innerWidth;
    window.ReactNativeWebView.postMessage(JSON.stringify({ width: width, height: height, event: event }));
  }
  `;
}
export function getStateFromProps(props, state) {
  const { height: oldHeight, width: oldWidth } = state;
  const height = props.style ? props.style.height : null;
  const width = props.style ? props.style.width : null;
  if (isSizeChanged(height, oldHeight, width, oldWidth)) {
    return {
      height: height || oldHeight,
      width: width || oldWidth,
      isSizeChanged: true
    };
  }
  return null;
}
// add viewport setting to meta for WKWebView
const makeScalePageToFit = `
var meta = document.createElement('meta'); 
meta.setAttribute('name', 'viewport'); 
meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);
`;
export function getBaseScript(style) {
  return `
  ;
  if (!document.getElementById("rnahw-wrapper")) {
    var wrapper = document.createElement('div');
    wrapper.id = 'rnahw-wrapper';
    while (document.body.firstChild instanceof Node) {
      wrapper.appendChild(document.body.firstChild);
    }
    document.body.appendChild(wrapper);
  }
  var width = ${getWidth(style)};
  ${updateSizeWithMessage('wrapper')}
  window.addEventListener('load', updateSize);
  window.addEventListener('resize', updateSize);
  ${domMutationObserveScript}
  ${Platform.OS === 'ios' ? makeScalePageToFit : ''}
  updateSize();
  `;
}
 |