Skip to content

Commit

Permalink
Merge pull request #798 from devrnt/747-autoboot-is-not-booting-inter…
Browse files Browse the repository at this point in the history
…com-by-the-time-trackevent-is-called

747 autoboot is not booting intercom by the time trackevent is called
  • Loading branch information
devrnt authored Feb 8, 2025
2 parents f65e3a7 + fec6233 commit cbedef9
Show file tree
Hide file tree
Showing 17 changed files with 530 additions and 89 deletions.
5 changes: 5 additions & 0 deletions .changeset/little-bikes-itch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'react-use-intercom': patch
---

Fix initializing intercom api
27 changes: 0 additions & 27 deletions .github/dependabot.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,4 @@ jobs:
- uses: preactjs/compressed-size-action@v2
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
pattern: "packages/**/dist/**/*.?(m)js"
pattern: "packages/**/dist/**/*.?(c)js"
24 changes: 24 additions & 0 deletions apps/examples/vite/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
3 changes: 3 additions & 0 deletions apps/examples/vite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# react-use-intercom in a Vite app

Replace `INTERCOM_APP_ID` with your Intercom app id.
38 changes: 38 additions & 0 deletions apps/examples/vite/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import js from '@eslint/js'
import globals from 'globals'
import react from 'eslint-plugin-react'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'

export default [
{ ignores: ['dist'] },
{
files: ['**/*.{js,jsx}'],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
parserOptions: {
ecmaVersion: 'latest',
ecmaFeatures: { jsx: true },
sourceType: 'module',
},
},
settings: { react: { version: '18.3' } },
plugins: {
react,
'react-hooks': reactHooks,
'react-refresh': reactRefresh,
},
rules: {
...js.configs.recommended.rules,
...react.configs.recommended.rules,
...react.configs['jsx-runtime'].rules,
...reactHooks.configs.recommended.rules,
'react/jsx-no-target-blank': 'off',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
},
]
13 changes: 13 additions & 0 deletions apps/examples/vite/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>
29 changes: 29 additions & 0 deletions apps/examples/vite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "vite-example",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-use-intercom": "*"
},
"devDependencies": {
"@eslint/js": "^9.19.0",
"@types/react": "^19.0.8",
"@types/react-dom": "^19.0.3",
"@vitejs/plugin-react-swc": "^3.5.0",
"eslint": "^9.19.0",
"eslint-plugin-react": "^7.37.4",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-react-refresh": "^0.4.18",
"globals": "^15.14.0",
"vite": "^6.1.0"
}
}
43 changes: 43 additions & 0 deletions apps/examples/vite/src/app.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { useEffect } from 'react';
import { IntercomProvider, useIntercom } from 'react-use-intercom';

const INTERCOM_APP_ID = 'jcabc7e3';

export function App() {
return (
<IntercomProvider
appId={INTERCOM_APP_ID}
autoBoot
onShow={() => alert('show')}
>
<OurApp />
</IntercomProvider>
);
}

function OurApp() {
return (
<main>
<p>Our App</p>
<TrackEvent />
</main>
);
}

function TrackEvent() {
const { trackEvent, boot, shutdown } = useIntercom();

useEffect(() => {
trackEvent('event');
}, [trackEvent]);

return (
<>
<p>Tracing event in effect</p>
<button onClick={() => boot()}>Boot</button>
<button onClick={() => shutdown()}>Shutdown</button>
</>
);
}

export default App;
10 changes: 10 additions & 0 deletions apps/examples/vite/src/main.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';

import { App } from './app.jsx';

createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
);
11 changes: 11 additions & 0 deletions apps/examples/vite/vite.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react-swc';

// https://vite.dev/config/
export default defineConfig({
server: {
port: 9300,
},
plugins: [react()],
clearScreen: false,
});
27 changes: 0 additions & 27 deletions apps/playground/cypress/e2e/boot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,31 +53,4 @@ describe('boot', () => {
cy.get('[data-cy=show]').click();
cy.get('.intercom-lightweight-app-launcher-icon-open').should('not.exist');
});

it('should allow calling `boot` multiple times', () => {
cy.get('[data-cy=boot]').click();

// Wait for the route aliased as 'intercomPing' to respond
// without changing or stubbing its response
cy.wait('@intercomPing');

cy.get('.intercom-lightweight-app-launcher-icon-open').should('exist');
cy.window().should('have.property', 'Intercom');
cy.window().should('have.deep.property', 'intercomSettings', {
app_id: 'jcabc7e3',
});

cy.get('[data-cy="boot-seeded"]').click();

// Wait for the route aliased as 'intercomPing' to respond
// without changing or stubbing its response
cy.wait('@intercomPing');

cy.get('.intercom-lightweight-app-launcher-icon-open').should('exist');
cy.window().should('have.property', 'Intercom');
cy.window().should('have.deep.property', 'intercomSettings', {
app_id: 'jcabc7e3',
name: 'Russo',
});
});
});
3 changes: 3 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import eslint from '@eslint/js';
import prettierConfig from 'eslint-config-prettier';
import reactPlugin from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import simpleImportSort from 'eslint-plugin-simple-import-sort';
import tseslint from 'typescript-eslint';

Expand All @@ -12,6 +13,7 @@ export default tseslint.config(
files: ['**/*.{js,jsx,ts,tsx}'],
plugins: {
react: reactPlugin,
'react-hooks': reactHooks,
'simple-import-sort': simpleImportSort,
},
languageOptions: {
Expand All @@ -27,6 +29,7 @@ export default tseslint.config(
},
},
rules: {
...reactHooks.configs.recommended.rules,
'simple-import-sort/imports': 'error',
'sort-imports': 'off',
'import/order': 'off',
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"eslint": "^9.20.0",
"eslint-config-prettier": "^10.0.1",
"eslint-plugin-prettier": "^5.2.3",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-simple-import-sort": "^12.1.1",
"prettier": "^3.4.2",
"turbo": "^2.4.0",
Expand Down
11 changes: 5 additions & 6 deletions packages/react-use-intercom/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,13 @@
],
"exports": {
".": {
"browser": "./dist/index.js",
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
},
"import": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"require": {
"types": "./dist/index.d.cts",
"default": "./dist/index.cjs"
}
}
},
Expand Down Expand Up @@ -95,4 +94,4 @@
"tsup": "^8.3.6",
"typescript": "^5.7.3"
}
}
}
51 changes: 25 additions & 26 deletions packages/react-use-intercom/src/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,6 @@ export const IntercomProvider: React.FC<
);
}

const onHideWrapper = React.useCallback(() => {
setIsOpen(false);
if (onHide) onHide();
}, [onHide, setIsOpen]);

const onShowWrapper = React.useCallback(() => {
setIsOpen(true);
if (onShow) onShow();
}, [onShow, setIsOpen]);

const boot = React.useCallback(
(props?: IntercomProps) => {
if (!window.Intercom && !shouldInitialize) {
Expand All @@ -69,15 +59,26 @@ export const IntercomProvider: React.FC<
return;
}

// Attach the listeners
if (isBooted.current) {
return;
}

// Register the listeners
// This is done in the booth method because after shutting down
// the callbacks should be re-registered
IntercomAPI('onHide', onHideWrapper);
IntercomAPI('onShow', onShowWrapper);
// the callbacks should be re-registered on a reboot
IntercomAPI('onHide', () => {
setIsOpen(false);
onHide?.();
});
IntercomAPI('onShow', () => {
setIsOpen(true);
onShow?.();
});
IntercomAPI('onUserEmailSupplied', onUserEmailSupplied);

if (onUnreadCountChange)
if (onUnreadCountChange) {
IntercomAPI('onUnreadCountChange', onUnreadCountChange);
}

const metaData: RawIntercomBootProps = {
app_id: appId,
Expand All @@ -92,25 +93,23 @@ export const IntercomProvider: React.FC<
[
apiBase,
appId,
onHideWrapper,
onShowWrapper,
onHide,
onShow,
onUnreadCountChange,
onUserEmailSupplied,
shouldInitialize,
],
);

React.useEffect(() => {
if (!isSSR && shouldInitialize && !isInitialized.current) {
initialize(appId, initializeDelay);

if (autoBoot) {
boot(autoBootProps);
}
if (!isSSR && shouldInitialize && !isInitialized.current) {
initialize(appId, initializeDelay);

isInitialized.current = true;
if (autoBoot) {
boot(autoBootProps);
}
}, [appId, autoBoot, autoBootProps, boot, initializeDelay, shouldInitialize]);

isInitialized.current = true;
}

const ensureIntercom = React.useCallback(
(functionName: string, callback: (() => void) | (() => string)) => {
Expand Down
Loading

0 comments on commit cbedef9

Please sign in to comment.