@seamly/web-ui 20.7.0 → 20.8.0-beta.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 (226) hide show
  1. package/build/dist/lib/hooks.js +1 -1
  2. package/build/dist/lib/hooks.min.js +1 -1
  3. package/build/dist/lib/index.debug.js +945 -790
  4. package/build/dist/lib/index.debug.min.js +1 -1
  5. package/build/dist/lib/index.debug.min.js.LICENSE.txt +187 -131
  6. package/build/dist/lib/index.js +24800 -19606
  7. package/build/dist/lib/index.min.js +1 -1
  8. package/build/dist/lib/index.min.js.LICENSE.txt +38 -4
  9. package/build/dist/lib/standalone.js +32920 -26742
  10. package/build/dist/lib/standalone.min.js +1 -1
  11. package/build/dist/lib/standalone.min.js.LICENSE.txt +39 -0
  12. package/build/dist/lib/storage.js +2 -2
  13. package/build/dist/lib/storage.min.js +1 -1
  14. package/build/dist/lib/style-guide.js +8780 -7907
  15. package/build/dist/lib/style-guide.min.js +2 -1
  16. package/build/dist/lib/style-guide.min.js.LICENSE.txt +38 -0
  17. package/build/dist/lib/styles.css +1 -1
  18. package/build/dist/lib/utils.js +1 -2
  19. package/build/dist/lib/utils.min.js +1 -1
  20. package/package.json +19 -9
  21. package/src/icons/avatar_agent-32.svg +7 -0
  22. package/src/icons/avatar_bot-32.svg +6 -1
  23. package/src/javascripts/api/index.js +1 -1
  24. package/src/javascripts/{config.js → config.ts} +3 -1
  25. package/src/javascripts/config.types.ts +96 -0
  26. package/src/javascripts/domains/app/actions.ts +83 -0
  27. package/src/javascripts/domains/app/app.types.ts +3 -0
  28. package/src/javascripts/domains/app/hooks.js +3 -5
  29. package/src/javascripts/domains/app/selectors.ts +6 -0
  30. package/src/javascripts/domains/app/slice.ts +30 -0
  31. package/src/javascripts/domains/config/actions.ts +45 -0
  32. package/src/javascripts/domains/config/hooks.ts +19 -0
  33. package/src/javascripts/domains/config/selectors.ts +24 -0
  34. package/src/javascripts/domains/config/slice.ts +113 -0
  35. package/src/javascripts/domains/errors/index.js +13 -9
  36. package/src/javascripts/domains/forms/context.ts +14 -0
  37. package/src/javascripts/domains/forms/forms.types.ts +24 -0
  38. package/src/javascripts/domains/forms/{hooks.js → hooks.ts} +23 -26
  39. package/src/javascripts/domains/forms/{provider.js → provider.tsx} +20 -14
  40. package/src/javascripts/domains/forms/{selectors.js → selectors.ts} +7 -8
  41. package/src/javascripts/domains/forms/slice.ts +84 -0
  42. package/src/javascripts/domains/forms/utils.ts +15 -0
  43. package/src/javascripts/domains/i18n/actions.ts +24 -0
  44. package/src/javascripts/domains/i18n/{hooks.js → hooks.ts} +2 -2
  45. package/src/javascripts/domains/i18n/i18n.types.ts +6 -0
  46. package/src/javascripts/domains/i18n/selectors.ts +16 -0
  47. package/src/javascripts/domains/i18n/{reducer.js → slice.ts} +40 -37
  48. package/src/javascripts/domains/interrupt/{hooks.js → hooks.ts} +2 -2
  49. package/src/javascripts/domains/interrupt/{middleware.js → middleware.ts} +11 -8
  50. package/src/javascripts/domains/interrupt/selectors.ts +6 -0
  51. package/src/javascripts/domains/interrupt/slice.ts +40 -0
  52. package/src/javascripts/domains/options/middleware.js +9 -6
  53. package/src/javascripts/domains/redux/redux.types.ts +11 -0
  54. package/src/javascripts/domains/store/index.ts +53 -0
  55. package/src/javascripts/domains/store/slice.ts +642 -0
  56. package/src/javascripts/domains/store/store.types.ts +146 -0
  57. package/src/javascripts/domains/translations/components/chat-status.js +2 -2
  58. package/src/javascripts/domains/translations/components/options-button.js +1 -1
  59. package/src/javascripts/domains/translations/components/options-dialog/form.js +5 -5
  60. package/src/javascripts/domains/translations/components/options-dialog/index.js +2 -2
  61. package/src/javascripts/domains/translations/hooks.ts +114 -0
  62. package/src/javascripts/domains/translations/middleware.js +29 -27
  63. package/src/javascripts/domains/translations/selectors.ts +12 -0
  64. package/src/javascripts/domains/translations/slice.ts +120 -0
  65. package/src/javascripts/domains/translations/translations.types.ts +19 -0
  66. package/src/javascripts/domains/visibility/{actions.js → actions.ts} +25 -19
  67. package/src/javascripts/domains/visibility/{hooks.js → hooks.ts} +13 -10
  68. package/src/javascripts/domains/visibility/{selectors.js → selectors.ts} +3 -6
  69. package/src/javascripts/domains/visibility/slice.ts +38 -0
  70. package/src/javascripts/domains/visibility/utils.js +0 -9
  71. package/src/javascripts/domains/visibility/visibility.types.ts +6 -0
  72. package/src/javascripts/index.ts +92 -0
  73. package/src/javascripts/lib/engine/index.js +15 -11
  74. package/src/javascripts/lib/external-api/initialize-api.js +1 -1
  75. package/src/javascripts/lib/id.js +5 -8
  76. package/src/javascripts/lib/mutex.js +3 -1
  77. package/src/javascripts/lib/store/providers/cookie-storage.js +1 -1
  78. package/src/javascripts/lib/store/providers/session-storage.js +1 -1
  79. package/src/javascripts/package/hooks.js +2 -2
  80. package/src/javascripts/package/utils.js +0 -1
  81. package/src/javascripts/schema.ts +1448 -0
  82. package/src/javascripts/style-guide/components/app.js +6 -6
  83. package/src/javascripts/style-guide/components/static-core.js +87 -65
  84. package/src/javascripts/style-guide/components/view.js +4 -4
  85. package/src/javascripts/style-guide/state-helpers/index.js +5 -5
  86. package/src/javascripts/style-guide/states.js +67 -7
  87. package/src/javascripts/style-guide.ts +5 -0
  88. package/src/javascripts/ui/components/app-options/index.js +2 -4
  89. package/src/javascripts/ui/components/conversation/component-filter.js +1 -1
  90. package/src/javascripts/ui/components/conversation/conversation.js +11 -7
  91. package/src/javascripts/ui/components/conversation/event/card-message.js +2 -2
  92. package/src/javascripts/ui/components/conversation/event/carousel-component/components/controls.js +1 -1
  93. package/src/javascripts/ui/components/conversation/event/carousel-message/components/slide.js +1 -1
  94. package/src/javascripts/ui/components/conversation/event/carousel-message/index.js +2 -2
  95. package/src/javascripts/ui/components/conversation/event/choice-prompt.js +3 -3
  96. package/src/javascripts/ui/components/conversation/event/conversation-suggestions.js +19 -15
  97. package/src/javascripts/ui/components/conversation/event/cta.js +2 -2
  98. package/src/javascripts/ui/components/conversation/event/divider/variants/default.js +1 -1
  99. package/src/javascripts/ui/components/conversation/event/divider/variants/new-translation.js +44 -5
  100. package/src/javascripts/ui/components/conversation/event/event-participant.js +2 -2
  101. package/src/javascripts/ui/components/conversation/event/hooks/use-formatted-date.js +2 -2
  102. package/src/javascripts/ui/components/conversation/event/image-lightbox.js +1 -1
  103. package/src/javascripts/ui/components/conversation/event/image.js +6 -8
  104. package/src/javascripts/ui/components/conversation/event/participant.js +2 -2
  105. package/src/javascripts/ui/components/conversation/event/splash.js +4 -4
  106. package/src/javascripts/ui/components/conversation/event/text.js +2 -2
  107. package/src/javascripts/ui/components/conversation/event/translation.js +3 -3
  108. package/src/javascripts/ui/components/conversation/event/upload.js +3 -3
  109. package/src/javascripts/ui/components/conversation/event/video.js +2 -2
  110. package/src/javascripts/ui/components/conversation/message-container.js +4 -26
  111. package/src/javascripts/ui/components/core/seamly-api-context.js +1 -1
  112. package/src/javascripts/ui/components/core/seamly-core.js +15 -14
  113. package/src/javascripts/ui/components/core/seamly-event-subscriber.js +98 -92
  114. package/src/javascripts/ui/components/core/seamly-file-upload.js +20 -24
  115. package/src/javascripts/ui/components/core/seamly-initializer.js +1 -1
  116. package/src/javascripts/ui/components/core/seamly-instance-functions-loader.js +5 -4
  117. package/src/javascripts/ui/components/core/seamly-new-notifications.js +2 -2
  118. package/src/javascripts/ui/components/core/seamly-read-state.js +10 -17
  119. package/src/javascripts/ui/components/entry/deprecated-toggle-button.js +3 -3
  120. package/src/javascripts/ui/components/entry/entry-container.js +4 -6
  121. package/src/javascripts/ui/components/entry/text-entry/hooks.js +3 -3
  122. package/src/javascripts/ui/components/entry/text-entry/index.js +3 -2
  123. package/src/javascripts/ui/components/entry/text-entry/text-entry-form.js +6 -10
  124. package/src/javascripts/ui/components/entry/upload/file-upload-form.js +2 -2
  125. package/src/javascripts/ui/components/entry/upload/index.js +10 -9
  126. package/src/javascripts/ui/components/entry/upload-toggle.js +2 -2
  127. package/src/javascripts/ui/components/faq/faq.js +9 -7
  128. package/src/javascripts/ui/components/form-controls/file-input.js +1 -1
  129. package/src/javascripts/ui/components/form-controls/form.js +1 -1
  130. package/src/javascripts/ui/components/form-controls/input.js +1 -1
  131. package/src/javascripts/ui/components/form-controls/select.js +1 -1
  132. package/src/javascripts/ui/components/layout/agent-info.js +4 -4
  133. package/src/javascripts/ui/components/layout/chat-frame.js +3 -3
  134. package/src/javascripts/ui/components/layout/chat.js +11 -12
  135. package/src/javascripts/ui/components/layout/deprecated-app-frame.js +10 -9
  136. package/src/javascripts/ui/components/layout/header.js +1 -1
  137. package/src/javascripts/ui/components/layout/interrupt.js +23 -24
  138. package/src/javascripts/ui/components/layout/pre-chat-messages.js +11 -11
  139. package/src/javascripts/ui/components/layout/privacy-disclaimer.js +2 -2
  140. package/src/javascripts/ui/components/options/options-button.js +14 -10
  141. package/src/javascripts/ui/components/options/transcript/index.js +2 -2
  142. package/src/javascripts/ui/components/options/transcript/transcript-form.js +1 -1
  143. package/src/javascripts/ui/components/suggestions/index.js +14 -10
  144. package/src/javascripts/ui/components/view/deprecated-view.js +19 -16
  145. package/src/javascripts/ui/components/view/index.js +12 -12
  146. package/src/javascripts/ui/components/view/inline-view.js +2 -2
  147. package/src/javascripts/ui/components/view/window-view/collapse-button.js +3 -3
  148. package/src/javascripts/ui/components/view/window-view/index.js +13 -13
  149. package/src/javascripts/ui/components/view/window-view/window-open-button.js +13 -13
  150. package/src/javascripts/ui/components/warnings/idle-detach-warning.js +1 -1
  151. package/src/javascripts/ui/components/warnings/resume-conversation-prompt.js +1 -1
  152. package/src/javascripts/ui/components/widgets/lightbox.js +2 -2
  153. package/src/javascripts/ui/components/widgets/upload-progress.js +1 -1
  154. package/src/javascripts/ui/hooks/component-helper-hooks.js +1 -1
  155. package/src/javascripts/ui/hooks/file-upload-hooks.js +4 -6
  156. package/src/javascripts/ui/hooks/focus-helper-hooks.js +14 -12
  157. package/src/javascripts/ui/hooks/live-region-hooks.js +2 -0
  158. package/src/javascripts/ui/hooks/seamly-api-hooks.js +8 -3
  159. package/src/javascripts/ui/hooks/seamly-entry-hooks.js +28 -25
  160. package/src/javascripts/ui/hooks/seamly-hooks.js +25 -25
  161. package/src/javascripts/ui/hooks/seamly-option-hooks.js +17 -19
  162. package/src/javascripts/ui/hooks/seamly-state-hooks.js +20 -13
  163. package/src/javascripts/ui/hooks/use-seamly-chat.js +15 -25
  164. package/src/javascripts/ui/hooks/use-seamly-commands.js +46 -46
  165. package/src/javascripts/ui/hooks/use-seamly-idle-detach-countdown.js +22 -24
  166. package/src/javascripts/ui/hooks/use-seamly-resume-conversation-prompt.js +8 -9
  167. package/src/javascripts/ui/hooks/use-single-file-upload.js +4 -6
  168. package/src/javascripts/ui/hooks/utility-hooks.js +4 -4
  169. package/src/javascripts/ui/utils/form-utils.js +0 -145
  170. package/src/javascripts/ui/utils/general-utils.js +3 -4
  171. package/src/javascripts/ui/utils/seamly-utils.ts +73 -0
  172. package/src/stylesheets/5-components/_message-carousel.scss +10 -8
  173. package/webpack/config.common.js +16 -0
  174. package/webpack/config.dev.js +1 -0
  175. package/webpack/config.package.js +26 -5
  176. package/webpack/defaults.js +7 -2
  177. package/webpack/parts/babel-loader-browser-plugins.js +1 -0
  178. package/webpack/parts/dev-server.js +4 -3
  179. package/CHANGELOG.md +0 -791
  180. package/src/javascripts/domains/app/actions.js +0 -112
  181. package/src/javascripts/domains/app/index.js +0 -7
  182. package/src/javascripts/domains/app/reducer.js +0 -16
  183. package/src/javascripts/domains/app/selectors.js +0 -8
  184. package/src/javascripts/domains/app/utils.js +0 -4
  185. package/src/javascripts/domains/config/actions.js +0 -7
  186. package/src/javascripts/domains/config/hooks.js +0 -23
  187. package/src/javascripts/domains/config/index.js +0 -7
  188. package/src/javascripts/domains/config/reducer.js +0 -79
  189. package/src/javascripts/domains/config/selectors.js +0 -23
  190. package/src/javascripts/domains/config/utils.js +0 -4
  191. package/src/javascripts/domains/forms/actions.js +0 -21
  192. package/src/javascripts/domains/forms/context.js +0 -6
  193. package/src/javascripts/domains/forms/index.js +0 -8
  194. package/src/javascripts/domains/forms/reducer.js +0 -84
  195. package/src/javascripts/domains/forms/utils.js +0 -20
  196. package/src/javascripts/domains/i18n/actions.js +0 -20
  197. package/src/javascripts/domains/i18n/index.js +0 -7
  198. package/src/javascripts/domains/i18n/selectors.js +0 -15
  199. package/src/javascripts/domains/i18n/utils.js +0 -4
  200. package/src/javascripts/domains/interrupt/actions.js +0 -4
  201. package/src/javascripts/domains/interrupt/index.js +0 -9
  202. package/src/javascripts/domains/interrupt/reducer.js +0 -22
  203. package/src/javascripts/domains/interrupt/selectors.js +0 -6
  204. package/src/javascripts/domains/interrupt/utils.js +0 -4
  205. package/src/javascripts/domains/options/index.js +0 -1
  206. package/src/javascripts/domains/redux/context.js +0 -6
  207. package/src/javascripts/domains/redux/create-redux-store.js +0 -21
  208. package/src/javascripts/domains/redux/hooks.js +0 -80
  209. package/src/javascripts/domains/redux/index.js +0 -19
  210. package/src/javascripts/domains/redux/provider.js +0 -5
  211. package/src/javascripts/domains/redux/utils.js +0 -12
  212. package/src/javascripts/domains/store/index.js +0 -46
  213. package/src/javascripts/domains/store/state-reducer.js +0 -56
  214. package/src/javascripts/domains/translations/actions.js +0 -11
  215. package/src/javascripts/domains/translations/hooks.js +0 -103
  216. package/src/javascripts/domains/translations/index.js +0 -10
  217. package/src/javascripts/domains/translations/reducer.js +0 -69
  218. package/src/javascripts/domains/translations/selectors.js +0 -16
  219. package/src/javascripts/domains/translations/utils.js +0 -4
  220. package/src/javascripts/domains/visibility/index.js +0 -8
  221. package/src/javascripts/domains/visibility/reducer.js +0 -24
  222. package/src/javascripts/index.js +0 -153
  223. package/src/javascripts/lib/redux-helpers/index.js +0 -99
  224. package/src/javascripts/style-guide.js +0 -5
  225. package/src/javascripts/ui/hooks/use-seamly-dispatch.js +0 -3
  226. package/src/javascripts/ui/utils/seamly-utils.js +0 -832
@@ -1,832 +0,0 @@
1
- import { randomId } from 'lib/id'
2
- import { getTimeFromSeconds } from './general-utils'
3
-
4
- export const eventTypes = {
5
- info: 'info',
6
- message: 'message',
7
- participant: 'participant',
8
- system: 'system',
9
- }
10
-
11
- export const payloadTypes = {
12
- choicePrompt: 'choice_prompt',
13
- text: 'text',
14
- image: 'image',
15
- video: 'video',
16
- participant: 'participant',
17
- divider: 'divider',
18
- translation: 'translation',
19
- message: 'message',
20
- countdown: 'countdown',
21
- upload: 'upload',
22
- cta: 'cta',
23
- splash: 'splash',
24
- }
25
-
26
- export const entryTypes = {
27
- text: 'text',
28
- upload: 'upload',
29
- }
30
-
31
- export const readStates = {
32
- received: 'received',
33
- read: 'read',
34
- }
35
-
36
- export const actionTypes = {
37
- pickChoice: 'pick_choice',
38
- navigate: 'navigate',
39
- custom: 'custom',
40
- typing: 'typing',
41
- read: 'read',
42
- detachService: 'detach_service',
43
- interactivityUpdate: 'interactivity_update',
44
- dismiss: 'dismiss',
45
- sendTranscript: 'send_transcript',
46
- setTopic: 'set_topic',
47
- setTranslation: 'set_translation',
48
- clickCta: 'click_cta',
49
- clickCard: 'click_card',
50
- }
51
-
52
- export const dismissTypes = {
53
- resumeConversationPrompt: 'resume_conversation_prompt',
54
- }
55
-
56
- export const ariaLiveLevels = {
57
- assertive: 'assertive',
58
- polite: 'polite',
59
- }
60
-
61
- export const dividerKeys = {
62
- new_topic: 'newTopic',
63
- new_translation: 'newTranslation',
64
- }
65
-
66
- export const featureKeys = {
67
- sendTranscript: 'sendTranscript',
68
- typingPeekahead: 'typingPeekahead',
69
- uploads: 'uploads',
70
- }
71
-
72
- export const seamlyActions = {
73
- ADD_EVENT: 'ADD_EVENT',
74
- CLEAR_EVENTS: 'CLEAR_EVENTS',
75
- SET_HISTORY: 'SET_HISTORY',
76
- SET_EVENTS_READ: 'SET_EVENTS_READ',
77
- SET_LOADED_IMAGE_EVENT_IDS: 'SET_LOADED_IMAGE_EVENT_IDS',
78
- ACK_EVENT: 'ACK_EVENT',
79
- SET_IS_LOADING: 'SET_IS_LOADING',
80
- CLEAR_PARTICIPANTS: 'CLEAR_PARTICIPANTS',
81
- SET_PARTICIPANT: 'SET_PARTICIPANT',
82
- SET_HEADER_TITLE: 'SET_HEADER_TITLE',
83
- SET_HEADER_SUB_TITLE: 'SET_HEADER_SUB_TITLE',
84
- RESET_HISTORY_LOADED_FLAG: 'RESET_HISTORY_LOADED_FLAG',
85
- SET_ACTIVE_SERVICE: 'SET_ACTIVE_SERVICE',
86
- INIT_IDLE_DETACH_COUNTDOWN: 'INIT_IDLE_DETACH_COUNTDOWN',
87
- DECREMENT_IDLE_DETACH_COUNTDOWN_COUNTER:
88
- 'DECREMENT_IDLE_DETACH_COUNTDOWN_COUNTER',
89
- STOP_IDLE_DETACH_COUNTDOWN_COUNTER: 'STOP_IDLE_DETACH_COUNTDOWN_COUNTER',
90
- CLEAR_IDLE_DETACH_COUNTDOWN: 'CLEAR_IDLE_DETACH_COUNTDOWN',
91
- INIT_RESUME_CONVERSATION_PROMPT: 'INIT_RESUME_CONVERSATION_PROMPT',
92
- CLEAR_RESUME_CONVERSATION_PROMPT: 'CLEAR_RESUME_CONVERSATION_PROMPT',
93
- SET_SERVICE_DATA_ITEM: 'SET_SERVICE_DATA_ITEM',
94
- SET_FEATURES: 'SET_FEATURES',
95
- SET_FEATURE_ENABLED_STATE: 'SET_FEATURE_ENABLED_STATE',
96
- CLEAR_FEATURES: 'CLEAR_FEATURES',
97
- SET_INITIAL_STATE: 'SET_INITIAL_STATE',
98
- SET_USER_SELECTED_OPTIONS: 'SET_USER_SELECTED_OPTIONS',
99
- SET_USER_SELECTED_OPTION: 'SET_USER_SELECTED_OPTION',
100
- SHOW_OPTION: 'SHOW_OPTION',
101
- HIDE_OPTION: 'HIDE_OPTION',
102
- SET_SERVICE_ENTRY_METADATA: 'SET_SERVICE_ENTRY_METADATA',
103
- SET_BLOCK_AUTO_ENTRY_SWITCH: 'SET_BLOCK_AUTO_ENTRY_SWITCH',
104
- SET_ACTIVE_ENTRY_TYPE: 'SET_ACTIVE_ENTRY_TYPE',
105
- SET_USER_ENTRY_TYPE: 'SET_USER_ENTRY_TYPE',
106
- REGISTER_UPLOAD: 'REGISTER_UPLOAD',
107
- SET_UPLOAD_PROGRESS: 'SET_UPLOAD_PROGRESS',
108
- SET_UPLOAD_COMPLETE: 'SET_UPLOAD_COMPLETE',
109
- SET_UPLOAD_ERROR: 'SET_UPLOAD_ERROR',
110
- CLEAR_UPLOAD: 'CLEAR_UPLOAD',
111
- CLEAR_ALL_UPLOADS: 'CLEAR_ALL_UPLOADS',
112
- SET_SEAMLY_CONTAINER_ELEMENT: 'SET_SEAMLY_CONTAINER_ELEMENT',
113
- }
114
-
115
- export const cardTypes = {
116
- ask: 'ask',
117
- navigate: 'navigate',
118
- topic: 'topic',
119
- }
120
-
121
- const {
122
- ADD_EVENT,
123
- CLEAR_EVENTS,
124
- SET_HISTORY,
125
- SET_EVENTS_READ,
126
- SET_LOADED_IMAGE_EVENT_IDS,
127
- ACK_EVENT,
128
- SET_IS_LOADING,
129
- CLEAR_PARTICIPANTS,
130
- SET_PARTICIPANT,
131
- SET_HEADER_TITLE,
132
- SET_HEADER_SUB_TITLE,
133
- RESET_HISTORY_LOADED_FLAG,
134
- SET_ACTIVE_SERVICE,
135
- INIT_IDLE_DETACH_COUNTDOWN,
136
- DECREMENT_IDLE_DETACH_COUNTDOWN_COUNTER,
137
- STOP_IDLE_DETACH_COUNTDOWN_COUNTER,
138
- CLEAR_IDLE_DETACH_COUNTDOWN,
139
- INIT_RESUME_CONVERSATION_PROMPT,
140
- CLEAR_RESUME_CONVERSATION_PROMPT,
141
- SET_SERVICE_DATA_ITEM,
142
- SET_FEATURES,
143
- SET_FEATURE_ENABLED_STATE,
144
- CLEAR_FEATURES,
145
- SET_INITIAL_STATE,
146
- SET_USER_SELECTED_OPTION,
147
- SET_USER_SELECTED_OPTIONS,
148
- SHOW_OPTION,
149
- HIDE_OPTION,
150
- SET_BLOCK_AUTO_ENTRY_SWITCH,
151
- SET_USER_ENTRY_TYPE,
152
- SET_ACTIVE_ENTRY_TYPE,
153
- SET_SERVICE_ENTRY_METADATA,
154
- REGISTER_UPLOAD,
155
- SET_UPLOAD_PROGRESS,
156
- SET_UPLOAD_COMPLETE,
157
- SET_UPLOAD_ERROR,
158
- CLEAR_UPLOAD,
159
- CLEAR_ALL_UPLOADS,
160
- SET_SEAMLY_CONTAINER_ELEMENT,
161
- } = seamlyActions
162
-
163
- export const isUnreadMessage = ({ type, payload }) =>
164
- (type === eventTypes.message && !payload.fromClient) ||
165
- (type === eventTypes.info && payload.type === payloadTypes.text)
166
-
167
- const orderHistory = (events) => {
168
- return events.sort(
169
- (
170
- { payload: { occurredAt: occurredAtA } },
171
- { payload: { occurredAt: occurredAtB } },
172
- ) => occurredAtA - occurredAtB,
173
- )
174
- }
175
-
176
- export const mergeHistory = (stateEvents, historyEvents) => {
177
- const newStateEvents = stateEvents.filter(
178
- (stateEvent) =>
179
- // Deduplicate the event streams, giving events in historyEvents
180
- // precedence so the server is able to push changes to events.
181
- !historyEvents.some(
182
- (historyEvent) => historyEvent.payload.id === stateEvent.payload.id,
183
- ),
184
- )
185
-
186
- const newHistoryEvents = historyEvents
187
- .filter(
188
- (historyEvent) =>
189
- // Remove all non displayable participant messages
190
- !(
191
- historyEvent.type === 'participant' &&
192
- !historyEvent.payload.participant.introduction
193
- ),
194
- )
195
- // Reverse is done here because the server sends the history in the order
196
- // newest to oldest. In the case of exactly the same occurredAt timestamps
197
- // these messages will be shown in the wrong order if not reversed. For
198
- // the normal merging logic there is no added effect.
199
- .reverse()
200
-
201
- return orderHistory([...newHistoryEvents, ...newStateEvents])
202
- }
203
-
204
- const participantReducer = (state, action) => {
205
- switch (action.type) {
206
- case CLEAR_PARTICIPANTS:
207
- return {
208
- participants: {},
209
- currentAgent: '',
210
- }
211
- case SET_PARTICIPANT:
212
- // TODO: a) Styleguide only! b) Should be removed after styleguide overhaul.
213
- if (!state) {
214
- return {
215
- participants: {},
216
- currentAgent: '',
217
- }
218
- }
219
-
220
- const { participants } = state || { participants: {} }
221
- const { id, avatar, name, introduction } = action.participant
222
- const oldParticipant = participants[id]
223
-
224
- const newParticipants = {
225
- ...participants,
226
- [id]: oldParticipant
227
- ? {
228
- ...oldParticipant,
229
- ...(avatar ? { avatar } : {}),
230
- ...(name ? { name } : {}),
231
- ...(introduction ? { introduction } : {}),
232
- }
233
- : action.participant,
234
- }
235
-
236
- return {
237
- ...state,
238
- participants: newParticipants,
239
- currentAgent:
240
- state.currentAgent !== id && !action.fromClient
241
- ? id
242
- : state.currentAgent,
243
- }
244
- default:
245
- return state
246
- }
247
- }
248
-
249
- const headerTitlesReducer = (state, action) => {
250
- switch (action.type) {
251
- case SET_HEADER_TITLE:
252
- return {
253
- ...state,
254
- title: action.title,
255
- }
256
- case SET_HEADER_SUB_TITLE:
257
- return {
258
- ...state,
259
- subTitle: action.title,
260
- }
261
- default:
262
- return state
263
- }
264
- }
265
-
266
- const calculateNewEntryMeta = (entryMeta, payload) => {
267
- const { entry } = payload
268
- const { blockAutoEntrySwitch } = entryMeta
269
-
270
- if (!entry) {
271
- return { ...entryMeta, optionsOverride: {} }
272
- }
273
-
274
- const { type, options } = entry
275
-
276
- let newActive = entryMeta.active
277
-
278
- if (!blockAutoEntrySwitch && type !== entryMeta.userSelected) {
279
- newActive = type
280
- }
281
-
282
- return {
283
- ...entryMeta,
284
- active: newActive,
285
- optionsOverride: {
286
- ...entryMeta.optionsOverride,
287
- [type]: options || {},
288
- },
289
- }
290
- }
291
-
292
- export const seamlyStateReducer = (state, action) => {
293
- switch (action.type) {
294
- case ADD_EVENT:
295
- const { type: eventType, payload } = action.event
296
-
297
- const accountHasUploads = state.options.features.hasOwnProperty(
298
- featureKeys.uploads,
299
- )
300
-
301
- const newEntryMeta = calculateNewEntryMeta(state.entryMeta, payload)
302
-
303
- let newOptions = { ...state.options }
304
-
305
- // This enabled override of the service enabled value for uploads.
306
- // If a message is sent with entry of type upload it will temporarily
307
- // override service value and enable uploads.
308
- if (
309
- accountHasUploads &&
310
- (eventType === eventTypes.message ||
311
- eventType === eventTypes.participant) &&
312
- !payload.fromClient
313
- ) {
314
- const entryType = payload?.entry?.type
315
- newOptions = {
316
- ...newOptions,
317
- features: {
318
- ...newOptions.features,
319
- uploads: {
320
- ...newOptions.features.uploads,
321
- enabledFromEntry: entryType === entryTypes.upload,
322
- },
323
- },
324
- }
325
- }
326
- const incrementUnread = isUnreadMessage(action.event)
327
-
328
- // We check for duplicated and ignore them as in some error of the websocket
329
- // a duplicate join can be active for a while until the server connection
330
- // times out.
331
- const eventExists = state.events.find((e) => e.payload.id === payload.id)
332
- if (eventExists) {
333
- return state
334
- }
335
-
336
- return {
337
- ...state,
338
- entryMeta:
339
- !accountHasUploads && newEntryMeta.active === entryTypes.upload
340
- ? { ...state.entryMeta }
341
- : newEntryMeta,
342
- options: newOptions,
343
- unreadEvents: incrementUnread
344
- ? state.unreadEvents + 1
345
- : state.unreadEvents,
346
- events: [
347
- ...state.events,
348
- {
349
- ...action.event,
350
- // The payload spread should be done after adding the message
351
- // status to enable overriding the status when setting
352
- // event optimistically.
353
- payload: {
354
- ...(incrementUnread && {
355
- messageStatus: payload.fromClient
356
- ? readStates.read
357
- : readStates.received,
358
- }),
359
- // We add a randomid to use as key for mapping of Events to avoid rerendering
360
- key: randomId(),
361
- ...payload,
362
- },
363
- },
364
- ],
365
- }
366
- case ACK_EVENT:
367
- // If any ACKs are sent without transactionID the conversation crashes.
368
- // Ensure that this edge case is handled gracefully.
369
- if (!action.event.payload.transactionId) {
370
- console.warn('ACK received without transaction ID.')
371
- return state
372
- }
373
-
374
- const matchedEvent = state.events.find(
375
- (m) => m.payload.transactionId === action.event.payload.transactionId,
376
- )
377
-
378
- const { id, occurredAt } = action.event.payload
379
-
380
- return matchedEvent
381
- ? {
382
- ...state,
383
- events: orderHistory(
384
- state.events.map((m) =>
385
- m.payload.id === matchedEvent.payload.id
386
- ? {
387
- ...m,
388
- payload: { ...m.payload, id, occurredAt },
389
- }
390
- : m,
391
- ),
392
- ),
393
- }
394
- : state
395
-
396
- case CLEAR_EVENTS:
397
- return { ...state, unreadEvents: 0, loadedImageEventIds: [], events: [] }
398
- case SET_EVENTS_READ:
399
- return {
400
- ...state,
401
- unreadEvents: 0,
402
- events: state.events.map((event) => {
403
- if (action.ids.indexOf(event.payload.id) !== -1) {
404
- return {
405
- ...event,
406
- payload: {
407
- ...event.payload,
408
- ...(event.payload.messageStatus === readStates.received && {
409
- messageStatus: readStates.read,
410
- }),
411
- },
412
- }
413
- }
414
- return event
415
- }),
416
- }
417
- case SET_LOADED_IMAGE_EVENT_IDS:
418
- return {
419
- ...state,
420
- loadedImageEventIds: [...state.loadedImageEventIds, action.eventId],
421
- }
422
- case SET_HISTORY:
423
- const {
424
- events: history,
425
- participants,
426
- activeServiceSessionId,
427
- activeServiceSettings = {},
428
- serviceData,
429
- resumeConversationPrompt,
430
- } = action.history
431
-
432
- const events = mergeHistory(state.events, history)
433
-
434
- const mergedParticipants = {
435
- ...state.participantInfo.participants,
436
- ...participants,
437
- }
438
-
439
- const lastParticipantEvent = events
440
- .slice()
441
- .reverse()
442
- .find(
443
- (m) =>
444
- (m.type === 'message' || m.type === 'participant') &&
445
- !m.payload.fromClient,
446
- )
447
-
448
- let lastParticipantId = null
449
-
450
- if (lastParticipantEvent) {
451
- if (lastParticipantEvent.type === 'message') {
452
- lastParticipantId = lastParticipantEvent.payload.participant
453
- }
454
- if (lastParticipantEvent.type === 'participant') {
455
- lastParticipantId = lastParticipantEvent.payload.participant.id
456
- }
457
- }
458
-
459
- const { entry, uploads } = activeServiceSettings
460
-
461
- const historyNewEntryMeta = calculateNewEntryMeta(
462
- {
463
- ...state.entryMeta,
464
- ...entry,
465
- active: entry.default || payloadTypes.text,
466
- options: { ...(entry && entry.options ? entry.options : {}) },
467
- },
468
- events[events.length - 1].payload,
469
- )
470
-
471
- let newFeatures = { ...state.options.features }
472
-
473
- const newFeaturesHasUpload = newFeatures.hasOwnProperty(
474
- featureKeys.uploads,
475
- )
476
-
477
- // Only set uploads if it was initialised by the account config.
478
- if (newFeaturesHasUpload) {
479
- const entryType = lastParticipantEvent?.payload?.entry?.type
480
- newFeatures = {
481
- ...newFeatures,
482
- uploads: {
483
- enabled: !!(uploads && uploads.enabled),
484
- enabledFromEntry: entryType === entryTypes.upload,
485
- },
486
- }
487
- }
488
-
489
- const returnState = {
490
- ...state,
491
- unreadEvents: events.filter(
492
- (event) =>
493
- event.type === 'message' &&
494
- event.payload.messageStatus === readStates.received,
495
- ).length,
496
- events: events.filter(
497
- (e) =>
498
- e.type !== 'participant' || !!e.payload.participant.introduction,
499
- ),
500
- participantInfo: {
501
- ...state.participantInfo,
502
- ...(lastParticipantId
503
- ? participantReducer(state.participantInfo, {
504
- type: SET_PARTICIPANT,
505
- participant: mergedParticipants[lastParticipantId],
506
- })
507
- : {}),
508
- participants: mergedParticipants,
509
- },
510
- historyLoaded: true,
511
- serviceInfo: {
512
- ...state.serviceInfo,
513
- activeServiceSessionId,
514
- },
515
- serviceData: serviceData || {},
516
- options: {
517
- ...state.options,
518
- features: newFeatures,
519
- },
520
- entryMeta:
521
- !newFeaturesHasUpload &&
522
- historyNewEntryMeta.active === entryTypes.upload
523
- ? { ...state.entryMeta }
524
- : historyNewEntryMeta,
525
- resumeConversationPrompt: resumeConversationPrompt || false,
526
- }
527
-
528
- if (lastParticipantId) {
529
- returnState.headerTitles = headerTitlesReducer(state.headerTitles, {
530
- type: SET_HEADER_SUB_TITLE,
531
- title: mergedParticipants[lastParticipantId].name,
532
- })
533
- }
534
-
535
- return returnState
536
- case RESET_HISTORY_LOADED_FLAG:
537
- return {
538
- ...state,
539
- historyLoaded: false,
540
- }
541
- case SET_IS_LOADING:
542
- return { ...state, isLoading: action.isLoading }
543
- case INIT_IDLE_DETACH_COUNTDOWN:
544
- const { delaySeconds, delayTime } = action
545
- return {
546
- ...state,
547
- idleDetachCountdown: {
548
- hasCountdown: true,
549
- isActive: true,
550
- wasStopped: false,
551
- count: delaySeconds,
552
- remaining: delaySeconds,
553
- timer: delayTime,
554
- },
555
- }
556
- case DECREMENT_IDLE_DETACH_COUNTDOWN_COUNTER:
557
- const { idleDetachCountdown } = state
558
-
559
- const { remaining: prevRemaining } = idleDetachCountdown
560
-
561
- const remaining = prevRemaining - 1
562
-
563
- return {
564
- ...state,
565
- idleDetachCountdown: {
566
- ...state.idleDetachCountdown,
567
- remaining,
568
- timer: getTimeFromSeconds(remaining),
569
- },
570
- }
571
- case STOP_IDLE_DETACH_COUNTDOWN_COUNTER: {
572
- return {
573
- ...state,
574
- idleDetachCountdown: {
575
- ...state.idleDetachCountdown,
576
- isActive: false,
577
- wasStopped: true,
578
- },
579
- }
580
- }
581
- case CLEAR_IDLE_DETACH_COUNTDOWN:
582
- return {
583
- ...state,
584
- idleDetachCountdown: { hasCountdown: false, isActive: false },
585
- }
586
- case INIT_RESUME_CONVERSATION_PROMPT:
587
- return {
588
- ...state,
589
- resumeConversationPrompt: true,
590
- }
591
- case CLEAR_RESUME_CONVERSATION_PROMPT:
592
- return {
593
- ...state,
594
- resumeConversationPrompt: false,
595
- }
596
- case SET_PARTICIPANT:
597
- case CLEAR_PARTICIPANTS:
598
- return {
599
- ...state,
600
- participantInfo: participantReducer(state.participantInfo, action),
601
- }
602
- case SET_ACTIVE_SERVICE:
603
- if (
604
- state.serviceInfo.activeServiceSessionId !==
605
- action.activeServiceSessionId
606
- ) {
607
- return {
608
- ...state,
609
- serviceInfo: {
610
- ...state.serviceInfo,
611
- activeServiceSessionId: action.activeServiceSessionId,
612
- },
613
- }
614
- }
615
- return state
616
- case SET_HEADER_TITLE:
617
- case SET_HEADER_SUB_TITLE:
618
- return {
619
- ...state,
620
- headerTitles: headerTitlesReducer(state.headerTitles, action),
621
- }
622
- case SET_INITIAL_STATE:
623
- const { initialState } = action
624
- return {
625
- ...state,
626
- initialState,
627
- unreadEvents: initialState.unreadMessageCount,
628
- }
629
- case SET_SERVICE_DATA_ITEM:
630
- return {
631
- ...state,
632
- serviceData: {
633
- ...state.serviceData,
634
- [action.payload.type]: action.payload,
635
- },
636
- }
637
- case SET_FEATURES:
638
- return {
639
- ...state,
640
- options: {
641
- ...state.options,
642
- features: action.features,
643
- },
644
- }
645
- case SET_FEATURE_ENABLED_STATE:
646
- return state.options.features.hasOwnProperty(action.key)
647
- ? {
648
- ...state,
649
- options: {
650
- ...state.options,
651
- features: {
652
- ...state.options.features,
653
- [action.key]: {
654
- ...(state.options.features[action.key] || {}),
655
- enabled: action.enabled,
656
- },
657
- },
658
- },
659
- }
660
- : state
661
- case CLEAR_FEATURES:
662
- return {
663
- ...state,
664
- options: {
665
- ...state.options,
666
- features: {},
667
- },
668
- }
669
- case SHOW_OPTION:
670
- return {
671
- ...state,
672
- options: {
673
- ...state.options,
674
- panelActive: true,
675
- optionActive: action.optionName,
676
- },
677
- }
678
- case HIDE_OPTION:
679
- return {
680
- ...state,
681
- options: {
682
- ...state.options,
683
- panelActive: false,
684
- optionActive: '',
685
- },
686
- }
687
- case SET_USER_SELECTED_OPTIONS:
688
- return {
689
- ...state,
690
- options: {
691
- ...state.options,
692
- userSelectedOptions: action.options,
693
- },
694
- }
695
- case SET_USER_SELECTED_OPTION:
696
- const { option, value } = action
697
- return {
698
- ...state,
699
- options: {
700
- ...state.options,
701
- userSelectedOptions: {
702
- ...state.options.userSelectedOptions,
703
- [option]: value,
704
- },
705
- },
706
- }
707
- case SET_BLOCK_AUTO_ENTRY_SWITCH:
708
- const { value: blockAutoEntrySwitch } = action
709
-
710
- return {
711
- ...state,
712
- entryMeta: {
713
- ...state.entryMeta,
714
- blockAutoEntrySwitch,
715
- },
716
- }
717
- case SET_SERVICE_ENTRY_METADATA:
718
- const { entryMeta } = action
719
-
720
- return {
721
- ...state,
722
- entryMeta: {
723
- ...state.entryMeta,
724
- ...entryMeta,
725
- active: entryMeta.default,
726
- options: { ...(entryMeta.options || {}) },
727
- overrideOptions: {},
728
- },
729
- }
730
- case SET_ACTIVE_ENTRY_TYPE:
731
- const { entryType: active } = action
732
-
733
- return {
734
- ...state,
735
- entryMeta: {
736
- ...state.entryMeta,
737
- active,
738
- },
739
- }
740
- case SET_USER_ENTRY_TYPE:
741
- const { entryType: userSelected } = action
742
-
743
- return {
744
- ...state,
745
- entryMeta: {
746
- ...state.entryMeta,
747
- userSelected,
748
- },
749
- }
750
- case REGISTER_UPLOAD:
751
- return {
752
- ...state,
753
- currentUploads: [
754
- ...state.currentUploads,
755
- {
756
- id: action.fileId,
757
- name: action.fileName,
758
- progress: 1,
759
- uploading: true,
760
- complete: false,
761
- error: '',
762
- uploadHandle: action.uploadHandle,
763
- },
764
- ],
765
- }
766
- case SET_UPLOAD_PROGRESS:
767
- return {
768
- ...state,
769
- currentUploads: state.currentUploads.map((fileUpload) => {
770
- if (fileUpload.id === action.fileId) {
771
- return {
772
- ...fileUpload,
773
- progress: action.progress,
774
- uploading: action.progress !== 100,
775
- uploadHandle:
776
- action.progress === 100 ? null : fileUpload.uploadHandle,
777
- }
778
- }
779
- return fileUpload
780
- }),
781
- }
782
- case SET_UPLOAD_ERROR:
783
- return {
784
- ...state,
785
- currentUploads: state.currentUploads.map((fileUpload) => {
786
- if (fileUpload.id === action.fileId) {
787
- return {
788
- ...fileUpload,
789
- error: action.errorText,
790
- progress: 0,
791
- uploading: false,
792
- uploadHandle: null,
793
- }
794
- }
795
- return fileUpload
796
- }),
797
- }
798
- case SET_UPLOAD_COMPLETE:
799
- return {
800
- ...state,
801
- currentUploads: state.currentUploads.map((fileUpload) => {
802
- if (fileUpload.id === action.fileId) {
803
- return {
804
- ...fileUpload,
805
- complete: true,
806
- }
807
- }
808
- return fileUpload
809
- }),
810
- }
811
- case CLEAR_UPLOAD:
812
- return {
813
- ...state,
814
- currentUploads: state.currentUploads.filter(
815
- (fileUpload) => fileUpload.id !== action.fileId,
816
- ),
817
- }
818
- case CLEAR_ALL_UPLOADS:
819
- return {
820
- ...state,
821
- currentUploads: [],
822
- }
823
- case SET_SEAMLY_CONTAINER_ELEMENT: {
824
- return {
825
- ...state,
826
- seamlyContainerElement: action.element,
827
- }
828
- }
829
- default:
830
- return state
831
- }
832
- }