Skip to content

Adding optional prop for lazy load the intercom script #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
May 10, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions playground/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
ProviderEventsPage,
ProviderApiPage,
UseIntercomTourPage,
UseIntercomWithDelay
} from './modules';

import { Page, Style } from './modules/common';
Expand Down Expand Up @@ -47,6 +48,7 @@ const App = () => {
<Route path="/providerApi" component={ProviderApiPage} />
<Route path="/useIntercom" component={UseIntercomPage} />
<Route path="/useIntercomTour" component={UseIntercomTourPage} />
<Route path="/useIntercomWithTimeout" component={UseIntercomWithDelay} />
<Route path="/" exact>
<Navigation>
<Link to="/provider">
Expand All @@ -61,6 +63,9 @@ const App = () => {
<Link to="/useIntercomTour">
<code>useIntercom with tour</code>
</Link>
<Link to="/useIntercomWithTimeout">
<code>useIntercom with delayed boot</code>
</Link>
</Navigation>
</Route>
</Router>
Expand Down
1 change: 1 addition & 0 deletions playground/modules/useIntercom/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export { default as UseIntercomPage } from './useIntercom';
export { default as UseIntercomTourPage } from './useIntercomTour';
export { default as UseIntercomWithDelay } from './useIntercomWithDelay'
51 changes: 51 additions & 0 deletions playground/modules/useIntercom/useIntercomWithDelay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import * as React from 'react';
import styled from 'styled-components';

import { IntercomProvider, useIntercom } from '../../../.';

import { Button } from '../common';

const Grid = styled.div`
display: grid;
grid-template-columns: repeat(1, 1fr);
width: 100%;
`;

const Item = styled.div`
display: grid;
grid-template-rows: min-content;

&::after {
content: '';
margin: 2rem 0 1.5rem;
border-bottom: 2px solid var(--grey);
width: 100%;
}
`;

const RawUseIntercomPage = () => {
const {
boot,
} = useIntercom();
const handleBoot = React.useCallback(() => boot(), [boot]);

return (
<Grid>
<Item>
<p>
Intercom will be autobooted after 5000ms
</p>
</Item>
</Grid>
);
};

const UseIntercomWithDelayPage = () => {
return (
<IntercomProvider appId="jcabc7e3" initializeDelay={5000} autoBoot>
<RawUseIntercomPage />
</IntercomProvider>
);
};

export default UseIntercomWithDelayPage;
17 changes: 10 additions & 7 deletions src/initialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
* Snippet to initialize the Intercom instance
*
* @param appId - Intercom app id
* @param [timeout=0] - Amount of milliseconds that the initialization should be delayed, defaults to 0
*
* @see {@link https://developers.intercom.com/installing-intercom/docs/basic-javascript}
*/
const initialize = (appId: string) => {
const initialize = (appId: string, timeout = 0) => {
var w = window;
var ic = w.Intercom;
if (typeof ic === 'function') {
Expand All @@ -23,12 +24,14 @@ const initialize = (appId: string) => {
};
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/' + appId;
var x = d.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
setTimeout(function() {
var s = d.createElement('script');
s.type = 'text/javascript';
s.async = true;
s.src = 'https://widget.intercom.io/widget/' + appId;
var x = d.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
}, timeout);
};
if (document.readyState === 'complete') {
l();
Expand Down
3 changes: 2 additions & 1 deletion src/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export const IntercomProvider: React.FC<IntercomProviderProps> = ({
onUnreadCountChange,
shouldInitialize = !isSSR,
apiBase,
initializeDelay,
...rest
}) => {
const isBooted = React.useRef(autoBoot);
Expand All @@ -36,7 +37,7 @@ export const IntercomProvider: React.FC<IntercomProviderProps> = ({
);

if (!isSSR && !window.Intercom && shouldInitialize) {
initialize(appId);
initialize(appId, initializeDelay);
// Only add listeners on initialization
if (onHide) IntercomAPI('onHide', onHide);
if (onShow) IntercomAPI('onShow', onShow);
Expand Down
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -419,4 +419,10 @@ export type IntercomProviderProps = {
* Format https://${INTERCOM_APP_ID}.intercom-messenger.com
*/
apiBase?: string;
/**
* Indicates if the intercom initialization should be delayed, delay is in ms
*
* @remarks If not set delay is set to 0ms
* */
initializeDelay?: number;
};
25 changes: 25 additions & 0 deletions test/useIntercom.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,4 +44,29 @@ describe('useIntercom', () => {

expect(window.intercomSettings).toEqual({ app_id: INTERCOM_APP_ID });
});

test('should set wait for a certain amount of ms until booting, booting before that will do nothing', async () => {
const { result, waitFor } = renderHook(() => useIntercom(), {
wrapper: ({ children }) => (
<IntercomProvider appId={INTERCOM_APP_ID} initializeDelay={5000}>{children}</IntercomProvider>
),
});

const { boot } = result.current;

act(() => {
boot();
});

expect(window.intercomSettings).toEqual({app_id: undefined});

await waitFor(() => {}, {timeout: 5000});

act(() => {
boot();
});

expect(window.intercomSettings).toEqual({ app_id: INTERCOM_APP_ID });

});
});