@chat21/chat21-web-widget 5.1.0-rc5 → 5.1.0-rc7

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 CHANGED
@@ -6,6 +6,12 @@
6
6
  ### **Copyrigth**:
7
7
  *Tiledesk SRL*
8
8
 
9
+ # 5.1.0-rc.7
10
+ - **added**: ability to allows emoji after message is sent
11
+
12
+ # 5.1.0-rc.6
13
+ - **removed**: hideRestartConversationOptionsMenu
14
+
9
15
  # 5.1.0-rc.5
10
16
  # 5.1.0-rc.4
11
17
  - **bug-fixed**: Dockerfile for angular 18
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:18.19.1-alpine3.18 as builder
4
+ FROM node:20.12.2-alpine3.19 as builder
5
5
 
6
6
  COPY package.json package-lock.json ./
7
7
 
@@ -15,7 +15,7 @@ COPY . .
15
15
 
16
16
  ## Build the angular app in production mode and store the artifacts in dist folder
17
17
 
18
- RUN npm run ng build -- --configuration="prod" --output-path=dist --base-href="./" --output-hashing=none
18
+ RUN npx ng build --configuration="prod" --output-path=dist --base-href=./ --output-hashing=none
19
19
 
20
20
 
21
21
  ### STAGE 2: Setup ###
package/deploy_beta.sh CHANGED
@@ -1,7 +1,8 @@
1
1
  # npm version prerelease --preid=beta
2
2
  version=`node -e 'console.log(require("./package.json").version)'`
3
3
  echo "version $version"
4
-
4
+ echo "____________WIDGET-V5______________"
5
+ echo "CREATING TAG ON GIT FOR version: $version"
5
6
 
6
7
  # Get curent branch name
7
8
  current_branch=$(git rev-parse --abbrev-ref HEAD)
package/deploy_prod.sh CHANGED
@@ -1,8 +1,8 @@
1
- # npm version patch
1
+ # npm version prerelease --preid=beta
2
2
  version=`node -e 'console.log(require("./package.json").version)'`
3
- ECHO "____________WIDGET-V5______________"
3
+ echo "version $version"
4
+ echo "____________WIDGET-V5______________"
4
5
  echo "CREATING TAG ON GIT FOR version: $version"
5
- # echo "version $version"
6
6
 
7
7
  # Get curent branch name
8
8
  current_branch=$(git rev-parse --abbrev-ref HEAD)
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.0-rc5",
4
+ "version": "5.1.0-rc7",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -15,7 +15,6 @@
15
15
  [hideHeaderCloseButton]="g?.hideHeaderCloseButton"
16
16
  [hideHeaderBackButton]="g?.singleConversation"
17
17
  [hideCloseConversationOptionMenu]="(isConversationArchived || g?.hideCloseConversationOptionMenu)"
18
- [hideRestartConversationOptionsMenu]="(isConversationArchived || (!g?.singleConversation && !hideTextAreaContent) || g?.hideRestartConversationOptionsMenu)"
19
18
  [hideHeaderConversationOptionsMenu]="g?.hideHeaderConversationOptionsMenu"
20
19
  [hideSignOutOptionMenu]="(!g?.singleConversation || !g?.showLogoutOption)"
21
20
  [hideChatDetailOptionMenu]="(!g?.isDevMode)"
@@ -113,7 +112,7 @@
113
112
  [attributes]="g?.attributes"
114
113
  [senderId]="senderId"
115
114
  [tenant]="g?.tenant"
116
- [projectid]="g?.projectid"
115
+ [project]="g?.project"
117
116
  [channelType]="g?.channelType"
118
117
  [userFullname]="g?.userFullname"
119
118
  [userEmail]="g?.userEmail"
@@ -11,7 +11,8 @@ import { ChatManager } from 'src/chat21-core/providers/chat-manager';
11
11
  import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
12
12
  import { TYPE_MSG_FILE, TYPE_MSG_IMAGE, TYPE_MSG_TEXT } from 'src/chat21-core/utils/constants';
13
13
  import { convertColorToRGBA } from 'src/chat21-core/utils/utils';
14
- import { isImage } from 'src/chat21-core/utils/utils-message';
14
+ import { findAndRemoveEmoji, isImage } from 'src/chat21-core/utils/utils-message';
15
+ import { ProjectModel } from 'src/models/project';
15
16
 
16
17
  @Component({
17
18
  selector: 'chat-conversation-footer',
@@ -24,7 +25,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
24
25
  @Input() attributes: string;
25
26
  @Input() senderId: string;
26
27
  @Input() tenant: string;
27
- @Input() projectid: string;
28
+ @Input() project: ProjectModel;
28
29
  @Input() channelType: string;
29
30
  @Input() userFullname: string;
30
31
  @Input() userEmail: string;
@@ -83,8 +84,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
83
84
 
84
85
  convertColorToRGBA = convertColorToRGBA;
85
86
  private logger: LoggerService = LoggerInstance.getInstance()
86
- constructor(public g: Globals,
87
- private chatManager: ChatManager,
87
+ constructor(private chatManager: ChatManager,
88
88
  private typingService: TypingService,
89
89
  private uploadService: UploadService) { }
90
90
 
@@ -253,7 +253,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
253
253
  // return snapshot.ref.getDownloadURL(); // Will return a promise with the download link
254
254
  // }).then(downloadURL => {
255
255
  // that.logger.log('[CONV-FOOTER] AppComponent::uploadSingle:: downloadURL', downloadURL]);
256
- // that.g.wdLog([`Successfully uploaded file and got download link - ${downloadURL}`]);
257
256
 
258
257
  // metadata.src = downloadURL;
259
258
  // let type_message = TYPE_MSG_TEXT;
@@ -321,6 +320,8 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
321
320
  (metadata) ? metadata = metadata : metadata = '';
322
321
  this.onEmojiiPickerShow.emit(false)
323
322
  this.logger.log('[CONV-FOOTER] SEND MESSAGE: ', msg, type, metadata, additional_attributes);
323
+
324
+ msg = this.checkForEmojii(msg)
324
325
  if (msg && msg.trim() !== '' || type === TYPE_MSG_IMAGE || type === TYPE_MSG_FILE ) {
325
326
 
326
327
  // msg = htmlEntities(msg);
@@ -345,7 +346,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
345
346
  // fine-sponziello
346
347
  // this.conversationHandlerService = this.chatManager.getConversationHandlerByConversationId(this.conversationWith)
347
348
  const senderId = this.senderId;
348
- const projectid = this.projectid;
349
+ const projectid = this.project.id;
349
350
  const channelType = this.channelType;
350
351
  const userFullname = this.userFullname;
351
352
  const userEmail = this.userEmail;
@@ -514,6 +515,15 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
514
515
  //}, false);
515
516
  }
516
517
 
518
+
519
+ checkForEmojii(text){
520
+ //remove emojii only if "emojii" exist and is set to false
521
+ if(this.project && this.project.settings?.allow_send_emoji === false){
522
+ return findAndRemoveEmoji(text)
523
+ }
524
+ return text
525
+ }
526
+
517
527
 
518
528
 
519
529
  onTextAreaChange(){
@@ -632,7 +642,6 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
632
642
  * @param str
633
643
  */
634
644
  setWritingMessages(str) {
635
- //this.messagingService.setWritingMessages(str, this.g.channelType);
636
645
  this.typingService.setTyping(this.conversationWith, str, this.senderId, this.userFullname )
637
646
  }
638
647
 
@@ -112,7 +112,7 @@
112
112
 
113
113
 
114
114
  <!-- ICON RESTART CONVERSATION -->
115
- <div class="c21-header-button c21-right" *ngIf="!hideRestartConversationOptionsMenu" (click)="restartChat()">
115
+ <!-- <div class="c21-header-button c21-right" *ngIf="!hideRestartConversationOptionsMenu" (click)="restartChat()">
116
116
  <svg role="img" id="refresh" aria-labelledby="altIconTitle" class="icon-menu" xmlns="http://www.w3.org/2000/svg"
117
117
  width="20px" height="20px" viewBox="0 0 20 20">
118
118
  <path d="M9.6,18.2c0.6,0,1-0.7,1-1.5s-0.5-1.5-1-1.5H6c-0.6,0-1-0.7-1-1.5V7.8h1c0.4,0,0.8-0.4,1-0.9c0.2-0.6,0.1-1.2-0.2-1.6 l-2.1-3c-0.4-0.6-1.1-0.6-1.5,0l-2.1,3C0.9,5.7,0.8,6.3,1,6.9s0.5,0.9,1,0.9h1v5.9c0,2.5,1.4,4.4,3.1,4.4H9.6z"/>
@@ -120,7 +120,7 @@
120
120
  <title id="altIconTitle">{{ translationMap?.get('RESTART') }}</title>
121
121
  </svg>
122
122
  <span class="label-menu-item">{{ translationMap?.get('RESTART') }}</span>
123
- </div>
123
+ </div> -->
124
124
 
125
125
  <!-- ICON MAXIMIZE -->
126
126
  <!-- <div class="c21-header-button c21-right" *ngIf="heightStatus==='min'" (click)="maximizeMinimize('max')">
@@ -23,7 +23,6 @@ export class ConversationHeaderComponent implements OnInit, OnChanges {
23
23
  @Input() typingLocation: string;
24
24
  @Input() isTrascriptDownloadEnabled: boolean;
25
25
  @Input() hideCloseConversationOptionMenu: boolean;
26
- @Input() hideRestartConversationOptionsMenu: boolean;
27
26
  @Input() hideHeaderCloseButton: boolean;
28
27
  @Input() hideHeaderBackButton: boolean;
29
28
  @Input() hideHeaderConversationOptionsMenu: boolean;
@@ -1,5 +1,7 @@
1
1
  import { Component, ElementRef, AfterViewInit, Input, ViewChild } from '@angular/core';
2
2
  import { DomSanitizer, SafeUrl } from '@angular/platform-browser';
3
+ import { LoggerService } from 'src/chat21-core/providers/abstract/logger.service';
4
+ import { LoggerInstance } from 'src/chat21-core/providers/logger/loggerInstance';
3
5
  import { convertColorToRGBA } from 'src/chat21-core/utils/utils';
4
6
 
5
7
  @Component({
@@ -26,13 +28,13 @@ export class AudioComponent implements AfterViewInit {
26
28
  currentTime: number = 0;
27
29
  isPlaying: boolean = false;
28
30
 
31
+ private logger: LoggerService = LoggerInstance.getInstance();
29
32
  constructor(
30
33
  private sanitizer: DomSanitizer,
31
34
  private elementRef: ElementRef
32
35
  ) {}
33
36
 
34
37
  ngAfterViewInit() {
35
- console.log('stylesssss', this.stylesMap)
36
38
  if (this.audioBlob) {
37
39
  this.rawAudioUrl = URL.createObjectURL(this.audioBlob);
38
40
  this.audioUrl = this.sanitizer.bypassSecurityTrustUrl(this.rawAudioUrl);
@@ -136,21 +138,33 @@ export class AudioComponent implements AfterViewInit {
136
138
  return `${minutes}:${sec < 10 ? '0' + sec : sec}`;
137
139
  }
138
140
 
139
- getAudioDuration() {
140
- const audio = new Audio();
141
- audio.src = this.rawAudioUrl!;
142
- audio.addEventListener('loadedmetadata', () => {
143
- if (audio.duration === Infinity) {
144
- audio.currentTime = Number.MAX_SAFE_INTEGER;
145
- audio.ontimeupdate = () => {
146
- audio.ontimeupdate = null;
147
- audio.currentTime = 0;
148
- this.audioDuration = audio.duration;
149
- };
150
- } else {
151
- this.audioDuration = audio.duration;
152
- }
153
- });
141
+ async getAudioDuration() {
142
+ // const audio = new Audio();
143
+ // audio.src = this.rawAudioUrl!;
144
+ // audio.addEventListener('loadedmetadata', () => {
145
+ // if (audio.duration === Infinity) {
146
+ // audio.currentTime = Number.MAX_SAFE_INTEGER;
147
+ // audio.ontimeupdate = () => {
148
+ // audio.ontimeupdate = null;
149
+ // audio.currentTime = 0;
150
+ // this.audioDuration = audio.duration;
151
+ // };
152
+ // } else {
153
+ // this.audioDuration = audio.duration;
154
+ // }
155
+ // });
156
+
157
+ const response = await fetch(this.rawAudioUrl!);
158
+ this.logger.debug('getAudioDuration: response ---> ', response)
159
+ const arrayBuffer = await response.arrayBuffer();
160
+ this.logger.debug('getAudioDuration: arrayBuffer ---> ', arrayBuffer)
161
+ const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)();
162
+ this.logger.debug('getAudioDuration: audioContext ---> ', audioContext)
163
+ const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
164
+ this.logger.debug('getAudioDuration: audioBuffer ---> ', audioBuffer)
165
+ this.audioDuration = audioBuffer.duration;
166
+ this.logger.debug('getAudioDuration: audioDuration ---> ', this.audioDuration)
167
+
154
168
  }
155
169
 
156
170
  extractFirstColor(gradient: string): string | null {
@@ -865,11 +865,6 @@ export class GlobalSettingsService {
865
865
  if (TEMP !== undefined) {
866
866
  globals.hideCloseConversationOptionMenu = (TEMP === true) ? true : false;;
867
867
  }
868
- TEMP = tiledeskSettings['hideRestartConversationOptionsMenu'];
869
- // this.logger.debug('[GLOBAL-SET] setVariablesFromSettings > hideHeaderConversationOptionsMenu:: ', TEMP]);
870
- if (TEMP !== undefined) {
871
- globals.hideRestartConversationOptionsMenu = (TEMP === true) ? true : false;;
872
- }
873
868
  TEMP = tiledeskSettings['hideHeaderConversationOptionsMenu'];
874
869
  // this.logger.debug('[GLOBAL-SET] setVariablesFromSettings > hideHeaderConversationOptionsMenu:: ', TEMP]);
875
870
  if (TEMP !== undefined) {
@@ -1240,10 +1235,6 @@ export class GlobalSettingsService {
1240
1235
  if (TEMP !== null) {
1241
1236
  this.globals.hideCloseConversationOptionMenu = TEMP;
1242
1237
  }
1243
- TEMP = el.nativeElement.getAttribute('hideRestartConversationOptionsMenu');
1244
- if (TEMP !== null) {
1245
- this.globals.hideRestartConversationOptionsMenu = TEMP;
1246
- }
1247
1238
  TEMP = el.nativeElement.getAttribute('hideSettings');
1248
1239
  if (TEMP !== null) {
1249
1240
  this.globals.hideSettings = TEMP;
@@ -1637,11 +1628,6 @@ export class GlobalSettingsService {
1637
1628
  globals.hideCloseConversationOptionMenu = stringToBoolean(TEMP);
1638
1629
  }
1639
1630
 
1640
- TEMP = getParameterByName(windowContext, 'tiledesk_hideRestartConversationOptionsMenu');
1641
- if (TEMP) {
1642
- globals.hideRestartConversationOptionsMenu = stringToBoolean(TEMP);
1643
- }
1644
-
1645
1631
  TEMP = getParameterByName(windowContext, 'tiledesk_hideSettings');
1646
1632
  if (TEMP) {
1647
1633
  globals.hideSettings = stringToBoolean(TEMP);
@@ -163,7 +163,6 @@ export class Globals {
163
163
  openExternalLinkButton: boolean;
164
164
  hideHeaderConversationOptionsMenu: boolean;
165
165
  hideCloseConversationOptionMenu: boolean;
166
- hideRestartConversationOptionsMenu: boolean;
167
166
  hideSettings: boolean;
168
167
  filterByRequester: boolean;
169
168
  persistence;
@@ -337,8 +336,6 @@ export class Globals {
337
336
  /** enable to close a conversation from upper-right header menu */
338
337
  this.hideCloseConversationOptionMenu = false;
339
338
  /** enable to hide/show options menu in conversation detail header */
340
- this.hideRestartConversationOptionsMenu = false;
341
- /** enable to hide/show options menu in conversation detail header */
342
339
  this.hideSettings = false;
343
340
  /** enable to hide/show options menu in home component */
344
341
  this.filterByRequester = false;
@@ -528,7 +525,7 @@ export class Globals {
528
525
  'fullscreenMode': this.fullscreenMode,
529
526
  'filterByRequester': this.filterByRequester,
530
527
  'hideHeaderConversationOptionsMenu': this.hideHeaderConversationOptionsMenu, 'hideHeaderCloseButton': this.hideHeaderCloseButton,
531
- 'hideCloseConversationOptionMenu': this.hideCloseConversationOptionMenu, 'hideRestartConversationOptionsMenu': this.hideRestartConversationOptionsMenu,
528
+ 'hideCloseConversationOptionMenu': this.hideCloseConversationOptionMenu,
532
529
  'hideSettings': this.hideSettings,
533
530
  'isLogEnabled': this.isLogEnabled,
534
531
  'isOpen': this.isOpen, 'isShown': this.isShown,
@@ -613,7 +613,7 @@
613
613
  var brandJson = JSON.parse(xhr.response)
614
614
  if(brandJson){
615
615
  /** TITLE AND FAVICON **/
616
- brandJson['WIDGET'].META_TITLE? document.body.title = brandJson['WIDGET'].META_TITLE : null;
616
+ brandJson['WIDGET'].META_TITLE? document.title = brandJson['WIDGET'].META_TITLE : null;
617
617
  brandJson['WIDGET'].FAVICON_URL? document.querySelector("link[rel~='icon']").setAttribute('href', brandJson['WIDGET'].FAVICON_URL) : null;
618
618
  /** FOOTER-LOGO **/
619
619
  brandJson['COMMON'].COMPANY_LOGO? document.getElementById('footer-logo').src = brandJson['COMMON'].COMPANY_LOGO : null;
@@ -624,6 +624,13 @@
624
624
  brandJson['COMMON'].BRAND_PRIMARY_COLOR? document.body.style.setProperty('--base-company-logo', brandJson['COMMON'].BRAND_PRIMARY_COLOR): null;
625
625
  /** IFRAME TITLE**/
626
626
  brandJson['COMMON'].COMPANY_NAME? document.getElementById('tiledeskiframe').title = brandJson['COMMON'].COMPANY_NAME + ' Widget' : null;
627
+ /** META sharing ELEMENTS */
628
+ if(brandJson['WIDGET'].META_SHARE_INFO && Object.keys(brandJson['WIDGET'].META_SHARE_INFO).length > 0){
629
+ Object.keys(brandJson['WIDGET'].META_SHARE_INFO).forEach(key => {
630
+ var meta = document.querySelector("meta[property^='og:"+key.toLowerCase()+"']");
631
+ meta.setAttribute('content', brandJson['WIDGET'].META_SHARE_INFO[key])
632
+ })
633
+ }
627
634
  }
628
635
  }
629
636
 
@@ -719,7 +719,7 @@
719
719
  var brandJson = JSON.parse(xhr.response)
720
720
  if(brandJson){
721
721
  /** TITLE AND FAVICON **/
722
- brandJson['WIDGET'].META_TITLE? document.body.title = brandJson['WIDGET'].META_TITLE : null;
722
+ brandJson['WIDGET'].META_TITLE? document.title = brandJson['WIDGET'].META_TITLE : null;
723
723
  brandJson['WIDGET'].FAVICON_URL? document.querySelector("link[rel~='icon']").setAttribute('href', brandJson['WIDGET'].FAVICON_URL) : null;
724
724
  /** FOOTER-LOGO **/
725
725
  brandJson['COMMON'].COMPANY_LOGO? document.getElementById('footer-logo').src = brandJson['COMMON'].COMPANY_LOGO : null;
@@ -737,6 +737,13 @@
737
737
  }
738
738
  /** IFRAME TITLE**/
739
739
  brandJson['COMMON'].COMPANY_LOGO? document.getElementById('tiledeskiframe').title = brandJson['COMMON'].COMPANY_NAME + ' Widget' : null;
740
+ /** META sharing ELEMENTS */
741
+ if(brandJson['WIDGET'].META_SHARE_INFO && Object.keys(brandJson['WIDGET'].META_SHARE_INFO).length > 0){
742
+ Object.keys(brandJson['WIDGET'].META_SHARE_INFO).forEach(key => {
743
+ var meta = document.querySelector("meta[property^='og:"+key.toLowerCase()+"']");
744
+ meta.setAttribute('content', brandJson['WIDGET'].META_SHARE_INFO[key])
745
+ })
746
+ }
740
747
  }
741
748
  }
742
749
  }
@@ -1263,13 +1270,6 @@
1263
1270
  window.Tiledesk('restart')
1264
1271
  }
1265
1272
 
1266
- function onClickHideRestartConversationOptionsMenu(){
1267
- let status = document.querySelector('input[name="hideRestartConversationOptionsMenu"]:checked').value
1268
- window.tiledeskSettings['hideRestartConversationOptionsMenu'] = stringToBoolean(status)
1269
- console.log('onClickHideRestartConversationOptionsMenu:', window.tiledeskSettings)
1270
- window.Tiledesk('restart')
1271
- }
1272
-
1273
1273
  function onClickAllowTranscriptDownload(){
1274
1274
  let status = document.querySelector('input[name="allowTranscriptDownload"]:checked').value
1275
1275
  window.tiledeskSettings['allowTranscriptDownload'] = stringToBoolean(status)
@@ -2277,16 +2277,6 @@
2277
2277
  <button class="btn btn-light" onclick="onClickHideCloseConversationOptionMenu()">Test this setting <i class="fa fa-magic" aria-hidden="true"></i></button>
2278
2278
  </div>
2279
2279
  </div>
2280
- <div class="row">
2281
- <div class="col-md-5 formElement"><span><em><strong>hideRestartConversationOptionsMenu</strong></em></span></div>
2282
- <div class="col-md-5">
2283
- <input class="form-check-input" type="radio" name="hideRestartConversationOptionsMenu" value="true"><label>True</label>
2284
- <input class="form-check-input" type="radio" name="hideRestartConversationOptionsMenu" value="false" checked><label >False</label>
2285
- </div>
2286
- <div class="col-md-2">
2287
- <button class="btn btn-light" onclick="onClickHideRestartConversationOptionsMenu()">Test this setting <i class="fa fa-magic" aria-hidden="true"></i></button>
2288
- </div>
2289
- </div>
2290
2280
  <div class="row">
2291
2281
  <div class="col-md-5 formElement"><span><em><strong>allowTranscriptDownload</strong></em></span></div>
2292
2282
  <div class="col-md-5">
@@ -6,7 +6,7 @@
6
6
  <meta charset="utf-8">
7
7
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
8
8
 
9
- <title>Widget test page </title>
9
+ <title>Widget test page</title>
10
10
  <style>
11
11
 
12
12
  @-moz-keyframes blink {0%{opacity:1;} 50%{opacity:0;} 100%{opacity:1;}} /* Firefox */
@@ -295,7 +295,10 @@
295
295
  window.Tiledesk('onBeforeInit', function(event_data) {
296
296
  console.log("onBeforeInit Tiledesk FN", event_data);
297
297
 
298
- var brandSrc = event_data.detail.appConfigs.brandSrc? getBrandResources(event_data.detail.appConfigs.brandSrc) : null;
298
+ if(event_data.detail.appConfigs.brandSrc){
299
+ getBrandResources(event_data.detail.appConfigs.brandSrc)
300
+ }
301
+ // var brandSrc = event_data.detail.appConfigs.brandSrc? : null;
299
302
 
300
303
  setTimeout(() => {
301
304
  if(event_data && event_data.detail && event_data.detail.appConfigs){
@@ -408,7 +411,7 @@
408
411
  var brandJson = JSON.parse(xhr.response)
409
412
  if(brandJson){
410
413
  /** TITLE AND FAVICON **/
411
- brandJson['WIDGET'].META_TITLE? document.body.title = brandJson['WIDGET'].META_TITLE : null;
414
+ brandJson['WIDGET'].META_TITLE? document.title = brandJson['WIDGET'].META_TITLE : null;
412
415
  brandJson['WIDGET'].FAVICON_URL? document.querySelector("link[rel~='icon']").setAttribute('href', brandJson['WIDGET'].FAVICON_URL) : null;
413
416
  /** FOOTER-LOGO **/
414
417
  brandJson['COMMON'].COMPANY_LOGO? document.getElementById('footer-logo').src = brandJson['COMMON'].COMPANY_LOGO : null;
@@ -421,6 +424,13 @@
421
424
  brandJson['COMMON'].DOCS? null: document.getElementById('share').style.display = 'none'
422
425
  /** IFRAME TITLE**/
423
426
  brandJson['COMMON'].COMPANY_LOGO? document.getElementById('tiledeskiframe').title = brandJson['COMMON'].COMPANY_NAME + ' Widget' : null;
427
+ /** META sharing ELEMENTS */
428
+ if(brandJson['WIDGET'].META_SHARE_INFO && Object.keys(brandJson['WIDGET'].META_SHARE_INFO).length > 0){
429
+ Object.keys(brandJson['WIDGET'].META_SHARE_INFO).forEach(key => {
430
+ var meta = document.querySelector("meta[property^='og:"+key.toLowerCase()+"']");
431
+ meta.setAttribute('content', brandJson['WIDGET'].META_SHARE_INFO[key])
432
+ })
433
+ }
424
434
  }
425
435
 
426
436
  }
@@ -194,9 +194,13 @@ export function isEmojii(message: any){
194
194
  // https://localcoder.org/javascript-detect-if-a-string-contains-only-unicode-emojis
195
195
  try {
196
196
  if(!message) return false;
197
+ // Removes all characters that are NOT emojis (unicode > \u1eeff)
197
198
  const onlyEmojis = message.replace(new RegExp('[\u0000-\u1eeff]', 'g'), '')
199
+ // Removes spaces, line breaks, and carriage returns from the string
198
200
  const visibleChars = message.replace(new RegExp('[\n\r\s]+|( )+', 'g'), '')
201
+ // Removes Chinese characters from the string
199
202
  const chineseChars = message.replace(new RegExp('[\u4e00-\u9fa5]', 'g'), '')
203
+
200
204
  if(onlyEmojis === '' || visibleChars == '' || chineseChars=='') return false
201
205
  return (onlyEmojis.length === visibleChars.length && onlyEmojis.length <= 2)
202
206
  } catch(e) {
@@ -204,6 +208,22 @@ export function isEmojii(message: any){
204
208
  }
205
209
  }
206
210
 
211
+ export function findAndRemoveEmoji(text): string{
212
+
213
+ if (!text) return text;
214
+
215
+ // Regex to find most unicode emojis
216
+ // Source: https://thekevinscott.com/emojis-in-javascript/
217
+ const emojiRegex = /([\u2700-\u27BF]|[\uE000-\uF8FF]|[\uD83C-\uDBFF][\uDC00-\uDFFF]|[\u2011-\u26FF]|\uD83D[\uDE00-\uDE4F])/g;
218
+
219
+ // Removes all found emojis
220
+ text = text.replace(emojiRegex, '');
221
+
222
+ // Removes any multiple spaces left by the removal of emojis
223
+ text = text.replace(/\s{2,}/g, ' ').trim();
224
+ return text
225
+ }
226
+
207
227
  export function isJustRecived(startedAt, time) {
208
228
  if (time > startedAt) {
209
229
  return true;
@@ -24,7 +24,8 @@ export class ProjectModel {
24
24
  public color?: string,
25
25
  public welcomeTitle?: string,
26
26
  public welcomeMsg?: string,
27
- public attributes?: IRules
27
+ public attributes?: IRules,
28
+ public settings?:{ [key: string]: any },
28
29
  ) { }
29
30
 
30
31
  initialize (
@@ -43,6 +44,7 @@ export class ProjectModel {
43
44
  trialDaysLeft?: number,
44
45
  trialExpired?: boolean,
45
46
  updatedAt?: string,
47
+ settings?: { [key: string]: any },
46
48
  versions?: string,
47
49
  ) {
48
50
  this.id = id;
@@ -60,6 +62,7 @@ export class ProjectModel {
60
62
  this.trialDaysLeft = trialDaysLeft;
61
63
  this.trialExpired = trialExpired;
62
64
  this.updatedAt = updatedAt;
65
+ this.settings = settings;
63
66
  this.versions = versions;
64
67
  }
65
68