@botonic/react 0.23.3 → 0.24.0-alpha.1

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.
Files changed (177) hide show
  1. package/index.d.ts +1 -1
  2. package/lib/cjs/assets/arrow-down.svg +3 -0
  3. package/lib/cjs/assets/arrow-scroll-down.svg +3 -0
  4. package/lib/cjs/assets/index-types.d.ts +4 -0
  5. package/lib/cjs/assets/index-types.js +2 -0
  6. package/lib/cjs/assets/index-types.js.map +1 -0
  7. package/lib/cjs/components/custom-message.js +2 -2
  8. package/lib/cjs/components/custom-message.js.map +1 -1
  9. package/lib/cjs/components/index-types.d.ts +10 -4
  10. package/lib/cjs/components/index-types.js.map +1 -1
  11. package/lib/cjs/components/message.js +21 -17
  12. package/lib/cjs/components/message.js.map +1 -1
  13. package/lib/cjs/components/timestamps.d.ts +2 -2
  14. package/lib/cjs/components/timestamps.js +5 -5
  15. package/lib/cjs/components/timestamps.js.map +1 -1
  16. package/lib/cjs/constants.d.ts +7 -5
  17. package/lib/cjs/constants.js +10 -6
  18. package/lib/cjs/constants.js.map +1 -1
  19. package/lib/cjs/contexts.js +6 -0
  20. package/lib/cjs/contexts.js.map +1 -1
  21. package/lib/cjs/dev-app.js +9 -3
  22. package/lib/cjs/dev-app.js.map +1 -1
  23. package/lib/cjs/index-types.d.ts +16 -2
  24. package/lib/cjs/index-types.js +7 -0
  25. package/lib/cjs/index-types.js.map +1 -1
  26. package/lib/cjs/msg-to-botonic.js +5 -2
  27. package/lib/cjs/msg-to-botonic.js.map +1 -1
  28. package/lib/cjs/webchat/actions.d.ts +19 -17
  29. package/lib/cjs/webchat/actions.js +19 -17
  30. package/lib/cjs/webchat/actions.js.map +1 -1
  31. package/lib/cjs/webchat/components/styled-scrollbar.js +1 -1
  32. package/lib/cjs/webchat/devices/device-adapter.js +1 -1
  33. package/lib/cjs/webchat/devices/device-adapter.js.map +1 -1
  34. package/lib/cjs/webchat/devices/webchat-resizer.js +1 -1
  35. package/lib/cjs/webchat/devices/webchat-resizer.js.map +1 -1
  36. package/lib/cjs/webchat/hooks/use-typing.d.ts +1 -1
  37. package/lib/cjs/webchat/hooks/use-typing.js +1 -3
  38. package/lib/cjs/webchat/hooks/use-typing.js.map +1 -1
  39. package/lib/cjs/webchat/hooks/use-webchat.d.ts +5 -1
  40. package/lib/cjs/webchat/hooks/use-webchat.js +15 -1
  41. package/lib/cjs/webchat/hooks/use-webchat.js.map +1 -1
  42. package/lib/cjs/webchat/index-types.d.ts +2 -1
  43. package/lib/cjs/webchat/message-list/index.d.ts +1 -0
  44. package/lib/cjs/webchat/message-list/index.js +77 -0
  45. package/lib/cjs/webchat/message-list/index.js.map +1 -0
  46. package/lib/cjs/webchat/message-list/intro-message.d.ts +1 -0
  47. package/lib/cjs/webchat/message-list/intro-message.js +23 -0
  48. package/lib/cjs/webchat/message-list/intro-message.js.map +1 -0
  49. package/lib/cjs/webchat/message-list/scroll-button.d.ts +5 -0
  50. package/lib/cjs/webchat/message-list/scroll-button.js +22 -0
  51. package/lib/cjs/webchat/message-list/scroll-button.js.map +1 -0
  52. package/lib/cjs/webchat/message-list/styles.d.ts +4 -0
  53. package/lib/cjs/webchat/message-list/styles.js +50 -0
  54. package/lib/cjs/webchat/message-list/styles.js.map +1 -0
  55. package/lib/cjs/webchat/message-list/unread-messages-banner.d.ts +6 -0
  56. package/lib/cjs/webchat/message-list/unread-messages-banner.js +21 -0
  57. package/lib/cjs/webchat/message-list/unread-messages-banner.js.map +1 -0
  58. package/lib/cjs/webchat/message-list/use-debounce.d.ts +1 -0
  59. package/lib/cjs/webchat/message-list/use-debounce.js +18 -0
  60. package/lib/cjs/webchat/message-list/use-debounce.js.map +1 -0
  61. package/lib/cjs/webchat/messages-reducer.js +31 -9
  62. package/lib/cjs/webchat/messages-reducer.js.map +1 -1
  63. package/lib/cjs/webchat/trigger-button/index.js +3 -2
  64. package/lib/cjs/webchat/trigger-button/index.js.map +1 -1
  65. package/lib/cjs/webchat/webchat-reducer.js +1 -1
  66. package/lib/cjs/webchat/webchat-reducer.js.map +1 -1
  67. package/lib/cjs/webchat/webchat.js +38 -22
  68. package/lib/cjs/webchat/webchat.js.map +1 -1
  69. package/lib/cjs/webchat-app.js +24 -9
  70. package/lib/cjs/webchat-app.js.map +1 -1
  71. package/lib/esm/assets/arrow-down.svg +3 -0
  72. package/lib/esm/assets/arrow-scroll-down.svg +3 -0
  73. package/lib/esm/assets/index-types.d.ts +4 -0
  74. package/lib/esm/assets/index-types.js +2 -0
  75. package/lib/esm/assets/index-types.js.map +1 -0
  76. package/lib/esm/components/custom-message.js +2 -2
  77. package/lib/esm/components/custom-message.js.map +1 -1
  78. package/lib/esm/components/index-types.d.ts +10 -4
  79. package/lib/esm/components/index-types.js.map +1 -1
  80. package/lib/esm/components/message.js +22 -18
  81. package/lib/esm/components/message.js.map +1 -1
  82. package/lib/esm/components/timestamps.d.ts +2 -2
  83. package/lib/esm/components/timestamps.js +5 -5
  84. package/lib/esm/components/timestamps.js.map +1 -1
  85. package/lib/esm/constants.d.ts +7 -5
  86. package/lib/esm/constants.js +9 -5
  87. package/lib/esm/constants.js.map +1 -1
  88. package/lib/esm/contexts.js +6 -0
  89. package/lib/esm/contexts.js.map +1 -1
  90. package/lib/esm/dev-app.js +9 -3
  91. package/lib/esm/dev-app.js.map +1 -1
  92. package/lib/esm/index-types.d.ts +16 -2
  93. package/lib/esm/index-types.js +6 -1
  94. package/lib/esm/index-types.js.map +1 -1
  95. package/lib/esm/msg-to-botonic.js +6 -3
  96. package/lib/esm/msg-to-botonic.js.map +1 -1
  97. package/lib/esm/webchat/actions.d.ts +19 -17
  98. package/lib/esm/webchat/actions.js +19 -17
  99. package/lib/esm/webchat/actions.js.map +1 -1
  100. package/lib/esm/webchat/components/styled-scrollbar.js +1 -1
  101. package/lib/esm/webchat/devices/device-adapter.js +1 -1
  102. package/lib/esm/webchat/devices/device-adapter.js.map +1 -1
  103. package/lib/esm/webchat/devices/webchat-resizer.js +1 -1
  104. package/lib/esm/webchat/devices/webchat-resizer.js.map +1 -1
  105. package/lib/esm/webchat/hooks/use-typing.d.ts +1 -1
  106. package/lib/esm/webchat/hooks/use-typing.js +1 -3
  107. package/lib/esm/webchat/hooks/use-typing.js.map +1 -1
  108. package/lib/esm/webchat/hooks/use-webchat.d.ts +5 -1
  109. package/lib/esm/webchat/hooks/use-webchat.js +15 -1
  110. package/lib/esm/webchat/hooks/use-webchat.js.map +1 -1
  111. package/lib/esm/webchat/index-types.d.ts +2 -1
  112. package/lib/esm/webchat/message-list/index.d.ts +1 -0
  113. package/lib/esm/webchat/message-list/index.js +73 -0
  114. package/lib/esm/webchat/message-list/index.js.map +1 -0
  115. package/lib/esm/webchat/message-list/intro-message.d.ts +1 -0
  116. package/lib/esm/webchat/message-list/intro-message.js +18 -0
  117. package/lib/esm/webchat/message-list/intro-message.js.map +1 -0
  118. package/lib/esm/webchat/message-list/scroll-button.d.ts +5 -0
  119. package/lib/esm/webchat/message-list/scroll-button.js +17 -0
  120. package/lib/esm/webchat/message-list/scroll-button.js.map +1 -0
  121. package/lib/esm/webchat/message-list/styles.d.ts +4 -0
  122. package/lib/esm/webchat/message-list/styles.js +46 -0
  123. package/lib/esm/webchat/message-list/styles.js.map +1 -0
  124. package/lib/esm/webchat/message-list/unread-messages-banner.d.ts +6 -0
  125. package/lib/esm/webchat/message-list/unread-messages-banner.js +16 -0
  126. package/lib/esm/webchat/message-list/unread-messages-banner.js.map +1 -0
  127. package/lib/esm/webchat/message-list/use-debounce.d.ts +1 -0
  128. package/lib/esm/webchat/message-list/use-debounce.js +14 -0
  129. package/lib/esm/webchat/message-list/use-debounce.js.map +1 -0
  130. package/lib/esm/webchat/messages-reducer.js +31 -9
  131. package/lib/esm/webchat/messages-reducer.js.map +1 -1
  132. package/lib/esm/webchat/trigger-button/index.js +3 -2
  133. package/lib/esm/webchat/trigger-button/index.js.map +1 -1
  134. package/lib/esm/webchat/webchat-reducer.js +1 -1
  135. package/lib/esm/webchat/webchat-reducer.js.map +1 -1
  136. package/lib/esm/webchat/webchat.js +39 -23
  137. package/lib/esm/webchat/webchat.js.map +1 -1
  138. package/lib/esm/webchat-app.js +25 -10
  139. package/lib/esm/webchat-app.js.map +1 -1
  140. package/package.json +7 -5
  141. package/src/assets/arrow-down.svg +3 -0
  142. package/src/assets/arrow-scroll-down.svg +3 -0
  143. package/src/assets/index-types.ts +4 -0
  144. package/src/components/custom-message.jsx +2 -2
  145. package/src/components/index-types.ts +8 -4
  146. package/src/components/message.jsx +29 -21
  147. package/src/components/timestamps.jsx +5 -5
  148. package/src/constants.js +9 -6
  149. package/src/contexts.tsx +6 -0
  150. package/src/dev-app.jsx +9 -3
  151. package/src/index-types.ts +18 -3
  152. package/src/msg-to-botonic.jsx +2 -3
  153. package/src/webchat/actions.ts +19 -17
  154. package/src/webchat/components/styled-scrollbar.jsx +1 -1
  155. package/src/webchat/devices/device-adapter.js +1 -1
  156. package/src/webchat/devices/webchat-resizer.js +1 -1
  157. package/src/webchat/hooks/use-typing.ts +0 -3
  158. package/src/webchat/hooks/use-webchat.ts +18 -2
  159. package/src/webchat/index-types.ts +2 -1
  160. package/src/webchat/message-list/index.tsx +125 -0
  161. package/src/webchat/message-list/intro-message.tsx +38 -0
  162. package/src/webchat/message-list/scroll-button.tsx +45 -0
  163. package/src/webchat/message-list/styles.ts +49 -0
  164. package/src/webchat/message-list/unread-messages-banner.tsx +52 -0
  165. package/src/webchat/message-list/use-debounce.ts +16 -0
  166. package/src/webchat/messages-reducer.ts +42 -5
  167. package/src/webchat/trigger-button/index.tsx +9 -4
  168. package/src/webchat/webchat-reducer.ts +0 -1
  169. package/src/webchat/webchat.jsx +73 -50
  170. package/src/webchat-app.jsx +25 -14
  171. package/lib/cjs/webchat/message-list.d.ts +0 -1
  172. package/lib/cjs/webchat/message-list.js +0 -39
  173. package/lib/cjs/webchat/message-list.js.map +0 -1
  174. package/lib/esm/webchat/message-list.d.ts +0 -1
  175. package/lib/esm/webchat/message-list.js +0 -34
  176. package/lib/esm/webchat/message-list.js.map +0 -1
  177. package/src/webchat/message-list.jsx +0 -77
@@ -0,0 +1,45 @@
1
+ import React, { useContext } from 'react'
2
+
3
+ import ArrowScrollDown from '../../assets/arrow-scroll-down.svg'
4
+ import { WEBCHAT } from '../../constants'
5
+ import { WebchatContext } from '../../contexts'
6
+ import { resolveImage } from '../../util/environment'
7
+ import { ContainerScrollButton } from './styles'
8
+ import { useDebounce } from './use-debounce'
9
+
10
+ interface ScrollButtonProps {
11
+ handleClick: () => void
12
+ }
13
+
14
+ export const ScrollButton = ({
15
+ handleClick,
16
+ }: ScrollButtonProps): JSX.Element => {
17
+ const { getThemeProperty } = useContext(WebchatContext)
18
+
19
+ const show = useDebounce()
20
+
21
+ const CustomScrollButton = getThemeProperty(
22
+ WEBCHAT.CUSTOM_PROPERTIES.scrollButtonCustom,
23
+ undefined
24
+ )
25
+
26
+ const scrollButtonEnabled = getThemeProperty(
27
+ WEBCHAT.CUSTOM_PROPERTIES.scrollButtonEnabled,
28
+ CustomScrollButton
29
+ )
30
+
31
+ return (
32
+ scrollButtonEnabled &&
33
+ show && (
34
+ <>
35
+ {CustomScrollButton ? (
36
+ <CustomScrollButton handleScrollToBottom={handleClick} />
37
+ ) : (
38
+ <ContainerScrollButton onClick={handleClick}>
39
+ <img src={resolveImage(ArrowScrollDown)} />
40
+ </ContainerScrollButton>
41
+ )}
42
+ </>
43
+ )
44
+ )
45
+ }
@@ -0,0 +1,49 @@
1
+ import styled from 'styled-components'
2
+
3
+ export const ContainerMessage = styled.div`
4
+ display: flex;
5
+ overflow-x: hidden;
6
+ flex-direction: column;
7
+ flex: none;
8
+ white-space: pre;
9
+ word-wrap: break-word;
10
+ `
11
+
12
+ export const DefaultIntroImage = styled.img`
13
+ max-height: 50%;
14
+ width: 100%;
15
+ `
16
+
17
+ export const ContainerScrollButton = styled.div`
18
+ position: absolute;
19
+ right: 10px;
20
+ bottom: 65px;
21
+
22
+ background-color: #6d6a78;
23
+ cursor: pointer;
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: center;
27
+
28
+ width: 37px;
29
+ height: 37px;
30
+ border-radius: 50%;
31
+ `
32
+
33
+ export const ContainerUnreadMessagesBanner = styled.div`
34
+ display: flex;
35
+ justify-content: center;
36
+ align-items: center;
37
+ gap: 5px;
38
+
39
+ border-top: 1px solid #e8e8ea;
40
+ padding: 8px;
41
+ color: #6d6a78;
42
+ font-size: 14px;
43
+ font-weight: 400;
44
+ width: 100%;
45
+
46
+ img {
47
+ width: 10px;
48
+ }
49
+ `
@@ -0,0 +1,52 @@
1
+ import React, { useContext } from 'react'
2
+
3
+ import ArrowDown from '../../assets/arrow-down.svg'
4
+ import { WEBCHAT } from '../../constants'
5
+ import { WebchatContext } from '../../contexts'
6
+ import { resolveImage } from '../../util/environment'
7
+ import { ContainerUnreadMessagesBanner } from './styles'
8
+
9
+ interface UnreadMessagesBannerProps {
10
+ unreadMessagesBannerRef: React.RefObject<HTMLDivElement>
11
+ }
12
+
13
+ export const UnreadMessagesBanner = ({
14
+ unreadMessagesBannerRef,
15
+ }: UnreadMessagesBannerProps): JSX.Element => {
16
+ const { getThemeProperty, webchatState } = useContext(WebchatContext)
17
+
18
+ const CustomUnreadMessagesBanner = getThemeProperty(
19
+ WEBCHAT.CUSTOM_PROPERTIES.notificationsBannerCustom,
20
+ undefined
21
+ )
22
+
23
+ const notificationsBannerEnabled = getThemeProperty(
24
+ WEBCHAT.CUSTOM_PROPERTIES.notificationsBannerEnabled,
25
+ undefined
26
+ )
27
+
28
+ const notificationsEnabled = getThemeProperty(
29
+ WEBCHAT.CUSTOM_PROPERTIES.notificationsEnabled,
30
+ CustomUnreadMessagesBanner || notificationsBannerEnabled
31
+ )
32
+
33
+ const text = getThemeProperty(
34
+ WEBCHAT.CUSTOM_PROPERTIES.notificationsBannerText,
35
+ 'unread messages'
36
+ )
37
+
38
+ return (
39
+ notificationsEnabled && (
40
+ <div ref={unreadMessagesBannerRef}>
41
+ {CustomUnreadMessagesBanner ? (
42
+ <CustomUnreadMessagesBanner />
43
+ ) : (
44
+ <ContainerUnreadMessagesBanner>
45
+ <img src={resolveImage(ArrowDown)} />
46
+ {webchatState.numUnreadMessages} {text}
47
+ </ContainerUnreadMessagesBanner>
48
+ )}
49
+ </div>
50
+ )
51
+ )
52
+ }
@@ -0,0 +1,16 @@
1
+ import { useEffect, useState } from 'react'
2
+
3
+ export function useDebounce(delay?: number) {
4
+ const [show, setShow] = useState(false)
5
+ useEffect(() => {
6
+ const timeoutId = setTimeout(() => {
7
+ setShow(true)
8
+ }, delay || 500)
9
+
10
+ return () => {
11
+ clearTimeout(timeoutId)
12
+ }
13
+ }, [])
14
+
15
+ return show
16
+ }
@@ -19,12 +19,20 @@ export const messagesReducer = (
19
19
  ...state,
20
20
  messagesJSON: [],
21
21
  messagesComponents: [],
22
+ numUnreadMessages: 0,
22
23
  }
23
24
  case WebchatAction.UPDATE_LAST_MESSAGE_DATE:
24
25
  return {
25
26
  ...state,
26
27
  lastMessageUpdate: action.payload,
27
28
  }
29
+ case WebchatAction.RESET_UNREAD_MESSAGES:
30
+ return resetUnreadMessages(state)
31
+ case WebchatAction.SET_LAST_MESSAGE_VISIBLE:
32
+ return {
33
+ ...state,
34
+ isLastMessageVisible: action.payload,
35
+ }
28
36
  default:
29
37
  throw new Error()
30
38
  }
@@ -36,15 +44,38 @@ function addMessageComponent(
36
44
  ) {
37
45
  const messageComponent = action.payload
38
46
  const isUnreadMessage =
39
- !state.isWebchatOpen && messageComponent.props?.ack !== 1
40
- const unreadMessages = isUnreadMessage
41
- ? state.unreadMessages + 1
42
- : state.unreadMessages
47
+ messageComponent.props?.isUnread &&
48
+ messageComponent.props?.sent_by !== 'user'
49
+
50
+ const numUnreadMessages = isUnreadMessage
51
+ ? state.numUnreadMessages + 1
52
+ : state.numUnreadMessages
43
53
 
44
54
  return {
45
55
  ...state,
46
56
  messagesComponents: [...(state.messagesComponents || []), messageComponent],
47
- unreadMessages,
57
+ numUnreadMessages,
58
+ }
59
+ }
60
+
61
+ function resetUnreadMessages(state: WebchatState) {
62
+ const messagesComponents = state.messagesComponents.map(messageComponent => {
63
+ if (messageComponent.props.isUnread) {
64
+ messageComponent.props.isUnread = false
65
+ }
66
+ return messageComponent
67
+ })
68
+ const messagesJSON = state.messagesJSON.map(messageJSON => {
69
+ if (messageJSON.isUnread) {
70
+ messageJSON.isUnread = false
71
+ }
72
+ return messageJSON
73
+ })
74
+ return {
75
+ ...state,
76
+ messagesComponents,
77
+ messagesJSON,
78
+ numUnreadMessages: 0,
48
79
  }
49
80
  }
50
81
 
@@ -71,6 +102,11 @@ function updateMessageReducer(
71
102
  ],
72
103
  }
73
104
  }
105
+
106
+ const numUnreadMessages = state.messagesComponents.filter(
107
+ messageComponent => messageComponent.props.isUnread
108
+ ).length
109
+
74
110
  return {
75
111
  ...state,
76
112
  messagesJSON: [
@@ -79,6 +115,7 @@ function updateMessageReducer(
79
115
  ...state.messagesJSON.slice(msgIndex + 1),
80
116
  ],
81
117
  ...updatedMessageComponents,
118
+ numUnreadMessages,
82
119
  }
83
120
  }
84
121
 
@@ -32,11 +32,16 @@ export const TriggerButton = (): JSX.Element => {
32
32
  WEBCHAT.CUSTOM_PROPERTIES.triggerButtonStyle
33
33
  )
34
34
 
35
- const notificationsEnabled = getThemeProperty(
36
- WEBCHAT.CUSTOM_PROPERTIES.triggerButtonNotificationsEnabled,
35
+ const notificationsTriggerButtonEnabled = getThemeProperty(
36
+ WEBCHAT.CUSTOM_PROPERTIES.notificationsTriggerButtonEnabled,
37
37
  false
38
38
  )
39
39
 
40
+ const notificationsEnabled = getThemeProperty(
41
+ WEBCHAT.CUSTOM_PROPERTIES.notificationsEnabled,
42
+ notificationsTriggerButtonEnabled
43
+ )
44
+
40
45
  const CustomTriggerButton = getThemeProperty(
41
46
  WEBCHAT.CUSTOM_PROPERTIES.customTrigger,
42
47
  undefined
@@ -49,9 +54,9 @@ export const TriggerButton = (): JSX.Element => {
49
54
 
50
55
  return (
51
56
  <div onClick={handleClick}>
52
- {webchatState.unreadMessages !== 0 && notificationsEnabled && (
57
+ {webchatState.numUnreadMessages !== 0 && notificationsEnabled && (
53
58
  <UnreadMessagesCounter className='trigger-notifications'>
54
- {webchatState.unreadMessages}
59
+ {webchatState.numUnreadMessages}
55
60
  </UnreadMessagesCounter>
56
61
  )}
57
62
  {CustomTriggerButton ? (
@@ -26,7 +26,6 @@ export function webchatReducer(
26
26
  return {
27
27
  ...state,
28
28
  isWebchatOpen,
29
- unreadMessages: isWebchatOpen ? 0 : state.unreadMessages,
30
29
  }
31
30
  }
32
31
  case WebchatAction.TOGGLE_EMOJI_PICKER:
@@ -15,14 +15,9 @@ import { v4 as uuidv4 } from 'uuid'
15
15
  import { Audio, Document, Image, Text, Video } from '../components'
16
16
  import { Handoff } from '../components/handoff'
17
17
  import { normalizeWebchatSettings } from '../components/webchat-settings'
18
- import {
19
- COLORS,
20
- MAX_ALLOWED_SIZE_MB,
21
- ROLES,
22
- SENDERS,
23
- WEBCHAT,
24
- } from '../constants'
18
+ import { COLORS, MAX_ALLOWED_SIZE_MB, ROLES, WEBCHAT } from '../constants'
25
19
  import { RequestContext, WebchatContext } from '../contexts'
20
+ import { SENDERS } from '../index-types'
26
21
  import {
27
22
  getFullMimeWhitelist,
28
23
  getMediaType,
@@ -52,7 +47,6 @@ import {
52
47
  PersistentMenu,
53
48
  } from './components/persistent-menu'
54
49
  import { SendButton } from './components/send-button'
55
- import { TypingIndicator } from './components/typing-indicator'
56
50
  import { DeviceAdapter } from './devices/device-adapter'
57
51
  import { StyledWebchatHeader } from './header'
58
52
  import {
@@ -143,30 +137,32 @@ const DarkBackgroundMenu = styled.div`
143
137
  // eslint-disable-next-line complexity, react/display-name
144
138
  export const Webchat = forwardRef((props, ref) => {
145
139
  const {
146
- webchatState,
147
140
  addMessage,
148
141
  addMessageComponent,
149
- updateMessage,
150
- updateReplies,
151
- updateLatestInput,
152
- updateTyping,
153
- updateWebview,
154
- updateSession,
155
- updateLastRoutePath,
156
- updateHandoff,
157
- updateTheme,
158
- updateDevSettings,
159
- toggleWebchat,
160
- toggleEmojiPicker,
161
- togglePersistentMenu,
162
- toggleCoverComponent,
142
+ clearMessages,
163
143
  doRenderCustomComponent,
144
+ openWebviewT,
145
+ resetUnreadMessages,
146
+ setCurrentAttachment,
164
147
  setError,
148
+ setLastMessageVisible,
165
149
  setOnline,
166
- clearMessages,
167
- openWebviewT,
150
+ toggleCoverComponent,
151
+ toggleEmojiPicker,
152
+ togglePersistentMenu,
153
+ toggleWebchat,
154
+ updateDevSettings,
155
+ updateHandoff,
168
156
  updateLastMessageDate,
169
- setCurrentAttachment,
157
+ updateLastRoutePath,
158
+ updateLatestInput,
159
+ updateMessage,
160
+ updateReplies,
161
+ updateSession,
162
+ updateTheme,
163
+ updateTyping,
164
+ updateWebview,
165
+ webchatState,
170
166
  // eslint-disable-next-line react-hooks/rules-of-hooks
171
167
  } = props.webchatHooks || useWebchat()
172
168
  const firstUpdate = useRef(true)
@@ -224,13 +220,16 @@ export const Webchat = forwardRef((props, ref) => {
224
220
  }, [webchatState.currentAttachment])
225
221
 
226
222
  const sendUserInput = async input => {
227
- props.onUserInput &&
223
+ if (props.onUserInput) {
224
+ resetUnreadMessages()
225
+ scrollToBottom({ host })
228
226
  props.onUserInput({
229
227
  user: webchatState.session.user,
230
228
  input: input,
231
229
  session: webchatState.session,
232
230
  lastRoutePath: webchatState.lastRoutePath,
233
231
  })
232
+ }
234
233
  }
235
234
 
236
235
  const sendChatEvent = async chatEvent => {
@@ -290,14 +289,14 @@ export const Webchat = forwardRef((props, ref) => {
290
289
  updateSession(session)
291
290
  if (shouldKeepSessionOnReload({ initialDevSettings, devSettings })) {
292
291
  if (messages) {
293
- messages.forEach(m => {
294
- addMessage(m)
295
- const newComponent = msgToBotonic(
296
- { ...m, delay: 0, typing: 0 },
292
+ messages.forEach(message => {
293
+ addMessage(message)
294
+ const newMessageComponent = msgToBotonic(
295
+ { ...message, delay: 0, typing: 0 },
297
296
  (props.theme.message && props.theme.message.customTypes) ||
298
297
  props.theme.customMessageTypes
299
298
  )
300
- if (newComponent) addMessageComponent(newComponent)
299
+ if (newMessageComponent) addMessageComponent(newMessageComponent)
301
300
  })
302
301
  }
303
302
  if (initialSession) updateSession(merge(initialSession, session))
@@ -312,14 +311,19 @@ export const Webchat = forwardRef((props, ref) => {
312
311
  }, [])
313
312
 
314
313
  useEffect(() => {
315
- if (!webchatState.isWebchatOpen) return
314
+ if (!webchatState.isWebchatOpen) {
315
+ if (webchatState.isLastMessageVisible) {
316
+ resetUnreadMessages()
317
+ }
318
+ return
319
+ }
316
320
  deviceAdapter.init(host)
317
- scrollToBottom({ behavior: 'auto', host })
318
321
  }, [webchatState.isWebchatOpen])
319
322
 
320
323
  useEffect(() => {
321
- if (onStateChange && typeof onStateChange === 'function')
324
+ if (onStateChange && typeof onStateChange === 'function') {
322
325
  onStateChange(webchatState)
326
+ }
323
327
  saveWebchatState(webchatState)
324
328
  }, [
325
329
  webchatState.messagesJSON,
@@ -410,7 +414,7 @@ export const Webchat = forwardRef((props, ref) => {
410
414
  addMessageComponent(
411
415
  <Text
412
416
  id={input.id}
413
- from={SENDERS.user}
417
+ sentBy={SENDERS.user}
414
418
  blob={false}
415
419
  style={{
416
420
  backgroundColor: COLORS.SCORPION_GRAY,
@@ -484,7 +488,7 @@ export const Webchat = forwardRef((props, ref) => {
484
488
  let messageComponent = null
485
489
  if (isText(input)) {
486
490
  messageComponent = (
487
- <Text id={input.id} payload={input.payload} from={SENDERS.user}>
491
+ <Text id={input.id} payload={input.payload} sentBy={SENDERS.user}>
488
492
  {input.data}
489
493
  </Text>
490
494
  )
@@ -492,7 +496,7 @@ export const Webchat = forwardRef((props, ref) => {
492
496
  const temporaryDisplayUrl = URL.createObjectURL(input.data)
493
497
  const mediaProps = {
494
498
  id: input.id,
495
- from: SENDERS.user,
499
+ sentBy: SENDERS.user,
496
500
  src: temporaryDisplayUrl,
497
501
  }
498
502
  if (isImage(input)) {
@@ -532,8 +536,21 @@ export const Webchat = forwardRef((props, ref) => {
532
536
  useImperativeHandle(ref, () => ({
533
537
  addBotResponse: ({ response, session, lastRoutePath }) => {
534
538
  updateTyping(false)
535
- if (Array.isArray(response)) response.map(r => addMessageComponent(r))
536
- else if (response) addMessageComponent(response)
539
+
540
+ const isUnread =
541
+ !webchatState.isLastMessageVisible || webchatState.numUnreadMessages > 0
542
+
543
+ if (Array.isArray(response)) {
544
+ response.forEach(r => {
545
+ addMessageComponent({ ...r, props: { ...r.props, isUnread } })
546
+ })
547
+ } else if (response) {
548
+ addMessageComponent({
549
+ ...response,
550
+ props: { ...response.props, isUnread },
551
+ })
552
+ }
553
+
537
554
  if (session) {
538
555
  updateSession(merge(session, { user: webchatState.session.user }))
539
556
  const action = session._botonic_action || ''
@@ -541,7 +558,9 @@ export const Webchat = forwardRef((props, ref) => {
541
558
  if (handoff && isDev) addMessageComponent(<Handoff />)
542
559
  updateHandoff(handoff)
543
560
  }
561
+
544
562
  if (lastRoutePath) updateLastRoutePath(lastRoutePath)
563
+
545
564
  updateLastMessageDate(currentDateString())
546
565
  },
547
566
  setTyping: typing => updateTyping(typing),
@@ -685,7 +704,9 @@ export const Webchat = forwardRef((props, ref) => {
685
704
  firstUpdate.current = false
686
705
  return
687
706
  }
707
+
688
708
  if (webchatState.isWebchatOpen && props.onOpen) props.onOpen()
709
+
689
710
  if (!webchatState.isWebchatOpen && props.onClose && !firstUpdate.current) {
690
711
  props.onClose()
691
712
  toggleEmojiPicker(false)
@@ -693,11 +714,6 @@ export const Webchat = forwardRef((props, ref) => {
693
714
  }
694
715
  }, [webchatState.isWebchatOpen])
695
716
 
696
- const webchatMessageList = () => (
697
- <WebchatMessageList style={{ flex: 1 }}>
698
- {webchatState.typing && <TypingIndicator />}
699
- </WebchatMessageList>
700
- )
701
717
  const webchatReplies = () => <WebchatReplies replies={webchatState.replies} />
702
718
 
703
719
  const isUserInputEnabled = () => {
@@ -737,8 +753,12 @@ export const Webchat = forwardRef((props, ref) => {
737
753
  <Textarea
738
754
  inputRef={textArea}
739
755
  name='text'
740
- onFocus={() => deviceAdapter.onFocus(host)}
741
- onBlur={() => deviceAdapter.onBlur()}
756
+ onFocus={() => {
757
+ deviceAdapter.onFocus(host)
758
+ }}
759
+ onBlur={() => {
760
+ deviceAdapter.onBlur()
761
+ }}
742
762
  maxRows={4}
743
763
  wrap='soft'
744
764
  maxLength='1000'
@@ -746,7 +766,7 @@ export const Webchat = forwardRef((props, ref) => {
746
766
  WEBCHAT.CUSTOM_PROPERTIES.textPlaceholder,
747
767
  WEBCHAT.DEFAULTS.PLACEHOLDER
748
768
  )}
749
- autoFocus={true}
769
+ autoFocus={false}
750
770
  onKeyDown={e => onKeyDown(e)}
751
771
  onKeyUp={onKeyUp}
752
772
  style={{
@@ -810,7 +830,6 @@ export const Webchat = forwardRef((props, ref) => {
810
830
  useEffect(() => {
811
831
  // Prod mode
812
832
  saveWebchatState(webchatState)
813
- scrollToBottom({ host })
814
833
  }, [webchatState.themeUpdates])
815
834
 
816
835
  // Only needed for dev/serve mode
@@ -849,6 +868,8 @@ export const Webchat = forwardRef((props, ref) => {
849
868
  getThemeProperty,
850
869
  openWebview,
851
870
  resolveCase,
871
+ resetUnreadMessages,
872
+ setLastMessageVisible,
852
873
  sendAttachment,
853
874
  sendInput,
854
875
  sendPayload,
@@ -886,7 +907,9 @@ export const Webchat = forwardRef((props, ref) => {
886
907
  <ErrorMessage>{webchatState.error.message}</ErrorMessage>
887
908
  </ErrorMessageContainer>
888
909
  )}
889
- {webchatMessageList()}
910
+
911
+ <WebchatMessageList style={{ flex: 1 }} host={host} />
912
+
890
913
  {webchatState.replies &&
891
914
  Object.keys(webchatState.replies).length > 0 &&
892
915
  webchatReplies()}
@@ -4,7 +4,8 @@ import merge from 'lodash.merge'
4
4
  import React, { createRef } from 'react'
5
5
  import { render, unmountComponentAtNode } from 'react-dom'
6
6
 
7
- import { SENDERS, WEBCHAT } from './constants'
7
+ import { WEBCHAT } from './constants'
8
+ import { SENDERS } from './index-types'
8
9
  import { msgToBotonic } from './msg-to-botonic'
9
10
  import { isShadowDOMSupported, onDOMLoaded } from './util/dom'
10
11
  import { Webchat } from './webchat/webchat'
@@ -110,7 +111,11 @@ export class WebchatApp {
110
111
 
111
112
  async onUserInput({ user, input }) {
112
113
  this.onMessage &&
113
- this.onMessage(this, { from: SENDERS.user, message: input })
114
+ this.onMessage(this, {
115
+ sentBy: SENDERS.user,
116
+ message: input,
117
+ isUnread: false,
118
+ })
114
119
  return this.hubtypeService.postMessage(user, input)
115
120
  }
116
121
 
@@ -145,15 +150,15 @@ export class WebchatApp {
145
150
  if (event.action === 'connectionChange') {
146
151
  this.onConnectionChange && this.onConnectionChange(this, event.online)
147
152
  this.webchatRef.current.setOnline(event.online)
148
- } else if (event.action === 'update_message_info')
153
+ } else if (event.action === 'update_message_info') {
149
154
  this.updateMessageInfo(event.message.id, event.message)
150
- else if (event.message.type === 'update_webchat_settings')
155
+ } else if (event.message?.type === 'update_webchat_settings') {
151
156
  this.updateWebchatSettings(event.message.data)
152
- else if (event.message.type === 'sender_action')
157
+ } else if (event.message?.type === 'sender_action') {
153
158
  this.setTyping(event.message.data === 'typing_on')
154
- else {
159
+ } else {
155
160
  this.onMessage &&
156
- this.onMessage(this, { from: SENDERS.bot, message: event.message })
161
+ this.onMessage(this, { sentBy: SENDERS.bot, message: event.message })
157
162
  this.addBotMessage(event.message)
158
163
  }
159
164
  }
@@ -163,12 +168,18 @@ export class WebchatApp {
163
168
  }
164
169
 
165
170
  addBotMessage(message) {
171
+ message.ack = 0
172
+ message.isUnread = true
173
+ message.sentBy = message.sent_by?.split('message_sent_by_')[1]
174
+ delete message.sent_by
175
+ const response = msgToBotonic(
176
+ message,
177
+ (this.theme.message && this.theme.message.customTypes) ||
178
+ this.theme.customMessageTypes
179
+ )
180
+
166
181
  this.webchatRef.current.addBotResponse({
167
- response: msgToBotonic(
168
- message,
169
- (this.theme.message && this.theme.message.customTypes) ||
170
- this.theme.customMessageTypes
171
- ),
182
+ response,
172
183
  })
173
184
  }
174
185
 
@@ -181,11 +192,11 @@ export class WebchatApp {
181
192
  }
182
193
 
183
194
  addUserText(text) {
184
- this.webchatRef.current.addUserMessage({ type: INPUT.TEXT, data: text })
195
+ this.addUserMessage({ type: INPUT.TEXT, data: text })
185
196
  }
186
197
 
187
198
  addUserPayload(payload) {
188
- this.webchatRef.current.addUserMessage({ type: INPUT.POSTBACK, payload })
199
+ this.addUserMessage({ type: INPUT.POSTBACK, payload })
189
200
  }
190
201
 
191
202
  setTyping(typing) {
@@ -1 +0,0 @@
1
- export function WebchatMessageList(props: any): JSX.Element;
@@ -1,39 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WebchatMessageList = void 0;
4
- const tslib_1 = require("tslib");
5
- const jsx_runtime_1 = require("react/jsx-runtime");
6
- const react_1 = tslib_1.__importStar(require("react"));
7
- const Fade_1 = tslib_1.__importDefault(require("react-reveal/Fade"));
8
- const styled_components_1 = tslib_1.__importDefault(require("styled-components"));
9
- const constants_1 = require("../constants");
10
- const contexts_1 = require("../contexts");
11
- const environment_1 = require("../util/environment");
12
- const react_2 = require("../util/react");
13
- const styled_scrollbar_1 = require("./components/styled-scrollbar");
14
- const StyledMessages = styled_components_1.default.div `
15
- display: flex;
16
- overflow-x: hidden;
17
- flex-direction: column;
18
- flex: none;
19
- white-space: pre;
20
- word-wrap: break-word;
21
- `;
22
- const DefaultIntroImage = styled_components_1.default.img `
23
- max-height: 50%;
24
- width: 100%;
25
- `;
26
- const WebchatMessageList = props => {
27
- const { webchatState, getThemeProperty } = (0, react_1.useContext)(contexts_1.WebchatContext);
28
- const animationsEnabled = getThemeProperty(constants_1.WEBCHAT.CUSTOM_PROPERTIES.enableAnimations, true);
29
- const CustomIntro = getThemeProperty(constants_1.WEBCHAT.CUSTOM_PROPERTIES.customIntro);
30
- const introImage = getThemeProperty(constants_1.WEBCHAT.CUSTOM_PROPERTIES.introImage);
31
- const introStyle = getThemeProperty(constants_1.WEBCHAT.CUSTOM_PROPERTIES.introStyle);
32
- const scrollbarOptions = Object.assign({ enable: true, autoHide: true }, getThemeProperty(constants_1.WEBCHAT.CUSTOM_PROPERTIES.scrollbar));
33
- const DefaultIntro = introImage && ((0, jsx_runtime_1.jsx)(DefaultIntroImage, { style: Object.assign({}, introStyle), src: (0, environment_1.resolveImage)(introImage) }));
34
- return ((0, jsx_runtime_1.jsxs)(styled_scrollbar_1.StyledScrollbar, Object.assign({ role: constants_1.ROLES.MESSAGE_LIST,
35
- // TODO: Distinguis between multiple instances of webchat, e.g. `${uniqueId}-botonic-scrollable`
36
- id: 'botonic-scrollable-content', scrollbar: scrollbarOptions, autoHide: scrollbarOptions.autoHide, ismessagescontainer: 'true', style: Object.assign({}, props.style) }, { children: [(CustomIntro || DefaultIntro) && ((0, jsx_runtime_1.jsx)(react_2.ConditionalWrapper, Object.assign({ condition: animationsEnabled, wrapper: children => (0, jsx_runtime_1.jsx)(Fade_1.default, { children: children }) }, { children: CustomIntro ? (0, jsx_runtime_1.jsx)(CustomIntro, {}) : DefaultIntro }))), webchatState.messagesComponents.map((e, i) => ((0, jsx_runtime_1.jsx)(StyledMessages, Object.assign({ role: constants_1.ROLES.MESSAGE }, { children: e }), i))), props.children] })));
37
- };
38
- exports.WebchatMessageList = WebchatMessageList;
39
- //# sourceMappingURL=message-list.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"message-list.js","sourceRoot":"src/","sources":["webchat/message-list.jsx"],"names":[],"mappings":";;;;;AAAA,uDAAyC;AACzC,qEAAoC;AACpC,kFAAsC;AAEtC,4CAA6C;AAC7C,0CAA4C;AAC5C,qDAAkD;AAClD,yCAAkD;AAClD,oEAA+D;AAE/D,MAAM,cAAc,GAAG,2BAAM,CAAC,GAAG,CAAA;;;;;;;CAOhC,CAAA;AAED,MAAM,iBAAiB,GAAG,2BAAM,CAAC,GAAG,CAAA;;;CAGnC,CAAA;AAEM,MAAM,kBAAkB,GAAG,KAAK,CAAC,EAAE;IACxC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,IAAA,kBAAU,EAAC,yBAAc,CAAC,CAAA;IACrE,MAAM,iBAAiB,GAAG,gBAAgB,CACxC,mBAAO,CAAC,iBAAiB,CAAC,gBAAgB,EAC1C,IAAI,CACL,CAAA;IACD,MAAM,WAAW,GAAG,gBAAgB,CAAC,mBAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAA;IAC3E,MAAM,UAAU,GAAG,gBAAgB,CAAC,mBAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;IACzE,MAAM,UAAU,GAAG,gBAAgB,CAAC,mBAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAEzE,MAAM,gBAAgB,iBACjB,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAChC,gBAAgB,CAAC,mBAAO,CAAC,iBAAiB,CAAC,SAAS,CAAC,CACzD,CAAA;IAED,MAAM,YAAY,GAAG,UAAU,IAAI,CACjC,uBAAC,iBAAiB,IAChB,KAAK,oBACA,UAAU,GAEf,GAAG,EAAE,IAAA,0BAAY,EAAC,UAAU,CAAC,GAC7B,CACH,CAAA;IAED,OAAO,CACL,wBAAC,kCAAe,kBACd,IAAI,EAAE,iBAAK,CAAC,YAAY;QACxB,gGAAgG;QAChG,EAAE,EAAC,4BAA4B,EAC/B,SAAS,EAAE,gBAAgB,EAC3B,QAAQ,EAAE,gBAAgB,CAAC,QAAQ,EACnC,mBAAmB,EAAC,MAAM,EAC1B,KAAK,oBACA,KAAK,CAAC,KAAK,kBAGf,CAAC,WAAW,IAAI,YAAY,CAAC,IAAI,CAChC,uBAAC,0BAAkB,kBACjB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,uBAAC,cAAI,cAAE,QAAQ,GAAQ,gBAE3C,WAAW,CAAC,CAAC,CAAC,uBAAC,WAAW,KAAG,CAAC,CAAC,CAAC,YAAY,IAC1B,CACtB,EACA,YAAY,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAC7C,uBAAC,cAAc,kBAAC,IAAI,EAAE,iBAAK,CAAC,OAAO,gBAChC,CAAC,KADsC,CAAC,CAE1B,CAClB,CAAC,EACD,KAAK,CAAC,QAAQ,KACC,CACnB,CAAA;AACH,CAAC,CAAA;AApDY,QAAA,kBAAkB,sBAoD9B"}
@@ -1 +0,0 @@
1
- export function WebchatMessageList(props: any): JSX.Element;