@chat21/chat21-web-widget 5.1.7-rc9 → 5.1.9-ar

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,8 +6,15 @@
6
6
  ### **Copyrigth**:
7
7
  *Tiledesk SRL*
8
8
 
9
- # 5.1.7-rc9
10
- - **removed**: 'DOMAIN_NOT_ALLOWED' in textarea footer component
9
+ # 5.1.9-ar
10
+ - **bug-fixed**: set default widget size
11
+
12
+ # 5.1.8-ar
13
+ - **changed**: update emoji detection logic in conversation-footer and utils
14
+ - **bug-fixed**: 'DOMAIN_NOT_ALLOWED' in textarea footer component
15
+ - **bug-fixed**: departmentId and departmentName is incorrect in attributes
16
+
17
+ # 5.1.8
11
18
 
12
19
  # 5.1.7-rc8
13
20
  - **changed**: Updated the translations of the tooltips in the footer-component
@@ -19,6 +26,9 @@
19
26
  # 5.1.7-rc6
20
27
  - **added**: Added MAX_ATTACHMENT_ERROR error message when uploading a file larger than 10 MB
21
28
 
29
+ # this branch
30
+ - **bug-fixed**: set the color of the buttons with visibility control to the font color (setButtonColors function)
31
+
22
32
  # 5.1.7-rc5
23
33
  - **bug-fixed**: bug fixed BUTTON STYLES
24
34
 
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.7-rc9",
4
+ "version": "5.1.9-ar",
5
5
  "license": "MIT",
6
6
  "homepage": "https://www.tiledesk.com",
7
7
  "repository": {
@@ -401,9 +401,11 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
401
401
  this.triggerLoadParamsEvent(); // first trigger
402
402
  //this.setAvailableAgentsStatus();
403
403
 
404
-
405
404
  /** NETWORK STATUS */
406
- this.listenToNetworkStatus()
405
+ this.listenToNetworkStatus();
406
+
407
+ /** SET WIDGET SIZE */
408
+ this.onWidgetSizeChange(this.g.size);
407
409
 
408
410
  }
409
411
 
@@ -727,7 +729,7 @@ export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
727
729
  // visualizzo l'iframe!!!
728
730
  this.triggerOnViewInit();
729
731
  this.g.setParentBodyStyleMobile(this.g.isOpen, this.g.isMobile);
730
- this.g.setElementStyle(this.g.isOpen)
732
+ this.g.setElementStyle(this.g.isOpen);
731
733
  // this.triggerOnAuthStateChanged(true)
732
734
  // mostro il widget
733
735
  // setTimeout(() => {
@@ -1441,5 +1441,4 @@ export class ConversationComponent implements OnInit, AfterViewInit, OnChanges {
1441
1441
  this.isHovering = false
1442
1442
  }
1443
1443
 
1444
- }
1445
-
1444
+ }
@@ -570,7 +570,7 @@ export class ConversationFooterComponent implements OnInit, OnChanges {
570
570
 
571
571
  checkForEmojii(text){
572
572
  //remove emojii only if "emojii" exist and is set to false
573
- if(this.project && this.project.settings?.allow_send_emoji === false){
573
+ if(!this.showEmojiFooterButton){
574
574
  this.showAlertEmoji = isEmoji(text);
575
575
  if(this.showAlertEmoji){
576
576
  return false
@@ -1,4 +1,5 @@
1
1
  import { Component, ElementRef, EventEmitter, Input, OnInit, Output, SimpleChanges } from '@angular/core';
2
+ import { getColorBck } from 'src/chat21-core/utils/utils-user';
2
3
 
3
4
  @Component({
4
5
  selector: 'chat-action-button-attachment',
@@ -26,9 +27,10 @@ export class ActionButtonComponent implements OnInit {
26
27
  //decomment if element should have same color of themeColor and fregroundColor
27
28
  if(this.fontSize) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonFontSize', this.fontSize);
28
29
  if(this.backgroundColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonBackgroundColor', this.backgroundColor);
29
- if(this.textColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--textColor', this.textColor);
30
+ if(this.textColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--buttonTextColor', this.textColor);
30
31
  if(this.hoverBackgroundColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--hoverBackgroundColor', this.hoverBackgroundColor);
31
32
  if(this.hoverTextColor) this.elementRef.nativeElement.querySelector('.action').style.setProperty('--hoverTextColor', this.hoverTextColor);
33
+
32
34
  }
33
35
 
34
36
  onMouseOver(event){
@@ -10,7 +10,7 @@ import { TemplateBindingParseResult } from '@angular/compiler';
10
10
  import { AppStorageService } from '../../chat21-core/providers/abstract/app-storage.service';
11
11
  import { LoggerService } from '../../chat21-core/providers/abstract/logger.service';
12
12
  import { LoggerInstance } from '../../chat21-core/providers/logger/loggerInstance';
13
- import { invertColor, isAllowedUrlInText, isJsonArray } from '../../chat21-core/utils/utils';
13
+ import { ensureAccessibleTextColor, invertColor, isAllowedUrlInText, isJsonArray, normalizeColorToHex } from '../../chat21-core/utils/utils';
14
14
  import { AppConfigService } from './app-config.service';
15
15
 
16
16
 
@@ -322,10 +322,14 @@ export class GlobalSettingsService {
322
322
  if (response !== null) {
323
323
  this.setVariablesFromService(this.globals, response);
324
324
  }
325
+ /** set button colors */
326
+ this.setButtonColors();
327
+
325
328
  this.setVariableFromStorage(this.globals);
326
329
  this.setVariablesFromSettings(this.globals);
327
330
  this.setVariablesFromAttributeHtml(this.globals, this.el);
328
331
  this.setVariablesFromUrlParameters(this.globals);
332
+
329
333
  this.setDepartmentFromExternal();
330
334
  /** set color with gradient from theme's colors */
331
335
  this.globals.setColorWithGradient();
@@ -333,11 +337,19 @@ export class GlobalSettingsService {
333
337
  this.setCssIframe();
334
338
  /** set main style */
335
339
  this.setStyle();
336
-
337
- this.logger.debug('[GLOBAL-SET] ***** END SET PARAMETERS *****');
338
340
  this.obsSettingsService.next(true);
339
341
  }
340
342
 
343
+ private setButtonColors() {
344
+ this.logger.debug('[GLOBAL-SET] ***** END SET PARAMETERS *****', this.globals);
345
+ const bubbleSentBackground = this.globals?.bubbleSentBackground;
346
+ const buttonBackgroundColor = this.globals?.buttonBackgroundColor;
347
+
348
+ this.globals.buttonTextColor = ensureAccessibleTextColor(buttonBackgroundColor, bubbleSentBackground);
349
+ this.globals.buttonHoverTextColor = ensureAccessibleTextColor(bubbleSentBackground, buttonBackgroundColor);
350
+
351
+ }
352
+
341
353
  /**
342
354
  *
343
355
  */
@@ -1936,7 +1948,7 @@ export class GlobalSettingsService {
1936
1948
  if (this.globals.departmentID) {
1937
1949
  this.globals.departments.forEach(department => {
1938
1950
  if (department._id === this.globals.departmentID) {
1939
- this.logger.debug('[GLOBAL-SET] setDepartmentFromExternal > EXTERNAL DEPARTMENT ::::' + department._id);
1951
+ console.log('[GLOBAL-SET] setDepartmentFromExternal > EXTERNAL DEPARTMENT ::::' + department._id);
1940
1952
  this.globals.setParameter('departmentDefault', department);
1941
1953
  this.setDepartment(department);
1942
1954
  isValidID = true;
@@ -1964,7 +1976,7 @@ export class GlobalSettingsService {
1964
1976
  * save attributes in this.appStorageService
1965
1977
  */
1966
1978
  setDepartment(department) {
1967
- this.logger.debug('[GLOBAL-SET] setDepartment: ', JSON.stringify(department));
1979
+ this.logger.log('[GLOBAL-SET] setDepartment: ', JSON.stringify(department));
1968
1980
  this.globals.setParameter('departmentSelected', department);
1969
1981
  // let attributes = this.globals.attributes;
1970
1982
  let attributes: any = JSON.parse(this.appStorageService.getItem('attributes'));
@@ -1983,7 +1995,7 @@ export class GlobalSettingsService {
1983
1995
  this.logger.debug('[GLOBAL-SET] setDepartment > setAttributes: ', JSON.stringify(attributes));
1984
1996
  this.globals.setParameter('departmentSelected', department);
1985
1997
  this.globals.setParameter('attributes', attributes);
1986
- // this.appStorageService.setItem('attributes', JSON.stringify(attributes));
1998
+ this.appStorageService.setItem('attributes', JSON.stringify(attributes));
1987
1999
 
1988
2000
  }
1989
2001
  // ========= end:: GET DEPARTEMENTS ============//
@@ -333,12 +333,15 @@ export function replaceEndOfLine(text) {
333
333
 
334
334
  export function isEmoji(str: string) {
335
335
  // tslint:disable-next-line:max-line-length
336
- const ranges = ['(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])'];
337
- if (str.match(ranges.join('|'))) {
338
- return true;
339
- } else {
340
- return false;
341
- }
336
+ // const ranges = ['(?:[\u2700-\u27bf]|(?:\ud83c[\udde6-\uddff]){2}|[\ud800-\udbff][\udc00-\udfff]|[\u0023-\u0039]\ufe0f?\u20e3|\u3299|\u3297|\u303d|\u3030|\u24c2|\ud83c[\udd70-\udd71]|\ud83c[\udd7e-\udd7f]|\ud83c\udd8e|\ud83c[\udd91-\udd9a]|\ud83c[\udde6-\uddff]|[\ud83c[\ude01-\ude02]|\ud83c\ude1a|\ud83c\ude2f|[\ud83c[\ude32-\ude3a]|[\ud83c[\ude50-\ude51]|\u203c|\u2049|[\u25aa-\u25ab]|\u25b6|\u25c0|[\u25fb-\u25fe]|\u00a9|\u00ae|\u2122|\u2139|\ud83c\udc04|[\u2600-\u26FF]|\u2b05|\u2b06|\u2b07|\u2b1b|\u2b1c|\u2b50|\u2b55|\u231a|\u231b|\u2328|\u23cf|[\u23e9-\u23f3]|[\u23f8-\u23fa]|\ud83c\udccf|\u2934|\u2935|[\u2190-\u21ff])'];
337
+ // if (str.match(ranges.join('|'))) {
338
+ // return true;
339
+ // } else {
340
+ // return false;
341
+ // }
342
+ const emojiRegex = /\p{Extended_Pictographic}/u;
343
+ return emojiRegex.test(str);
344
+
342
345
  }
343
346
 
344
347
  export function setColorFromString(str: string) {
@@ -386,6 +389,115 @@ export function convertColorToRGBA(color, opacity) {
386
389
  return result;
387
390
  }
388
391
 
392
+ export function normalizeColorToHex(input?: string): string | null {
393
+ if (!input) {
394
+ return null;
395
+ }
396
+ let color = input.trim();
397
+ if (color.toLowerCase().includes('gradient')) {
398
+ const match = color.match(/(#[0-9a-fA-F]{3,8}|rgba?\([^)]*\))/);
399
+ if (!match) {
400
+ return null;
401
+ }
402
+ color = match[0];
403
+ }
404
+ if (color.startsWith('#')) {
405
+ const hex = color.slice(1);
406
+ if (hex.length === 3) {
407
+ return (
408
+ '#' +
409
+ hex
410
+ .split('')
411
+ .map((char) => char + char)
412
+ .join('')
413
+ .toLowerCase()
414
+ );
415
+ }
416
+ if (hex.length === 4) {
417
+ return (
418
+ '#' +
419
+ hex
420
+ .slice(0, 3)
421
+ .split('')
422
+ .map((char) => char + char)
423
+ .join('')
424
+ .toLowerCase()
425
+ );
426
+ }
427
+ if (hex.length === 6 || hex.length === 8) {
428
+ return '#' + hex.slice(0, 6).toLowerCase();
429
+ }
430
+ return null;
431
+ }
432
+ const rgbaMatch = color.match(/rgba?\s*\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*([\d.]+))?\s*\)/i);
433
+ if (rgbaMatch) {
434
+ const [, r, g, b] = rgbaMatch;
435
+ const toHex = (value: number) => {
436
+ const clamped = Math.max(0, Math.min(255, Math.round(value)));
437
+ return clamped.toString(16).padStart(2, '0');
438
+ };
439
+ return `#${toHex(parseFloat(r))}${toHex(parseFloat(g))}${toHex(parseFloat(b))}`;
440
+ }
441
+ return null;
442
+ }
443
+
444
+ export function ensureAccessibleTextColor(backgroundColor?: string, fontColor?: string, minContrast = 4.5): string | null {
445
+ const bgHex = normalizeColorToHex(backgroundColor);
446
+ if (!bgHex) {
447
+ return normalizeColorToHex(fontColor);
448
+ }
449
+
450
+ const fontHex = normalizeColorToHex(fontColor);
451
+ if (fontHex && getContrastRatio(bgHex, fontHex) >= minContrast) {
452
+ return fontHex;
453
+ }
454
+
455
+ const blackContrast = getContrastRatio(bgHex, '#000000');
456
+ const whiteContrast = getContrastRatio(bgHex, '#ffffff');
457
+ return blackContrast >= whiteContrast ? '#000000' : '#ffffff';
458
+ }
459
+
460
+ function getContrastRatio(backgroundHex: string, foregroundHex: string): number {
461
+ const bg = hexToRgb(backgroundHex);
462
+ const fg = hexToRgb(foregroundHex);
463
+ if (!bg || !fg) {
464
+ return 1;
465
+ }
466
+ const l1 = relativeLuminance(bg);
467
+ const l2 = relativeLuminance(fg);
468
+ const lighter = Math.max(l1, l2);
469
+ const darker = Math.min(l1, l2);
470
+ return (lighter + 0.05) / (darker + 0.05);
471
+ }
472
+
473
+ function relativeLuminance({ r, g, b }: { r: number; g: number; b: number }): number {
474
+ const srgb = [r, g, b].map((value) => {
475
+ const channel = value / 255;
476
+ return channel <= 0.03928 ? channel / 12.92 : Math.pow((channel + 0.055) / 1.055, 2.4);
477
+ });
478
+ return 0.2126 * srgb[0] + 0.7152 * srgb[1] + 0.0722 * srgb[2];
479
+ }
480
+
481
+ function hexToRgb(hex: string): { r: number; g: number; b: number } | null {
482
+ let value = hex.replace('#', '');
483
+ if (value.length === 3) {
484
+ value = value
485
+ .split('')
486
+ .map((char) => char + char)
487
+ .join('');
488
+ }
489
+ if (value.length !== 6) {
490
+ return null;
491
+ }
492
+ const r = parseInt(value.slice(0, 2), 16);
493
+ const g = parseInt(value.slice(2, 4), 16);
494
+ const b = parseInt(value.slice(4, 6), 16);
495
+ if ([r, g, b].some((channel) => Number.isNaN(channel))) {
496
+ return null;
497
+ }
498
+ return { r, g, b };
499
+ }
500
+
389
501
 
390
502
  // export function setLanguage(windowContext, translatorService) {
391
503
  // if (translatorService.getBrowserLanguage(windowContext)) {