@magmamath/students-features 0.3.0-rc.8 → 0.3.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 (157) hide show
  1. package/dist/commonjs/features/chatbot/components/Alternatives/Alternatives.js +6 -9
  2. package/dist/commonjs/features/chatbot/components/Alternatives/Alternatives.js.map +1 -1
  3. package/dist/commonjs/features/chatbot/components/ChatControls/ChatControls.js +13 -5
  4. package/dist/commonjs/features/chatbot/components/ChatControls/ChatControls.js.map +1 -1
  5. package/dist/commonjs/features/chatbot/components/ChatMessage/MessageLoader.js +4 -3
  6. package/dist/commonjs/features/chatbot/components/ChatMessage/MessageLoader.js.map +1 -1
  7. package/dist/commonjs/features/chatbot/components/ChatMessage/MessageTextToSpeech.js +2 -3
  8. package/dist/commonjs/features/chatbot/components/ChatMessage/MessageTextToSpeech.js.map +1 -1
  9. package/dist/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.js +5 -4
  10. package/dist/commonjs/features/chatbot/components/ChatMessage/ReceivedMessage.js.map +1 -1
  11. package/dist/commonjs/features/chatbot/components/ChatMessages/ChatbotMessages.js +6 -9
  12. package/dist/commonjs/features/chatbot/components/ChatMessages/ChatbotMessages.js.map +1 -1
  13. package/dist/commonjs/features/chatbot/components/Chatbot.js +8 -9
  14. package/dist/commonjs/features/chatbot/components/Chatbot.js.map +1 -1
  15. package/dist/commonjs/features/chatbot/model/ChatBotModel.js +83 -91
  16. package/dist/commonjs/features/chatbot/model/ChatBotModel.js.map +1 -1
  17. package/dist/commonjs/features/chatbot/model/api.js.map +1 -1
  18. package/dist/commonjs/features/chatbot/model/messagesHelper.js +46 -0
  19. package/dist/commonjs/features/chatbot/model/messagesHelper.js.map +1 -0
  20. package/dist/commonjs/features/chatbot/model/t2s.js +1 -2
  21. package/dist/commonjs/features/chatbot/model/t2s.js.map +1 -1
  22. package/dist/commonjs/features/chatbot/model/translation.helpers.js +69 -0
  23. package/dist/commonjs/features/chatbot/model/translation.helpers.js.map +1 -0
  24. package/dist/commonjs/features/chatbot/model/translation.js +121 -140
  25. package/dist/commonjs/features/chatbot/model/translation.js.map +1 -1
  26. package/dist/commonjs/features/chatbot/types/model.types.js.map +1 -1
  27. package/dist/commonjs/index.js +9 -1
  28. package/dist/commonjs/index.js.map +1 -1
  29. package/dist/commonjs/lib/effector/createEntityFieldStore.js +14 -13
  30. package/dist/commonjs/lib/effector/createEntityFieldStore.js.map +1 -1
  31. package/dist/commonjs/lib/helpers/types.js +2 -0
  32. package/dist/commonjs/lib/helpers/types.js.map +1 -0
  33. package/dist/commonjs/shared/icons/ChatbotIcon.js +613 -106
  34. package/dist/commonjs/shared/icons/ChatbotIcon.js.map +1 -1
  35. package/dist/module/features/chatbot/components/Alternatives/Alternatives.js +6 -9
  36. package/dist/module/features/chatbot/components/Alternatives/Alternatives.js.map +1 -1
  37. package/dist/module/features/chatbot/components/ChatControls/ChatControls.js +13 -5
  38. package/dist/module/features/chatbot/components/ChatControls/ChatControls.js.map +1 -1
  39. package/dist/module/features/chatbot/components/ChatMessage/MessageLoader.js +4 -3
  40. package/dist/module/features/chatbot/components/ChatMessage/MessageLoader.js.map +1 -1
  41. package/dist/module/features/chatbot/components/ChatMessage/MessageTextToSpeech.js +2 -3
  42. package/dist/module/features/chatbot/components/ChatMessage/MessageTextToSpeech.js.map +1 -1
  43. package/dist/module/features/chatbot/components/ChatMessage/ReceivedMessage.js +5 -4
  44. package/dist/module/features/chatbot/components/ChatMessage/ReceivedMessage.js.map +1 -1
  45. package/dist/module/features/chatbot/components/ChatMessages/ChatbotMessages.js +6 -9
  46. package/dist/module/features/chatbot/components/ChatMessages/ChatbotMessages.js.map +1 -1
  47. package/dist/module/features/chatbot/components/Chatbot.js +8 -9
  48. package/dist/module/features/chatbot/components/Chatbot.js.map +1 -1
  49. package/dist/module/features/chatbot/index.js.map +1 -1
  50. package/dist/module/features/chatbot/model/ChatBotModel.js +84 -92
  51. package/dist/module/features/chatbot/model/ChatBotModel.js.map +1 -1
  52. package/dist/module/features/chatbot/model/api.js.map +1 -1
  53. package/dist/module/features/chatbot/model/messagesHelper.js +41 -0
  54. package/dist/module/features/chatbot/model/messagesHelper.js.map +1 -0
  55. package/dist/module/features/chatbot/model/t2s.js +1 -2
  56. package/dist/module/features/chatbot/model/t2s.js.map +1 -1
  57. package/dist/module/features/chatbot/model/translation.helpers.js +63 -0
  58. package/dist/module/features/chatbot/model/translation.helpers.js.map +1 -0
  59. package/dist/module/features/chatbot/model/translation.js +122 -141
  60. package/dist/module/features/chatbot/model/translation.js.map +1 -1
  61. package/dist/module/features/chatbot/types/model.types.js.map +1 -1
  62. package/dist/module/index.js +1 -0
  63. package/dist/module/index.js.map +1 -1
  64. package/dist/module/lib/effector/createEntityFieldStore.js +12 -13
  65. package/dist/module/lib/effector/createEntityFieldStore.js.map +1 -1
  66. package/dist/module/lib/helpers/types.js +2 -0
  67. package/dist/module/lib/helpers/types.js.map +1 -0
  68. package/dist/module/shared/icons/ChatbotIcon.js +614 -107
  69. package/dist/module/shared/icons/ChatbotIcon.js.map +1 -1
  70. package/dist/typescript/commonjs/features/chatbot/components/Alternatives/Alternatives.d.ts.map +1 -1
  71. package/dist/typescript/commonjs/features/chatbot/components/ChatControls/ChatControls.d.ts +5 -1
  72. package/dist/typescript/commonjs/features/chatbot/components/ChatControls/ChatControls.d.ts.map +1 -1
  73. package/dist/typescript/commonjs/features/chatbot/components/ChatMessages/ChatbotMessages.d.ts.map +1 -1
  74. package/dist/typescript/commonjs/features/chatbot/components/Chatbot.d.ts +5 -1
  75. package/dist/typescript/commonjs/features/chatbot/components/Chatbot.d.ts.map +1 -1
  76. package/dist/typescript/commonjs/features/chatbot/index.d.ts +2 -1
  77. package/dist/typescript/commonjs/features/chatbot/index.d.ts.map +1 -1
  78. package/dist/typescript/commonjs/features/chatbot/model/ChatBotModel.d.ts +15 -45
  79. package/dist/typescript/commonjs/features/chatbot/model/ChatBotModel.d.ts.map +1 -1
  80. package/dist/typescript/commonjs/features/chatbot/model/api.d.ts +5 -7
  81. package/dist/typescript/commonjs/features/chatbot/model/api.d.ts.map +1 -1
  82. package/dist/typescript/commonjs/features/chatbot/model/messagesHelper.d.ts +21 -0
  83. package/dist/typescript/commonjs/features/chatbot/model/messagesHelper.d.ts.map +1 -0
  84. package/dist/typescript/commonjs/features/chatbot/model/t2s.d.ts +1 -1
  85. package/dist/typescript/commonjs/features/chatbot/model/t2s.d.ts.map +1 -1
  86. package/dist/typescript/commonjs/features/chatbot/model/translation.d.ts +30 -13
  87. package/dist/typescript/commonjs/features/chatbot/model/translation.d.ts.map +1 -1
  88. package/dist/typescript/commonjs/features/chatbot/model/translation.helpers.d.ts +10 -0
  89. package/dist/typescript/commonjs/features/chatbot/model/translation.helpers.d.ts.map +1 -0
  90. package/dist/typescript/commonjs/features/chatbot/types/api.types.d.ts +1 -0
  91. package/dist/typescript/commonjs/features/chatbot/types/api.types.d.ts.map +1 -1
  92. package/dist/typescript/commonjs/features/chatbot/types/model.types.d.ts +6 -3
  93. package/dist/typescript/commonjs/features/chatbot/types/model.types.d.ts.map +1 -1
  94. package/dist/typescript/commonjs/features/chatbot/types/translation.types.d.ts +20 -5
  95. package/dist/typescript/commonjs/features/chatbot/types/translation.types.d.ts.map +1 -1
  96. package/dist/typescript/commonjs/index.d.ts +1 -0
  97. package/dist/typescript/commonjs/index.d.ts.map +1 -1
  98. package/dist/typescript/commonjs/lib/effector/createEntityFieldStore.d.ts +6 -5
  99. package/dist/typescript/commonjs/lib/effector/createEntityFieldStore.d.ts.map +1 -1
  100. package/dist/typescript/commonjs/lib/helpers/types.d.ts +2 -0
  101. package/dist/typescript/commonjs/lib/helpers/types.d.ts.map +1 -0
  102. package/dist/typescript/commonjs/shared/icons/ChatbotIcon.d.ts.map +1 -1
  103. package/dist/typescript/module/features/chatbot/components/Alternatives/Alternatives.d.ts.map +1 -1
  104. package/dist/typescript/module/features/chatbot/components/ChatControls/ChatControls.d.ts +5 -1
  105. package/dist/typescript/module/features/chatbot/components/ChatControls/ChatControls.d.ts.map +1 -1
  106. package/dist/typescript/module/features/chatbot/components/ChatMessages/ChatbotMessages.d.ts.map +1 -1
  107. package/dist/typescript/module/features/chatbot/components/Chatbot.d.ts +5 -1
  108. package/dist/typescript/module/features/chatbot/components/Chatbot.d.ts.map +1 -1
  109. package/dist/typescript/module/features/chatbot/index.d.ts +2 -1
  110. package/dist/typescript/module/features/chatbot/index.d.ts.map +1 -1
  111. package/dist/typescript/module/features/chatbot/model/ChatBotModel.d.ts +15 -45
  112. package/dist/typescript/module/features/chatbot/model/ChatBotModel.d.ts.map +1 -1
  113. package/dist/typescript/module/features/chatbot/model/api.d.ts +5 -7
  114. package/dist/typescript/module/features/chatbot/model/api.d.ts.map +1 -1
  115. package/dist/typescript/module/features/chatbot/model/messagesHelper.d.ts +21 -0
  116. package/dist/typescript/module/features/chatbot/model/messagesHelper.d.ts.map +1 -0
  117. package/dist/typescript/module/features/chatbot/model/t2s.d.ts +1 -1
  118. package/dist/typescript/module/features/chatbot/model/t2s.d.ts.map +1 -1
  119. package/dist/typescript/module/features/chatbot/model/translation.d.ts +30 -13
  120. package/dist/typescript/module/features/chatbot/model/translation.d.ts.map +1 -1
  121. package/dist/typescript/module/features/chatbot/model/translation.helpers.d.ts +10 -0
  122. package/dist/typescript/module/features/chatbot/model/translation.helpers.d.ts.map +1 -0
  123. package/dist/typescript/module/features/chatbot/types/api.types.d.ts +1 -0
  124. package/dist/typescript/module/features/chatbot/types/api.types.d.ts.map +1 -1
  125. package/dist/typescript/module/features/chatbot/types/model.types.d.ts +6 -3
  126. package/dist/typescript/module/features/chatbot/types/model.types.d.ts.map +1 -1
  127. package/dist/typescript/module/features/chatbot/types/translation.types.d.ts +20 -5
  128. package/dist/typescript/module/features/chatbot/types/translation.types.d.ts.map +1 -1
  129. package/dist/typescript/module/index.d.ts +1 -0
  130. package/dist/typescript/module/index.d.ts.map +1 -1
  131. package/dist/typescript/module/lib/effector/createEntityFieldStore.d.ts +6 -5
  132. package/dist/typescript/module/lib/effector/createEntityFieldStore.d.ts.map +1 -1
  133. package/dist/typescript/module/lib/helpers/types.d.ts +2 -0
  134. package/dist/typescript/module/lib/helpers/types.d.ts.map +1 -0
  135. package/dist/typescript/module/shared/icons/ChatbotIcon.d.ts.map +1 -1
  136. package/package.json +1 -1
  137. package/src/features/chatbot/components/Alternatives/Alternatives.tsx +4 -9
  138. package/src/features/chatbot/components/ChatControls/ChatControls.tsx +6 -3
  139. package/src/features/chatbot/components/ChatMessage/MessageLoader.tsx +3 -2
  140. package/src/features/chatbot/components/ChatMessage/MessageTextToSpeech.tsx +1 -2
  141. package/src/features/chatbot/components/ChatMessage/ReceivedMessage.tsx +4 -3
  142. package/src/features/chatbot/components/ChatMessages/ChatbotMessages.tsx +4 -9
  143. package/src/features/chatbot/components/Chatbot.tsx +5 -8
  144. package/src/features/chatbot/index.ts +7 -1
  145. package/src/features/chatbot/model/ChatBotModel.ts +81 -98
  146. package/src/features/chatbot/model/api.ts +24 -33
  147. package/src/features/chatbot/model/messagesHelper.ts +48 -0
  148. package/src/features/chatbot/model/t2s.ts +1 -2
  149. package/src/features/chatbot/model/translation.helpers.ts +58 -0
  150. package/src/features/chatbot/model/translation.ts +147 -160
  151. package/src/features/chatbot/types/api.types.ts +1 -0
  152. package/src/features/chatbot/types/model.types.ts +7 -3
  153. package/src/features/chatbot/types/translation.types.ts +21 -5
  154. package/src/index.ts +1 -0
  155. package/src/lib/effector/createEntityFieldStore.ts +11 -9
  156. package/src/lib/helpers/types.ts +1 -0
  157. package/src/shared/icons/ChatbotIcon.tsx +500 -85
@@ -22,6 +22,7 @@ type ChatbotProps = {
22
22
  }
23
23
  ButtonWrapper: ComponentType<PropsWithChildren>
24
24
  renderer?: (props: ChatbotRenderer) => ReactNode
25
+ iconSize?: { width: number; height: number } // TODO: use number instead
25
26
  }
26
27
 
27
28
  export const Chatbot = ({
@@ -35,18 +36,13 @@ export const Chatbot = ({
35
36
  isTranslationEnabled,
36
37
  renderer,
37
38
  ButtonWrapper,
39
+ iconSize,
38
40
  }: ChatbotProps) => {
39
- const currentKey = useUnit(model.$currentKey)
40
41
  const alternatives = useUnit(model.$alternatives)
41
-
42
- const isAvailable = useStoreMap({
43
- store: model.availableChats.$state,
44
- keys: [currentKey],
45
- fn: state => !!state[currentKey],
46
- })
42
+ const isAvailable = useStoreMap(model.$currentChatData, ({ isAvailable }) => isAvailable)
47
43
 
48
44
  const translateMessages = () => {
49
- void model.translation.translateBatchFx({
45
+ void model.translation.translateAllMessagesFx({
50
46
  targetLanguage: translationTargetLanguage,
51
47
  })
52
48
  }
@@ -78,6 +74,7 @@ export const Chatbot = ({
78
74
  onPressClose={closeChat}
79
75
  isTranslationEnabled={isTranslationEnabled}
80
76
  ButtonWrapper={ButtonWrapper}
77
+ iconSize={iconSize}
81
78
  />
82
79
  </>
83
80
  )
@@ -1,4 +1,10 @@
1
1
  export { Chatbot } from './components/Chatbot'
2
2
  export { ChatbotModel } from './model/ChatBotModel'
3
3
  export { AudioStatus, type AudioProvider } from './types/t2s.types'
4
- export { MessageVariant, type ConversationMessage, type ChatbotRenderer } from './types/model.types'
4
+ export {
5
+ MessageVariant,
6
+ type ConversationMessage,
7
+ type ChatbotRenderer,
8
+ type ChatbotModelProps,
9
+ } from './types/model.types'
10
+ export type { PostMessageResponse, ChatAnswer } from './types/api.types'
@@ -4,10 +4,9 @@ import {
4
4
  restore,
5
5
  sample,
6
6
  type Store,
7
- type Effect,
8
- combine,
9
7
  createStore,
10
8
  createEffect,
9
+ combine,
11
10
  } from 'effector'
12
11
  import { createControllerEffect, createEntityFieldStore } from '../../../lib/effector'
13
12
  import {
@@ -18,12 +17,12 @@ import {
18
17
  SetHintMessageProps,
19
18
  StartConversationFxData,
20
19
  } from '../types/model.types'
21
- import { ChatAnswer, GetAlternativesResponse, PostMessageResponse } from '../types/api.types'
22
- import { generateRandomId } from '../../../lib/helpers/helpers'
20
+ import { GetAlternativesResponse } from '../types/api.types'
23
21
  import { ChatbotAPI } from './api'
24
22
  import { ChatbotTranslation } from './translation'
25
23
  import { ChatTextToSpeechModel } from './t2s'
26
24
  import { AudioProvider } from '../types/t2s.types'
25
+ import { messagesHelper } from './messagesHelper'
27
26
 
28
27
  type ReinitConversationProps = {
29
28
  key: string
@@ -42,9 +41,8 @@ export class ChatbotModel {
42
41
 
43
42
  readonly setIsOpen = createEvent<boolean>()
44
43
  readonly toggleOpen = createEvent()
45
- readonly $isOpen = restore(this.setIsOpen, false).on(this.toggleOpen, isOpen => !isOpen)
44
+ readonly $isOpen = restore(this.setIsOpen, false).on(this.toggleOpen, (isOpen) => !isOpen)
46
45
 
47
- // separate messages and alternatives class?
48
46
  public readonly removeLastMessage = createEvent()
49
47
  private readonly setLastMessageKey = createEvent<string>()
50
48
  public readonly $lastMessageKey = restore(this.setLastMessageKey, null)
@@ -52,134 +50,120 @@ export class ChatbotModel {
52
50
  readonly setScrollActive = createEvent<boolean>()
53
51
  readonly $isScrollActive = restore(this.setScrollActive, false)
54
52
 
55
- readonly sendHelpRequestFx: Effect<SendHelpParams, PostMessageResponse | ConversationMessage>
53
+ readonly sendHelpRequestFx
56
54
 
57
55
  readonly defaultMessages: ChatbotModelProps['messages']
58
56
 
57
+ readonly messages = createEntityFieldStore<ConversationMessage[]>()
58
+ readonly threadIds = createEntityFieldStore<string>()
59
+ readonly availableChats = createEntityFieldStore<boolean>()
60
+
61
+ public readonly $currentChatData = combine(
62
+ {
63
+ messages: this.messages.$state,
64
+ threadIds: this.threadIds.$state,
65
+ availableChats: this.availableChats.$state,
66
+ key: this.$currentKey,
67
+ },
68
+ ({ messages, threadIds, availableChats, key }) => {
69
+ return {
70
+ messages: messages[key] ?? [],
71
+ threadId: threadIds[key] ?? null,
72
+ isAvailable: availableChats[key] ?? false,
73
+ key,
74
+ }
75
+ },
76
+ )
77
+
59
78
  constructor({ api, messages, $key }: ChatbotModelProps) {
60
79
  this.api = new ChatbotAPI(api)
61
80
 
62
81
  this.defaultMessages = messages
63
- if ($key) {
64
- sample({
65
- source: $key,
66
- target: this.$currentKey,
67
- })
68
- }
82
+ if ($key) sample({ source: $key, target: this.$currentKey })
69
83
 
70
84
  this.$alternatives = restore(this.api.getAlternativesFx.doneData, null)
71
85
  .on(this.setAlternatives, (_, payload) => payload)
72
86
  .reset(this.resetAlternatives)
73
87
 
74
- // TODO: do not pass this, just what you need
75
- this.translation = new ChatbotTranslation(this)
88
+ this.translation = new ChatbotTranslation({
89
+ defaultMessages: messages,
90
+ $key: this.$currentKey,
91
+ api: this.api,
92
+ messagesModel: this.messages,
93
+ alternativesModel: {
94
+ $store: this.$alternatives,
95
+ set: this.setAlternatives,
96
+ },
97
+ })
98
+
76
99
  this.t2s = new ChatTextToSpeechModel({ $isOpen: this.$isOpen, api: this.api })
77
100
 
78
101
  this.sendHelpRequestFx = this.createSendHelpRequestFx()
79
102
  this.initChatReplyWatcher()
80
103
  }
81
104
 
82
- readonly messages = createEntityFieldStore<ConversationMessage[]>()
83
- readonly threadIds = createEntityFieldStore<string>()
84
- readonly availableChats = createEntityFieldStore<boolean>()
85
-
86
105
  private createSendHelpRequestFx() {
87
- return attach({
88
- source: [this.$currentKey, this.messages.$state, this.translation.$isTranslated],
89
- mapParams: (params: SendHelpParams, [key, messages, isTranslated]) => ({
106
+ const effect = attach({
107
+ source: [this.$currentKey, this.translation.$isTranslated],
108
+ mapParams: (params: SendHelpParams, [key, isTranslated]) => ({
90
109
  ...params,
91
110
  key,
92
- messages,
93
111
  isTranslated,
94
112
  }),
95
113
  effect: createControllerEffect(
96
114
  async ({
97
115
  payload,
98
- message = '',
99
- translationTargetLanguage,
116
+ message,
117
+ translationTargetLanguage: targetLanguage,
100
118
  translatedMessage,
101
119
  key,
102
- messages,
103
120
  isTranslated,
104
121
  }: SendHelpProps) => {
105
122
  this.setLastMessageKey(key)
106
-
107
- const currentMessages = messages[key] || []
108
-
109
123
  this.messages.setField({
110
124
  key,
111
- data: [
112
- ...currentMessages,
113
- {
114
- id: generateRandomId(),
115
- message: message ?? '',
116
- translatedMessage,
117
- isOwnMessage: true,
118
- threadId: payload.threadId ?? '',
119
- options: [],
120
- },
125
+ fn: (currentMessages) => [
126
+ ...(currentMessages || []),
127
+ messagesHelper.createOwn({ message, translatedMessage, threadId: payload.threadId }),
121
128
  ],
122
129
  })
123
130
 
124
131
  const response = await this.api.postMessageFx(payload)
132
+ let messages = [messagesHelper.createAnswer(response)]
133
+ if (response.endMessage) {
134
+ messages.push(messagesHelper.createLast(this.defaultMessages.endMessage))
135
+ }
125
136
  if (isTranslated) {
126
- return await this.translation.translateMessageFx({
127
- targetLanguage: translationTargetLanguage as string,
128
- message: {
129
- ...response,
130
- id: generateRandomId(),
131
- isOwnMessage: false,
132
- },
133
- })
137
+ messages = await this.translation.translateMessagesFx({ targetLanguage, messages })
134
138
  }
135
139
 
136
- return response
140
+ this.messages.setField({
141
+ key,
142
+ fn: (currentMessages) => [...(currentMessages || []), ...messages],
143
+ })
144
+ this.threadIds.setField({ key, data: response.threadId })
137
145
  },
138
146
  ),
139
147
  })
140
- }
141
148
 
142
- private initChatReplyWatcher() {
143
149
  sample({
144
- clock: this.sendHelpRequestFx.doneData,
145
- source: [this.$currentKey, this.messages.$state] as const,
146
- fn: ([key, messages], response) => ({ key, messages: messages[key] || [], response }),
147
- }).watch(({ key, messages, response }) => {
148
- this.messages.setField({
149
- key,
150
- data: [
151
- ...messages,
152
- {
153
- id: generateRandomId(),
154
- message: response.message,
155
- isOwnMessage: false,
156
- threadId: response.threadId,
157
- options: response.options,
158
- translatedMessage:
159
- 'translatedMessage' in response ? response.translatedMessage : undefined,
160
- },
161
- ],
162
- })
163
-
164
- this.threadIds.setField({ key, data: response.threadId })
165
- })
166
-
167
- sample({
168
- clock: this.sendHelpRequestFx.fail,
169
- source: [this.$currentKey, this.messages.$state] as const,
170
- fn: ([key, messages]) => ({ key, data: [...messages[key], this.defaultMessages.error] }),
150
+ clock: effect.fail,
151
+ source: this.$currentChatData,
152
+ fn: ({ key, messages }) => ({ key, data: [...messages, this.defaultMessages.error] }),
171
153
  filter: (_, { error }) => error.message !== 'Request aborted manually',
172
154
  target: this.messages.setField,
173
155
  })
174
156
 
157
+ return effect
158
+ }
159
+
160
+ private initChatReplyWatcher() {
175
161
  sample({
176
162
  clock: this.removeLastMessage,
177
163
  source: [this.$lastMessageKey, this.messages.$state] as const,
178
164
  fn: ([lastMessageKey, messages]) => {
179
- const mockData = { key: '', data: [] }
180
- if (!lastMessageKey) return mockData
181
- const updatedMessages = messages[lastMessageKey]
182
- if (!updatedMessages?.length) return mockData
165
+ if (!lastMessageKey) return { key: '', data: [] }
166
+ const updatedMessages = [...messages[lastMessageKey]]
183
167
  updatedMessages.pop()
184
168
  return { key: lastMessageKey, data: updatedMessages }
185
169
  },
@@ -189,27 +173,20 @@ export class ChatbotModel {
189
173
  }
190
174
 
191
175
  public readonly startConversation = attach({
192
- source: {
193
- key: this.$currentKey,
194
- messages: this.messages.$state,
195
- },
196
- mapParams: (_: void, source) => ({
197
- key: source.key,
198
- messages: source.messages[source.key] ?? [],
199
- }),
176
+ source: this.$currentChatData,
177
+ mapParams: (_: void, source) => source,
200
178
  effect: createEffect(({ key, messages }: StartConversationFxData) => {
201
179
  if (messages.length) return this.reinitConversation({ key })
202
-
203
180
  this.messages.setField({ key, data: [this.defaultMessages.start] })
204
181
  this.availableChats.setField({ key, data: true })
205
182
  }),
206
183
  })
207
184
 
208
- public setHintMessage({ entityId, fieldId, ...message }: SetHintMessageProps) {
185
+ public setHintMessage({ key, ...message }: SetHintMessageProps) {
209
186
  const options = this.$alternatives.getState()?.options.hints ?? message.options
210
187
  this.messages.setField({
211
- key: `${entityId}-${fieldId}`,
212
- fn: messages => {
188
+ key,
189
+ fn: (messages) => {
213
190
  if (!messages || messages.length > 1) return
214
191
  return [{ ...message, options }]
215
192
  },
@@ -219,13 +196,19 @@ export class ChatbotModel {
219
196
  public readonly reinitConversation = createEffect(({ key }: ReinitConversationProps) => {
220
197
  this.messages.setField({
221
198
  key,
222
- fn: messages => {
223
- if (!messages?.length) return
224
- const lastMessage = messages[messages.length - 1]
199
+ fn: (messages) => {
200
+ if (!messages?.length || messages.length === 1) return
225
201
  const copy = [...messages]
226
- copy.splice(messages.length - 1, 1, {
202
+ while (copy.at(-1)?.endMessage) {
203
+ copy.pop()
204
+ }
205
+
206
+ const lastMessage = copy.at(-1)
207
+ if (!lastMessage) return
208
+
209
+ copy.splice(copy.length - 1, 1, {
227
210
  ...lastMessage,
228
- options: this.defaultMessages.start.options,
211
+ options: [this.defaultMessages.anotherHintOption],
229
212
  })
230
213
  return copy
231
214
  },
@@ -1,46 +1,37 @@
1
- import { createEffect, Effect } from 'effector'
2
-
1
+ import { createEffect } from 'effector'
3
2
  import { createControllerEffect } from '../../../lib/effector'
4
- import { ControlledEffect } from '../../../lib/effector/createControllerEffect'
5
3
  import { ChatbotModelProps } from '../types/model.types'
6
- import {
7
- GetAlternativesResponse,
8
- PostMessagePayload,
9
- PostMessageResponse,
10
- GoogleTranslatePayload,
11
- GoogleTranslateResponse,
12
- GoogleText2SpeechPayload,
13
- GoogleText2SpeechResponse,
14
- GetAlternativesPayload,
15
- } from '../types/api.types'
4
+ import { GoogleTranslatePayload, GoogleTranslateResponse } from '../types/api.types'
16
5
  import { replaceKatexSyntax } from '../helpers'
17
6
 
18
7
  export class ChatbotAPI {
19
- postMessageFx: ControlledEffect<PostMessagePayload, PostMessageResponse>
20
- getAlternativesFx: Effect<GetAlternativesPayload, GetAlternativesResponse>
21
- translateTextFx: Effect<GoogleTranslatePayload, GoogleTranslateResponse>
22
- textToSpeechTextFx: Effect<GoogleText2SpeechPayload, GoogleText2SpeechResponse>
8
+ public readonly postMessageFx
9
+ public readonly getAlternativesFx
10
+ public readonly translateTextFx
11
+ public readonly textToSpeechTextFx
23
12
 
24
13
  constructor(api: ChatbotModelProps['api']) {
25
14
  this.postMessageFx = createControllerEffect(api.postMessage)
26
15
  this.getAlternativesFx = createEffect(api.getAlternatives)
27
- this.translateTextFx = createEffect(async (payload: GoogleTranslatePayload) => {
28
- const response = await api.postTranslateText({
29
- ...payload,
30
- text: replaceKatexSyntax(payload.text),
31
- })
16
+ this.translateTextFx = createEffect(
17
+ async (payload: GoogleTranslatePayload): Promise<GoogleTranslateResponse> => {
18
+ const response = await api.postTranslateText({
19
+ ...payload,
20
+ text: replaceKatexSyntax(payload.text),
21
+ })
32
22
 
33
- return {
34
- ...response,
35
- data: {
36
- ...response.data,
37
- translations: response.data.translations.map(translation => ({
38
- ...translation,
39
- translatedText: replaceKatexSyntax([translation.translatedText], true)[0],
40
- })),
41
- },
42
- }
43
- })
23
+ return {
24
+ ...response,
25
+ data: {
26
+ ...response.data,
27
+ translations: response.data.translations.map((translation) => ({
28
+ ...translation,
29
+ translatedText: replaceKatexSyntax([translation.translatedText], true)[0],
30
+ })),
31
+ },
32
+ }
33
+ },
34
+ )
44
35
  this.textToSpeechTextFx = createEffect(api.postTextToSpeech)
45
36
  }
46
37
  }
@@ -0,0 +1,48 @@
1
+ import { generateRandomId } from '../../../lib/helpers/helpers'
2
+ import { ConversationMessage, CreateMessageResponse } from '../types/model.types'
3
+
4
+ type OwnMessageProps = {
5
+ message?: string
6
+ translatedMessage?: string
7
+ threadId?: string | null
8
+ }
9
+
10
+ export class messagesHelper {
11
+ public static createAnswer(data: CreateMessageResponse): ConversationMessage {
12
+ return {
13
+ id: generateRandomId(),
14
+ isOwnMessage: false,
15
+ message: data.message,
16
+ threadId: data.threadId,
17
+ options: data.options,
18
+ translatedMessage: data.translatedMessage,
19
+ }
20
+ }
21
+
22
+ public static createLast(data: CreateMessageResponse) {
23
+ return {
24
+ id: generateRandomId(),
25
+ message: data.message,
26
+ translatedMessage: data.translatedMessage,
27
+ isOwnMessage: false,
28
+ options: [],
29
+ threadId: '',
30
+ endMessage: true,
31
+ }
32
+ }
33
+
34
+ public static createOwn({
35
+ message = '',
36
+ translatedMessage,
37
+ threadId,
38
+ }: OwnMessageProps): ConversationMessage {
39
+ return {
40
+ id: generateRandomId(),
41
+ message,
42
+ translatedMessage,
43
+ threadId: threadId || '',
44
+ isOwnMessage: true,
45
+ options: [],
46
+ }
47
+ }
48
+ }
@@ -1,8 +1,7 @@
1
- import { restore, createEvent, Store, sample } from 'effector'
1
+ import { restore, createEvent, Store, sample, createEffect } from 'effector'
2
2
  import { AUDIO_CONFIG, DEFAULT_VOICE } from '../constants'
3
3
  import { AudioProvider, AudioStatus, PlayTextToSpeechProps } from '../types/t2s.types'
4
4
  import { ChatbotAPI } from './api'
5
- import { createEffect } from 'effector/effector.umd'
6
5
 
7
6
  type ChatTextToSpeechModelProps = {
8
7
  $isOpen: Store<boolean>
@@ -0,0 +1,58 @@
1
+ import {
2
+ AddTranslationToAlternativesProps,
3
+ GetOptionsProps,
4
+ GetOptionsResult,
5
+ } from '../types/translation.types'
6
+ import { ChatAnswer, GetAlternativesResponse } from '../types/api.types'
7
+
8
+ export function getOptionsForTranslation({
9
+ lastMessage,
10
+ alternatives,
11
+ }: GetOptionsProps): GetOptionsResult {
12
+ if (!lastMessage) return { lastMessage: null, alternatives: null }
13
+ if (!lastMessage.options.length) {
14
+ if (!alternatives) return { lastMessage: null, alternatives: null }
15
+ const hintAlternatives = alternatives.options.hints ?? []
16
+ const defaultAlternatives = alternatives.options.default ?? []
17
+ return {
18
+ lastMessage: null,
19
+ alternatives: {
20
+ hints: hintAlternatives.map(({ text }) => text),
21
+ default: defaultAlternatives.map(({ text }) => text),
22
+ },
23
+ }
24
+ }
25
+
26
+ return {
27
+ lastMessage: lastMessage.options.map(({ text }) => text),
28
+ alternatives: null,
29
+ }
30
+ }
31
+
32
+ export function addTranslationsToAlternative({
33
+ alternatives,
34
+ translatedHints,
35
+ translatedDefaults,
36
+ }: AddTranslationToAlternativesProps): GetAlternativesResponse {
37
+ return {
38
+ ...alternatives,
39
+ options: {
40
+ ...alternatives.options,
41
+ hints: translatedHints.map((translatedText, index) => ({
42
+ ...alternatives.options.hints[index],
43
+ translatedText,
44
+ })),
45
+ default: translatedDefaults.map((translatedText, index) => ({
46
+ ...alternatives.options.default[index],
47
+ translatedText,
48
+ })),
49
+ },
50
+ }
51
+ }
52
+
53
+ export function addTranslationToOptions(options: ChatAnswer[], translations: string[]) {
54
+ return options.map((option, index) => ({
55
+ ...option,
56
+ translatedText: translations[index],
57
+ }))
58
+ }