0

I've got a React Native application for Android that has live chat support (using Intercom). To access Intercom I'm using WebView with injectedJavaScript to show the UI. It works fine on my dev build, but when I do a release build it complains it cannot find window.Intercom (I get the same relative issue if I remove the window.)

Here's the code I'm trying to run

IntercomContainer.js

// =============================================================================
// Components >> IntercomContainer
// =============================================================================
// @flow

// Import
// =============================================================================

import * as React from 'react';
import { View, WebView } from 'react-native';
import Spinner from 'react-native-loading-spinner-overlay';

import styles from './styles';

// Content
// =============================================================================

type State = {
    isLoading: boolean,
};

type Props = {
    appId: string,
}

// Render
// =============================================================================

export default class IntercomContainer extends React.Component<Props, State> {

    props: Props = {
        appId: '',
    };

    state: State = {
        isLoading: true,
    }

    setState: Function;

    injectedJS = (appId: string) => {
        return `
            try {

                window.Intercom('boot', {
                    app_id: '${appId}',
                }); 

                window.Intercom('show');
                window.Intercom('onShow', function() { 
                    document.getElementById('message').innerHTML = '';
                    setTimeout(() => {
                        document.getElementById('message').innerHTML = 'Click on the chat button in the bottom-right to open chat...';
                    }, 1000)
                });

            } catch(e) {
                alert('Intercom failed to load: ' + e.message);
            }
        `;
    }

    onLoadEnd = () => {
        this.setState({
            isLoading: false,
        });
    }

    render(){
        const { appId } = this.props;
        const { isLoading } = this.state;

        return (
            <View style={styles.container}>
                <Spinner visible={isLoading} />
                <WebView
                    injectedJavaScript={this.injectedJS(appId)}
                    source={require('./IntercomWebView.html')}
                    onLoadEnd={this.onLoadEnd}
                    javaScriptEnabled={true}
                    style={styles.webView}
                />
            </View>
        );
    }
}

IntercomWebView.html

<!DOCTYPE html>
<head>
    <script>
        // intercom JS library
        var APP_ID = '';
        (function(){
            debugger;
            console.log("Executing function main...");
            var w=window;
            var ic=w.Intercom;
            if (typeof ic === "function") {
                ic('reattach_activator');
                ic('update',intercomSettings);
            } else {
                var d=document;
                var i= function() {
                    i.c(arguments)
                };
                i.q=[];
                i.c=function(args){
                    i.q.push(args)
                };
                w.Intercom=i;

                function l(){
                    debugger;
                    console.log("Executing function l...");
                    var s=d.createElement('script');
                    s.type='text/javascript';
                    s.async=true;
                    s.src='https://widget.intercom.io/widget/' + APP_ID;
                    var x=d.getElementsByTagName('script')[0];
                    x.parentNode.insertBefore(s,x);
                }

                if(w.attachEvent){
                    w.attachEvent('onload',l);
                }else{
                    w.addEventListener('load',l,false);
                }
            }
        })();
    </script>
    <style>
        main {
            align-items: center;
            background-color: #fefefe;
            color: #999;
            display: flex;
            font-family: sans-serif;
            height: 80vh;
            justify-content: center;
            text-align: center;
        }
    </style>
</head>
<body>
    <main id="message">
        loading...
    </main>
</body>
</html>

Thanks!

2 Answers 2

1

Most likely the root cause of your issue is the same as postMessage bug. Your code which uses Intercom object is being loaded before javascript code which initilizes this object. As a workaround you can call this code in setTimeout with some magic value, or implement more "neat" solution where you'll defer actual calls of Intercom object until it is initialized

Sign up to request clarification or add additional context in comments.

1 Comment

Awesome, thank you. I'll give this a go when I get a chance and report back. Thanks!
0

This seems to be an issue as referred to above with the delay, but also a cookies problem.

I managed to get around this with the following, similar to the original question;

const injectedJavaScript = `
  var APP_ID = "YOUR_APP_ID";
  // Wait for a "time" before trying to execute
  setTimeout(function() {
    try {
      window.Intercom('boot', {
        app_id: APP_ID,
        email: 'an_email_@an_address.com',
        user_id: 'unique_id'
      });
      // i want to show by default, when ready
      window.Intercom('show');
      // then i am doing some stuff to show the "instruction" to reopen by the icon if they close
      var instruction = document.getElementById("instruction");
      window.Intercom('onHide', function() {
        instruction.classList.add("show");
      })
    } catch(e) {
      alert('Intercom failed to load: ' + e.message);
    }
  }, 500)
`

My WebView looks like this;

return (
  <View flex={1}>
    <WebView
      javaScriptEnabled
      scrollEnabled={false}
      bounces={false}
      originWhitelist={['*']}
      injectedJavaScript={injectedJavaScript}
      source={{
        html: `
          <head>
            <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0">
            <style>
              p#instruction {
                opacity: 0;
                font-family: 'Rubik', sans-serif;
                text-align: center;
                font-size: 14px;
                position: absolute;
                top: 50%;
                left: 0;
                margin-top: -8px;
                width: 100%;
                -webkit-transition: opacity 0.5s linear;
                -moz-transition: opacity 0.5s linear;
                -o-transition: opacity 0.5s linear;
                -ms-transition: opacity 0.5s linear;
                transition: opacity 0.5s linear;
              }
              p#instruction.show {
                opacity: 1;
              }

            </style>
          </head>
          <body>
            <p id="instruction">Click the icon to open chat</p>
            <script>
              var APP_ID = "YOUR_APP_ID";

              (function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/' + APP_ID;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s,x);};if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();
            </script>
          </body>
        `,
        baseUrl: 'https://a-base-url.co.uk', // This part is important! This solved the cookie issue for me
      }}
      useWebKit
      onLoad={() => console.warn('do something on load')}
    />
  </View>
)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.