@chat21/chat21-web-widget 5.1.34-rc1 → 5.1.34

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 (193) hide show
  1. package/.github/workflows/docker-community-push-latest.yml +13 -23
  2. package/.github/workflows/docker-image-tag-community-tag-push.yml +12 -22
  3. package/CHANGELOG.md +8 -129
  4. package/Dockerfile +5 -4
  5. package/angular.json +3 -21
  6. package/docs/changelog/this-branch.md +0 -36
  7. package/env.sample +2 -3
  8. package/nginx.conf +2 -22
  9. package/package.json +3 -10
  10. package/src/app/app.component.html +2 -2
  11. package/src/app/app.component.scss +14 -25
  12. package/src/app/app.component.spec.ts +6 -21
  13. package/src/app/app.component.ts +9 -10
  14. package/src/app/app.module.ts +0 -13
  15. package/src/app/component/conversation-detail/conversation/conversation.component.html +11 -25
  16. package/src/app/component/conversation-detail/conversation/conversation.component.scss +2 -40
  17. package/src/app/component/conversation-detail/conversation/conversation.component.spec.ts +75 -644
  18. package/src/app/component/conversation-detail/conversation/conversation.component.ts +14 -100
  19. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.html +13 -25
  20. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.spec.ts +5 -123
  21. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.ts +0 -1
  22. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.html +10 -23
  23. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.scss +1 -19
  24. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.spec.ts +149 -242
  25. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.ts +5 -8
  26. package/src/app/component/conversation-detail/conversation-emojii/conversation-emojii.component.spec.ts +3 -53
  27. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +96 -200
  28. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +6 -211
  29. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.spec.ts +78 -452
  30. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +76 -291
  31. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.html +53 -113
  32. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.scss +4 -12
  33. package/src/app/component/conversation-detail/conversation-header/conversation-header.component.spec.ts +29 -274
  34. package/src/app/component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component.html +9 -23
  35. package/src/app/component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component.spec.ts +8 -80
  36. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.html +23 -29
  37. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.spec.ts +16 -185
  38. package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.ts +14 -34
  39. package/src/app/component/error-alert/error-alert.component.spec.ts +5 -65
  40. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.html +7 -16
  41. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.scss +0 -21
  42. package/src/app/component/eyeeye-catcher-card/eyeeye-catcher-card.component.spec.ts +7 -89
  43. package/src/app/component/form/form-builder/form-builder.component.html +1 -1
  44. package/src/app/component/form/form-builder/form-builder.component.spec.ts +21 -163
  45. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.html +4 -8
  46. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.scss +5 -10
  47. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.spec.ts +16 -90
  48. package/src/app/component/form/inputs/form-checkbox/form-checkbox.component.ts +0 -26
  49. package/src/app/component/form/inputs/form-label/form-label.component.spec.ts +11 -45
  50. package/src/app/component/form/inputs/form-radio-button/form-radio-button.component.spec.ts +6 -24
  51. package/src/app/component/form/inputs/form-select/form-select.component.spec.ts +5 -14
  52. package/src/app/component/form/inputs/form-text/form-text.component.html +12 -14
  53. package/src/app/component/form/inputs/form-text/form-text.component.scss +1 -11
  54. package/src/app/component/form/inputs/form-text/form-text.component.spec.ts +17 -113
  55. package/src/app/component/form/inputs/form-text/form-text.component.ts +3 -35
  56. package/src/app/component/form/inputs/form-textarea/form-textarea.component.html +11 -13
  57. package/src/app/component/form/inputs/form-textarea/form-textarea.component.scss +5 -6
  58. package/src/app/component/form/inputs/form-textarea/form-textarea.component.spec.ts +13 -149
  59. package/src/app/component/form/inputs/form-textarea/form-textarea.component.ts +0 -26
  60. package/src/app/component/form/prechat-form/prechat-form.component.html +11 -14
  61. package/src/app/component/form/prechat-form/prechat-form.component.spec.ts +10 -102
  62. package/src/app/component/form/prechat-form/prechat-form.component.ts +1 -8
  63. package/src/app/component/home/home.component.html +31 -38
  64. package/src/app/component/home/home.component.scss +2 -4
  65. package/src/app/component/home/home.component.spec.ts +11 -226
  66. package/src/app/component/home-conversations/home-conversations.component.html +26 -30
  67. package/src/app/component/home-conversations/home-conversations.component.scss +0 -3
  68. package/src/app/component/home-conversations/home-conversations.component.spec.ts +36 -212
  69. package/src/app/component/last-message/last-message.component.html +9 -15
  70. package/src/app/component/last-message/last-message.component.scss +2 -16
  71. package/src/app/component/last-message/last-message.component.spec.ts +23 -204
  72. package/src/app/component/last-message/last-message.component.ts +1 -4
  73. package/src/app/component/launcher-button/launcher-button.component.html +13 -8
  74. package/src/app/component/launcher-button/launcher-button.component.spec.ts +8 -104
  75. package/src/app/component/list-all-conversations/list-all-conversations.component.html +17 -12
  76. package/src/app/component/list-all-conversations/list-all-conversations.component.scss +0 -2
  77. package/src/app/component/list-conversations/list-conversations.component.html +22 -22
  78. package/src/app/component/menu-options/menu-options.component.html +20 -30
  79. package/src/app/component/menu-options/menu-options.component.spec.ts +9 -125
  80. package/src/app/component/message/audio/audio.component.html +15 -13
  81. package/src/app/component/message/audio/audio.component.spec.ts +5 -140
  82. package/src/app/component/message/audio/audio.component.ts +5 -1
  83. package/src/app/component/message/avatar/avatar.component.html +2 -2
  84. package/src/app/component/message/avatar/avatar.component.spec.ts +7 -99
  85. package/src/app/component/message/bubble-message/bubble-message.component.html +51 -38
  86. package/src/app/component/message/bubble-message/bubble-message.component.scss +1 -54
  87. package/src/app/component/message/bubble-message/bubble-message.component.spec.ts +57 -154
  88. package/src/app/component/message/bubble-message/bubble-message.component.ts +11 -89
  89. package/src/app/component/message/buttons/action-button/action-button.component.html +4 -3
  90. package/src/app/component/message/buttons/action-button/action-button.component.spec.ts +5 -49
  91. package/src/app/component/message/buttons/link-button/link-button.component.scss +8 -5
  92. package/src/app/component/message/buttons/link-button/link-button.component.spec.ts +5 -50
  93. package/src/app/component/message/buttons/text-button/text-button.component.spec.ts +5 -44
  94. package/src/app/component/message/carousel/carousel.component.html +16 -29
  95. package/src/app/component/message/carousel/carousel.component.scss +8 -20
  96. package/src/app/component/message/carousel/carousel.component.spec.ts +3 -80
  97. package/src/app/component/message/carousel/carousel.component.ts +0 -16
  98. package/src/app/component/message/frame/frame.component.html +4 -9
  99. package/src/app/component/message/frame/frame.component.spec.ts +15 -34
  100. package/src/app/component/message/frame/frame.component.ts +2 -7
  101. package/src/app/component/message/html/html.component.html +1 -1
  102. package/src/app/component/message/html/html.component.scss +1 -1
  103. package/src/app/component/message/html/html.component.spec.ts +7 -24
  104. package/src/app/component/message/image/image.component.html +10 -12
  105. package/src/app/component/message/image/image.component.scss +0 -16
  106. package/src/app/component/message/image/image.component.spec.ts +15 -101
  107. package/src/app/component/message/image/image.component.ts +51 -90
  108. package/src/app/component/message/info-message/info-message.component.spec.ts +14 -26
  109. package/src/app/component/message/like-unlike/like-unlike.component.html +9 -7
  110. package/src/app/component/message/like-unlike/like-unlike.component.spec.ts +3 -31
  111. package/src/app/component/message/return-receipt/return-receipt.component.spec.ts +17 -38
  112. package/src/app/component/message/text/text.component.html +3 -3
  113. package/src/app/component/message/text/text.component.scss +86 -80
  114. package/src/app/component/message/text/text.component.spec.ts +13 -106
  115. package/src/app/component/message-attachment/message-attachment.component.spec.ts +13 -134
  116. package/src/app/component/selection-department/selection-department.component.html +23 -21
  117. package/src/app/component/selection-department/selection-department.component.spec.ts +14 -159
  118. package/src/app/component/selection-department/selection-department.component.ts +1 -8
  119. package/src/app/component/send-button/send-button.component.html +13 -5
  120. package/src/app/component/send-button/send-button.component.spec.ts +2 -2
  121. package/src/app/component/star-rating-widget/star-rating-widget.component.html +81 -51
  122. package/src/app/directives/tooltip.directive.spec.ts +4 -8
  123. package/src/app/modals/confirm-close/confirm-close.component.html +8 -20
  124. package/src/app/modals/confirm-close/confirm-close.component.scss +0 -3
  125. package/src/app/modals/confirm-close/confirm-close.component.spec.ts +4 -13
  126. package/src/app/modals/confirm-close/confirm-close.component.ts +1 -8
  127. package/src/app/pipe/html-entites-encode.pipe.spec.ts +2 -35
  128. package/src/app/pipe/marked.pipe.spec.ts +2 -38
  129. package/src/app/pipe/marked.pipe.ts +41 -51
  130. package/src/app/providers/app-config.service.ts +2 -4
  131. package/src/app/providers/brand.service.spec.ts +2 -23
  132. package/src/app/providers/brand.service.ts +1 -1
  133. package/src/app/providers/global-settings.service.spec.ts +14 -1009
  134. package/src/app/providers/global-settings.service.ts +2 -82
  135. package/src/app/providers/translator.service.ts +6 -26
  136. package/src/app/sass/_variables.scss +0 -3
  137. package/src/app/sass/animations.scss +1 -19
  138. package/src/app/utils/globals.ts +1 -21
  139. package/src/app/utils/utils-resources.ts +1 -1
  140. package/src/assets/i18n/en.json +99 -106
  141. package/src/assets/i18n/es.json +100 -107
  142. package/src/assets/i18n/fr.json +100 -107
  143. package/src/assets/i18n/it.json +98 -107
  144. package/src/assets/twp/index-dev.html +0 -18
  145. package/src/chat21-core/models/message.ts +1 -2
  146. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +2 -3
  147. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +0 -12
  148. package/src/chat21-core/providers/scripts/script.service.spec.ts +2 -12
  149. package/src/chat21-core/providers/tiledesk/tiledesk-requests.service.ts +1 -1
  150. package/src/chat21-core/utils/utils-message.ts +0 -7
  151. package/src/chat21-core/utils/utils.ts +2 -5
  152. package/src/widget-config-template.json +1 -4
  153. package/src/widget-config.json +1 -4
  154. package/tsconfig.json +0 -5
  155. package/.angular-mcp-cache/package.json +0 -1
  156. package/.cursor/angular18-accessibility-auditor-skill.md +0 -442
  157. package/.cursor/mcp.json +0 -15
  158. package/.github/workflows/build.yml +0 -22
  159. package/.github/workflows/playwright.yml +0 -27
  160. package/mocks/voice-websocket-mock/server.cjs +0 -245
  161. package/playwright.config.ts +0 -41
  162. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.html +0 -46
  163. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.scss +0 -83
  164. package/src/app/component/conversation-detail/stream-audio-spectrum/stream-audio-spectrum.component.ts +0 -192
  165. package/src/app/component/form/prechat-form-test-mock.ts +0 -35
  166. package/src/app/component/message/audio-sync/audio-sync.component.html +0 -18
  167. package/src/app/component/message/audio-sync/audio-sync.component.scss +0 -65
  168. package/src/app/component/message/audio-sync/audio-sync.component.spec.ts +0 -103
  169. package/src/app/component/message/audio-sync/audio-sync.component.ts +0 -643
  170. package/src/app/providers/tts-audio-playback-coordinator.service.spec.ts +0 -117
  171. package/src/app/providers/tts-audio-playback-coordinator.service.ts +0 -109
  172. package/src/app/providers/voice/STT&TTS/openai-voice.config.ts +0 -12
  173. package/src/app/providers/voice/STT&TTS/openai-voice.provider.ts +0 -171
  174. package/src/app/providers/voice/STT&TTS/speech-provider.abstract.ts +0 -39
  175. package/src/app/providers/voice/audio.types.ts +0 -40
  176. package/src/app/providers/voice/vad.service.spec.ts +0 -28
  177. package/src/app/providers/voice/vad.service.ts +0 -70
  178. package/src/app/providers/voice/voice-streaming.service.spec.ts +0 -23
  179. package/src/app/providers/voice/voice-streaming.service.ts +0 -702
  180. package/src/app/providers/voice/voice-streaming.types.ts +0 -112
  181. package/src/app/providers/voice/voice.service.spec.ts +0 -227
  182. package/src/app/providers/voice/voice.service.ts +0 -973
  183. package/src/app/shims/onnxruntime-web-wasm.ts +0 -4
  184. package/src/assets/onnx/ort-wasm-simd-threaded.mjs +0 -59
  185. package/src/assets/onnx/ort-wasm-simd-threaded.wasm +0 -0
  186. package/src/assets/sounds/keyboard.mp3 +0 -0
  187. package/src/assets/twp/tiledesk_widget_files/widget-css-override-example.css +0 -14
  188. package/src/assets/vad/silero_vad_legacy.onnx +0 -0
  189. package/src/assets/vad/vad.worklet.bundle.min.js +0 -1
  190. package/src/chat21-core/providers/chat-manager.spec.ts +0 -72
  191. package/tests/widget-form-rich.spec.ts +0 -67
  192. package/tests/widget-index-dev-settings.spec.ts +0 -52
  193. package/tests/widget-twp-iframe.spec.ts +0 -39
@@ -1,4 +1,4 @@
1
- import { Component, ComponentFactoryResolver, ElementRef, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChanges, ViewChild, ViewContainerRef } from '@angular/core';
1
+ import { Component, ComponentFactoryResolver, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChanges, ViewChild, ViewContainerRef } from '@angular/core';
2
2
  import { error } from 'console';
3
3
  import { FILE_SIZE_LIMIT } from 'src/app/utils/constants';
4
4
  import { Globals } from 'src/app/utils/globals';
@@ -15,18 +15,13 @@ import { TYPE_MSG_FILE, TYPE_MSG_IMAGE, TYPE_MSG_TEXT } from 'src/chat21-core/ut
15
15
  import { convertColorToRGBA, isAllowedUrlInText, isEmoji } from 'src/chat21-core/utils/utils';
16
16
  import { findAndRemoveEmoji, isImage } from 'src/chat21-core/utils/utils-message';
17
17
  import { ProjectModel } from 'src/models/project';
18
- import { Subscription } from 'rxjs';
19
- import { VoiceService } from 'src/app/providers/voice/voice.service';
20
- import { VoiceStreamingSessionConfig } from 'src/app/providers/voice/voice-streaming.types';
21
- import { TtsAudioPlaybackCoordinator } from 'src/app/providers/tts-audio-playback-coordinator.service';
22
- import { TiledeskAuthService } from 'src/chat21-core/providers/tiledesk/tiledesk-auth.service';
23
18
 
24
19
  @Component({
25
20
  selector: 'chat-conversation-footer',
26
21
  templateUrl: './conversation-footer.component.html',
27
22
  styleUrls: ['./conversation-footer.component.scss']
28
23
  })
29
- export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy {
24
+ export class ConversationFooterComponent implements OnInit, OnChanges {
30
25
 
31
26
  @Input() conversationWith: string;
32
27
  @Input() attributes: string;
@@ -37,9 +32,8 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
37
32
  @Input() userFullname: string;
38
33
  @Input() userEmail: string;
39
34
  @Input() showAttachmentFooterButton: boolean;
40
- @Input() showEmojiFooterButton: boolean;
41
- @Input() showAudioRecorderFooterButton: boolean;
42
- @Input() showAudioStreamFooterButton: boolean;
35
+ @Input() showEmojiFooterButton: boolean
36
+ @Input() showAudioRecorderFooterButton: boolean
43
37
  // @Input() showContinueConversationButton: boolean;
44
38
  @Input() isConversationArchived: boolean;
45
39
  @Input() hideTextAreaContent: boolean;
@@ -48,7 +42,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
48
42
  @Input() isEmojiiPickerShow: boolean;
49
43
  @Input() footerMessagePlaceholder: string;
50
44
  @Input() fileUploadAccept: string;
51
- @Input() closeChatInConversation: boolean;
52
45
  @Input() dropEvent: Event;
53
46
  @Input() poweredBy: string;
54
47
  @Input() stylesMap: Map<string, string>
@@ -59,9 +52,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
59
52
  @Output() onChangeTextArea = new EventEmitter<any>();
60
53
  @Output() onAttachmentFileButtonClicked = new EventEmitter<any>();
61
54
  @Output() onNewConversationButtonClicked = new EventEmitter();
62
- @Output() onStreamAudioActiveChange = new EventEmitter<boolean>();
63
- @Output() onStreamAudioConnectingChange = new EventEmitter<boolean>();
64
- @Output() onCloseChatButtonClicked = new EventEmitter();
65
55
 
66
56
  @ViewChild('chat21_file') public chat21_file: ElementRef;
67
57
  // @ViewChild('emojii_container', {read: ViewContainerRef}) selector;
@@ -95,67 +85,24 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
95
85
 
96
86
  showAlertEmoji: boolean = false
97
87
 
98
- /** Stream audio UI: icona equalizer → X; alert con onde animate sopra il footer */
99
- isStreamAudioActive = false;
100
- /** True while the WebSocket session is being established (between click and session_started). */
101
- isStreamAudioConnecting = false;
102
- /** True while the bot's TTS audio is playing — mic segments are suppressed, spectrum turns grey. */
103
- isBotSpeaking = false;
104
- /** Sottoscrizione ai segmenti audio (VAD → WebM) dal {@link VoiceService}. */
105
- private voiceAudioSubscription?: Subscription;
106
- /** Sottoscrizione a `transcript` finale dalla WSS. */
107
- private voiceTranscriptSubscription?: Subscription;
108
- /** Sottoscrizione al volume audio (real-time) dal {@link VoiceService}. */
109
- private voiceVolumeSubscription?: Subscription;
110
- /** Sottoscrizione allo stato TTS (bot sta parlando). */
111
- private botSpeakingSub?: Subscription;
112
- /** Passato a {@link StreamAudioSpectrumComponent} per disegnare la linea spettro. */
113
- currentVolume = 0;
114
- /** Last user utterance transcribed — persists during bot processing to show in voice panel. */
115
- lastVoiceTranscript = '';
116
-
117
- get voiceStatusLabel(): string {
118
- if (this.isStreamAudioConnecting && !this.isStreamAudioActive) {
119
- return this.translationMap?.get('VOICE_CONNECTING') || 'Connecting...';
120
- }
121
- if (this.isStreamAudioActive && this.isBotSpeaking) {
122
- return this.translationMap?.get('VOICE_PROCESSING') || 'Processing...';
123
- }
124
- return this.translationMap?.get('VOICE_LISTENING') || 'Listening...';
125
- }
126
-
127
- get maxAttachmentLabel(): string {
128
- const template = this.translationMap?.get('MAX_ATTACHMENT')
129
- || `Max allowed size {{FILE_SIZE_LIMIT}}Mb`;
130
- return template.replace(/\{\{FILE_SIZE_LIMIT\}\}/g, String(this.file_size_limit));
131
- }
132
-
133
88
  file_size_limit = FILE_SIZE_LIMIT;
134
89
  attachmentTooltip: string = '';
135
- isErrorNetwork: boolean = false;
136
90
 
137
91
 
138
92
  convertColorToRGBA = convertColorToRGBA;
139
93
  private logger: LoggerService = LoggerInstance.getInstance()
140
- constructor(
141
- private chatManager: ChatManager,
142
- private typingService: TypingService,
143
- private uploadService: UploadService,
144
- private voiceService: VoiceService,
145
- private ttsPlayback: TtsAudioPlaybackCoordinator,
146
- private tiledeskAuthService: TiledeskAuthService,
147
- public g: Globals,
148
- ) {}
94
+ constructor(private chatManager: ChatManager,
95
+ private typingService: TypingService,
96
+ private uploadService: UploadService) { }
149
97
 
150
98
  ngOnInit() {
151
99
  // this.updateAttachmentTooltip();
152
100
  }
153
101
 
102
+
154
103
  ngOnChanges(changes: SimpleChanges){
155
104
  if(changes['conversationWith'] && changes['conversationWith'].currentValue !== undefined){
156
105
  this.conversationHandlerService = this.chatManager.getConversationHandlerByConversationId(this.conversationWith);
157
- this.isStreamAudioActive = false;
158
- void this.stopVoice();
159
106
  }
160
107
  if(changes['hideTextReply'] && changes['hideTextReply'].currentValue !== undefined){
161
108
  this.restoreTextArea();
@@ -195,159 +142,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
195
142
  // }, 500);
196
143
  // }
197
144
 
198
- /**
199
- * Stream voce: con `voiceIngress` solo WSS (no VAD) — transcript + TTS dal server.
200
- * Senza ingresso WSS: VAD + upload per segmento.
201
- */
202
- async initVoice() {
203
- this.voiceAudioSubscription?.unsubscribe();
204
- this.voiceVolumeSubscription?.unsubscribe();
205
- this.botSpeakingSub?.unsubscribe();
206
- this.voiceTranscriptSubscription?.unsubscribe();
207
-
208
- const voiceIngress = this.buildVoiceIngressStreamConfig();
209
- this.voiceAudioSubscription = undefined;
210
- this.voiceTranscriptSubscription = this.voiceService.voiceTranscript$.subscribe(({ text }) => {
211
- // Guard: stop accepting transcript text once the proxy is processing (thinking/speaking)
212
- if (text && !this.isBotSpeaking) {
213
- this.textInputTextArea = text;
214
- this.lastVoiceTranscript = text;
215
- // The proxy publishes the user utterance to Chat21 via AMQP on utterance-end;
216
- // no sendMessage call is needed here — doing so would produce duplicate messages.
217
- }
218
- });
219
-
220
- this.voiceVolumeSubscription = this.voiceService.volume$.subscribe((volume) => {
221
- this.currentVolume = volume;
222
- });
223
- this.botSpeakingSub = this.voiceService.isAcquisitionBlocked$.subscribe((blocked) => {
224
- this.isBotSpeaking = blocked;
225
- if (blocked) {
226
- // Proxy has started thinking/speaking — clear the textarea preview
227
- this.textInputTextArea = '';
228
- }
229
- });
230
- await this.voiceService.startSession(voiceIngress ? { voiceIngressStream: voiceIngress } : {});
231
- }
232
-
233
- private buildVoiceIngressStreamConfig(): VoiceStreamingSessionConfig | null {
234
- const token = this.tiledeskAuthService.getTiledeskToken() ?? '';
235
- const sender = this.tiledeskAuthService.getCurrentUser()?.uid ?? '';
236
- const recipient = this.conversationWith ?? '';
237
- if (!token || !sender || !recipient) {
238
- this.logger.warn('[CONV-FOOTER] buildVoiceIngressStreamConfig: missing required fields', {
239
- hasToken: !!token,
240
- hasSender: !!sender,
241
- hasRecipient: !!recipient,
242
- });
243
- return null;
244
- }
245
- const { recipientFullname, attributes, channelType } = this.buildSendMessageContext();
246
- this.logger.log('[CONV-FOOTER] buildVoiceIngressStreamConfig', { sender, recipient, channelType });
247
- return {
248
- token,
249
- sender,
250
- recipient,
251
- // Use Deepgram multilingual code-switching so the model detects the spoken
252
- // language from the audio stream regardless of browser locale.
253
- // Source: https://developers.deepgram.com/docs/multilingual-code-switching
254
- lang: 'multi',
255
- text: '',
256
- type: 'text',
257
- recipient_fullname: recipientFullname ?? '',
258
- sender_fullname: recipientFullname ?? '',
259
- attributes: attributes ?? {},
260
- metadata: '',
261
- channel_type: channelType ?? '',
262
- };
263
- }
264
-
265
- /**
266
- * Merge `attributes` di componente con `additional_attributes` e risolve `recipientFullname` come in sendMessage.
267
- */
268
- private buildSendMessageContext(additional_attributes?: any) {
269
- let recipientFullname = this.translationMap.get('GUEST_LABEL');
270
- const g_attributes = this.attributes;
271
- const attributes = <any>{};
272
- if (g_attributes) {
273
- for (const [key, value] of Object.entries(g_attributes)) {
274
- attributes[key] = value;
275
- }
276
- }
277
- if (additional_attributes) {
278
- for (const [key, value] of Object.entries(additional_attributes)) {
279
- attributes[key] = value;
280
- }
281
- }
282
- const senderId = this.senderId;
283
- const projectid = this.project.id;
284
- const channelType = this.channelType;
285
- const userFullname = this.userFullname;
286
- const userEmail = this.userEmail;
287
- const conversationWith = this.conversationWith;
288
-
289
- if (userFullname) {
290
- recipientFullname = userFullname;
291
- } else if (userEmail) {
292
- recipientFullname = userEmail;
293
- } else if (attributes && attributes['userFullname']) {
294
- recipientFullname = attributes['userFullname'];
295
- } else {
296
- recipientFullname = this.translationMap.get('GUEST_LABEL');
297
- }
298
-
299
- return {
300
- recipientFullname,
301
- attributes,
302
- senderId,
303
- projectid,
304
- channelType,
305
- conversationWith,
306
- };
307
- }
308
- async stopVoice(options?: { discardInProgressSegment?: boolean }) {
309
- // Stop all active TTS audio immediately and reveal all text.
310
- this.ttsPlayback.stopAll();
311
-
312
- this.voiceAudioSubscription?.unsubscribe();
313
- this.voiceAudioSubscription = undefined;
314
-
315
- this.voiceTranscriptSubscription?.unsubscribe();
316
- this.voiceTranscriptSubscription = undefined;
317
-
318
- this.voiceVolumeSubscription?.unsubscribe();
319
- this.voiceVolumeSubscription = undefined;
320
-
321
- this.botSpeakingSub?.unsubscribe();
322
- this.botSpeakingSub = undefined;
323
- this.isBotSpeaking = false;
324
-
325
- await this.voiceService.stopSession(options);
326
- this.currentVolume = 0;
327
- this.textInputTextArea = '';
328
- this.lastVoiceTranscript = '';
329
- }
330
-
331
- /**
332
- * Messaggio in arrivo da un altro mittente mentre lo stream è attivo: con VAD legacy scarta il segmento in corso.
333
- * Con sola sessione WSS non ha effetto sul mic (nessun recorder a segmenti locale).
334
- */
335
- interruptStreamDueToPeerMessage(): void {
336
- if (!this.isStreamAudioActive) {
337
- return;
338
- }
339
- this.logger.log('[CONV-FOOTER] discard recording segment: incoming message from peer (stream stays on)');
340
- try {
341
- this.voiceService.discardCurrentRecordingSegment();
342
- } catch (e) {
343
- this.logger.error('[CONV-FOOTER] interruptStreamDueToPeerMessage', e);
344
- }
345
- }
346
-
347
- ngOnDestroy() {
348
- void this.stopVoice();
349
- }
350
-
351
145
  // ========= begin:: functions send image ======= //
352
146
  // START LOAD IMAGE //
353
147
  /** load the selected image locally and open the pop up preview */
@@ -585,14 +379,40 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
585
379
  // msg = replaceEndOfLine(msg);
586
380
  // msg = msg.trim();
587
381
 
588
- const {
589
- recipientFullname,
590
- attributes,
591
- senderId,
592
- projectid,
593
- channelType,
594
- conversationWith,
595
- } = this.buildSendMessageContext(additional_attributes);
382
+ let recipientFullname = this.translationMap.get('GUEST_LABEL');
383
+ // sponziello: adds ADDITIONAL ATTRIBUTES TO THE MESSAGE
384
+ const g_attributes = this.attributes;
385
+ // added <any> to resolve the Error occurred during the npm installation: Property 'userFullname' does not exist on type '{}'
386
+ const attributes = <any>{};
387
+ if (g_attributes) {
388
+ for (const [key, value] of Object.entries(g_attributes)) {
389
+ attributes[key] = value;
390
+ }
391
+ }
392
+ if (additional_attributes) {
393
+ for (const [key, value] of Object.entries(additional_attributes)) {
394
+ attributes[key] = value;
395
+ }
396
+ }
397
+ // fine-sponziello
398
+ // this.conversationHandlerService = this.chatManager.getConversationHandlerByConversationId(this.conversationWith)
399
+ const senderId = this.senderId;
400
+ const projectid = this.project.id;
401
+ const channelType = this.channelType;
402
+ const userFullname = this.userFullname;
403
+ const userEmail = this.userEmail;
404
+ const conversationWith = this.conversationWith;
405
+
406
+
407
+ if (userFullname) {
408
+ recipientFullname = userFullname;
409
+ } else if (userEmail) {
410
+ recipientFullname = userEmail;
411
+ } else if (attributes && attributes['userFullname']) {
412
+ recipientFullname = attributes['userFullname'];
413
+ } else {
414
+ recipientFullname = this.translationMap.get('GUEST_LABEL');
415
+ }
596
416
 
597
417
  this.onBeforeMessageSent.emit({
598
418
  senderFullname: recipientFullname,
@@ -701,7 +521,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
701
521
  }
702
522
  }
703
523
 
704
- prepareAndUpload(audioBlob: Blob, text: string = '') {
524
+ prepareAndUpload(audioBlob: Blob) {
705
525
 
706
526
  this.isFilePendingToUpload = true;
707
527
 
@@ -731,7 +551,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
731
551
  this.logger.log('[UPLOAD] metadata:', metadata);
732
552
 
733
553
  // stesso metodo che già usi
734
- this.uploadSingle(metadata, file, text);
554
+ this.uploadSingle(metadata, file, '');
735
555
  }
736
556
 
737
557
  // Funzione per convertire Blob in Base64 usando FileReader
@@ -838,39 +658,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
838
658
  }
839
659
  }
840
660
 
841
- async onStreamPressed(event: Event) {
842
- this.logger.log('[CONV-FOOTER] onStreamPressed:event', event);
843
- event.preventDefault();
844
- if (this.showAlertEmoji) {
845
- return;
846
- }
847
- // Treat a click during connecting as a cancel request (same as turning off).
848
- const turningOn = !this.isStreamAudioActive && !this.isStreamAudioConnecting;
849
- this.logger.log('[CONV-FOOTER] onStreamPressed', { turningOn });
850
- if (turningOn) {
851
- this.isStreamAudioConnecting = true;
852
- this.onStreamAudioConnectingChange.emit(true);
853
- try {
854
- this.currentVolume = 0;
855
- await this.initVoice();
856
- this.isStreamAudioActive = true;
857
- } catch (e) {
858
- this.logger.error('[CONV-FOOTER] onStreamPressed: initVoice failed', e);
859
- this.isStreamAudioActive = false;
860
- } finally {
861
- this.isStreamAudioConnecting = false;
862
- this.onStreamAudioConnectingChange.emit(false);
863
- }
864
- } else {
865
- await this.stopVoice();
866
- this.isStreamAudioActive = false;
867
- this.isStreamAudioConnecting = false;
868
- this.onStreamAudioConnectingChange.emit(false);
869
- }
870
- this.onStreamAudioActiveChange.emit(this.isStreamAudioActive);
871
- this.logger.log('[CONV-FOOTER] isStreamAudioActive', this.isStreamAudioActive);
872
- }
873
-
874
661
  async onEmojiiPickerClicked(){
875
662
  // if(this.loadPickerModule){
876
663
  // this.loadPickerModule = false;
@@ -922,10 +709,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
922
709
  this.onNewConversationButtonClicked.emit();
923
710
  }
924
711
 
925
- onCloseChat(event){
926
- this.onCloseChatButtonClicked.emit();
927
- }
928
-
929
712
  // onContinueConversation(){
930
713
  // this.hideTextAreaContent = false;
931
714
  // this.onBackButton.emit(false)
@@ -962,46 +745,48 @@ export class ConversationFooterComponent implements OnInit, OnChanges, OnDestroy
962
745
  }
963
746
 
964
747
  /**
965
- * Single keyboard handler for the message textarea.
966
- *
967
- * - Enter (no modifier) -> send message
968
- * - Shift / Alt / Ctrl / Meta + Enter -> insert a newline (default browser behavior)
969
- * - Tab -> prevented, to keep focus inside the chat
970
- *
971
- * Modifier check is intentionally on `keydown` because `keypress` is deprecated
972
- * and does not consistently fire for modifier combos across browsers.
748
+ * when I press a key I call this method which:
749
+ * check if 'enter' has been pressed
750
+ * if you clear text
751
+ * set field height as min by default
752
+ * takes out the focus and resets it after a few moments
753
+ * (this is a patch to keep the focus and eliminate the br of the send !!!)
754
+ * send message
973
755
  * @param event
974
756
  */
975
- onkeydown(event: KeyboardEvent) {
757
+ onkeypress(event) {
976
758
  const keyCode = event.which || event.keyCode;
977
-
978
- if (keyCode === 13) { // ENTER
979
- const hasModifier = event.metaKey || event.shiftKey || event.altKey || event.ctrlKey;
980
- if (hasModifier) {
981
- // Let the textarea insert a newline on its own (do not preventDefault).
982
- return;
983
- }
984
-
985
- // Plain Enter -> send the message
986
- event.preventDefault();
987
-
988
- if (this.showAlertEmoji) {
989
- return;
990
- }
991
-
992
- const target = document.getElementById('chat21-main-message-context') as HTMLInputElement;
993
- if (target) {
994
- this.textInputTextArea = target.value;
759
+ this.textInputTextArea = ((document.getElementById('chat21-main-message-context') as HTMLInputElement).value);
760
+ if (keyCode === 13) { // ENTER pressed
761
+ if(this.showAlertEmoji){
762
+ return;
995
763
  }
996
-
997
764
  if (this.textInputTextArea && this.textInputTextArea.trim() !== '') {
765
+ // that.logger.log('[CONV-FOOTER] sendMessage -> ', this.textInputTextArea);
766
+ // this.resizeInputField();
767
+ // this.messagingService.sendMessage(msg, TYPE_MSG_TEXT);
768
+ // this.setDepartment();
769
+ // this.textInputTextArea = replaceBr(this.textInputTextArea);
998
770
  this.sendMessage(this.textInputTextArea, TYPE_MSG_TEXT);
771
+ // this.restoreTextArea();
999
772
  }
1000
- return;
773
+ } else if (keyCode === 9) { // TAB pressed
774
+ event.preventDefault();
1001
775
  }
776
+ }
1002
777
 
1003
- if (keyCode === 9) { // TAB
778
+
779
+ /**
780
+ * HANDLE: cmd+enter, shiftKey+enter, alt+enter, ctrl+enter
781
+ * @param event
782
+ */
783
+ onkeydown(event){
784
+ const keyCode = event.which || event.keyCode;
785
+ // metaKey -> COMMAND , shiftKey -> SHIFT, altKey -> ALT, ctrlKey -> CONTROL
786
+ if( (event.metaKey || event.shiftKey || event.altKey || event.ctrlKey) && keyCode===13){
1004
787
  event.preventDefault();
788
+ this.textInputTextArea += '\r\n';
789
+ this.resizeInputField();
1005
790
  }
1006
791
  }
1007
792