@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 +12 -2
- package/package.json +1 -1
- package/src/app/app.component.ts +5 -3
- package/src/app/component/conversation-detail/conversation/conversation.component.ts +1 -2
- package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts +1 -1
- package/src/app/component/message/buttons/action-button/action-button.component.ts +3 -1
- package/src/app/providers/global-settings.service.ts +18 -6
- package/src/chat21-core/utils/utils.ts +118 -6
package/CHANGELOG.md
CHANGED
|
@@ -6,8 +6,15 @@
|
|
|
6
6
|
### **Copyrigth**:
|
|
7
7
|
*Tiledesk SRL*
|
|
8
8
|
|
|
9
|
-
# 5.1.
|
|
10
|
-
- **
|
|
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
package/src/app/app.component.ts
CHANGED
|
@@ -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(() => {
|
package/src/app/component/conversation-detail/conversation-footer/conversation-footer.component.ts
CHANGED
|
@@ -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.
|
|
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('--
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
339
|
-
} else {
|
|
340
|
-
|
|
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)) {
|