@botonic/react 1.0.0-beta.0 → 1.0.0-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/components/button.js +2 -0
- package/lib/components/button.js.map +1 -1
- package/lib/components/components.js +1 -1
- package/lib/components/image.js +47 -5
- package/lib/components/image.js.map +1 -1
- package/lib/components/index.js +6 -6
- package/lib/components/markdown.js +1 -1
- package/lib/components/multichannel/multichannel-utils.js +8 -6
- package/lib/components/multichannel/multichannel-utils.js.map +1 -1
- package/lib/components/timestamps.js +1 -1
- package/lib/constants.js +2 -1
- package/lib/constants.js.map +1 -1
- package/lib/dev-app.js +7 -6
- package/lib/dev-app.js.map +1 -1
- package/lib/index.d.ts +3 -0
- package/lib/index.js +20 -20
- package/lib/message-utils.js +1 -1
- package/lib/util/dom.js +8 -2
- package/lib/util/dom.js.map +1 -1
- package/lib/util/environment.js +1 -1
- package/lib/util/objects.js +1 -1
- package/lib/util/react.js +1 -1
- package/lib/util/webchat.js +1 -1
- package/lib/webchat/actions.js +5 -1
- package/lib/webchat/actions.js.map +1 -1
- package/lib/webchat/devices/device-adapter.js +14 -4
- package/lib/webchat/devices/device-adapter.js.map +1 -1
- package/lib/webchat/devices/scrollbar-controller.js +5 -3
- package/lib/webchat/devices/scrollbar-controller.js.map +1 -1
- package/lib/webchat/header.js +1 -1
- package/lib/webchat/hooks.js +25 -6
- package/lib/webchat/hooks.js.map +1 -1
- package/lib/webchat/index.js +1 -1
- package/lib/webchat/webchat-reducer.js +11 -0
- package/lib/webchat/webchat-reducer.js.map +1 -1
- package/lib/webchat/webchat.js +21 -4
- package/lib/webchat/webchat.js.map +1 -1
- package/lib/webchat/webview.js +1 -1
- package/lib/webchat-app.js +20 -9
- package/lib/webchat-app.js.map +1 -1
- package/package.json +6 -6
- package/src/components/button.jsx +2 -0
- package/src/dev-app.jsx +8 -3
- package/src/experimental/components/message.jsx +8 -2
- package/src/experimental/constants.js +189 -0
- package/src/experimental/contexts.jsx +36 -0
- package/src/experimental/dev-app.jsx +14 -7
- package/src/experimental/index.js +94 -25
- package/src/experimental/msg-to-botonic.jsx +8 -8
- package/src/experimental/react-bot.jsx +1 -1
- package/src/experimental/util/dom.js +55 -0
- package/src/experimental/util/objects.js +39 -0
- package/src/experimental/util/webchat.js +61 -0
- package/src/experimental/webchat/actions.jsx +24 -0
- package/src/experimental/webchat/hooks.js +296 -0
- package/src/experimental/webchat/messages-reducer.js +86 -0
- package/src/experimental/webchat/session-view.jsx +166 -0
- package/src/experimental/webchat/webchat-dev.jsx +23 -19
- package/src/experimental/webchat/webchat-reducer.js +68 -0
- package/src/experimental/webchat/webchat.jsx +109 -82
- package/src/experimental/webchat-app.jsx +39 -15
- package/src/index.d.ts +1 -0
- package/src/util/dom.js +5 -3
- package/src/webchat/actions.jsx +1 -0
- package/src/webchat/devices/device-adapter.js +16 -4
- package/src/webchat/devices/scrollbar-controller.js +9 -4
- package/src/webchat/hooks.js +10 -0
- package/src/webchat/webchat-reducer.js +3 -0
- package/src/webchat/webchat.jsx +2 -1
- package/src/webchat-app.jsx +6 -4
- package/lib/experimental/components/audio.js +0 -46
- package/lib/experimental/components/audio.js.map +0 -1
- package/lib/experimental/components/carousel.js +0 -194
- package/lib/experimental/components/carousel.js.map +0 -1
- package/lib/experimental/components/custom-message.js +0 -132
- package/lib/experimental/components/custom-message.js.map +0 -1
- package/lib/experimental/components/document.js +0 -69
- package/lib/experimental/components/document.js.map +0 -1
- package/lib/experimental/components/image.js +0 -47
- package/lib/experimental/components/image.js.map +0 -1
- package/lib/experimental/components/index.js +0 -184
- package/lib/experimental/components/index.js.map +0 -1
- package/lib/experimental/components/location.js +0 -54
- package/lib/experimental/components/location.js.map +0 -1
- package/lib/experimental/components/markdown.js +0 -103
- package/lib/experimental/components/markdown.js.map +0 -1
- package/lib/experimental/components/message.js +0 -353
- package/lib/experimental/components/message.js.map +0 -1
- package/lib/experimental/components/text.js +0 -80
- package/lib/experimental/components/text.js.map +0 -1
- package/lib/experimental/components/video.js +0 -49
- package/lib/experimental/components/video.js.map +0 -1
- package/lib/experimental/components/whatsapp-template.js +0 -53
- package/lib/experimental/components/whatsapp-template.js.map +0 -1
- package/lib/experimental/dev-app.js +0 -240
- package/lib/experimental/dev-app.js.map +0 -1
- package/lib/experimental/index.js +0 -748
- package/lib/experimental/index.js.map +0 -1
- package/lib/experimental/msg-to-botonic.js +0 -162
- package/lib/experimental/msg-to-botonic.js.map +0 -1
- package/lib/experimental/node-app.js +0 -97
- package/lib/experimental/node-app.js.map +0 -1
- package/lib/experimental/react-bot.js +0 -167
- package/lib/experimental/react-bot.js.map +0 -1
- package/lib/experimental/webchat/assets/Inter-VariableFont_slnt,wght.ttf +0 -0
- package/lib/experimental/webchat/assets/botonic-logo-white.svg +0 -16
- package/lib/experimental/webchat/assets/messenger.svg +0 -10
- package/lib/experimental/webchat/assets/open-new-window.svg +0 -3
- package/lib/experimental/webchat/assets/open.svg +0 -3
- package/lib/experimental/webchat/assets/telegram.svg +0 -10
- package/lib/experimental/webchat/assets/webchat.svg +0 -21
- package/lib/experimental/webchat/assets/whatsapp.svg +0 -4
- package/lib/experimental/webchat/webchat-dev.js +0 -300
- package/lib/experimental/webchat/webchat-dev.js.map +0 -1
- package/lib/experimental/webchat/webchat.js +0 -1044
- package/lib/experimental/webchat/webchat.js.map +0 -1
- package/lib/experimental/webchat-app.js +0 -635
- package/lib/experimental/webchat-app.js.map +0 -1
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SET_CURRENT_ATTACHMENT,
|
|
3
|
+
SET_ERROR,
|
|
4
|
+
SET_ONLINE,
|
|
5
|
+
TOGGLE_COVER_COMPONENT,
|
|
6
|
+
TOGGLE_EMOJI_PICKER,
|
|
7
|
+
TOGGLE_PERSISTENT_MENU,
|
|
8
|
+
TOGGLE_WEBCHAT,
|
|
9
|
+
UPDATE_BOT_STATE,
|
|
10
|
+
UPDATE_DEV_SETTINGS,
|
|
11
|
+
UPDATE_HANDOFF,
|
|
12
|
+
UPDATE_JWT,
|
|
13
|
+
UPDATE_LAST_ROUTE_PATH,
|
|
14
|
+
UPDATE_LATEST_INPUT,
|
|
15
|
+
UPDATE_SESSION,
|
|
16
|
+
UPDATE_THEME,
|
|
17
|
+
UPDATE_TYPING,
|
|
18
|
+
UPDATE_USER,
|
|
19
|
+
UPDATE_WEBVIEW,
|
|
20
|
+
} from './actions'
|
|
21
|
+
import { messagesReducer } from './messages-reducer'
|
|
22
|
+
|
|
23
|
+
// eslint-disable-next-line complexity
|
|
24
|
+
export function webchatReducer(state, action) {
|
|
25
|
+
switch (action.type) {
|
|
26
|
+
case UPDATE_WEBVIEW:
|
|
27
|
+
return { ...state, ...action.payload }
|
|
28
|
+
case UPDATE_TYPING:
|
|
29
|
+
return { ...state, typing: action.payload }
|
|
30
|
+
case UPDATE_THEME:
|
|
31
|
+
return {
|
|
32
|
+
...state,
|
|
33
|
+
...action.payload,
|
|
34
|
+
}
|
|
35
|
+
case UPDATE_HANDOFF:
|
|
36
|
+
return { ...state, handoff: action.payload }
|
|
37
|
+
case TOGGLE_WEBCHAT:
|
|
38
|
+
return { ...state, isWebchatOpen: action.payload }
|
|
39
|
+
case TOGGLE_EMOJI_PICKER:
|
|
40
|
+
return { ...state, isEmojiPickerOpen: action.payload }
|
|
41
|
+
case TOGGLE_PERSISTENT_MENU:
|
|
42
|
+
return { ...state, isPersistentMenuOpen: action.payload }
|
|
43
|
+
case TOGGLE_COVER_COMPONENT:
|
|
44
|
+
return { ...state, isCoverComponentOpen: action.payload }
|
|
45
|
+
case SET_ERROR:
|
|
46
|
+
return { ...state, error: action.payload || {} }
|
|
47
|
+
case SET_ONLINE:
|
|
48
|
+
return { ...state, online: action.payload }
|
|
49
|
+
case UPDATE_DEV_SETTINGS:
|
|
50
|
+
return { ...state, devSettings: { ...action.payload } }
|
|
51
|
+
case UPDATE_LATEST_INPUT:
|
|
52
|
+
return { ...state, latestInput: action.payload }
|
|
53
|
+
case UPDATE_LAST_ROUTE_PATH:
|
|
54
|
+
return { ...state, lastRoutePath: action.payload }
|
|
55
|
+
case SET_CURRENT_ATTACHMENT:
|
|
56
|
+
return { ...state, currentAttachment: action.payload }
|
|
57
|
+
case UPDATE_JWT:
|
|
58
|
+
return { ...state, jwt: action.payload }
|
|
59
|
+
case UPDATE_USER:
|
|
60
|
+
return { ...state, user: action.payload }
|
|
61
|
+
case UPDATE_SESSION:
|
|
62
|
+
return { ...state, session: action.payload }
|
|
63
|
+
case UPDATE_BOT_STATE:
|
|
64
|
+
return { ...state, botState: action.payload }
|
|
65
|
+
default:
|
|
66
|
+
return messagesReducer(state, action)
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -2,7 +2,7 @@ import { INPUT, isMobile, params2queryString } from '@botonic/core'
|
|
|
2
2
|
import {
|
|
3
3
|
MessageEventAck,
|
|
4
4
|
MessageEventFrom,
|
|
5
|
-
} from '@botonic/core/
|
|
5
|
+
} from '@botonic/core/src/models/events/message'
|
|
6
6
|
import { motion } from 'framer-motion'
|
|
7
7
|
import merge from 'lodash.merge'
|
|
8
8
|
import React, {
|
|
@@ -42,12 +42,6 @@ import { scrollToBottom } from '../../util/dom'
|
|
|
42
42
|
import { isDev, resolveImage } from '../../util/environment'
|
|
43
43
|
import { ConditionalWrapper } from '../../util/react'
|
|
44
44
|
import { deserializeRegex, stringifyWithRegexs } from '../../util/regexs'
|
|
45
|
-
import {
|
|
46
|
-
_getThemeProperty,
|
|
47
|
-
getServerErrorMessage,
|
|
48
|
-
initSession,
|
|
49
|
-
shouldKeepSessionOnReload,
|
|
50
|
-
} from '../../util/webchat'
|
|
51
45
|
import { Attachment } from '../../webchat/components/attachment'
|
|
52
46
|
import {
|
|
53
47
|
EmojiPicker,
|
|
@@ -61,12 +55,6 @@ import { SendButton } from '../../webchat/components/send-button'
|
|
|
61
55
|
import { TypingIndicator } from '../../webchat/components/typing-indicator'
|
|
62
56
|
import { DeviceAdapter } from '../../webchat/devices/device-adapter'
|
|
63
57
|
import { StyledWebchatHeader } from '../../webchat/header'
|
|
64
|
-
import {
|
|
65
|
-
useComponentWillMount,
|
|
66
|
-
usePrevious,
|
|
67
|
-
useTyping,
|
|
68
|
-
useWebchat,
|
|
69
|
-
} from '../../webchat/hooks'
|
|
70
58
|
import { WebchatMessageList } from '../../webchat/message-list'
|
|
71
59
|
import { WebchatReplies } from '../../webchat/replies'
|
|
72
60
|
import { useStorageState } from '../../webchat/use-storage-state-hook'
|
|
@@ -74,7 +62,18 @@ import { WebviewContainer } from '../../webchat/webview'
|
|
|
74
62
|
import { Audio, Document, Image, Video } from '../components'
|
|
75
63
|
import { Text } from '../components/text'
|
|
76
64
|
import { msgToBotonic } from '../msg-to-botonic'
|
|
77
|
-
|
|
65
|
+
import {
|
|
66
|
+
_getThemeProperty,
|
|
67
|
+
getServerErrorMessage,
|
|
68
|
+
initUser,
|
|
69
|
+
shouldKeepSessionOnReload,
|
|
70
|
+
} from '../util/webchat'
|
|
71
|
+
import {
|
|
72
|
+
useComponentWillMount,
|
|
73
|
+
usePrevious,
|
|
74
|
+
useTyping,
|
|
75
|
+
useWebchat,
|
|
76
|
+
} from '../webchat/hooks'
|
|
78
77
|
export const getParsedAction = botonicAction => {
|
|
79
78
|
const splittedAction = botonicAction.split('create_case:')
|
|
80
79
|
if (splittedAction.length <= 1) return undefined
|
|
@@ -182,7 +181,6 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
182
181
|
updateLatestInput,
|
|
183
182
|
updateTyping,
|
|
184
183
|
updateWebview,
|
|
185
|
-
updateSession,
|
|
186
184
|
updateLastRoutePath,
|
|
187
185
|
updateHandoff,
|
|
188
186
|
updateTheme,
|
|
@@ -198,13 +196,24 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
198
196
|
closeWebviewT,
|
|
199
197
|
updateLastMessageDate,
|
|
200
198
|
setCurrentAttachment,
|
|
199
|
+
updateJwt,
|
|
200
|
+
updateUser,
|
|
201
|
+
updateSession,
|
|
202
|
+
updateBotState,
|
|
201
203
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
202
204
|
} = props.webchatHooks || useWebchat()
|
|
205
|
+
|
|
203
206
|
const firstUpdate = useRef(true)
|
|
204
|
-
const isOnline = () => webchatState.
|
|
207
|
+
const isOnline = () => webchatState.isWebchatOnline
|
|
205
208
|
const currentDateString = () => new Date().toISOString()
|
|
206
209
|
const theme = merge(webchatState.theme, props.theme)
|
|
207
|
-
const {
|
|
210
|
+
const {
|
|
211
|
+
initialUser,
|
|
212
|
+
initialSession,
|
|
213
|
+
initialBotState,
|
|
214
|
+
initialDevSettings,
|
|
215
|
+
onStateChange,
|
|
216
|
+
} = props
|
|
208
217
|
const getThemeProperty = _getThemeProperty(theme)
|
|
209
218
|
|
|
210
219
|
const storage = props.storage === undefined ? localStorage : props.storage
|
|
@@ -226,11 +235,13 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
226
235
|
JSON.parse(
|
|
227
236
|
stringifyWithRegexs({
|
|
228
237
|
messages: webchatState.messagesJSON,
|
|
229
|
-
session: webchatState.session,
|
|
230
|
-
lastRoutePath: webchatState.lastRoutePath,
|
|
231
238
|
devSettings: webchatState.devSettings,
|
|
232
239
|
lastMessageUpdate: webchatState.lastMessageUpdate,
|
|
233
240
|
themeUpdates: webchatState.themeUpdates,
|
|
241
|
+
jwt: webchatState.jwt,
|
|
242
|
+
user: webchatState.user,
|
|
243
|
+
session: webchatState.session,
|
|
244
|
+
botState: webchatState.botState,
|
|
234
245
|
})
|
|
235
246
|
)
|
|
236
247
|
)
|
|
@@ -256,17 +267,12 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
256
267
|
}, [webchatState.currentAttachment])
|
|
257
268
|
|
|
258
269
|
const sendUserInput = async input => {
|
|
259
|
-
input = {
|
|
260
|
-
...input,
|
|
261
|
-
ack: MessageEventAck.DRAFT,
|
|
262
|
-
from: MessageEventFrom.USER,
|
|
263
|
-
}
|
|
264
270
|
props.onUserInput &&
|
|
265
271
|
props.onUserInput({
|
|
266
|
-
user: webchatState.
|
|
272
|
+
user: webchatState.user,
|
|
267
273
|
input,
|
|
268
274
|
session: webchatState.session,
|
|
269
|
-
|
|
275
|
+
botState: webchatState.botState,
|
|
270
276
|
})
|
|
271
277
|
}
|
|
272
278
|
|
|
@@ -300,16 +306,18 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
300
306
|
|
|
301
307
|
// Load initial state from storage
|
|
302
308
|
useEffect(() => {
|
|
303
|
-
|
|
309
|
+
const {
|
|
304
310
|
messages,
|
|
305
|
-
session,
|
|
306
311
|
lastRoutePath,
|
|
307
312
|
devSettings,
|
|
308
313
|
lastMessageUpdate,
|
|
309
314
|
themeUpdates,
|
|
315
|
+
user,
|
|
316
|
+
session,
|
|
317
|
+
botState,
|
|
310
318
|
} = botonicState || {}
|
|
311
|
-
|
|
312
|
-
|
|
319
|
+
updateUser(merge(initialUser, initUser(user)))
|
|
320
|
+
|
|
313
321
|
if (shouldKeepSessionOnReload({ initialDevSettings, devSettings })) {
|
|
314
322
|
if (messages) {
|
|
315
323
|
messages.forEach(m => {
|
|
@@ -322,9 +330,16 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
322
330
|
if (newComponent) addMessageComponent(newComponent)
|
|
323
331
|
})
|
|
324
332
|
}
|
|
325
|
-
if (initialSession)
|
|
326
|
-
|
|
327
|
-
|
|
333
|
+
if (initialSession) {
|
|
334
|
+
updateSession(merge(initialSession, session))
|
|
335
|
+
}
|
|
336
|
+
if (initialBotState) {
|
|
337
|
+
updateBotState(merge(initialBotState, botState))
|
|
338
|
+
}
|
|
339
|
+
} else {
|
|
340
|
+
updateSession(merge(initialSession, session))
|
|
341
|
+
updateBotState(merge(initialBotState, botState))
|
|
342
|
+
}
|
|
328
343
|
if (devSettings) updateDevSettings(devSettings)
|
|
329
344
|
else if (initialDevSettings) updateDevSettings(initialDevSettings)
|
|
330
345
|
if (lastMessageUpdate) updateLastMessageDate(lastMessageUpdate)
|
|
@@ -340,19 +355,26 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
340
355
|
}, [webchatState.isWebchatOpen])
|
|
341
356
|
|
|
342
357
|
useEffect(() => {
|
|
343
|
-
if (
|
|
344
|
-
onStateChange
|
|
358
|
+
if (
|
|
359
|
+
onStateChange &&
|
|
360
|
+
typeof onStateChange === 'function' &&
|
|
361
|
+
webchatState.user.id
|
|
362
|
+
) {
|
|
363
|
+
onStateChange({ ...webchatState, updateJwt })
|
|
364
|
+
}
|
|
345
365
|
saveWebchatState(webchatState)
|
|
346
366
|
}, [
|
|
347
367
|
webchatState.messagesJSON,
|
|
348
|
-
webchatState.session,
|
|
349
|
-
webchatState.lastRoutePath,
|
|
350
368
|
webchatState.devSettings,
|
|
351
369
|
webchatState.lastMessageUpdate,
|
|
370
|
+
webchatState.jwt,
|
|
371
|
+
webchatState.user,
|
|
372
|
+
webchatState.session,
|
|
373
|
+
webchatState.botState,
|
|
352
374
|
])
|
|
353
375
|
|
|
354
376
|
useAsyncEffect(async () => {
|
|
355
|
-
if (!webchatState.
|
|
377
|
+
if (!webchatState.isWebchatOnline) {
|
|
356
378
|
setError({
|
|
357
379
|
message: getServerErrorMessage(props.server),
|
|
358
380
|
})
|
|
@@ -361,7 +383,7 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
361
383
|
setError(undefined)
|
|
362
384
|
}
|
|
363
385
|
}
|
|
364
|
-
}, [webchatState.
|
|
386
|
+
}, [webchatState.isWebchatOnline])
|
|
365
387
|
|
|
366
388
|
useTyping({ webchatState, updateTyping, updateMessage, host })
|
|
367
389
|
|
|
@@ -428,7 +450,7 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
428
450
|
)
|
|
429
451
|
if (!Array.isArray(blockInputs)) return false
|
|
430
452
|
for (const rule of blockInputs) {
|
|
431
|
-
if (getBlockInputs(rule, input.
|
|
453
|
+
if (getBlockInputs(rule, input.text)) {
|
|
432
454
|
addMessageComponent(
|
|
433
455
|
<Text
|
|
434
456
|
id={input.id}
|
|
@@ -503,36 +525,36 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
503
525
|
|
|
504
526
|
const messageComponentFromInput = input => {
|
|
505
527
|
let messageComponent = null
|
|
528
|
+
let props = { ...input }
|
|
506
529
|
if (isText(input)) {
|
|
507
|
-
messageComponent =
|
|
508
|
-
<Text id={input.id} payload={input.payload} from={SENDERS.user}>
|
|
509
|
-
{input.data}
|
|
510
|
-
</Text>
|
|
511
|
-
)
|
|
530
|
+
messageComponent = <Text {...props}>{input.text}</Text>
|
|
512
531
|
} else if (isMedia(input)) {
|
|
513
|
-
const temporaryDisplayUrl = URL.createObjectURL(input.
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
}
|
|
519
|
-
if (isImage(input)) messageComponent = <Image {...mediaProps} />
|
|
520
|
-
else if (isAudio(input)) messageComponent = <Audio {...mediaProps} />
|
|
521
|
-
else if (isVideo(input)) messageComponent = <Video {...mediaProps} />
|
|
522
|
-
else if (isDocument(input))
|
|
523
|
-
messageComponent = <Document {...mediaProps} />
|
|
532
|
+
const temporaryDisplayUrl = URL.createObjectURL(input.src)
|
|
533
|
+
props = { ...props, src: temporaryDisplayUrl }
|
|
534
|
+
if (isImage(input)) messageComponent = <Image {...props} />
|
|
535
|
+
else if (isAudio(input)) messageComponent = <Audio {...props} />
|
|
536
|
+
else if (isVideo(input)) messageComponent = <Video {...props} />
|
|
537
|
+
else if (isDocument(input)) messageComponent = <Document {...props} />
|
|
524
538
|
}
|
|
525
539
|
return messageComponent
|
|
526
540
|
}
|
|
527
541
|
|
|
528
542
|
const sendInput = async input => {
|
|
529
543
|
if (!input || Object.keys(input).length == 0) return
|
|
530
|
-
if (isText(input) && (!input.
|
|
544
|
+
if (isText(input) && (!input.text || !input.text.trim())) return // in case trim() doesn't work in a browser we can use !/\S/.test(input.text)
|
|
531
545
|
if (isText(input) && checkBlockInput(input)) return
|
|
532
546
|
if (!input.id) input.id = uuidv4()
|
|
547
|
+
const { idFromChannel, channel } = webchatState.user
|
|
548
|
+
input = {
|
|
549
|
+
idFromChannel,
|
|
550
|
+
channel,
|
|
551
|
+
ack: MessageEventAck.DRAFT,
|
|
552
|
+
from: MessageEventFrom.USER,
|
|
553
|
+
...input,
|
|
554
|
+
}
|
|
533
555
|
const messageComponent = messageComponentFromInput(input)
|
|
534
556
|
if (messageComponent) addMessageComponent(messageComponent)
|
|
535
|
-
if (isMedia(input)) input.
|
|
557
|
+
if (isMedia(input)) input.src = await readDataURL(input.src)
|
|
536
558
|
sendUserInput(input)
|
|
537
559
|
updateLatestInput(input)
|
|
538
560
|
isOnline() && updateLastMessageDate(currentDateString())
|
|
@@ -545,27 +567,28 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
545
567
|
https://stackoverflow.com/questions/37949981/call-child-method-from-parent
|
|
546
568
|
*/
|
|
547
569
|
|
|
548
|
-
const
|
|
549
|
-
|
|
570
|
+
const mergeAndUpdateUser = userToUpdate =>
|
|
571
|
+
updateUser(merge(webchatState.user, userToUpdate))
|
|
550
572
|
|
|
551
573
|
useImperativeHandle(ref, () => ({
|
|
552
574
|
addBotResponse: ({ response, session, lastRoutePath }) => {
|
|
553
575
|
updateTyping(false)
|
|
554
576
|
if (Array.isArray(response)) response.map(r => addMessageComponent(r))
|
|
555
577
|
else if (response) addMessageComponent(response)
|
|
556
|
-
if (session) {
|
|
557
|
-
updateSession(merge(session, { user: webchatState.session.user }))
|
|
558
|
-
const action = session._botonic_action || ''
|
|
559
|
-
const handoff = action.startsWith('create_case')
|
|
560
|
-
if (handoff && isDev) addMessageComponent(<Handoff />)
|
|
561
|
-
updateHandoff(handoff)
|
|
562
|
-
}
|
|
563
|
-
if (lastRoutePath) updateLastRoutePath(lastRoutePath)
|
|
564
578
|
updateLastMessageDate(currentDateString())
|
|
565
579
|
},
|
|
566
580
|
setTyping: typing => updateTyping(typing),
|
|
567
581
|
addUserMessage: message => sendInput(message),
|
|
568
|
-
updateUser:
|
|
582
|
+
updateUser: mergeAndUpdateUser,
|
|
583
|
+
updateBotState: botState => {
|
|
584
|
+
// TODO: Review handoff logic for 1.0
|
|
585
|
+
// const action = botState.botonicAction || ''
|
|
586
|
+
// // const isHandoff = action.startsWith('create_case')
|
|
587
|
+
if (botState.isHandoff && isDev) addMessageComponent(<Handoff />)
|
|
588
|
+
updateBotState(botState)
|
|
589
|
+
// updateHandoff(botState.isHandoff)
|
|
590
|
+
},
|
|
591
|
+
updateSession: updateSession,
|
|
569
592
|
openWebchat: () => toggleWebchat(true),
|
|
570
593
|
closeWebchat: () => toggleWebchat(false),
|
|
571
594
|
toggleWebchat: () => toggleWebchat(!webchatState.isWebchatOpen),
|
|
@@ -598,26 +621,30 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
598
621
|
}))
|
|
599
622
|
|
|
600
623
|
const resolveCase = () => {
|
|
601
|
-
updateHandoff(false)
|
|
602
|
-
|
|
624
|
+
// updateHandoff(false)
|
|
625
|
+
updateBotState({
|
|
626
|
+
...webchatState.botState,
|
|
627
|
+
isHandoff: false,
|
|
628
|
+
botonicAction: null,
|
|
629
|
+
})
|
|
603
630
|
}
|
|
604
631
|
|
|
605
|
-
const
|
|
632
|
+
const previousBotState = usePrevious(webchatState.botState)
|
|
606
633
|
useEffect(() => {
|
|
607
634
|
// Resume conversation after handoff
|
|
608
635
|
if (
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
!webchatState.
|
|
636
|
+
previousBotState &&
|
|
637
|
+
previousBotState.botonicAction &&
|
|
638
|
+
!webchatState.botState.botonicAction
|
|
612
639
|
) {
|
|
613
|
-
const action = getParsedAction(
|
|
640
|
+
const action = getParsedAction(previousBotState.botonicAction)
|
|
614
641
|
if (action && action.on_finish) sendPayload(action.on_finish)
|
|
615
642
|
}
|
|
616
|
-
}, [webchatState.
|
|
643
|
+
}, [webchatState.botState.botonicAction])
|
|
617
644
|
|
|
618
645
|
const sendText = async (text, payload) => {
|
|
619
646
|
if (!text) return
|
|
620
|
-
const input = { type: INPUT.TEXT,
|
|
647
|
+
const input = { type: INPUT.TEXT, text, payload }
|
|
621
648
|
await sendInput(input)
|
|
622
649
|
}
|
|
623
650
|
|
|
@@ -633,7 +660,7 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
633
660
|
if (!attachmentType) return
|
|
634
661
|
const input = {
|
|
635
662
|
type: attachmentType,
|
|
636
|
-
|
|
663
|
+
src: attachment.file,
|
|
637
664
|
}
|
|
638
665
|
await sendInput(input)
|
|
639
666
|
setCurrentAttachment(undefined)
|
|
@@ -653,8 +680,8 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
653
680
|
}
|
|
654
681
|
|
|
655
682
|
const webviewRequestContext = {
|
|
656
|
-
getString: stringId => props.getString(stringId, webchatState.
|
|
657
|
-
setLocale: locale => props.getString(locale, webchatState.
|
|
683
|
+
getString: stringId => props.getString(stringId, webchatState.botState),
|
|
684
|
+
setLocale: locale => props.getString(locale, webchatState.botState),
|
|
658
685
|
session: webchatState.session || {},
|
|
659
686
|
params: webchatState.webviewParams || {},
|
|
660
687
|
closeWebview: closeWebview,
|
|
@@ -914,7 +941,7 @@ export const Webchat = forwardRef((props, ref) => {
|
|
|
914
941
|
updateMessage,
|
|
915
942
|
updateReplies,
|
|
916
943
|
updateLatestInput,
|
|
917
|
-
updateUser:
|
|
944
|
+
updateUser: mergeAndUpdateUser,
|
|
918
945
|
updateWebchatDevSettings: updateWebchatDevSettings,
|
|
919
946
|
}}
|
|
920
947
|
>
|
|
@@ -3,9 +3,9 @@ import merge from 'lodash.merge'
|
|
|
3
3
|
import React, { createRef } from 'react'
|
|
4
4
|
import { render } from 'react-dom'
|
|
5
5
|
|
|
6
|
-
import { SENDERS, WEBCHAT } from '
|
|
7
|
-
import { isShadowDOMSupported, onDOMLoaded } from '../util/dom'
|
|
6
|
+
import { SENDERS, WEBCHAT } from './constants'
|
|
8
7
|
import { msgToBotonic } from './msg-to-botonic'
|
|
8
|
+
import { isShadowDOMSupported, onDOMLoaded } from './util/dom'
|
|
9
9
|
import { Webchat } from './webchat/webchat'
|
|
10
10
|
|
|
11
11
|
export class WebchatApp {
|
|
@@ -139,18 +139,27 @@ export class WebchatApp {
|
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
onServiceEvent(event) {
|
|
142
|
-
|
|
142
|
+
const { action, ...eventData } = event
|
|
143
|
+
if (action === 'connection_change')
|
|
143
144
|
this.webchatRef.current.setOnline(event.online)
|
|
144
|
-
else if (
|
|
145
|
-
this.updateMessageInfo(
|
|
146
|
-
} else if (
|
|
147
|
-
this.
|
|
148
|
-
} else if (
|
|
149
|
-
this.
|
|
150
|
-
} else {
|
|
145
|
+
else if (action === 'update_message_info') {
|
|
146
|
+
this.updateMessageInfo(eventData.id, eventData)
|
|
147
|
+
} else if (action === 'update_user') {
|
|
148
|
+
this.updateUser(eventData)
|
|
149
|
+
} else if (action === 'update_session') {
|
|
150
|
+
this.updateSession(eventData.session)
|
|
151
|
+
} else if (action === 'update_bot_state') {
|
|
152
|
+
this.updateBotState(eventData.botState)
|
|
153
|
+
}
|
|
154
|
+
// TODO: Discuss how this updates to be done
|
|
155
|
+
else if (eventData.type === 'update_webchat_settings')
|
|
156
|
+
this.updateWebchatSettings(event.data)
|
|
157
|
+
else if (eventData.type === 'sender_action')
|
|
158
|
+
this.setTyping(event.data === 'typing_on')
|
|
159
|
+
else if (eventData.eventType === 'message') {
|
|
151
160
|
this.onMessage &&
|
|
152
|
-
this.onMessage(this, { from: SENDERS.bot, message:
|
|
153
|
-
this.addBotMessage(
|
|
161
|
+
this.onMessage(this, { from: SENDERS.bot, message: eventData })
|
|
162
|
+
this.addBotMessage(eventData)
|
|
154
163
|
}
|
|
155
164
|
}
|
|
156
165
|
|
|
@@ -158,6 +167,14 @@ export class WebchatApp {
|
|
|
158
167
|
this.webchatRef.current.updateUser(user)
|
|
159
168
|
}
|
|
160
169
|
|
|
170
|
+
updateSession(session) {
|
|
171
|
+
this.webchatRef.current.updateSession(session)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
updateBotState(botState) {
|
|
175
|
+
this.webchatRef.current.updateBotState(botState)
|
|
176
|
+
}
|
|
177
|
+
|
|
161
178
|
addBotMessage(message) {
|
|
162
179
|
this.webchatRef.current.addBotResponse({
|
|
163
180
|
response: msgToBotonic(
|
|
@@ -240,7 +257,7 @@ export class WebchatApp {
|
|
|
240
257
|
}
|
|
241
258
|
|
|
242
259
|
// eslint-disable-next-line complexity
|
|
243
|
-
getComponent(optionsAtRuntime = {}) {
|
|
260
|
+
getComponent(host, optionsAtRuntime = {}) {
|
|
244
261
|
let {
|
|
245
262
|
theme = {},
|
|
246
263
|
persistentMenu,
|
|
@@ -258,6 +275,7 @@ export class WebchatApp {
|
|
|
258
275
|
onOpen,
|
|
259
276
|
onClose,
|
|
260
277
|
onMessage,
|
|
278
|
+
hostId,
|
|
261
279
|
appId,
|
|
262
280
|
visibility,
|
|
263
281
|
server,
|
|
@@ -282,6 +300,8 @@ export class WebchatApp {
|
|
|
282
300
|
this.onMessage = onMessage || this.onMessage
|
|
283
301
|
this.visibility = visibility || this.visibility
|
|
284
302
|
this.appId = appId || this.appId
|
|
303
|
+
this.hostId = hostId || this.hostId
|
|
304
|
+
this.createRootElement(host)
|
|
285
305
|
return (
|
|
286
306
|
<Webchat
|
|
287
307
|
{...webchatOptions}
|
|
@@ -306,10 +326,15 @@ export class WebchatApp {
|
|
|
306
326
|
onUserInput={(...args) => this.onUserInput(...args)}
|
|
307
327
|
onStateChange={webchatState => this.onStateChange(webchatState)}
|
|
308
328
|
server={server}
|
|
329
|
+
doAuth={(...args) => this.doAuth(...args)}
|
|
309
330
|
/>
|
|
310
331
|
)
|
|
311
332
|
}
|
|
312
333
|
|
|
334
|
+
doAuth() {
|
|
335
|
+
// TODO: we should inject the service in question to WebchatApp and do call this one
|
|
336
|
+
}
|
|
337
|
+
|
|
313
338
|
async isWebchatVisible({ appId }) {
|
|
314
339
|
try {
|
|
315
340
|
const { status } = await HubtypeService.getWebchatVisibility({
|
|
@@ -337,11 +362,10 @@ export class WebchatApp {
|
|
|
337
362
|
|
|
338
363
|
async render(dest, optionsAtRuntime = {}) {
|
|
339
364
|
onDOMLoaded(async () => {
|
|
340
|
-
this.createRootElement(dest)
|
|
341
365
|
const isVisible = await this.resolveWebchatVisibility(optionsAtRuntime)
|
|
342
366
|
if (isVisible)
|
|
343
367
|
render(
|
|
344
|
-
this.getComponent(optionsAtRuntime),
|
|
368
|
+
this.getComponent(dest, optionsAtRuntime),
|
|
345
369
|
this.getReactMountNode(dest)
|
|
346
370
|
)
|
|
347
371
|
})
|
package/src/index.d.ts
CHANGED
package/src/util/dom.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { WEBCHAT } from '../constants'
|
|
2
2
|
|
|
3
|
+
export const getScrollableContent = webchatElement => {
|
|
4
|
+
return webchatElement.querySelector(WEBCHAT.SELECTORS.SCROLLABLE_CONTENT)
|
|
5
|
+
}
|
|
6
|
+
|
|
3
7
|
export const getScrollableArea = webchatElement => {
|
|
4
8
|
const getArea = area => {
|
|
5
|
-
const botonicScrollableContent = webchatElement
|
|
6
|
-
WEBCHAT.SELECTORS.SCROLLABLE_CONTENT
|
|
7
|
-
)
|
|
9
|
+
const botonicScrollableContent = getScrollableContent(webchatElement)
|
|
8
10
|
const scrollableArea =
|
|
9
11
|
botonicScrollableContent && botonicScrollableContent.querySelector(area)
|
|
10
12
|
return scrollableArea
|
package/src/webchat/actions.jsx
CHANGED
|
@@ -4,21 +4,33 @@ import { ScrollbarController } from './scrollbar-controller'
|
|
|
4
4
|
import { WebchatResizer } from './webchat-resizer'
|
|
5
5
|
|
|
6
6
|
export class DeviceAdapter {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.currentDevice = this.getCurrentDevice()
|
|
9
|
+
}
|
|
10
|
+
|
|
7
11
|
init(host) {
|
|
8
|
-
this.currentDevice = navigator.platform
|
|
9
12
|
this.webchatResizer = new WebchatResizer(this.currentDevice, host)
|
|
10
13
|
this.scrollbarController = new ScrollbarController(this.currentDevice, host)
|
|
11
14
|
this.scrollbarController.handleScrollEvents()
|
|
12
15
|
}
|
|
13
16
|
|
|
17
|
+
getCurrentDevice() {
|
|
18
|
+
// navigator.platform deprecated. Ref: (https://erikmartinjordan.com/navigator-platform-deprecated-alternative)
|
|
19
|
+
if (navigator.userAgentData) return navigator.userAgentData.platform
|
|
20
|
+
return navigator.platform
|
|
21
|
+
}
|
|
22
|
+
|
|
14
23
|
onFocus(host) {
|
|
15
24
|
if (this.currentDevice !== DEVICES.MOBILE.IPHONE) {
|
|
16
25
|
scrollToBottom({ host, timeout: 800 })
|
|
17
26
|
return
|
|
18
27
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
28
|
+
setTimeout(() => {
|
|
29
|
+
// Place onFocus logic to be run the last on the queue of asynchronous events to give enough time to init method to be called. Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop#zero_delays
|
|
30
|
+
this.webchatResizer.onFocus(() =>
|
|
31
|
+
this.scrollbarController.handleOnTouchMoveEvents()
|
|
32
|
+
)
|
|
33
|
+
}, 0)
|
|
22
34
|
}
|
|
23
35
|
|
|
24
36
|
onBlur() {
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
getScrollableArea,
|
|
3
|
+
getScrollableContent,
|
|
4
|
+
getWebchatElement,
|
|
5
|
+
} from '../../util/dom'
|
|
2
6
|
import { DEVICES, isMobileDevice } from '.'
|
|
3
7
|
|
|
4
8
|
const debounced = (delay, fn) => {
|
|
@@ -28,7 +32,7 @@ export class ScrollbarController {
|
|
|
28
32
|
|
|
29
33
|
handleScrollEvents() {
|
|
30
34
|
/*
|
|
31
|
-
It handles scroll events for Mobile/Desktop.
|
|
35
|
+
It handles scroll events for Mobile/Desktop.
|
|
32
36
|
"ontouchmove" is the phone equivalent for "onmouseover"
|
|
33
37
|
*/
|
|
34
38
|
if (isMobileDevice()) {
|
|
@@ -61,11 +65,12 @@ export class ScrollbarController {
|
|
|
61
65
|
}
|
|
62
66
|
|
|
63
67
|
toggleOnMouseWheelEvents() {
|
|
68
|
+
const scrollableContent = getScrollableContent(this.webchat)
|
|
64
69
|
if (this.hasScrollbar()) {
|
|
65
|
-
|
|
70
|
+
scrollableContent.onmousewheel = {}
|
|
66
71
|
return
|
|
67
72
|
}
|
|
68
|
-
|
|
73
|
+
scrollableContent.onmousewheel = e => e.preventDefault()
|
|
69
74
|
}
|
|
70
75
|
|
|
71
76
|
handleOnTouchMoveEvents(e) {
|