Skip to content

Commit 8fa7c84

Browse files
author
Michael Dijkstra
authored
Merge pull request #75 from calibreapp/update-open-logic
Update Open and Loading
2 parents df9ea3b + dd6936f commit 8fa7c84

25 files changed

Lines changed: 264 additions & 244 deletions

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# React Live Chat Loader
22

33
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
4+
45
[![All Contributors](https://img.shields.io/badge/all_contributors-7-orange.svg?style=flat-square)](#contributors-)
56

67
<!-- ALL-CONTRIBUTORS-BADGE:END -->
@@ -38,6 +39,9 @@ track how long the page has been idle for and checks if the user is on a slow
3839
connection (using `navigator.connection.effectiveType`) or has data-saver enabled
3940
(using `navigator.connection.saveData`) to prevent loading.
4041

42+
Please note: Some chat widget providers open automatically based on the users
43+
interaction from their last session.
44+
4145
## Installation
4246

4347
To download react-live-chat-loader run:
@@ -312,6 +316,8 @@ You can customise the Userlike Widget by passing the following props to the
312316
To use Chatwoot import the `LiveChatLoaderProvider` and set the `provider` prop
313317
as `chatwoot` and the `providerKey` prop as your Chatwoot secret.
314318

319+
You can optionally set the `locale` and `baseUrl` props.
320+
315321
Then import the `Chatwoot` component.
316322

317323
```jsx

src/components/Chatwoot/index.tsx

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import React, { CSSProperties } from 'react'
44
const styles: {
55
button: CSSProperties
66
img: CSSProperties
7+
close: CSSProperties
78
} = {
89
button: {
910
borderRadius: '100px',
@@ -14,13 +15,21 @@ const styles: {
1415
height: '64px',
1516
position: 'fixed',
1617
width: '64px',
17-
zIndex: 2147483001,
18+
zIndex: 2147483001, // 1 more than the actual widget
1819
userSelect: 'none'
1920
},
2021
img: {
2122
height: '24px',
2223
margin: '20px',
2324
width: '24px'
25+
},
26+
close: {
27+
backgroundColor: "#fff",
28+
height: "24px",
29+
left: "32px",
30+
position: "absolute",
31+
top: "20px",
32+
width: "2px",
2433
}
2534
}
2635

@@ -43,11 +52,18 @@ const Provider = ({ color }: Props): JSX.Element | null => {
4352
backgroundColor: color
4453
}}
4554
>
46-
<img
47-
style={styles.img}
48-
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAUVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////8IN+deAAAAGnRSTlMAAwgJEBk0TVheY2R5eo+ut8jb5OXs8fX2+cjRDTIAAADsSURBVHgBldZbkoMgFIThRgQv8SKKgGf/C51UnJqaRI30/9zfe+NQUQ3TvG7bOk9DVeCmshmj/CuOTYnrdBfkUOg0zlOtl9OWVuEk4+QyZ3DIevmSt/ioTvK1VH/s5bY3YdM9SBZ/mUUyWgx+U06ycgp7D8msxSvtc4HXL9BLdj2elSEfhBJAI0QNgJEBI1BEBsQClVBVGDgwYOLAhJkDM1YOrNg4sLFAsLJgZsHEgoEFFQt0JAFGFjQsKAMJ0LFAexKgZYFyJIDxJIBNJEDNAtSJBLCeBDCOBFAPzwFA94ED+zmhwDO9358r8ANtIsMXi7qVAwAAAABJRU5ErkJggg=="
49-
alt="bubble-icon"
50-
/>
55+
{state === 'initial' ? (
56+
<img
57+
style={styles.img}
58+
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAMAAABg3Am1AAAAUVBMVEUAAAD///////////////////////////////////////////////////////////////////////////////////////////////////////8IN+deAAAAGnRSTlMAAwgJEBk0TVheY2R5eo+ut8jb5OXs8fX2+cjRDTIAAADsSURBVHgBldZbkoMgFIThRgQv8SKKgGf/C51UnJqaRI30/9zfe+NQUQ3TvG7bOk9DVeCmshmj/CuOTYnrdBfkUOg0zlOtl9OWVuEk4+QyZ3DIevmSt/ioTvK1VH/s5bY3YdM9SBZ/mUUyWgx+U06ycgp7D8msxSvtc4HXL9BLdj2elSEfhBJAI0QNgJEBI1BEBsQClVBVGDgwYOLAhJkDM1YOrNg4sLFAsLJgZsHEgoEFFQt0JAFGFjQsKAMJ0LFAexKgZYFyJIDxJIBNJEDNAtSJBLCeBDCOBFAPzwFA94ED+zmhwDO9358r8ANtIsMXi7qVAwAAAABJRU5ErkJggg=="
59+
alt="bubble-icon"
60+
/>
61+
) : (
62+
<>
63+
<div style={{ ...styles.close, transform: "rotate(45deg)" }} />
64+
<div style={{ ...styles.close, transform: "rotate(-45deg)" }} />
65+
</>
66+
)}
5167
</div>
5268
</div>
5369
)

src/components/Intercom/index.tsx

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const styles: {
99
close: CSSProperties
1010
} = {
1111
wrapper: {
12-
zIndex: 2147483001, // 1 more than the actual widget
12+
zIndex: 2147483004, // 1 more than the actual widget
1313
position: 'fixed',
1414
bottom: '20px',
1515
display: 'block',
@@ -137,16 +137,12 @@ const Intercom = ({ color }: Props): JSX.Element | null => {
137137
transform: state === 'initial' ? 'rotate(-30deg)' : 'rotate(0deg)'
138138
}}
139139
>
140-
<svg
141-
height="14px"
142-
width="14px"
143-
focusable="false"
144-
aria-hidden="true"
145-
>
140+
<svg focusable="false" viewBox="0 0 16 14" width="28" height="25" style={{ width : '16px' }}>
146141
<path
147142
fill="rgb(255, 255, 255)"
148-
d="M13.978 12.637l-1.341 1.341L6.989 8.33l-5.648 5.648L0 12.637l5.648-5.648L0 1.341 1.341 0l5.648 5.648L12.637 0l1.341 1.341L8.33 6.989l5.648 5.648z"
149143
fillRule="evenodd"
144+
clipRule="evenodd"
145+
d="M.116 4.884l1.768-1.768L8 9.232l6.116-6.116 1.768 1.768L8 12.768.116 4.884z"
150146
/>
151147
</svg>
152148
</div>

src/components/Messenger/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const CustomerChat = memo(
5656
greeting_dialog_delay: greetingDialogDelay
5757
}
5858

59-
return <div className="fb-customerchat" {...fields} />
59+
return <div><div className="fb-customerchat" {...fields} /></div>
6060
}
6161
)
6262

src/components/Userlike/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ const styles: {
77
icon: CSSProperties
88
} = {
99
container: {
10-
zIndex: 1,
10+
zIndex: 2147483648, // one more than provider
1111
position: 'fixed',
1212
border: '0',
1313
width: '64px',

src/hooks/useChat.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ const connection =
1111
window.navigator && (window.navigator as any).connection
1212
: null
1313

14-
let scriptLoaded = false
15-
1614
const useChat = (
1715
{
1816
loadWhenIdle
@@ -85,17 +83,9 @@ const useChat = (
8583
return
8684
}
8785

88-
if (state === 'opening') return
89-
if (state === 'open') return chatProvider.close()
90-
if (state === 'complete') return chatProvider.open()
91-
92-
if (!scriptLoaded) {
93-
scriptLoaded = true
94-
chatProvider.load({ providerKey, setState, appID, locale, baseUrl })
95-
}
86+
chatProvider.load({ providerKey, setState, appID, locale, baseUrl })
9687

9788
if (open) {
98-
setState('opening')
9989
chatProvider.open()
10090
setState('open')
10191
}

src/index.ts

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
1-
import { default as useChat } from './hooks/useChat'
2-
import { default as useProvider } from './hooks/useProvider'
3-
import { default as Drift } from './components/Drift'
4-
import { default as HelpScout } from './components/HelpScout'
5-
import { default as Intercom } from './components/Intercom'
6-
import { default as Messenger } from './components/Messenger'
7-
import { default as Userlike } from './components/Userlike'
8-
import { default as Chatwoot} from './components/Chatwoot'
9-
import { default as LiveChatLoaderProvider } from './components/LiveChatLoaderProvider'
10-
11-
export {
12-
useChat,
13-
useProvider,
14-
Drift,
15-
HelpScout,
16-
Intercom,
17-
Messenger,
18-
Userlike,
19-
Chatwoot,
20-
LiveChatLoaderProvider
21-
}
1+
export { default as useChat } from './hooks/useChat'
2+
export { default as useProvider } from './hooks/useProvider'
3+
export { default as Drift } from './components/Drift'
4+
export { default as HelpScout } from './components/HelpScout'
5+
export { default as Intercom } from './components/Intercom'
6+
export { default as Messenger } from './components/Messenger'
7+
export { default as Userlike } from './components/Userlike'
8+
export { default as Chatwoot } from './components/Chatwoot'
9+
export { default as LiveChatLoaderProvider } from './components/LiveChatLoaderProvider'

src/providers/chatwoot.ts

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { State } from 'types'
2+
import waitForLoad from '../utils/waitForLoad'
23

34
const domain = 'https://app.chatwoot.com'
45

@@ -21,15 +22,16 @@ declare global {
2122
}
2223

2324
/* eslint-disable */
24-
const loadScript = (onload: () => void, baseUrl: string): void => {
25-
if (window.$chatwoot) return
25+
const loadScript = (onload: () => void, baseUrl: string): boolean => {
26+
if (window.$chatwoot) return false
2627
;(function(d, t) {
2728
var script: HTMLScriptElement = d.createElement('script')
2829
var fisrtScript = d.getElementsByTagName('script')[0]
2930
script.src = baseUrl + '/packs/js/sdk.js'
3031
fisrtScript.parentNode?.insertBefore(script, fisrtScript)
3132
script.onload = onload
3233
})(document)
34+
return true
3335
}
3436
/* eslint-enable */
3537

@@ -44,23 +46,35 @@ const load = ({
4446
setState: (state: State) => void
4547
baseUrl?: string
4648
}): void => {
47-
loadScript(function() {
49+
const loaded = loadScript(function() {
4850
setTimeout(() => setState('complete'), 1000)
4951
window.chatwootSDK.run({
5052
websiteToken: providerKey,
5153
baseUrl,
5254
locale
5355
})
5456
}, baseUrl)
55-
}
5657

57-
const open = (): void => window.$chatwoot && window.$chatwoot.toggle()
58+
// Continue as long as userlike hasn’t already been initialised.
59+
if (loaded) {
60+
waitForLoad(
61+
() => !!window.$chatwoot?.hasLoaded,
62+
// Allow chatwoot to complete loading before removing fake widget
63+
() => setTimeout(() => setState('complete'), 2000)
64+
)
65+
}
66+
}
5867

59-
const close = (): void => window.$chatwoot && window.$chatwoot.toggle()
68+
const open = (): void => {
69+
window.chatwootSettings = window.chatwootSettings || {}
70+
window.chatwootSettings.showPopoutButton = true
71+
window.addEventListener('chatwoot:ready', function() {
72+
window.$chatwoot.toggle()
73+
})
74+
}
6075

6176
export default {
6277
domain,
6378
load,
64-
open,
65-
close
79+
open
6680
}

src/providers/drift.ts

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,17 @@ declare global {
1111
}
1212
}
1313

14-
const loadScript = () => {
15-
if (window.drift) return
14+
/* eslint-disable */
15+
const loadScript = (): boolean => {
16+
if (window.drift) return false
1617

1718
!(function() {
1819
const t = (window.driftt = window.drift = window.driftt || [])
1920
if (!t.init) {
2021
if (t.invoked) {
2122
return void (
2223
window.console &&
23-
//eslint-disable-next-line no-console
2424
console.error &&
25-
//eslint-disable-next-line no-console
2625
console.error('Drift snippet included twice.')
2726
)
2827
}
@@ -41,22 +40,17 @@ const loadScript = () => {
4140
'off',
4241
'on'
4342
]),
44-
//eslint-disable-next-line @typescript-eslint/no-explicit-any
4543
(t.factory = function(e: any) {
4644
return function() {
47-
//eslint-disable-next-line prefer-rest-params
4845
const n = Array.prototype.slice.call(arguments)
4946
return n.unshift(e), t.push(n), t
5047
}
5148
}),
52-
//eslint-disable-next-line @typescript-eslint/no-explicit-any
5349
t.methods.forEach(function(e: any) {
5450
t[e] = t.factory(e)
5551
}),
56-
//eslint-disable-next-line @typescript-eslint/no-explicit-any
5752
(t.load = function(t: any) {
5853
const e = 3e5,
59-
//eslint-disable-next-line @typescript-eslint/no-explicit-any
6054
n = Math.ceil((new Date() as any) / e) * e,
6155
o = document.createElement('script')
6256
;(o.type = 'text/javascript'),
@@ -68,38 +62,39 @@ const loadScript = () => {
6862
})
6963
}
7064
})()
65+
66+
return true
7167
}
72-
/* eslint:enable */
68+
/* eslint-enable */
7369

7470
const load = ({
7571
providerKey,
7672
setState
7773
}: {
7874
providerKey: string
7975
setState: (state: State) => void
80-
}): void => {
81-
loadScript()
82-
window.drift.load(providerKey)
83-
window.drift.SNIPPET_VERSION = '0.3.1'
84-
window.drift.on('ready', () => {
85-
setState('open')
86-
setTimeout(() => setState('complete'), 2000)
87-
})
76+
}): boolean => {
77+
const loaded = loadScript()
78+
79+
// Continue as long as drift hasn’t already been initialised.
80+
if (loaded) {
81+
window.drift.load(providerKey)
82+
window.drift.SNIPPET_VERSION = '0.3.1'
83+
window.drift.on('ready', () => {
84+
setState('complete')
85+
})
86+
}
87+
88+
return loaded
8889
}
8990

9091
const open = (): void =>
9192
window.drift.on('ready', (api: { showWelcomeMessage: () => void }) =>
9293
api.showWelcomeMessage()
9394
)
9495

95-
const close = (): void =>
96-
window.drift.on('ready', (api: { hideWelcomeMessage: () => void }) =>
97-
api.hideWelcomeMessage()
98-
)
99-
10096
export default {
10197
domain,
10298
load,
103-
open,
104-
close
99+
open
105100
}

0 commit comments

Comments
 (0)