@chat21/chat21-web-widget 5.1.30 → 5.1.32-rc2

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 (56) hide show
  1. package/.github/workflows/docker-community-push-latest.yml +23 -13
  2. package/.github/workflows/docker-image-tag-community-tag-push.yml +22 -12
  3. package/CHANGELOG.md +41 -2
  4. package/Dockerfile +4 -5
  5. package/angular.json +5 -2
  6. package/deploy_amazon_beta.sh +17 -7
  7. package/docs/changelog/this-branch.md +36 -0
  8. package/package.json +4 -1
  9. package/src/app/app.component.ts +10 -9
  10. package/src/app/app.module.ts +9 -0
  11. package/src/app/component/conversation-detail/conversation/conversation.component.html +7 -1
  12. package/src/app/component/conversation-detail/conversation/conversation.component.scss +2 -2
  13. package/src/app/component/conversation-detail/conversation/conversation.component.ts +34 -5
  14. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.html +2 -2
  15. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.scss +1 -1
  16. package/src/app/component/conversation-detail/conversation-content/conversation-content.component.ts +2 -0
  17. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +146 -79
  18. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +131 -13
  19. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +108 -7
  20. package/src/app/component/last-message/last-message.component.ts +4 -1
  21. package/src/app/component/message/audio/audio.component.ts +0 -5
  22. package/src/app/component/message/audio-sync/audio-sync.component.html +19 -0
  23. package/src/app/component/message/audio-sync/audio-sync.component.scss +65 -0
  24. package/src/app/component/message/audio-sync/audio-sync.component.spec.ts +23 -0
  25. package/src/app/component/message/audio-sync/audio-sync.component.ts +197 -0
  26. package/src/app/component/message/bubble-message/bubble-message.component.html +6 -1
  27. package/src/app/component/message/bubble-message/bubble-message.component.ts +2 -1
  28. package/src/app/providers/global-settings.service.ts +21 -0
  29. package/src/app/providers/translator.service.ts +2 -0
  30. package/src/app/providers/voice/STT&TTS/openai-voice.config.ts +12 -0
  31. package/src/app/providers/voice/STT&TTS/openai-voice.provider.ts +171 -0
  32. package/src/app/providers/voice/STT&TTS/speech-provider.abstract.ts +39 -0
  33. package/src/app/providers/voice/audio.types.ts +34 -0
  34. package/src/app/providers/voice/vad.service.spec.ts +28 -0
  35. package/src/app/providers/voice/vad.service.ts +70 -0
  36. package/src/app/providers/voice/voice.service.spec.ts +60 -0
  37. package/src/app/providers/voice/voice.service.ts +264 -0
  38. package/src/app/sass/_variables.scss +1 -0
  39. package/src/app/shims/onnxruntime-web-wasm.ts +4 -0
  40. package/src/app/utils/conversation-sender-classifier.ts +21 -0
  41. package/src/app/utils/globals.ts +7 -1
  42. package/src/assets/i18n/en.json +1 -0
  43. package/src/assets/i18n/es.json +1 -0
  44. package/src/assets/i18n/fr.json +1 -0
  45. package/src/assets/i18n/it.json +1 -0
  46. package/src/assets/onnx/ort-wasm-simd-threaded.mjs +59 -0
  47. package/src/assets/onnx/ort-wasm-simd-threaded.wasm +0 -0
  48. package/src/assets/vad/silero_vad_legacy.onnx +0 -0
  49. package/src/assets/vad/vad.worklet.bundle.min.js +1 -0
  50. package/src/chat21-core/models/message.ts +2 -1
  51. package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +3 -2
  52. package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +12 -0
  53. package/src/chat21-core/providers/tiledesk/tiledesk-requests.service.ts +1 -1
  54. package/src/chat21-core/utils/utils-message.ts +7 -0
  55. package/src/chat21-core/utils/utils.ts +5 -2
  56. package/tsconfig.json +5 -0
@@ -1,10 +1,10 @@
1
1
  name: Docker Image Community latest CI
2
2
 
3
- on:
4
- push:
3
+ on:
4
+ push:
5
5
  branches: [ master ]
6
- pull_request:
7
- branches: [ master ]
6
+ pull_request:
7
+ branches: [ master ]
8
8
 
9
9
  jobs:
10
10
  push_to_registry:
@@ -12,12 +12,22 @@ jobs:
12
12
  runs-on: ubuntu-latest
13
13
 
14
14
  steps:
15
- - uses: actions/checkout@v2
16
- name: Check out the repo
17
- - uses: docker/build-push-action@v1
18
- with:
19
- username: ${{ secrets.DOCKERHUB_USERNAME }}
20
- password: ${{ secrets.DOCKERHUB_TOKEN }}
21
- repository: chat21/chat21-web-widget
22
- push: true
23
- tags: latest
15
+ - name: Check out the repo
16
+ uses: actions/checkout@v2
17
+
18
+ - name: Set up Docker Buildx
19
+ uses: docker/setup-buildx-action@v2
20
+
21
+ - name: Log in to Docker Hub
22
+ uses: docker/login-action@v2
23
+ with:
24
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
25
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
26
+
27
+ - name: Build and push multiarch Docker image
28
+ uses: docker/build-push-action@v3
29
+ with:
30
+ context: .
31
+ push: true
32
+ platforms: linux/amd64,linux/arm64
33
+ tags: chat21/chat21-web-widget:latest
@@ -3,20 +3,30 @@ name: Publish Docker Community image tags
3
3
  on:
4
4
  push:
5
5
  tags:
6
- - '**' # Push events to every tag including hierarchical tags like
7
- jobs:
6
+ - '**' # Trigger su qualsiasi tag
8
7
 
8
+ jobs:
9
9
  push_to_registry:
10
10
  name: Push Docker image to Docker Hub
11
11
  runs-on: ubuntu-latest
12
+
12
13
  steps:
13
- - name: Check out the repo
14
- uses: actions/checkout@v2
15
- - name: Push to Docker Hub
16
- uses: docker/build-push-action@v1
17
- with:
18
- username: ${{ secrets.DOCKERHUB_USERNAME }}
19
- password: ${{ secrets.DOCKERHUB_TOKEN }}
20
- repository: chat21/chat21-web-widget
21
- push: true
22
- tag_with_ref: true
14
+ - name: Check out the repo
15
+ uses: actions/checkout@v2
16
+
17
+ - name: Set up Docker Buildx
18
+ uses: docker/setup-buildx-action@v2
19
+
20
+ - name: Log in to Docker Hub
21
+ uses: docker/login-action@v2
22
+ with:
23
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
24
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
25
+
26
+ - name: Build and push multiarch Docker image
27
+ uses: docker/build-push-action@v3
28
+ with:
29
+ context: .
30
+ push: true
31
+ platforms: linux/amd64,linux/arm64
32
+ tags: chat21/chat21-web-widget:${{ github.ref_name }}
package/CHANGELOG.md CHANGED
@@ -6,11 +6,28 @@
6
6
  ### **Copyrigth**:
7
7
  *Tiledesk SRL*
8
8
 
9
+ # 5.1.32-rc2
10
+ - **bug fixed**: minor streaming icon UI fixed
11
+
12
+ # 5.1.32-rc1
13
+ - **added**: Voice pipeline — VAD (`@ricky0123/vad-web`) with ONNX Runtime WASM served from `/assets/onnx` (`copy-onnx-wasm`), `VoiceService` with `audioSegment$` (WebM segments) and optional STT/TTS via unified OpenAI provider using `HttpClient`, transcript / error fields on segment payloads.
14
+ - **added**: Stream audio UI in conversation footer — toggle, real-time volume stream and animated waveform (`volume$`); mic session lifecycle wired to upload segments on speech end.
15
+ - **added**: `MessageModel.isJustRecived` — set when ingesting messages (MQTT/Firebase `addCommandMessage` for `command.type === "message"`, and default for non-command messages in `addedMessage` / `addedNew`) to distinguish “new in session” vs history.
16
+ - **added**: `chat-audio-sync` for TTS messages — karaoke-style word sync to audio, full `message` input, typography aligned with text bubbles; skips animation when `isJustRecived === false`; after playback ends sets `message.isJustRecived = false` so replays show full text without re-animating.
17
+ - **bug fixed**: `AnalyserNode.getByteFrequencyData` TypeScript error — `Uint8Array` created from an explicit `ArrayBuffer` for correct DOM typings.
18
+ - **bug fixed**: `isStreamAudioActive` no longer derived from per-frame mic level (`volume > 1`), which caused the stream button / active state to flash continuously while listening.
19
+
9
20
  # 5.1.30
10
21
  - **bug fixed**: startHidden is not working properly
11
22
 
12
- # 5.1.28
13
- - **bug fixed**: header option menu is deactivated on mobile
23
+ # 5.1.30-rc3
24
+ - **bug fixed**: bug fix user-typing with human is not available
25
+
26
+ # 5.1.30-rc2
27
+ - **bug fixed**: bug fix disabled user-typing with human
28
+
29
+ # 5.1.30-rc1
30
+ - **bug fixed**: startHidden is not working properly
14
31
 
15
32
  # 5.1.28
16
33
  - **bug fixed**: fixed Bot/Human conversation detection by correctly classifying bot replies
@@ -22,8 +39,22 @@
22
39
  - **changed**: Set the default autoStart value to false
23
40
  - **added**: Added the open widget loading spinner
24
41
  - **changed**: Load the widget without authentication and display the speech bubble
42
+
43
+ # 5.1.27-rc3
44
+ - **bug fixed**: fixed Bot/Human conversation detection by correctly classifying bot replies
45
+
46
+ # 5.1.27-rc2
47
+ - **bug fixed**: centralized fullscreen management on mobile and handled the case of the closed widget that remained fullscreen
48
+
49
+ # 5.1.27-rc1
50
+ - **added**: closeChatInConversation parameters
51
+ - **added**: close chat button under textarea footer component
52
+
53
+ # 5.1.26-rc6
25
54
  - **changed**: mobile always opens fullscreen and ignores legacy stored size”.
26
55
  - **changed**: changed user-typing
56
+
57
+ # 5.1.26-rc5
27
58
  - **changed**: Hide the resize-widget button when on mobile
28
59
  - **added**: added "I'm thinking" when the bot responds
29
60
 
@@ -85,6 +116,14 @@
85
116
  - **bug-fixed**: check showEmojiFooterButton to enable/disable emojii
86
117
  - **bug-fixed**: markdown is fired as an emojii and blocked by isEmojii check fn
87
118
 
119
+ <<<<<<< HEAD
120
+ =======
121
+ # 5.1.7-rc7
122
+ - **bug-fixed**: button new_conversation always appear. added subscription to conversationAdded
123
+
124
+ # 5.1.7-rc6
125
+ - **added**: Added MAX_ATTACHMENT_ERROR error message when uploading a file larger than 10 MB
126
+ >>>>>>> master-pre
88
127
 
89
128
  # 5.1.7-rc5
90
129
  - **bug-fixed**: bug fixed BUTTON STYLES
package/Dockerfile CHANGED
@@ -1,7 +1,7 @@
1
1
  ### STAGE 1: Build ###
2
2
 
3
3
  # We label our stage as ‘builder’
4
- FROM node:20.12.2-alpine3.19 as builder
4
+ FROM --platform=$BUILDPLATFORM node:20.12.2-alpine3.19 as builder
5
5
 
6
6
  COPY package.json package-lock.json ./
7
7
 
@@ -15,12 +15,11 @@ COPY . .
15
15
 
16
16
  ## Build the angular app in production mode and store the artifacts in dist folder
17
17
 
18
- RUN npx ng build --configuration="prod" --output-path=dist --base-href=./ --output-hashing=none
19
18
 
19
+ RUN npx ng build --configuration="prod" --output-path=dist --base-href=./ --output-hashing=none
20
20
 
21
21
  ### STAGE 2: Setup ###
22
-
23
- FROM nginx:1.14.1-alpine
22
+ FROM --platform=$BUILDPLATFORM nginx:1.14.1-alpine
24
23
 
25
24
  ## Copy our default nginx config
26
25
  COPY nginx.conf /etc/nginx/nginx.conf
@@ -33,4 +32,4 @@ COPY --from=builder /ng-app/dist/browser /usr/share/nginx/html
33
32
 
34
33
  RUN echo "Chat21 Web Widget Started!!"
35
34
 
36
- CMD ["/bin/sh", "-c", "envsubst < /usr/share/nginx/html/widget-config-template.json > /usr/share/nginx/html/widget-config.json && exec nginx -g 'daemon off;'"]
35
+ CMD ["/bin/sh", "-c", "envsubst < /usr/share/nginx/html/widget-config-template.json > /usr/share/nginx/html/widget-config.json && exec nginx -g 'daemon off;'"]
package/angular.json CHANGED
@@ -44,7 +44,8 @@
44
44
  "src/environments/real_data/widget-config-docker.json",
45
45
  "src/environments/real_data/widget-config-native-mqtt.json",
46
46
  "src/environments/real_data/widget-config-native-prod.json",
47
- "src/environments/real_data/widget-config-aws-stage.json"
47
+ "src/environments/real_data/widget-config-aws-stage.json",
48
+ "src/environments/real_data/widget-config-aws-aruba.json"
48
49
  ],
49
50
  "styles": [
50
51
  "src/app/sass/styles.scss"
@@ -59,7 +60,9 @@
59
60
  "idb",
60
61
  "accept-language-parser",
61
62
  "file-saver",
62
- "dayjs"
63
+ "dayjs",
64
+ "onnxruntime-web",
65
+ "@ricky0123/vad-web"
63
66
  ],
64
67
  "sourceMap": true,
65
68
  "optimization": false,
@@ -2,8 +2,16 @@
2
2
  version=`node -e 'console.log(require("./package.json").version)'`
3
3
  echo "version $version"
4
4
 
5
+ npm i
6
+
7
+ cp src/environments/real_data/environment.pre.ts src/environments/environment.pre.ts
8
+
5
9
  ng build --configuration="pre" --aot=true --base-href
6
10
 
11
+ ### SET HASHING : START ###
12
+ cp ./src/launch_template.js ./dist/browser/launch.js
13
+ node ./src/build_launch.js
14
+ ### SET HASHING : END ###
7
15
 
8
16
  # ########## --->>>> NATIVE-MQTT folder START <<<<<------ ########## #
9
17
 
@@ -23,15 +31,17 @@ ng build --configuration="pre" --aot=true --base-href
23
31
 
24
32
 
25
33
  # ########## --->>>> FIREBASE folder START <<<<<------ ########## #
26
- cd dist
27
- aws s3 sync . s3://tiledesk-widget-pre/v5/$version/ --cache-control max-age=300
28
- aws s3 sync . s3://tiledesk-widget-pre/v5/ --cache-control max-age=300
29
- cd ..
30
-
31
- #aws cloudfront create-invalidation --distribution-id E3EJDWEHY08CZZ --paths "/*"
32
- cd ..
34
+ cd dist/browser
35
+ aws s3 sync . s3://tiledesk-widget-pre/v5/$version/ --cache-control max-age=300 --exclude='launch.js' #7days
36
+ aws s3 sync . s3://tiledesk-widget-pre/v5/$version/ --cache-control "no-store,no-cache,private" --exclude='*' --include='launch.js'
37
+ aws s3 sync . s3://tiledesk-widget-pre/v5/ --cache-control max-age=300 --exclude='launch.js' #7days
38
+ aws s3 sync . s3://tiledesk-widget-pre/v5/ --cache-control "no-store,no-cache,private" --exclude='*' --include='launch.js'
39
+ cd ../..
33
40
 
34
41
  aws cloudfront create-invalidation --distribution-id E2V5O0YPR61V8P --paths "/*"
42
+
43
+ git restore src/environments/environment.pre.ts
44
+
35
45
  # echo new version deployed $NEW_VER/$NEW_BUILD/ on s3://tiledesk-widget-pre/v2
36
46
  echo new version deployed $version/ on s3://tiledesk-widget-pre/v5 and s3://tiledesk-widget-pre/v5/$version/
37
47
  echo available on https://s3.eu-west-1.amazonaws.com/tiledesk-widget-pre/v5/index.html
@@ -45,3 +45,39 @@ Questo branch migliora il feedback in conversazione e rende il comportamento del
45
45
  - Il callout non compare quando il widget e' aperto o quando la preview nuovo messaggio e' attiva.
46
46
  - La UI della conversazione indica chiaramente se l'ultimo responder e' bot o umano.
47
47
  - "Sto pensando..." compare solo nelle conversazioni bot e ha un comportamento prevedibile.
48
+ # This branch: identificazione bot o umano
49
+
50
+ ## Obiettivo
51
+
52
+ In questo branch e' stata introdotta una logica esplicita per capire, all'apertura della conversazione, se l'ultimo responder lato server e' un **bot** oppure un **umano**.
53
+
54
+ ## Come viene fatta l'identificazione
55
+
56
+ - La valutazione parte dai messaggi gia' caricati in conversazione.
57
+ - Viene cercato l'**ultimo messaggio ricevuto dal server** (non inviato dal client corrente).
58
+ - Quel messaggio viene classificato con una funzione dedicata (`classifyMessageSenderKind`) che usa piu' segnali:
59
+ - `attributes.flowAttributes.chatbot_id` (quando presente indica bot)
60
+ - pattern del mittente (es. `senderId` con prefisso bot, quando applicabile)
61
+ - informazioni del mittente (`sender_fullname` e metadati associati)
62
+
63
+ ## Regola speciale per messaggi di sistema
64
+
65
+ Se l'ultimo messaggio utile e' di tipo `system`, viene fatto un controllo aggiuntivo:
66
+
67
+ - se in `attributes` e' presente un evento con `messagelabel.key = MEMBER_JOINED_GROUP`
68
+ - e rappresenta il passaggio della conversazione a un operatore
69
+
70
+ allora la conversazione viene forzata a **Umano** anche se altri indizi potrebbero suggerire bot.
71
+
72
+ ## Risultato in UI
73
+
74
+ - In apertura conversazione viene mostrato un badge con stato:
75
+ - `Bot`
76
+ - `Umano`
77
+ - Questo stato viene ricalcolato al variare dei messaggi ricevuti.
78
+
79
+ ## Effetto sui feedback utente
80
+
81
+ - Il messaggio temporaneo `"sto pensando..."` viene mostrato solo quando la conversazione risulta di tipo **Bot**.
82
+ - Alla ricezione della prima risposta dal server, `"sto pensando..."` viene nascosto **immediatamente**.
83
+ - Non e' previsto alcun tempo minimo di visualizzazione del messaggio.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@chat21/chat21-web-widget",
3
3
  "author": "Tiledesk SRL",
4
- "version": "5.1.30",
4
+ "version": "5.1.32-rc2",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -10,6 +10,7 @@
10
10
  },
11
11
  "scripts": {
12
12
  "ng": "ng",
13
+ "copy-onnx-wasm": "mkdir -p src/assets/onnx && cp node_modules/onnxruntime-web/dist/ort-wasm-simd-threaded.mjs node_modules/onnxruntime-web/dist/ort-wasm-simd-threaded.wasm src/assets/onnx/",
13
14
  "start": "ng serve",
14
15
  "build": "ng build",
15
16
  "test": "ng test",
@@ -32,6 +33,7 @@
32
33
  "@ctrl/ngx-emoji-mart": "^9.2.0",
33
34
  "@ngx-translate/core": "^16.0.4",
34
35
  "@ngx-translate/http-loader": "^16.0.1",
36
+ "@ricky0123/vad-web": "^0.0.30",
35
37
  "accept-language-parser": "^1.5.0",
36
38
  "bootstrap": "^5.1.3",
37
39
  "dayjs": "^1.11.7",
@@ -40,6 +42,7 @@
40
42
  "humanize-duration-ts": "^2.1.1",
41
43
  "marked": "^16.3.0",
42
44
  "ngx-logger": "^5.0.11",
45
+ "onnxruntime-web": "^1.24.3",
43
46
  "replace": "^1.2.2",
44
47
  "rxjs": "^7.8.2",
45
48
  "source-map-explorer": "^2.5.3",
@@ -106,17 +106,16 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
106
106
 
107
107
  forceDisconnect: boolean = false;
108
108
 
109
+ //network status
110
+ isOnline: boolean = true;
111
+ loading: boolean = false;
112
+ private calloutScheduleTimeout: any = null;
113
+
109
114
  // alert error message
110
115
  isShowErrorMessage: boolean = false;
111
116
  errorMessage: string = '';
112
117
  errorKeyMessage: string = null;
113
118
  errorParams: Record<string, any> = {};
114
-
115
- //network status
116
- isOnline: boolean = true;
117
-
118
- loading: boolean = false;
119
- private calloutScheduleTimeout: any = null;
120
119
 
121
120
  private logger: LoggerService = LoggerInstance.getInstance();
122
121
  constructor(
@@ -170,13 +169,13 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
170
169
  if (conversation.attributes && conversation.attributes['subtype'] === 'info') {
171
170
  return;
172
171
  }
173
- if (conversation.is_new && this.isInitialized) {
172
+ if (conversation.is_new && that.isInitialized) {
174
173
  that.manageTabNotification(false, 'conv-added')
175
174
  // this.soundMessage();
176
175
  }
177
- if(this.g.isOpen === false){
178
- that.lastConversation = conversation;
176
+ if(this.g.isOpen === false && conversation.sender !== this.g.senderId && !isInfo(conversation)){
179
177
  that.g.isOpenNewMessage = true;
178
+ that.lastConversation = conversation;
180
179
  }
181
180
  } else {
182
181
  //widget closed
@@ -224,6 +223,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
224
223
  that.lastConversation = conversation;
225
224
  that.g.isOpenNewMessage = true;
226
225
  that.logger.debug('[APP-COMP] lastconversationnn', that.lastConversation)
226
+ that.logger.debug('[APP-COMP] lastconversationnn message' + JSON.stringify(that.lastConversation?.attributes?.commands))
227
227
  }
228
228
  let badgeNewConverstionNumber = that.conversationsHandlerService.countIsNew()
229
229
  that.g.setParameter('conversationsBadge', badgeNewConverstionNumber);
@@ -2319,6 +2319,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
2319
2319
  this.el.nativeElement.style.setProperty('--chat-header-height', this.g.hideHeaderConversation? '0px': null)
2320
2320
  this.el.nativeElement.style.setProperty('--font-size-bubble-message', this.g.fontSize)
2321
2321
  this.el.nativeElement.style.setProperty('--font-family-bubble-message', this.g.fontFamily)
2322
+ this.el.nativeElement.style.setProperty('--chat-footer-close-button-height', this.g.closeChatInConversation? '30px': '0px')
2322
2323
 
2323
2324
  }
2324
2325
 
@@ -25,6 +25,7 @@ import { InfoMessageComponent } from './component/message/info-message/info-mess
25
25
  import { HtmlComponent } from './component/message/html/html.component';
26
26
  import { FrameComponent } from './component/message/frame/frame.component';
27
27
  import { AudioComponent } from './component/message/audio/audio.component';
28
+ import { AudioSyncComponent } from './component/message/audio-sync/audio-sync.component';
28
29
  import { UserTypingComponent } from './../chat21-core/utils/user-typing/user-typing.component';
29
30
  /** MESSAGE ATTACHMENTS COMPONENTS */
30
31
  import { MessageAttachmentComponent } from './component/message-attachment/message-attachment.component';
@@ -136,6 +137,11 @@ import { Rules } from './utils/rules';
136
137
  import { ScriptService } from 'src/chat21-core/providers/scripts/script.service';
137
138
  import { CarouselComponent } from './component/message/carousel/carousel.component';
138
139
  import { BrandService } from './providers/brand.service';
140
+ import { OpenAiVoiceProviderService } from './providers/voice/STT&TTS/openai-voice.provider';
141
+ import {
142
+ SpeechToTextProvider,
143
+ TextToSpeechProvider,
144
+ } from './providers/voice/STT&TTS/speech-provider.abstract';
139
145
  import { ErrorAlertComponent } from './component/error-alert/error-alert.component';
140
146
  import { ConfirmCloseComponent } from './modals/confirm-close/confirm-close.component';
141
147
 
@@ -300,6 +306,7 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
300
306
  LinkButtonComponent,
301
307
  TextButtonComponent,
302
308
  AudioComponent,
309
+ AudioSyncComponent,
303
310
  UserTypingComponent,
304
311
  /**DIRECTIVES */
305
312
  HtmlEntitiesEncodePipe,
@@ -405,6 +412,8 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
405
412
  WaitingService,
406
413
  ScriptService,
407
414
  BrandService,
415
+ { provide: SpeechToTextProvider, useExisting: OpenAiVoiceProviderService },
416
+ { provide: TextToSpeechProvider, useExisting: OpenAiVoiceProviderService },
408
417
  provideHttpClient(withInterceptorsFromDi())
409
418
  ],
410
419
  bootstrap: [AppComponent]
@@ -64,7 +64,9 @@
64
64
  [nameUserTypingNow]="nameUserTypingNow"
65
65
  [typingLocation]="g?.typingLocation"
66
66
  [showThinkingMessage]="showThinkingMessage"
67
+ [lastServerSenderKind]="lastServerSenderKind"
67
68
  [fullscreenMode]="g?.fullscreenMode"
69
+ [isStreamAudioActive]="isStreamAudioActive"
68
70
  [translationMap]="translationMapContent"
69
71
  [stylesMap]="stylesMap"
70
72
  (onBeforeMessageRender)="onBeforeMessageRenderFN($event)"
@@ -131,12 +133,14 @@
131
133
  [showAttachmentFooterButton]="g?.showAttachmentFooterButton"
132
134
  [showEmojiFooterButton]="g?.showEmojiFooterButton"
133
135
  [showAudioRecorderFooterButton]="g?.showAudioRecorderFooterButton"
136
+ [showAudioStreamFooterButton]="g?.showAudioStreamFooterButton"
134
137
  [hideTextAreaContent]="(g?.singleConversation && hideTextAreaContent) || (isConversationArchived && !g?.allowReopen)"
135
138
  [isConversationArchived]="isConversationArchived"
136
139
  [hideTextReply]="hideFooterTextReply"
137
140
  [isMobile]="g?.isMobile"
138
141
  [isEmojiiPickerShow]="isEmojiiPickerShow"
139
142
  [footerMessagePlaceholder]="footerMessagePlaceholder"
143
+ [closeChatInConversation]="g?.closeChatInConversation"
140
144
  [fileUploadAccept]="g?.fileUploadAccept"
141
145
  [dropEvent]="dropEvent"
142
146
  [poweredBy]="g?.poweredBy"
@@ -147,7 +151,9 @@
147
151
  (onAfterSendMessage)="onAfterSendMessageFN($event)"
148
152
  (onChangeTextArea)="onChangeTextArea($event)"
149
153
  (onAttachmentFileButtonClicked)="onAttachmentFileButtonClicked($event)"
150
- (onNewConversationButtonClicked)="onNewConversationButtonClickedFN($event)">
154
+ (onNewConversationButtonClicked)="onNewConversationButtonClickedFN($event)"
155
+ (onStreamAudioActiveChange)="onStreamAudioActiveChange($event)"
156
+ (onCloseChatButtonClicked)="onCloseChatButtonClickedFN($event)">
151
157
  </chat-conversation-footer>
152
158
 
153
159
  </div>
@@ -137,7 +137,7 @@
137
137
  #dropZone_container{
138
138
  position: absolute;
139
139
  top: 52px;
140
- bottom: calc(var(--chat-footer-logo-height) + var(--chat-footer-height));
140
+ bottom: calc(var(--chat-footer-logo-height) + var(--chat-footer-height) + var(--chat-footer-close-button-height));
141
141
  left: 0;
142
142
  right: 0;
143
143
  background-color: rgba(240,248,255,0.6);
@@ -240,7 +240,7 @@ dialog:-internal-dialog-in-top-layer{
240
240
 
241
241
 
242
242
  ::ng-deep .chat21-sheet-content{
243
- bottom: calc(var(--chat-footer-logo-height) + var(--chat-footer-height) + 34px)!important;
243
+ bottom: calc(var(--chat-footer-logo-height) + var(--chat-footer-height) + var(--chat-footer-close-button-height) + 34px)!important;
244
244
  }
245
245
 
246
246
  }
@@ -161,6 +161,10 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
161
161
  membersConversation = ['SYSTEM'];
162
162
  // ========== end:: typying =======
163
163
 
164
+ // ========== begin:: stream audio ======= //
165
+ public isStreamAudioActive = false;
166
+ // ========== end:: stream audio ======= //
167
+
164
168
  @ViewChild(ConversationFooterComponent) conversationFooter: ConversationFooterComponent
165
169
  @ViewChild(ConversationContentComponent) conversationContent: ConversationContentComponent
166
170
  conversationHandlerService: ConversationHandlerService
@@ -246,7 +250,8 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
246
250
  'CONTINUE',
247
251
  'EMOJI_NOT_ELLOWED',
248
252
  'ATTACHMENT',
249
- 'EMOJI'
253
+ 'EMOJI',
254
+ 'CLOSE_CHAT'
250
255
  ];
251
256
 
252
257
  const keysContent = [
@@ -501,7 +506,7 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
501
506
  return this.isConversationArchived;
502
507
  }
503
508
 
504
- //FALLBACK TO TILEDESK
509
+ // //FALLBACK TO TILEDESK
505
510
  const requests_list = await this.tiledeskRequestService.getMyRequests().catch(err => {
506
511
  this.logger.error('[CONV-COMP] getConversationDetail: error getting request from Tiledesk', err);
507
512
  this.isConversationArchived=true
@@ -519,9 +524,9 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
519
524
  return this.isConversationArchived
520
525
  }
521
526
 
522
- this.isConversationArchived = true;
523
- return null;
524
- }
527
+ this.isConversationArchived = false;
528
+ return null;
529
+ }
525
530
 
526
531
  /**
527
532
  * this.g.recipientId:
@@ -877,6 +882,20 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
877
882
  this.subscriptions.push(subscribe);
878
883
  }
879
884
 
885
+ subscribtionKey = 'conversationsAdded';
886
+ subscribtion = this.subscriptions.find(item => item.key === subscribtionKey);
887
+ if(!subscribtion){
888
+
889
+ subscribtion = this.chatManager.conversationsHandlerService.conversationChanged.pipe(takeUntil(this.unsubscribe$)).subscribe((conversation) => {
890
+ this.logger.debug('[CONV-COMP] ***** DATAIL conversationsChanged *****', conversation, this.conversationWith, this.isConversationArchived);
891
+ if(conversation && conversation.recipient === this.conversationId){
892
+ this.isConversationArchived = false
893
+ }
894
+ });
895
+ const subscribe = {key: subscribtionKey, value: subscribtion };
896
+ this.subscriptions.push(subscribe);
897
+ }
898
+
880
899
  subscribtionKey = 'messageWait';
881
900
  subscribtion = this.subscriptions.find(item => item.key === subscribtionKey);
882
901
  if (!subscribtion) {
@@ -1383,6 +1402,16 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
1383
1402
  this.logger.debug('[CONV-COMP] floating onNewConversationButtonClicked')
1384
1403
  this.onNewConversationButtonClicked.emit()
1385
1404
  }
1405
+
1406
+ /** CALLED BY: conv-footer streaming audio button */
1407
+ onStreamAudioActiveChange(event: boolean){
1408
+ this.isStreamAudioActive = event
1409
+ }
1410
+ /** CALLED BY: conv-footer component */
1411
+ onCloseChatButtonClickedFN(event){
1412
+ this.logger.debug('[CONV-COMP] onCloseChatButtonClicked::::', event)
1413
+ this.onCloseChat()
1414
+ }
1386
1415
  // =========== END: event emitter function ====== //
1387
1416
 
1388
1417
 
@@ -22,7 +22,7 @@
22
22
  <div *ngFor="let message of messages; let first = first; let last = last; let i = index" tabindex="1521" class="rowMsg">
23
23
 
24
24
  <!-- message SENDER:: -->
25
- <div role="messaggio" *ngIf="messageType(MESSAGE_TYPE_MINE, message)" class="msg_container base_sent">
25
+ <div role="messaggio" *ngIf="messageType(MESSAGE_TYPE_MINE, message) && (!isStreamAudioActive && !message.isJustRecived)" class="msg_container base_sent">
26
26
 
27
27
  <!--backgroundColor non viene ancora usato -->
28
28
  <!-- class="messages msg_sent slide-in-right" -->
@@ -143,7 +143,7 @@
143
143
  </user-typing>
144
144
  </div>
145
145
 
146
- <div *ngIf="showThinkingMessage" class="msg_container base_receive thinking_receive">
146
+ <div *ngIf="showThinkingMessage && lastServerSenderKind === 'bot'" class="msg_container base_receive thinking_receive">
147
147
  <user-typing class="loading thinking-dots"
148
148
  [color]="stylesMap?.get('iconColor')"
149
149
  [translationMap]="translationMap"
@@ -44,7 +44,7 @@
44
44
  top: 0;
45
45
  right: 0;
46
46
  left: 0;
47
- bottom: calc(var(--chat-footer-logo-height) + var(--chat-footer-height));
47
+ bottom: calc(var(--chat-footer-logo-height) + var(--chat-footer-height) + var(--chat-footer-close-button-height));
48
48
  overflow: hidden;
49
49
  .time{
50
50
  margin-bottom: 20px;
@@ -24,7 +24,9 @@ export class ConversationContentComponent implements OnInit {
24
24
  @Input() nameUserTypingNow: string;
25
25
  @Input() typingLocation: string;
26
26
  @Input() showThinkingMessage: boolean;
27
+ @Input() lastServerSenderKind: 'bot' | 'human' | null;
27
28
  @Input() fullscreenMode: boolean;
29
+ @Input() isStreamAudioActive: boolean;
28
30
  @Input() translationMap: Map< string, string>;
29
31
  @Input() stylesMap: Map<string, string>;
30
32
  @Output() onBeforeMessageRender = new EventEmitter();