@chat21/chat21-web-widget 5.0.83 → 5.0.84-rc.2

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 (28) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/package.json +1 -1
  3. package/src/app/app.module.ts +5 -2
  4. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.html +29 -0
  5. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.scss +103 -0
  6. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.spec.ts +23 -0
  7. package/src/app/component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component.ts +96 -0
  8. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +14 -3
  9. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.scss +26 -10
  10. package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +131 -49
  11. package/src/app/component/message/audio-track/audio-track.component.html +32 -0
  12. package/src/app/component/message/audio-track/audio-track.component.scss +107 -0
  13. package/src/app/component/message/{audio/audio.component.spec.ts → audio-track/audio-track.component.spec.ts} +6 -6
  14. package/src/app/component/message/audio-track/audio-track.component.ts +147 -0
  15. package/src/app/component/message/bubble-message/bubble-message.component.html +31 -15
  16. package/src/app/component/message/bubble-message/bubble-message.component.scss +7 -0
  17. package/src/app/component/message/bubble-message/bubble-message.component.ts +1 -0
  18. package/src/app/utils/globals.ts +1 -1
  19. package/src/assets/twp/blank.html +3 -6
  20. package/src/assets/twp/chatbot-panel.html +5 -13
  21. package/src/assets/twp/index-dev.html +8 -16
  22. package/src/assets/twp/index.html +7 -13
  23. package/src/assets/twp/tiledesk_widget_files/bootstrap.min.css +4 -3
  24. package/src/assets/twp/tiledesk_widget_files/bootstrap.min.js +3 -4
  25. package/src/assets/twp/tiledesk_widget_files/jquery.min.js +2 -2
  26. package/src/app/component/message/audio/audio.component.html +0 -20
  27. package/src/app/component/message/audio/audio.component.scss +0 -122
  28. package/src/app/component/message/audio/audio.component.ts +0 -122
package/CHANGELOG.md CHANGED
@@ -6,6 +6,12 @@
6
6
  ### **Copyrigth**:
7
7
  *Tiledesk SRL*
8
8
 
9
+ # 5.0.84-rc.2
10
+ - **changed**: bootstrap, jquery and font-awesome libs
11
+
12
+ # 5.0.84-rc.1
13
+ - **removed**: innerHtml from document element
14
+
9
15
  # 5.0.83 in PROD
10
16
 
11
17
  # 5.0.83-rc.4
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.0.83",
4
+ "version": "5.0.84-rc.2",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -15,6 +15,7 @@ import { ConversationContentComponent } from './component/conversation-detail/co
15
15
  import { ConversationFooterComponent } from './component/conversation-detail/conversation-footer/conversation-footer.component';
16
16
  import { ConversationInternalFrameComponent } from './component/conversation-detail/conversation-internal-frame/conversation-internal-frame.component';
17
17
  import { ConversationPreviewComponent } from './component/conversation-detail/conversation-preview/conversation-preview.component';
18
+ import { ConversationAudioRecorderComponent } from './component/conversation-detail/conversation-audio-recorder/conversation-audio-recorder.component';
18
19
  /** CONVERSATION-DETAIL COMPONENTS */
19
20
  import { BubbleMessageComponent } from './component/message/bubble-message/bubble-message.component';
20
21
  import { AvatarComponent } from './component/message/avatar/avatar.component';
@@ -23,7 +24,7 @@ import { ImageComponent } from './component/message/image/image.component';
23
24
  import { InfoMessageComponent } from './component/message/info-message/info-message.component';
24
25
  import { HtmlComponent } from './component/message/html/html.component';
25
26
  import { FrameComponent } from './component/message/frame/frame.component';
26
- import { AudioComponent } from './component/message/audio/audio.component';
27
+ import { AudioTrackComponent } from './component/message/audio-track/audio-track.component';
27
28
  import { UserTypingComponent } from './../chat21-core/utils/user-typing/user-typing.component';
28
29
  /** MESSAGE ATTACHMENTS COMPONENTS */
29
30
  import { MessageAttachmentComponent } from './component/message-attachment/message-attachment.component';
@@ -138,6 +139,7 @@ import { ConfirmCloseComponent } from './modals/confirm-close/confirm-close.comp
138
139
 
139
140
 
140
141
 
142
+
141
143
  const appInitializerFn = (appConfig: AppConfigService, brandService: BrandService, logger: NGXLogger) => {
142
144
  return async() => {
143
145
  let customLogger = new CustomLogger(logger)
@@ -276,6 +278,7 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
276
278
  ConversationFooterComponent,
277
279
  ConversationPreviewComponent,
278
280
  ConversationInternalFrameComponent,
281
+ ConversationAudioRecorderComponent,
279
282
  BubbleMessageComponent,
280
283
  AvatarComponent,
281
284
  FrameComponent,
@@ -287,6 +290,7 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
287
290
  ActionButtonComponent,
288
291
  LinkButtonComponent,
289
292
  TextButtonComponent,
293
+ AudioTrackComponent,
290
294
  UserTypingComponent,
291
295
  /**DIRECTIVES */
292
296
  HtmlEntitiesEncodePipe,
@@ -295,7 +299,6 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
295
299
  SafeHtmlPipe,
296
300
  LikeUnlikeComponent,
297
301
  TooltipDirective,
298
- AudioComponent,
299
302
  CarouselComponent,
300
303
  NetworkOfflineComponent,
301
304
  ConfirmCloseComponent
@@ -0,0 +1,29 @@
1
+ <div class="audio-recorder">
2
+ <button *ngIf="audioUrl" (click)="deleteRecording()">
3
+ <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px"><path d="M280-120q-33 0-56.5-23.5T200-200v-520h-40v-80h200v-40h240v40h200v80h-40v520q0 33-23.5 56.5T680-120H280Zm80-160h80v-360h-80v360Zm160 0h80v-360h-80v360Z"/></svg>
4
+ <!-- <i class="material-icons">delete_outline</i> -->
5
+ </button>
6
+
7
+ <chat-audio-track *ngIf="audioBlob && audioUrl"
8
+ [audioBlob] = "audioBlob"
9
+ [color]="stylesMap.get('themeColor')"
10
+ [fontSize]="stylesMap.get('fontSize')"
11
+ [stylesMap]="stylesMap">
12
+ </chat-audio-track>
13
+
14
+ <button *ngIf="!audioUrl" class="mic-button" (mousedown)="startRecording()" (mouseup)="stopRecording()">
15
+ <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px">
16
+ <path d="M480-400q-50 0-85-35t-35-85v-240q0-50 35-85t85-35q50 0 85 35t35 85v240q0 50-35 85t-85 35Zm0-240Zm-40 520v-123q-104-14-172-93t-68-184h80q0 83 58.5 141.5T480-320q83 0 141.5-58.5T680-520h80q0 105-68 184t-172 93v123h-80Zm40-360q17 0 28.5-11.5T520-520v-240q0-17-11.5-28.5T480-800q-17 0-28.5 11.5T440-760v240q0 17 11.5 28.5T480-480Z"/>
17
+ </svg>
18
+ </button>
19
+ <!-- <button *ngIf="isRecording" (click)="stopRecording()"><i class="material-icons">pause_circle_outline</i></button> -->
20
+
21
+ <button *ngIf="audioUrl" (click)="sendMessage()">
22
+ <span class="v-align-center">
23
+ <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="20" width="24" viewBox="0 0 24 20" xml:space="preserve">
24
+ <path d="M1.8,18.9V1.7L22,10.3L1.8,18.9z M3.9,15.6l12.6-5.4L3.9,4.9v3.7l6.4,1.6l-6.4,1.6V15.6z M3.9,15.6V4.9v7V15.6z"/>
25
+ </svg>
26
+ </span>
27
+ </button>
28
+
29
+ </div>
@@ -0,0 +1,103 @@
1
+
2
+ @font-face {
3
+ font-family: 'Material Icons';
4
+ src: url('https://fonts.googleapis.com/icon?family=Material+Icons');
5
+ }
6
+
7
+ .material-icons.mic_none::before {
8
+ content: 'mic_none';
9
+ }
10
+
11
+ .audio-recorder {
12
+ text-align: center;
13
+ margin: 0px;
14
+ display: inline-flex;
15
+ align-items: center;
16
+ justify-content: center;
17
+ height: 100%;
18
+ width: 100%;
19
+ float: left;
20
+ gap: 10px
21
+ }
22
+
23
+ chat-audio-track {
24
+ display: flex;
25
+ width: 70%;
26
+ margin: 8px 0;
27
+ pointer-events: auto;
28
+ border-radius: var(--chat-footer-border-radius);
29
+ background-color: var(--chat-footer-background-color);
30
+ }
31
+
32
+ button {
33
+ margin: 0px;
34
+ padding: 0px;
35
+ font-size: 16px;
36
+ border: none;
37
+ background-color: transparent;
38
+ color: var(--icon-fill-color);
39
+ fill: var(--icon-fill-color);
40
+ height: var(--chat-footer-height);
41
+ }
42
+
43
+ .mic-button {
44
+ position: relative;
45
+ background-color: transparent;
46
+ border: none;
47
+ outline: none;
48
+ cursor: pointer;
49
+ padding: 20px;
50
+ border-radius: 50%;
51
+ overflow: hidden;
52
+ display: inline-flex;
53
+ justify-content: center;
54
+ align-items: center;
55
+ }
56
+
57
+ .mic-button svg {
58
+ width: 24px;
59
+ height: 24px;
60
+ fill: var(--icon-fill-color);
61
+ }
62
+
63
+ .mic-button::before {
64
+ content: '';
65
+ position: absolute;
66
+ top: auto;
67
+ left: auto;
68
+ width: 35px;
69
+ height: 35px;
70
+ background-color: var(--icon-fill-color);
71
+ border-radius: 50%;
72
+ transform: scale(0);
73
+ transition: transform 0.3s ease;
74
+ transform-origin: center;
75
+ z-index: -1;
76
+ }
77
+
78
+ .mic-button:active::before {
79
+ transform: scale(0.5);
80
+ animation: pulse 1s infinite ease-in-out;
81
+ }
82
+
83
+ .mic-button:active {
84
+ svg {
85
+ color: #fff;
86
+ fill: #fff;
87
+ }
88
+ }
89
+
90
+ @keyframes pulse {
91
+ 0% {
92
+ transform: scale(1);
93
+ opacity: 1;
94
+ }
95
+ 50% {
96
+ transform: scale(0.9);
97
+ opacity: 0.7;
98
+ }
99
+ 100% {
100
+ transform: scale(1);
101
+ opacity: 1;
102
+ }
103
+ }
@@ -0,0 +1,23 @@
1
+ import { ComponentFixture, TestBed } from '@angular/core/testing';
2
+
3
+ import { ConversationAudioRecorderComponent } from './conversation-audio-recorder.component';
4
+
5
+ describe('AudioRecorderComponent', () => {
6
+ let component: ConversationAudioRecorderComponent;
7
+ let fixture: ComponentFixture<ConversationAudioRecorderComponent>;
8
+
9
+ beforeEach(async () => {
10
+ await TestBed.configureTestingModule({
11
+ declarations: [ ConversationAudioRecorderComponent ]
12
+ })
13
+ .compileComponents();
14
+
15
+ fixture = TestBed.createComponent(ConversationAudioRecorderComponent);
16
+ component = fixture.componentInstance;
17
+ fixture.detectChanges();
18
+ });
19
+
20
+ it('should create', () => {
21
+ expect(component).toBeTruthy();
22
+ });
23
+ });
@@ -0,0 +1,96 @@
1
+ import { Component, EventEmitter, Input, Output } from '@angular/core';
2
+ import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
3
+
4
+ @Component({
5
+ selector: 'chat-audio-recorder',
6
+ templateUrl: './conversation-audio-recorder.component.html',
7
+ styleUrls: ['./conversation-audio-recorder.component.scss']
8
+ })
9
+ export class ConversationAudioRecorderComponent {
10
+
11
+ @Input() stylesMap: Map<string, string>;
12
+ @Output() startRecordingEvent = new EventEmitter<void>();
13
+ @Output() deleteRecordingEvent = new EventEmitter<void>();
14
+ @Output() endRecordingEvent = new EventEmitter<Blob | null>();
15
+ @Output() sendRecordingEvent = new EventEmitter<Blob | null>();
16
+
17
+ mediaRecorder: MediaRecorder | null = null;
18
+ audioChunks: Blob[] = [];
19
+ audioBlob: Blob | null = null;
20
+ audioUrl: SafeUrl | null = null;
21
+
22
+ isRecording = false;
23
+ rawAudioUrl: string | null = null;
24
+ isPlaying: boolean = false;
25
+ startTime: number;
26
+
27
+
28
+
29
+ constructor(private sanitizer: DomSanitizer) {}
30
+
31
+
32
+ startRecording() {
33
+ // console.log('startRecording');
34
+ this.startTime = Date.now();
35
+ navigator.mediaDevices.getUserMedia({ audio: true })
36
+ .then(stream => {
37
+ this.mediaRecorder = new MediaRecorder(stream);
38
+ this.mediaRecorder.start();
39
+ this.isRecording = true;
40
+ this.startRecordingEvent.emit();
41
+ this.mediaRecorder.addEventListener('dataavailable', (event) => {
42
+ this.audioChunks.push(event.data);
43
+ });
44
+
45
+ this.mediaRecorder.addEventListener('stop', () => {
46
+ this.audioBlob = new Blob(this.audioChunks, { type: 'audio/mpeg' });
47
+ this.rawAudioUrl = URL.createObjectURL(this.audioBlob);
48
+ this.audioUrl = this.sanitizer.bypassSecurityTrustUrl(this.rawAudioUrl);
49
+ this.audioChunks = [];
50
+ this.endRecordingEvent.emit(this.audioBlob);
51
+ });
52
+ })
53
+ .catch(error => {
54
+ console.error('Errore nell’accesso al microfono:', error);
55
+ });
56
+ }
57
+
58
+ stopRecording() {
59
+ let endTime = Date.now();
60
+ let time = endTime - this.startTime;
61
+ if(time > 500){
62
+ setTimeout(() => {
63
+ if (this.mediaRecorder) {
64
+ this.mediaRecorder.stop();
65
+ this.isRecording = false;
66
+ }
67
+ }, 300);
68
+
69
+ } else {
70
+ this.audioUrl = null;
71
+ this.isPlaying = false;
72
+ this.rawAudioUrl = null;
73
+ this.audioUrl = null;
74
+ this.audioBlob = null;
75
+ }
76
+
77
+
78
+ }
79
+
80
+ deleteRecording() {
81
+ this.audioUrl = null;
82
+ this.isPlaying = false;
83
+ this.rawAudioUrl = null;
84
+ this.audioUrl = null;
85
+ this.audioBlob = null;
86
+ this.deleteRecordingEvent.emit(null);
87
+ }
88
+
89
+ sendMessage(){
90
+ if (this.audioUrl) {
91
+ this.sendRecordingEvent.emit(this.audioBlob);
92
+ this.audioUrl = null;
93
+ }
94
+ }
95
+
96
+ }
@@ -7,7 +7,7 @@
7
7
  <!-- TEXTAREA + ICONS: conv active-->
8
8
  <div class="textarea-container" *ngIf="!hideTextAreaContent && !hideTextReply">
9
9
 
10
- <div class="icons-container">
10
+ <div *ngIf="!isStopRec" class="icons-container">
11
11
  <!-- ICON ATTACHMENT -->
12
12
  <label *ngIf="showAttachmentButton == true" tabindex="1502" aria-label="allegati" for="chat21-file" class="chat21-textarea-button" [class.active]="!isFilePendingToUpload && !hideTextReply" id="chat21-start-upload-doc">
13
13
  <span class="v-align-center">
@@ -44,7 +44,7 @@
44
44
 
45
45
 
46
46
 
47
- <div class="visible-text-area" [class.disabled] = "( isConversationArchived || hideTextReply)? true : null">
47
+ <div *ngIf="!isStopRec" class="visible-text-area" [class.disabled] = "( isConversationArchived || hideTextReply)? true : null">
48
48
  <!-- isFilePendingToUpload || -->
49
49
  <textarea
50
50
  [attr.disabled] = "(hideTextReply)? true : null"
@@ -67,13 +67,24 @@
67
67
  </div>
68
68
 
69
69
  <!-- ICON SEND -->
70
- <div tabindex="-1" class="chat21-textarea-button" [class.active]="textInputTextArea && !hideTextReply" id="chat21-button-send" (click)="onSendPressed($event)">
70
+ <div *ngIf="textInputTextArea && !isStopRec" tabindex="-1" class="chat21-textarea-button" [class.active]="textInputTextArea && !hideTextReply" id="chat21-button-send" (click)="onSendPressed($event)">
71
71
  <span class="v-align-center">
72
72
  <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" height="24" width="24" viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
73
73
  <path d="M1.8,18.9V1.7L22,10.3L1.8,18.9z M3.9,15.6l12.6-5.4L3.9,4.9v3.7l6.4,1.6l-6.4,1.6V15.6z M3.9,15.6V4.9v7V15.6z"/>
74
74
  </svg>
75
75
  </span>
76
76
  </div>
77
+
78
+ <!-- ICON REC -->
79
+ <div *ngIf="!textInputTextArea" tabindex="-1" class="chat21-audio-button" [class.active]="isStopRec" id="chat21-button-rec">
80
+ <chat-audio-recorder
81
+ (startRecordingEvent)="onStartRecording()"
82
+ (deleteRecordingEvent)="onDeleteRecording()"
83
+ (endRecordingEvent)="onEndRecording($event)"
84
+ (sendRecordingEvent)="onSendRecording($event)"
85
+ [stylesMap]="stylesMap">
86
+ </chat-audio-recorder>
87
+ </div>
77
88
  </div>
78
89
 
79
90
 
@@ -7,14 +7,16 @@
7
7
  display: flex;
8
8
  width: 100%;
9
9
  align-items: center;
10
- gap: 10px;
10
+ gap: 0px;
11
11
  justify-content: space-between;
12
12
  }
13
13
 
14
14
  .icons-container{
15
15
  display: flex;
16
16
  align-self: flex-end;
17
- margin-left: 8px
17
+ margin-left: 8px;
18
+ gap: 2px;
19
+ margin-right: 8px;
18
20
  }
19
21
 
20
22
  .visible-text-area {
@@ -31,7 +33,6 @@
31
33
  .chat21-textarea-button {
32
34
  fill: var(--icon-fill-color);
33
35
  pointer-events: auto;
34
-
35
36
  height: var(--chat-footer-height);
36
37
  bottom: 22px;
37
38
  opacity: 0.3;
@@ -185,11 +186,29 @@ textarea:active{
185
186
  }
186
187
 
187
188
  #chat21-button-send {
188
- // right: 8px;
189
- // bottom: 0;
190
189
  display: flex;
191
190
  align-self: flex-end;
192
- margin: 0 8px
191
+ margin: 0 8px;
192
+ width: 34px;
193
+ text-align: center;
194
+ justify-content: center;
195
+ }
196
+
197
+ #chat21-button-rec {
198
+ display: flex;
199
+ width: 34px;
200
+ text-align: center;
201
+ justify-content: center;
202
+ height: var(--chat-footer-height);
203
+ &.active{
204
+ width: 100%;
205
+ }
206
+ chat-audio-recorder {
207
+ width: 100%;
208
+ display: flex;
209
+ align-items: center;
210
+ justify-content: center;
211
+ }
193
212
  }
194
213
 
195
214
  #chat21-file{
@@ -337,7 +356,4 @@ textarea:active{
337
356
  // left: 10px;
338
357
  border: none;
339
358
  margin: -2px -2px 0px;
340
-
341
- }
342
-
343
-
359
+ }