@chat21/chat21-web-widget 5.0.66 → 5.0.68
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.
- package/CHANGELOG.md +8 -0
- package/package.json +1 -1
- package/src/app/app.component.ts +12 -9
- package/src/app/app.module.ts +6 -1
- package/src/app/component/conversation-detail/conversation-content/conversation-content.component.html +10 -0
- package/src/app/component/conversation-detail/conversation-content/conversation-content.component.scss +4 -0
- package/src/app/component/conversation-detail/conversation-emojii/conversation-emojii.component.html +11 -1
- package/src/app/component/conversation-detail/conversation-emojii/conversation-emojii.component.scss +8 -0
- package/src/app/component/conversation-detail/conversation-emojii/conversation-emojii.component.ts +24 -2
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html +6 -5
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +12 -5
- package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.ts +3 -2
- package/src/app/component/message/audio/audio.component.html +20 -0
- package/src/app/component/message/audio/audio.component.scss +122 -0
- package/src/app/component/message/audio/audio.component.spec.ts +23 -0
- package/src/app/component/message/audio/audio.component.ts +123 -0
- package/src/app/component/message/bubble-message/bubble-message.component.html +5 -0
- package/src/app/component/message/bubble-message/bubble-message.component.ts +2 -1
- package/src/app/component/message/carousel/carousel.component.html +29 -0
- package/src/app/component/message/carousel/carousel.component.scss +257 -0
- package/src/app/component/message/carousel/carousel.component.spec.ts +23 -0
- package/src/app/component/message/carousel/carousel.component.ts +111 -0
- package/src/app/providers/global-settings.service.ts +1 -1
- package/src/chat21-core/providers/firebase/firebase-conversation-handler.ts +53 -48
- package/src/chat21-core/providers/mqtt/mqtt-conversation-handler.ts +61 -54
- package/src/chat21-core/utils/utils-message.ts +14 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# chat21-web-widget ver 5.0
|
|
2
2
|
|
|
3
|
+
### 5.0.68 in PROD
|
|
4
|
+
- bug-fixed: metadata.includes is not a function at isAudio function
|
|
5
|
+
|
|
6
|
+
### 5.0.67 in PROD
|
|
7
|
+
- bug-fixed: when refresh the page and an already open conversation is selected, footer is blocked
|
|
8
|
+
- bug-fix: pdf preview image is not contained into its container
|
|
9
|
+
- bug-fixed: cannot push isHere() for presence management if user is disconnected and a notification is received
|
|
10
|
+
|
|
3
11
|
### 5.0.66 in PROD
|
|
4
12
|
- added: LWT e imHere() for presence management
|
|
5
13
|
|
package/package.json
CHANGED
package/src/app/app.component.ts
CHANGED
|
@@ -432,7 +432,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
432
432
|
|
|
433
433
|
const subUserLogOut = this.messagingAuthService.BSSignOut.subscribe((state) => {
|
|
434
434
|
// that.ngZone.run(() => {
|
|
435
|
-
|
|
435
|
+
this.logger.log('[FORCE] messagingAuthService BSSignOut', state, this.forceDisconnect)
|
|
436
436
|
if (state === true && !this.forceDisconnect) { //state = true -> user has logged out
|
|
437
437
|
/** ho effettuato il logout: nascondo il widget */
|
|
438
438
|
that.logger.debug('[APP-COMP] sono nel caso logout -1');
|
|
@@ -1507,7 +1507,9 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
1507
1507
|
// this.g.windowContext.window.document.title = this.tabTitle
|
|
1508
1508
|
} else {
|
|
1509
1509
|
// TAB IS ACTIVE --> restore title and DO NOT SOUND
|
|
1510
|
-
this.
|
|
1510
|
+
if(!this.forceDisconnect){
|
|
1511
|
+
this.presenceService.imHere()
|
|
1512
|
+
}
|
|
1511
1513
|
clearInterval(this.setIntervalTime)
|
|
1512
1514
|
this.setIntervalTime = null;
|
|
1513
1515
|
this.isTabVisible = true;
|
|
@@ -1587,7 +1589,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
1587
1589
|
this.logger.debug('[APP-COMP] openCloseWidget', recipientId, this.g.isOpen, this.g.startFromHome);
|
|
1588
1590
|
if (this.g.isOpen === false) {
|
|
1589
1591
|
if(this.forceDisconnect){
|
|
1590
|
-
|
|
1592
|
+
this.logger.log('[FORCE] onOpenCloseWidget --> reconnect', this.forceDisconnect)
|
|
1591
1593
|
this.messagingAuthService.createCustomToken(this.g.tiledeskToken)
|
|
1592
1594
|
this.forceDisconnect = false;
|
|
1593
1595
|
}
|
|
@@ -1729,7 +1731,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
1729
1731
|
if (this.g.isOpen === false) {
|
|
1730
1732
|
|
|
1731
1733
|
if(this.forceDisconnect){
|
|
1732
|
-
|
|
1734
|
+
this.logger.log('[FORCE] onSelectedConversation --> reconnect', this.forceDisconnect)
|
|
1733
1735
|
this.messagingAuthService.createCustomToken(this.g.tiledeskToken)
|
|
1734
1736
|
this.forceDisconnect = false;
|
|
1735
1737
|
}
|
|
@@ -2095,14 +2097,15 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
|
2095
2097
|
|
|
2096
2098
|
|
|
2097
2099
|
private listenToWidgetClick(){
|
|
2100
|
+
const that = this
|
|
2098
2101
|
let clickTimeout = setTimeout(() => {
|
|
2099
|
-
|
|
2102
|
+
that.logger.log('[FORCE] --> NO INTERACTION: disconnection... <--- ')
|
|
2100
2103
|
//disconnect
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
},
|
|
2104
|
+
that.forceDisconnect = true
|
|
2105
|
+
that.messagingAuthService.logout()
|
|
2106
|
+
}, that.g.disconnetTime * 1000);
|
|
2104
2107
|
window.addEventListener("click", function(){
|
|
2105
|
-
|
|
2108
|
+
that.logger.log('[FORCE] <<INTERACTION>> within 1 minute')
|
|
2106
2109
|
clearTimeout(clickTimeout)
|
|
2107
2110
|
})
|
|
2108
2111
|
}
|
package/src/app/app.module.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { ImageComponent } from './component/message/image/image.component';
|
|
|
23
23
|
import { InfoMessageComponent } from './component/message/info-message/info-message.component';
|
|
24
24
|
import { HtmlComponent } from './component/message/html/html.component';
|
|
25
25
|
import { FrameComponent } from './component/message/frame/frame.component';
|
|
26
|
+
import { AudioComponent } from './component/message/audio/audio.component';
|
|
26
27
|
import { UserTypingComponent } from './../chat21-core/utils/user-typing/user-typing.component';
|
|
27
28
|
/** MESSAGE ATTACHMENTS COMPONENTS */
|
|
28
29
|
import { MessageAttachmentComponent } from './component/message-attachment/message-attachment.component';
|
|
@@ -130,6 +131,8 @@ import { StarRatingWidgetService } from './providers/star-rating-widget.service'
|
|
|
130
131
|
import { LikeUnlikeComponent } from './component/message/like-unlike/like-unlike.component';
|
|
131
132
|
import { Rules } from './utils/rules';
|
|
132
133
|
import { ScriptService } from 'src/chat21-core/providers/scripts/script.service';
|
|
134
|
+
import { CarouselComponent } from './component/message/carousel/carousel.component';
|
|
135
|
+
|
|
133
136
|
|
|
134
137
|
|
|
135
138
|
const appInitializerFn = (appConfig: AppConfigService, logger: NGXLogger) => {
|
|
@@ -287,7 +290,9 @@ export function uploadFactory(http: HttpClient, appConfig: AppConfigService, app
|
|
|
287
290
|
DateAgoPipe,
|
|
288
291
|
SafeHtmlPipe,
|
|
289
292
|
LikeUnlikeComponent,
|
|
290
|
-
TooltipDirective
|
|
293
|
+
TooltipDirective,
|
|
294
|
+
AudioComponent,
|
|
295
|
+
CarouselComponent
|
|
291
296
|
],
|
|
292
297
|
imports: [
|
|
293
298
|
BrowserModule,
|
|
@@ -107,6 +107,16 @@
|
|
|
107
107
|
(onAttachmentButtonClicked)="onAttachmentButtonClickedFN($event)">
|
|
108
108
|
</chat-message-attachment>
|
|
109
109
|
</div>
|
|
110
|
+
|
|
111
|
+
<!-- carousel -->
|
|
112
|
+
<!-- <div *ngIf="message?.attributes && message?.attributes?.attachment && message?.attributes?.attachment?.gallery" [ngClass]="{'slide-in-left': false}" class="carousel_container">
|
|
113
|
+
<chat-carousel class="carousel_container"
|
|
114
|
+
[message]="message"
|
|
115
|
+
[stylesMap]="stylesMap"
|
|
116
|
+
(onElementRendered)="onElementRenderedFN($event)"
|
|
117
|
+
(onAttachmentButtonClicked)="onAttachmentButtonClickedFN($event)">
|
|
118
|
+
</chat-carousel>
|
|
119
|
+
</div> -->
|
|
110
120
|
|
|
111
121
|
</div>
|
|
112
122
|
|
package/src/app/component/conversation-detail/conversation-emojii/conversation-emojii.component.html
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
-
<
|
|
1
|
+
<emoji-mart id="emoji-mart"
|
|
2
|
+
class="emoji-mart"
|
|
3
|
+
[showPreview]="emojiiOptions?.showPreview"
|
|
4
|
+
[color]="stylesMap?.get('themeColor')"
|
|
5
|
+
[perLine]="emojiiOptions?.emojiPerLine"
|
|
6
|
+
[totalFrequentLines]="emojiiOptions?.totalFrequentLines"
|
|
7
|
+
[enableSearch]="emojiiOptions?.enableSearch"
|
|
8
|
+
[darkMode]="emojiiOptions?.darkMode"
|
|
9
|
+
[include]="emojiiOptions?.include"
|
|
10
|
+
(emojiSelect)="addEmojiFN($event)">
|
|
11
|
+
</emoji-mart>
|
package/src/app/component/conversation-detail/conversation-emojii/conversation-emojii.component.ts
CHANGED
|
@@ -1,10 +1,32 @@
|
|
|
1
|
-
import { Component } from '@angular/core';
|
|
1
|
+
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
|
|
2
2
|
|
|
3
3
|
@Component({
|
|
4
4
|
selector: 'chat-conversation-emojii',
|
|
5
5
|
templateUrl: './conversation-emojii.component.html',
|
|
6
6
|
styleUrls: ['./conversation-emojii.component.scss']
|
|
7
7
|
})
|
|
8
|
-
export class ConversationEmojiiComponent {
|
|
8
|
+
export class ConversationEmojiiComponent implements OnInit {
|
|
9
|
+
|
|
10
|
+
@Input() var: string;
|
|
11
|
+
@Output() addEmoji = new EventEmitter();
|
|
12
|
+
|
|
13
|
+
emojiiOptions = {
|
|
14
|
+
emojiPerLine : 9,
|
|
15
|
+
totalFrequentLines: 1,
|
|
16
|
+
showPreview: false,
|
|
17
|
+
darkMode: false,
|
|
18
|
+
enableSearch: false,
|
|
19
|
+
include: [ 'recent', 'people', 'nature', 'activity', 'flags']
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
constructor(){}
|
|
23
|
+
|
|
24
|
+
ngOnInit(): void {
|
|
25
|
+
console.log('varrrrr', this.var)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
addEmojiFN(event){
|
|
29
|
+
this.addEmoji.emit(event)
|
|
30
|
+
}
|
|
9
31
|
|
|
10
32
|
}
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.html
CHANGED
|
@@ -31,11 +31,11 @@
|
|
|
31
31
|
<!-- ICON EMOJII -->
|
|
32
32
|
<label tabindex="1504" aria-label="emojii" for="chat21-emojii" class="chat21-textarea-button" [class.active]="!isFilePendingToUpload && !hideTextReply" id="chat21-emoticon-picker" (click)="onEmojiiPickerClicked()">
|
|
33
33
|
<span class="v-align-center">
|
|
34
|
-
<svg xmlns="http://www.w3.org/2000/svg"
|
|
35
|
-
<path d="M0
|
|
36
|
-
<circle cx="15.
|
|
37
|
-
<circle cx="
|
|
38
|
-
<path d="M12
|
|
34
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24">
|
|
35
|
+
<path d="M0,0H20.57V20.57H0V0Z" fill="none"/>
|
|
36
|
+
<circle cx="15.02" cy="9.86" r="1.29"/>
|
|
37
|
+
<circle cx="9.02" cy="9.86" r="1.29"/>
|
|
38
|
+
<path d="M12.02,15.43c-1.27,0-2.36-.69-2.96-1.71h-1.43c.69,1.76,2.39,3,4.39,3s3.7-1.24,4.39-3h-1.43c-.6,1.02-1.69,1.71-2.96,1.71Zm0-12C7.28,3.43,3.45,7.27,3.45,12s3.83,8.57,8.56,8.57,8.58-3.84,8.58-8.57S16.75,3.43,12.01,3.43Zm0,15.43c-3.79,0-6.86-3.07-6.86-6.86s3.07-6.86,6.86-6.86,6.86,3.07,6.86,6.86-3.07,6.86-6.86,6.86Z"/>
|
|
39
39
|
</svg>
|
|
40
40
|
</span>
|
|
41
41
|
</label>
|
|
@@ -79,6 +79,7 @@
|
|
|
79
79
|
|
|
80
80
|
<!-- EMOJII PICKER-->
|
|
81
81
|
<div [style.visibility]="isEmojiiPickerShow?'visible':'hidden'" class="emoji-container" id="emoji-mart-container" #emoji_mart_container>
|
|
82
|
+
<!-- <ng-container #emojii_container></ng-container> -->
|
|
82
83
|
<emoji-mart id="emoji-mart"
|
|
83
84
|
*ngIf="showEmojiPicker"
|
|
84
85
|
class="emoji-mart"
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts
CHANGED
|
@@ -48,6 +48,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
48
48
|
@Output() onBackButton = new EventEmitter()
|
|
49
49
|
|
|
50
50
|
@ViewChild('chat21_file') public chat21_file: ElementRef;
|
|
51
|
+
// @ViewChild('emojii_container', {read: ViewContainerRef}) selector;
|
|
51
52
|
@ViewChild('emoji_mart_container', {read: ViewContainerRef}) public divEmojiiContainer: ViewContainerRef;
|
|
52
53
|
// ========= begin:: send image ======= //
|
|
53
54
|
selectedFiles: FileList;
|
|
@@ -454,12 +455,18 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
|
|
|
454
455
|
async onEmojiiPickerClicked(){
|
|
455
456
|
// if(this.loadPickerModule){
|
|
456
457
|
// this.loadPickerModule = false;
|
|
457
|
-
//
|
|
458
|
+
// // this.divEmojiiContainer.clear();
|
|
459
|
+
// this.vcref.clear();
|
|
460
|
+
// const { PickerModule } = await import("@ctrl/ngx-emoji-mart");
|
|
458
461
|
// import('../conversation-emojii/conversation-emojii.component').then(({ConversationEmojiiComponent})=> {
|
|
459
|
-
// this.divEmojiiContainer.
|
|
460
|
-
//
|
|
461
|
-
// this.divEmojiiContainer.
|
|
462
|
-
// this.divEmojiiContainer.
|
|
462
|
+
// // const instance = this.divEmojiiContainer.createComponent(ConversationEmojiiComponent);
|
|
463
|
+
// // // this.divEmojiiContainer.createEmbeddedView(instance.hostView)
|
|
464
|
+
// // this.divEmojiiContainer.insert(instance.hostView);
|
|
465
|
+
// // this.divEmojiiContainer = this.selector.createComponent(ConversationEmojiiComponent);
|
|
466
|
+
// let greetcomp = this.vcref.createComponent(
|
|
467
|
+
// this.cfr.resolveComponentFactory(ConversationEmojiiComponent)
|
|
468
|
+
// );
|
|
469
|
+
// greetcomp.instance.var = 'ssssss'
|
|
463
470
|
// });
|
|
464
471
|
// // this.divEmojiiContainer.nativeElement.insertAdjacentHTML('afterbegin', '<emoji-mart id="emoji-mart"' +
|
|
465
472
|
// // // '*ngIf="showEmojiPicker"'+
|
package/src/app/component/conversation-detail/conversation-preview/conversation-preview.component.ts
CHANGED
|
@@ -148,8 +148,8 @@ export class ConversationPreviewComponent implements OnInit {
|
|
|
148
148
|
const metadata = {
|
|
149
149
|
'name': imageXLoad.title,
|
|
150
150
|
'src': that.sanitizer.bypassSecurityTrustUrl(imageXLoad.src),
|
|
151
|
-
'width':
|
|
152
|
-
'height':
|
|
151
|
+
'width': '80px',
|
|
152
|
+
'height': '106px',
|
|
153
153
|
'type': attachment.metadata.type,
|
|
154
154
|
'uid': attachment.metadata.uid
|
|
155
155
|
};
|
|
@@ -158,6 +158,7 @@ export class ConversationPreviewComponent implements OnInit {
|
|
|
158
158
|
that.arrayFiles.push({metadata});
|
|
159
159
|
if (!that.fileSelected) {
|
|
160
160
|
that.fileSelected = Object.assign({}, metadata)
|
|
161
|
+
that.fileSelected = Object.assign(that.fileSelected, that.getMetadataSize(that.fileSelected))
|
|
161
162
|
}
|
|
162
163
|
};
|
|
163
164
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
<div id="audio_container" #audio_container>
|
|
4
|
+
|
|
5
|
+
<audio aria-label="traccia audio" #audio_msg controls controlsList="nodownload" id="audio_msg" (pause)="pauseAudioMsg($event)" (play)="playAudioMsg($event)" (timeupdate)="updateTimeAudioMsg($event)">
|
|
6
|
+
<source [src]="metadata?.src" [type]="metadata?.type">
|
|
7
|
+
<!-- {{metadata?.src}} -->
|
|
8
|
+
<!-- controlsList="nodownload" -->
|
|
9
|
+
</audio>
|
|
10
|
+
|
|
11
|
+
<!-- <button id="play-icon" (click)="onPlayPause('play')" *ngIf="status === 'play'">
|
|
12
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M10 8.64L15.27 12 10 15.36V8.64M8 5v14l11-7L8 5z"/></svg>
|
|
13
|
+
</button>
|
|
14
|
+
<button id="pause-icon" (click)="onPlayPause('pause')" *ngIf="status === 'pause'">
|
|
15
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"/></svg>
|
|
16
|
+
</button>
|
|
17
|
+
<div id="duration" #duration>0:00</div>
|
|
18
|
+
<input type="range" id="seek-slider" max="100" value="0"> -->
|
|
19
|
+
</div>
|
|
20
|
+
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#audio_container{
|
|
2
|
+
display: flex;
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
#play-icon,
|
|
6
|
+
#pause-icon {
|
|
7
|
+
margin: 20px 2.5% 10px 2.5%;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.time {
|
|
11
|
+
display: inline-block;
|
|
12
|
+
width: 37px;
|
|
13
|
+
text-align: center;
|
|
14
|
+
font-size: 20px;
|
|
15
|
+
margin: 28.5px 0 18.5px 0;
|
|
16
|
+
float: left;
|
|
17
|
+
}
|
|
18
|
+
output {
|
|
19
|
+
display: inline-block;
|
|
20
|
+
width: 32px;
|
|
21
|
+
text-align: center;
|
|
22
|
+
font-size: 20px;
|
|
23
|
+
margin: 10px 2.5% 0 5%;
|
|
24
|
+
float: left;
|
|
25
|
+
clear: left;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
input[type="range"] {
|
|
29
|
+
position: relative;
|
|
30
|
+
-webkit-appearance: none;
|
|
31
|
+
width: 48%;
|
|
32
|
+
margin: 0;
|
|
33
|
+
padding: 0;
|
|
34
|
+
height: 19px;
|
|
35
|
+
margin: 30px 2.5% 20px 2.5%;
|
|
36
|
+
float: left;
|
|
37
|
+
outline: none;
|
|
38
|
+
}
|
|
39
|
+
input[type="range"]::-webkit-slider-runnable-track {
|
|
40
|
+
width: 100%;
|
|
41
|
+
height: 3px;
|
|
42
|
+
cursor: pointer;
|
|
43
|
+
background: linear-gradient(to right, rgba(0, 125, 181, 0.6) var(--buffered-width), rgba(0, 125, 181, 0.2) var(--buffered-width));
|
|
44
|
+
}
|
|
45
|
+
input[type="range"]::before {
|
|
46
|
+
position: absolute;
|
|
47
|
+
content: "";
|
|
48
|
+
top: 8px;
|
|
49
|
+
left: 0;
|
|
50
|
+
width: var(--seek-before-width);
|
|
51
|
+
height: 3px;
|
|
52
|
+
background-color: #007db5;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
}
|
|
55
|
+
input[type="range"]::-webkit-slider-thumb {
|
|
56
|
+
position: relative;
|
|
57
|
+
-webkit-appearance: none;
|
|
58
|
+
box-sizing: content-box;
|
|
59
|
+
border: 1px solid #007db5;
|
|
60
|
+
height: 15px;
|
|
61
|
+
width: 15px;
|
|
62
|
+
border-radius: 50%;
|
|
63
|
+
background-color: #fff;
|
|
64
|
+
cursor: pointer;
|
|
65
|
+
margin: -7px 0 0 0;
|
|
66
|
+
}
|
|
67
|
+
input[type="range"]:active::-webkit-slider-thumb {
|
|
68
|
+
transform: scale(1.2);
|
|
69
|
+
background: #007db5;
|
|
70
|
+
}
|
|
71
|
+
input[type="range"]::-moz-range-track {
|
|
72
|
+
width: 100%;
|
|
73
|
+
height: 3px;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
background: linear-gradient(to right, rgba(0, 125, 181, 0.6) var(--buffered-width), rgba(0, 125, 181, 0.2) var(--buffered-width));
|
|
76
|
+
}
|
|
77
|
+
input[type="range"]::-moz-range-progress {
|
|
78
|
+
background-color: #007db5;
|
|
79
|
+
}
|
|
80
|
+
input[type="range"]::-moz-focus-outer {
|
|
81
|
+
border: 0;
|
|
82
|
+
}
|
|
83
|
+
input[type="range"]::-moz-range-thumb {
|
|
84
|
+
box-sizing: content-box;
|
|
85
|
+
border: 1px solid #007db5;
|
|
86
|
+
height: 15px;
|
|
87
|
+
width: 15px;
|
|
88
|
+
border-radius: 50%;
|
|
89
|
+
background-color: #fff;
|
|
90
|
+
cursor: pointer;
|
|
91
|
+
}
|
|
92
|
+
input[type="range"]:active::-moz-range-thumb {
|
|
93
|
+
transform: scale(1.2);
|
|
94
|
+
background: #007db5;
|
|
95
|
+
}
|
|
96
|
+
input[type="range"]::-ms-track {
|
|
97
|
+
width: 100%;
|
|
98
|
+
height: 3px;
|
|
99
|
+
cursor: pointer;
|
|
100
|
+
background: transparent;
|
|
101
|
+
border: solid transparent;
|
|
102
|
+
color: transparent;
|
|
103
|
+
}
|
|
104
|
+
input[type="range"]::-ms-fill-lower {
|
|
105
|
+
background-color: #007db5;
|
|
106
|
+
}
|
|
107
|
+
input[type="range"]::-ms-fill-upper {
|
|
108
|
+
background: linear-gradient(to right, rgba(0, 125, 181, 0.6) var(--buffered-width), rgba(0, 125, 181, 0.2) var(--buffered-width));
|
|
109
|
+
}
|
|
110
|
+
input[type="range"]::-ms-thumb {
|
|
111
|
+
box-sizing: content-box;
|
|
112
|
+
border: 1px solid #007db5;
|
|
113
|
+
height: 15px;
|
|
114
|
+
width: 15px;
|
|
115
|
+
border-radius: 50%;
|
|
116
|
+
background-color: #fff;
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
}
|
|
119
|
+
input[type="range"]:active::-ms-thumb {
|
|
120
|
+
transform: scale(1.2);
|
|
121
|
+
background: #007db5;
|
|
122
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
|
2
|
+
|
|
3
|
+
import { AudioComponent } from './audio.component';
|
|
4
|
+
|
|
5
|
+
describe('AudioComponent', () => {
|
|
6
|
+
let component: AudioComponent;
|
|
7
|
+
let fixture: ComponentFixture<AudioComponent>;
|
|
8
|
+
|
|
9
|
+
beforeEach(async () => {
|
|
10
|
+
await TestBed.configureTestingModule({
|
|
11
|
+
declarations: [ AudioComponent ]
|
|
12
|
+
})
|
|
13
|
+
.compileComponents();
|
|
14
|
+
|
|
15
|
+
fixture = TestBed.createComponent(AudioComponent);
|
|
16
|
+
component = fixture.componentInstance;
|
|
17
|
+
fixture.detectChanges();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('should create', () => {
|
|
21
|
+
expect(component).toBeTruthy();
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild } from '@angular/core';
|
|
2
|
+
// import lottieWeb from 'https://cdn.skypack.dev/lottie-web';
|
|
3
|
+
|
|
4
|
+
@Component({
|
|
5
|
+
selector: 'chat-audio',
|
|
6
|
+
templateUrl: './audio.component.html',
|
|
7
|
+
styleUrls: ['./audio.component.scss']
|
|
8
|
+
})
|
|
9
|
+
export class AudioComponent implements OnInit {
|
|
10
|
+
|
|
11
|
+
@Input() metadata: any;
|
|
12
|
+
@Output() onElementRendered = new EventEmitter<{element: string, status: boolean}>();
|
|
13
|
+
|
|
14
|
+
uidAudioPlayng: string = ''
|
|
15
|
+
divPlay: HTMLAudioElement
|
|
16
|
+
playState: HTMLElement
|
|
17
|
+
status: 'play' | 'pause' = 'play'
|
|
18
|
+
|
|
19
|
+
constructor(private elementRef: ElementRef) { }
|
|
20
|
+
|
|
21
|
+
ngOnInit() {
|
|
22
|
+
// console.log('metadataaaaaa', this.metadata)
|
|
23
|
+
// this.divPlay = this.elementRef.nativeElement.querySelector('#audio_container').querySelector('#audio_msg')
|
|
24
|
+
// this.playState= this.elementRef.nativeElement.querySelector('#audio_container').querySelector('#duration')
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
onPlayPause(status: string){
|
|
28
|
+
// const divPlay = (<HTMLAudioElement>document.getElementById('audio_msg'));
|
|
29
|
+
if(status === 'play') {
|
|
30
|
+
this.divPlay.play();
|
|
31
|
+
this.status = 'pause'
|
|
32
|
+
} else {
|
|
33
|
+
this.divPlay.pause();
|
|
34
|
+
this.status = 'play'
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
pauseAudioMsg(e) {
|
|
39
|
+
try {
|
|
40
|
+
// stop all audio
|
|
41
|
+
if (this.uidAudioPlayng) {
|
|
42
|
+
const divPlay = (<HTMLAudioElement>document.getElementById(this.uidAudioPlayng));
|
|
43
|
+
divPlay.pause();
|
|
44
|
+
// console.log('> pausa: ', divPlay);
|
|
45
|
+
}
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.log('> Error is: ', error);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
// console.log(e.target.id);
|
|
52
|
+
if (this.uidAudioPlayng) {
|
|
53
|
+
this.uidAudioPlayng = '';
|
|
54
|
+
}
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.log('> Error is: ', error);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
playAudioMsg(e) {
|
|
61
|
+
// stop all audio
|
|
62
|
+
if (this.uidAudioPlayng) {
|
|
63
|
+
const divPlay = (<HTMLAudioElement>document.getElementById(this.uidAudioPlayng));
|
|
64
|
+
divPlay.pause();
|
|
65
|
+
// console.log('> pausa: ', divPlay);
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
// console.log(e.target.id);
|
|
69
|
+
// set uid audio playng
|
|
70
|
+
this.uidAudioPlayng = e.target.id;
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.log('> Error is: ', error);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
updateTimeAudioMsg(ev){
|
|
77
|
+
var currTime = Math.floor(ev.target.currentTime);
|
|
78
|
+
var duration = Math.floor(ev.target.duration);
|
|
79
|
+
|
|
80
|
+
let minutes = 0;
|
|
81
|
+
if(currTime > 60){
|
|
82
|
+
minutes = Math.floor(currTime / 60);
|
|
83
|
+
}
|
|
84
|
+
const seconds = currTime - minutes * 60
|
|
85
|
+
// console.log('timeeee', minutes + ':' + seconds )
|
|
86
|
+
// this.playState.innerHTML = minutes + ':' + seconds
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
*
|
|
93
|
+
* @param uid
|
|
94
|
+
*/
|
|
95
|
+
playPausaAudioMsg(uid: string) {
|
|
96
|
+
// console.log('playPausaAudioMsg: ', uid);
|
|
97
|
+
const that = this;
|
|
98
|
+
try {
|
|
99
|
+
const divPause = (<HTMLAudioElement>document.getElementById(that.uidAudioPlayng));
|
|
100
|
+
const divPlay = (<HTMLAudioElement>document.getElementById(uid));
|
|
101
|
+
if (divPause) {
|
|
102
|
+
divPause.pause();
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (that.uidAudioPlayng === uid) {
|
|
106
|
+
that.uidAudioPlayng = '';
|
|
107
|
+
} else {
|
|
108
|
+
if (divPlay) {
|
|
109
|
+
setTimeout(function() {
|
|
110
|
+
// if (that.g.autoplay_activated) {
|
|
111
|
+
// divPlay.play();
|
|
112
|
+
// }
|
|
113
|
+
this.uidAudioPlayng = uid;
|
|
114
|
+
}, 300);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
} catch (error) {
|
|
119
|
+
console.log('> Error is: ', error);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
}
|
|
@@ -36,6 +36,11 @@
|
|
|
36
36
|
(onElementRendered)="onElementRenderedFN($event)">
|
|
37
37
|
</chat-frame>
|
|
38
38
|
|
|
39
|
+
<chat-audio *ngIf="isAudio(message)"
|
|
40
|
+
[metadata]="message.metadata"
|
|
41
|
+
(onElementRendered)="onElementRenderedFN($event)">
|
|
42
|
+
</chat-audio>
|
|
43
|
+
|
|
39
44
|
<!-- <chat-frame *ngIf="message.metadata && message.metadata.type && message.metadata.type.includes('video')"
|
|
40
45
|
[metadata]="message.metadata"
|
|
41
46
|
[width]="message.metadata.width"
|
|
@@ -5,7 +5,7 @@ import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service
|
|
|
5
5
|
import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
|
|
6
6
|
import { MAX_WIDTH_IMAGES, MESSAGE_TYPE_MINE, MESSAGE_TYPE_OTHERS, MIN_WIDTH_IMAGES } from 'src/chat21-core/utils/constants';
|
|
7
7
|
import { convertColorToRGBA } from 'src/chat21-core/utils/utils';
|
|
8
|
-
import { isFile, isFrame, isImage, messageType } from 'src/chat21-core/utils/utils-message';
|
|
8
|
+
import { isAudio, isFile, isFrame, isImage, messageType } from 'src/chat21-core/utils/utils-message';
|
|
9
9
|
import { getColorBck } from 'src/chat21-core/utils/utils-user';
|
|
10
10
|
|
|
11
11
|
@Component({
|
|
@@ -27,6 +27,7 @@ export class BubbleMessageComponent implements OnInit {
|
|
|
27
27
|
isImage = isImage;
|
|
28
28
|
isFile = isFile;
|
|
29
29
|
isFrame = isFrame;
|
|
30
|
+
isAudio = isAudio;
|
|
30
31
|
convertColorToRGBA = convertColorToRGBA
|
|
31
32
|
|
|
32
33
|
// ========== begin:: check message type functions ======= //
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<div class="wrapper">
|
|
2
|
+
<div id="left" class="arrow" (click)="goTo('previous')" >
|
|
3
|
+
<!-- *ngIf="activeElement > 1" -->
|
|
4
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
|
|
5
|
+
<path d="M0 0h24v24H0V0z" fill="none"/><path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12l4.58-4.59z"/>
|
|
6
|
+
</svg>
|
|
7
|
+
</div>
|
|
8
|
+
<div class="carousel">
|
|
9
|
+
<div class="card" *ngFor="let card of gallery">
|
|
10
|
+
<div class="card-image">
|
|
11
|
+
<img [src]="card?.preview?.src" alt="img" draggable="false">
|
|
12
|
+
</div>
|
|
13
|
+
<div class="card-content">
|
|
14
|
+
<div class="card-title">{{card?.title}}</div>
|
|
15
|
+
<div class="card-description">{{card?.description}}</div>
|
|
16
|
+
</div>
|
|
17
|
+
<div class="buttons" *ngIf="card?.buttons && card?.buttons.length > 0">
|
|
18
|
+
<div class="single-button action" *ngFor="let button of card?.buttons">
|
|
19
|
+
<div>{{button.value}}</div>
|
|
20
|
+
</div>
|
|
21
|
+
</div>
|
|
22
|
+
</div>
|
|
23
|
+
</div>
|
|
24
|
+
<div id="right" class="arrow" (click)="goTo('next')" *ngIf="activeElement !== gallery.length">
|
|
25
|
+
<svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 0 24 24" width="24px" fill="#000000">
|
|
26
|
+
<path d="M0 0h24v24H0V0z" fill="none"/><path d="M10.02 6L8.61 7.41 13.19 12l-4.58 4.59L10.02 18l6-6-6-6z"/>
|
|
27
|
+
</svg>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|