@botonic/react 0.23.3 → 0.24.0-alpha.0

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 (170) 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 +2 -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 +58 -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 +19 -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 +48 -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 +5 -0
  56. package/lib/cjs/webchat/message-list/unread-messages-banner.js +30 -0
  57. package/lib/cjs/webchat/message-list/unread-messages-banner.js.map +1 -0
  58. package/lib/cjs/webchat/messages-reducer.js +31 -9
  59. package/lib/cjs/webchat/messages-reducer.js.map +1 -1
  60. package/lib/cjs/webchat/trigger-button/index.js +3 -2
  61. package/lib/cjs/webchat/trigger-button/index.js.map +1 -1
  62. package/lib/cjs/webchat/webchat-reducer.js +1 -1
  63. package/lib/cjs/webchat/webchat-reducer.js.map +1 -1
  64. package/lib/cjs/webchat/webchat.js +39 -21
  65. package/lib/cjs/webchat/webchat.js.map +1 -1
  66. package/lib/cjs/webchat-app.js +24 -9
  67. package/lib/cjs/webchat-app.js.map +1 -1
  68. package/lib/esm/assets/arrow-down.svg +3 -0
  69. package/lib/esm/assets/arrow-scroll-down.svg +3 -0
  70. package/lib/esm/assets/index-types.d.ts +4 -0
  71. package/lib/esm/assets/index-types.js +2 -0
  72. package/lib/esm/assets/index-types.js.map +1 -0
  73. package/lib/esm/components/custom-message.js +2 -2
  74. package/lib/esm/components/custom-message.js.map +1 -1
  75. package/lib/esm/components/index-types.d.ts +10 -4
  76. package/lib/esm/components/index-types.js.map +1 -1
  77. package/lib/esm/components/message.js +22 -18
  78. package/lib/esm/components/message.js.map +1 -1
  79. package/lib/esm/components/timestamps.d.ts +2 -2
  80. package/lib/esm/components/timestamps.js +5 -5
  81. package/lib/esm/components/timestamps.js.map +1 -1
  82. package/lib/esm/constants.d.ts +7 -5
  83. package/lib/esm/constants.js +9 -5
  84. package/lib/esm/constants.js.map +1 -1
  85. package/lib/esm/contexts.js +6 -0
  86. package/lib/esm/contexts.js.map +1 -1
  87. package/lib/esm/dev-app.js +9 -3
  88. package/lib/esm/dev-app.js.map +1 -1
  89. package/lib/esm/index-types.d.ts +16 -2
  90. package/lib/esm/index-types.js +6 -1
  91. package/lib/esm/index-types.js.map +1 -1
  92. package/lib/esm/msg-to-botonic.js +6 -3
  93. package/lib/esm/msg-to-botonic.js.map +1 -1
  94. package/lib/esm/webchat/actions.d.ts +19 -17
  95. package/lib/esm/webchat/actions.js +19 -17
  96. package/lib/esm/webchat/actions.js.map +1 -1
  97. package/lib/esm/webchat/components/styled-scrollbar.js +1 -1
  98. package/lib/esm/webchat/devices/device-adapter.js +1 -1
  99. package/lib/esm/webchat/devices/device-adapter.js.map +1 -1
  100. package/lib/esm/webchat/devices/webchat-resizer.js +1 -1
  101. package/lib/esm/webchat/devices/webchat-resizer.js.map +1 -1
  102. package/lib/esm/webchat/hooks/use-typing.d.ts +1 -1
  103. package/lib/esm/webchat/hooks/use-typing.js +2 -3
  104. package/lib/esm/webchat/hooks/use-typing.js.map +1 -1
  105. package/lib/esm/webchat/hooks/use-webchat.d.ts +5 -1
  106. package/lib/esm/webchat/hooks/use-webchat.js +15 -1
  107. package/lib/esm/webchat/hooks/use-webchat.js.map +1 -1
  108. package/lib/esm/webchat/index-types.d.ts +2 -1
  109. package/lib/esm/webchat/message-list/index.d.ts +1 -0
  110. package/lib/esm/webchat/message-list/index.js +54 -0
  111. package/lib/esm/webchat/message-list/index.js.map +1 -0
  112. package/lib/esm/webchat/message-list/intro-message.d.ts +1 -0
  113. package/lib/esm/webchat/message-list/intro-message.js +18 -0
  114. package/lib/esm/webchat/message-list/intro-message.js.map +1 -0
  115. package/lib/esm/webchat/message-list/scroll-button.d.ts +5 -0
  116. package/lib/esm/webchat/message-list/scroll-button.js +14 -0
  117. package/lib/esm/webchat/message-list/scroll-button.js.map +1 -0
  118. package/lib/esm/webchat/message-list/styles.d.ts +4 -0
  119. package/lib/esm/webchat/message-list/styles.js +44 -0
  120. package/lib/esm/webchat/message-list/styles.js.map +1 -0
  121. package/lib/esm/webchat/message-list/unread-messages-banner.d.ts +5 -0
  122. package/lib/esm/webchat/message-list/unread-messages-banner.js +25 -0
  123. package/lib/esm/webchat/message-list/unread-messages-banner.js.map +1 -0
  124. package/lib/esm/webchat/messages-reducer.js +31 -9
  125. package/lib/esm/webchat/messages-reducer.js.map +1 -1
  126. package/lib/esm/webchat/trigger-button/index.js +3 -2
  127. package/lib/esm/webchat/trigger-button/index.js.map +1 -1
  128. package/lib/esm/webchat/webchat-reducer.js +1 -1
  129. package/lib/esm/webchat/webchat-reducer.js.map +1 -1
  130. package/lib/esm/webchat/webchat.js +40 -22
  131. package/lib/esm/webchat/webchat.js.map +1 -1
  132. package/lib/esm/webchat-app.js +25 -10
  133. package/lib/esm/webchat-app.js.map +1 -1
  134. package/package.json +7 -5
  135. package/src/assets/arrow-down.svg +3 -0
  136. package/src/assets/arrow-scroll-down.svg +3 -0
  137. package/src/assets/index-types.ts +4 -0
  138. package/src/components/custom-message.jsx +2 -2
  139. package/src/components/index-types.ts +8 -4
  140. package/src/components/message.jsx +29 -21
  141. package/src/components/timestamps.jsx +5 -5
  142. package/src/constants.js +9 -6
  143. package/src/contexts.tsx +6 -0
  144. package/src/dev-app.jsx +9 -3
  145. package/src/index-types.ts +18 -3
  146. package/src/msg-to-botonic.jsx +2 -3
  147. package/src/webchat/actions.ts +19 -17
  148. package/src/webchat/components/styled-scrollbar.jsx +1 -1
  149. package/src/webchat/devices/device-adapter.js +1 -1
  150. package/src/webchat/devices/webchat-resizer.js +1 -1
  151. package/src/webchat/hooks/use-typing.ts +3 -3
  152. package/src/webchat/hooks/use-webchat.ts +18 -2
  153. package/src/webchat/index-types.ts +2 -1
  154. package/src/webchat/message-list/index.tsx +103 -0
  155. package/src/webchat/message-list/intro-message.tsx +38 -0
  156. package/src/webchat/message-list/scroll-button.tsx +41 -0
  157. package/src/webchat/message-list/styles.ts +47 -0
  158. package/src/webchat/message-list/unread-messages-banner.tsx +62 -0
  159. package/src/webchat/messages-reducer.ts +42 -5
  160. package/src/webchat/trigger-button/index.tsx +9 -4
  161. package/src/webchat/webchat-reducer.ts +0 -1
  162. package/src/webchat/webchat.jsx +71 -49
  163. package/src/webchat-app.jsx +25 -14
  164. package/lib/cjs/webchat/message-list.d.ts +0 -1
  165. package/lib/cjs/webchat/message-list.js +0 -39
  166. package/lib/cjs/webchat/message-list.js.map +0 -1
  167. package/lib/esm/webchat/message-list.d.ts +0 -1
  168. package/lib/esm/webchat/message-list.js +0 -34
  169. package/lib/esm/webchat/message-list.js.map +0 -1
  170. package/src/webchat/message-list.jsx +0 -77
@@ -0,0 +1,47 @@
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
+ color: #6d6a78;
40
+ font-size: 14px;
41
+ font-weight: 400;
42
+ width: 100%;
43
+
44
+ img {
45
+ width: 10px;
46
+ }
47
+ `
@@ -0,0 +1,62 @@
1
+ import React, { useContext, useEffect, useRef } 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
+ numUnreadMessages: number
11
+ }
12
+
13
+ export const UnreadMessagesBanner = ({
14
+ numUnreadMessages,
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
+ const unreadMessagesBannerRef = useRef<HTMLDivElement>(null)
39
+ useEffect(() => {
40
+ if (webchatState.isWebchatOpen && unreadMessagesBannerRef.current) {
41
+ unreadMessagesBannerRef.current.scrollIntoView({
42
+ behavior: 'smooth',
43
+ block: 'center',
44
+ })
45
+ }
46
+ }, [webchatState.isWebchatOpen, unreadMessagesBannerRef])
47
+
48
+ return (
49
+ notificationsEnabled && (
50
+ <div ref={unreadMessagesBannerRef}>
51
+ {CustomUnreadMessagesBanner ? (
52
+ <CustomUnreadMessagesBanner />
53
+ ) : (
54
+ <ContainerUnreadMessagesBanner>
55
+ <img src={resolveImage(ArrowDown)} />
56
+ {numUnreadMessages} {text}
57
+ </ContainerUnreadMessagesBanner>
58
+ )}
59
+ </div>
60
+ )
61
+ )
62
+ }
@@ -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))
@@ -314,12 +313,13 @@ export const Webchat = forwardRef((props, ref) => {
314
313
  useEffect(() => {
315
314
  if (!webchatState.isWebchatOpen) return
316
315
  deviceAdapter.init(host)
317
- scrollToBottom({ behavior: 'auto', host })
316
+ // scrollToBottom({ behavior: 'auto', host })
318
317
  }, [webchatState.isWebchatOpen])
319
318
 
320
319
  useEffect(() => {
321
- if (onStateChange && typeof onStateChange === 'function')
320
+ if (onStateChange && typeof onStateChange === 'function') {
322
321
  onStateChange(webchatState)
322
+ }
323
323
  saveWebchatState(webchatState)
324
324
  }, [
325
325
  webchatState.messagesJSON,
@@ -410,7 +410,7 @@ export const Webchat = forwardRef((props, ref) => {
410
410
  addMessageComponent(
411
411
  <Text
412
412
  id={input.id}
413
- from={SENDERS.user}
413
+ sentBy={SENDERS.user}
414
414
  blob={false}
415
415
  style={{
416
416
  backgroundColor: COLORS.SCORPION_GRAY,
@@ -484,7 +484,7 @@ export const Webchat = forwardRef((props, ref) => {
484
484
  let messageComponent = null
485
485
  if (isText(input)) {
486
486
  messageComponent = (
487
- <Text id={input.id} payload={input.payload} from={SENDERS.user}>
487
+ <Text id={input.id} payload={input.payload} sentBy={SENDERS.user}>
488
488
  {input.data}
489
489
  </Text>
490
490
  )
@@ -492,7 +492,7 @@ export const Webchat = forwardRef((props, ref) => {
492
492
  const temporaryDisplayUrl = URL.createObjectURL(input.data)
493
493
  const mediaProps = {
494
494
  id: input.id,
495
- from: SENDERS.user,
495
+ sentBy: SENDERS.user,
496
496
  src: temporaryDisplayUrl,
497
497
  }
498
498
  if (isImage(input)) {
@@ -532,8 +532,21 @@ export const Webchat = forwardRef((props, ref) => {
532
532
  useImperativeHandle(ref, () => ({
533
533
  addBotResponse: ({ response, session, lastRoutePath }) => {
534
534
  updateTyping(false)
535
- if (Array.isArray(response)) response.map(r => addMessageComponent(r))
536
- else if (response) addMessageComponent(response)
535
+
536
+ const isUnread =
537
+ !webchatState.isLastMessageVisible || webchatState.numUnreadMessages > 0
538
+
539
+ if (Array.isArray(response)) {
540
+ response.forEach(r => {
541
+ addMessageComponent({ ...r, props: { ...r.props, isUnread } })
542
+ })
543
+ } else if (response) {
544
+ addMessageComponent({
545
+ ...response,
546
+ props: { ...response.props, isUnread },
547
+ })
548
+ }
549
+
537
550
  if (session) {
538
551
  updateSession(merge(session, { user: webchatState.session.user }))
539
552
  const action = session._botonic_action || ''
@@ -541,7 +554,9 @@ export const Webchat = forwardRef((props, ref) => {
541
554
  if (handoff && isDev) addMessageComponent(<Handoff />)
542
555
  updateHandoff(handoff)
543
556
  }
557
+
544
558
  if (lastRoutePath) updateLastRoutePath(lastRoutePath)
559
+
545
560
  updateLastMessageDate(currentDateString())
546
561
  },
547
562
  setTyping: typing => updateTyping(typing),
@@ -685,7 +700,9 @@ export const Webchat = forwardRef((props, ref) => {
685
700
  firstUpdate.current = false
686
701
  return
687
702
  }
703
+
688
704
  if (webchatState.isWebchatOpen && props.onOpen) props.onOpen()
705
+
689
706
  if (!webchatState.isWebchatOpen && props.onClose && !firstUpdate.current) {
690
707
  props.onClose()
691
708
  toggleEmojiPicker(false)
@@ -693,11 +710,6 @@ export const Webchat = forwardRef((props, ref) => {
693
710
  }
694
711
  }, [webchatState.isWebchatOpen])
695
712
 
696
- const webchatMessageList = () => (
697
- <WebchatMessageList style={{ flex: 1 }}>
698
- {webchatState.typing && <TypingIndicator />}
699
- </WebchatMessageList>
700
- )
701
713
  const webchatReplies = () => <WebchatReplies replies={webchatState.replies} />
702
714
 
703
715
  const isUserInputEnabled = () => {
@@ -737,8 +749,14 @@ export const Webchat = forwardRef((props, ref) => {
737
749
  <Textarea
738
750
  inputRef={textArea}
739
751
  name='text'
740
- onFocus={() => deviceAdapter.onFocus(host)}
741
- onBlur={() => deviceAdapter.onBlur()}
752
+ onFocus={() => {
753
+ scrollToBottom({ host })
754
+ resetUnreadMessages()
755
+ deviceAdapter.onFocus(host)
756
+ }}
757
+ onBlur={() => {
758
+ deviceAdapter.onBlur()
759
+ }}
742
760
  maxRows={4}
743
761
  wrap='soft'
744
762
  maxLength='1000'
@@ -746,7 +764,7 @@ export const Webchat = forwardRef((props, ref) => {
746
764
  WEBCHAT.CUSTOM_PROPERTIES.textPlaceholder,
747
765
  WEBCHAT.DEFAULTS.PLACEHOLDER
748
766
  )}
749
- autoFocus={true}
767
+ // autoFocus={true}
750
768
  onKeyDown={e => onKeyDown(e)}
751
769
  onKeyUp={onKeyUp}
752
770
  style={{
@@ -810,7 +828,7 @@ export const Webchat = forwardRef((props, ref) => {
810
828
  useEffect(() => {
811
829
  // Prod mode
812
830
  saveWebchatState(webchatState)
813
- scrollToBottom({ host })
831
+ // scrollToBottom({ host })
814
832
  }, [webchatState.themeUpdates])
815
833
 
816
834
  // Only needed for dev/serve mode
@@ -849,6 +867,8 @@ export const Webchat = forwardRef((props, ref) => {
849
867
  getThemeProperty,
850
868
  openWebview,
851
869
  resolveCase,
870
+ resetUnreadMessages,
871
+ setLastMessageVisible,
852
872
  sendAttachment,
853
873
  sendInput,
854
874
  sendPayload,
@@ -886,7 +906,9 @@ export const Webchat = forwardRef((props, ref) => {
886
906
  <ErrorMessage>{webchatState.error.message}</ErrorMessage>
887
907
  </ErrorMessageContainer>
888
908
  )}
889
- {webchatMessageList()}
909
+
910
+ <WebchatMessageList style={{ flex: 1 }} host={host} />
911
+
890
912
  {webchatState.replies &&
891
913
  Object.keys(webchatState.replies).length > 0 &&
892
914
  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;
@@ -1,34 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import React, { useContext } from 'react';
3
- import Fade from 'react-reveal/Fade';
4
- import styled from 'styled-components';
5
- import { ROLES, WEBCHAT } from '../constants';
6
- import { WebchatContext } from '../contexts';
7
- import { resolveImage } from '../util/environment';
8
- import { ConditionalWrapper } from '../util/react';
9
- import { StyledScrollbar } from './components/styled-scrollbar';
10
- const StyledMessages = styled.div `
11
- display: flex;
12
- overflow-x: hidden;
13
- flex-direction: column;
14
- flex: none;
15
- white-space: pre;
16
- word-wrap: break-word;
17
- `;
18
- const DefaultIntroImage = styled.img `
19
- max-height: 50%;
20
- width: 100%;
21
- `;
22
- export const WebchatMessageList = props => {
23
- const { webchatState, getThemeProperty } = useContext(WebchatContext);
24
- const animationsEnabled = getThemeProperty(WEBCHAT.CUSTOM_PROPERTIES.enableAnimations, true);
25
- const CustomIntro = getThemeProperty(WEBCHAT.CUSTOM_PROPERTIES.customIntro);
26
- const introImage = getThemeProperty(WEBCHAT.CUSTOM_PROPERTIES.introImage);
27
- const introStyle = getThemeProperty(WEBCHAT.CUSTOM_PROPERTIES.introStyle);
28
- const scrollbarOptions = Object.assign({ enable: true, autoHide: true }, getThemeProperty(WEBCHAT.CUSTOM_PROPERTIES.scrollbar));
29
- const DefaultIntro = introImage && (_jsx(DefaultIntroImage, { style: Object.assign({}, introStyle), src: resolveImage(introImage) }));
30
- return (_jsxs(StyledScrollbar, Object.assign({ role: ROLES.MESSAGE_LIST,
31
- // TODO: Distinguis between multiple instances of webchat, e.g. `${uniqueId}-botonic-scrollable`
32
- id: 'botonic-scrollable-content', scrollbar: scrollbarOptions, autoHide: scrollbarOptions.autoHide, ismessagescontainer: 'true', style: Object.assign({}, props.style) }, { children: [(CustomIntro || DefaultIntro) && (_jsx(ConditionalWrapper, Object.assign({ condition: animationsEnabled, wrapper: children => _jsx(Fade, { children: children }) }, { children: CustomIntro ? _jsx(CustomIntro, {}) : DefaultIntro }))), webchatState.messagesComponents.map((e, i) => (_jsx(StyledMessages, Object.assign({ role: ROLES.MESSAGE }, { children: e }), i))), props.children] })));
33
- };
34
- //# 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,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AACzC,OAAO,IAAI,MAAM,mBAAmB,CAAA;AACpC,OAAO,MAAM,MAAM,mBAAmB,CAAA;AAEtC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAE/D,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAA;;;;;;;CAOhC,CAAA;AAED,MAAM,iBAAiB,GAAG,MAAM,CAAC,GAAG,CAAA;;;CAGnC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,CAAC,EAAE;IACxC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,GAAG,UAAU,CAAC,cAAc,CAAC,CAAA;IACrE,MAAM,iBAAiB,GAAG,gBAAgB,CACxC,OAAO,CAAC,iBAAiB,CAAC,gBAAgB,EAC1C,IAAI,CACL,CAAA;IACD,MAAM,WAAW,GAAG,gBAAgB,CAAC,OAAO,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAA;IAC3E,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;IACzE,MAAM,UAAU,GAAG,gBAAgB,CAAC,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAA;IAEzE,MAAM,gBAAgB,iBACjB,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,EAChC,gBAAgB,CAAC,OAAO,CAAC,iBAAiB,CAAC,SAAS,CAAC,CACzD,CAAA;IAED,MAAM,YAAY,GAAG,UAAU,IAAI,CACjC,KAAC,iBAAiB,IAChB,KAAK,oBACA,UAAU,GAEf,GAAG,EAAE,YAAY,CAAC,UAAU,CAAC,GAC7B,CACH,CAAA;IAED,OAAO,CACL,MAAC,eAAe,kBACd,IAAI,EAAE,KAAK,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,KAAC,kBAAkB,kBACjB,SAAS,EAAE,iBAAiB,EAC5B,OAAO,EAAE,QAAQ,CAAC,EAAE,CAAC,KAAC,IAAI,cAAE,QAAQ,GAAQ,gBAE3C,WAAW,CAAC,CAAC,CAAC,KAAC,WAAW,KAAG,CAAC,CAAC,CAAC,YAAY,IAC1B,CACtB,EACA,YAAY,CAAC,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAC7C,KAAC,cAAc,kBAAC,IAAI,EAAE,KAAK,CAAC,OAAO,gBAChC,CAAC,KADsC,CAAC,CAE1B,CAClB,CAAC,EACD,KAAK,CAAC,QAAQ,KACC,CACnB,CAAA;AACH,CAAC,CAAA"}