@microsoft/omnichannel-chat-widget 1.8.4-main.cbab5fc → 1.8.4-main.cc63f01
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/README.md +13 -3
- package/lib/cjs/common/Constants.js +5 -0
- package/lib/cjs/common/facades/FacadeChatSDK.js +235 -9
- package/lib/cjs/common/telemetry/TelemetryConstants.js +14 -0
- package/lib/cjs/common/telemetry/TelemetryManager.js +6 -1
- package/lib/cjs/common/telemetry/loggers/appInsightsLogger.js +7 -7
- package/lib/cjs/common/telemetry/sanitizeSasInPayload.js +82 -0
- package/lib/cjs/common/utils/xssUtils.js +23 -51
- package/lib/cjs/common/utils.js +106 -17
- package/lib/cjs/components/citationpanestateful/CitationPaneStateful.js +8 -1
- package/lib/cjs/components/confirmationpanestateful/ConfirmationPaneStateful.js +12 -1
- package/lib/cjs/components/emailtranscriptpanestateful/EmailTranscriptPaneStateful.js +36 -13
- package/lib/cjs/components/errorboundary/ErrorBoundary.js +2 -1
- package/lib/cjs/components/livechatwidget/LiveChatWidget.js +9 -1
- package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +23 -6
- package/lib/cjs/components/livechatwidget/common/ChatWidgetEvents.js +1 -0
- package/lib/cjs/components/livechatwidget/common/PersistentConversationHandler.js +9 -0
- package/lib/cjs/components/livechatwidget/common/authHelper.js +44 -4
- package/lib/cjs/components/livechatwidget/common/createAdapter.js +3 -2
- package/lib/cjs/components/livechatwidget/common/createMarkdown.js +98 -5
- package/lib/cjs/components/livechatwidget/common/endChat.js +6 -0
- package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +186 -1
- package/lib/cjs/components/livechatwidget/common/liveChatConfigUtils.js +36 -4
- package/lib/cjs/components/livechatwidget/common/startChat.js +31 -14
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +124 -5
- package/lib/cjs/components/postchatloadingpanestateful/PostChatLoadingPaneStateful.js +15 -3
- package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +7 -4
- package/lib/cjs/components/prechatsurveypanestateful/PreChatSurveyPaneStateful.js +68 -2
- package/lib/cjs/components/prechatsurveypanestateful/common/defaultStyles/defaultGeneralPreChatSurveyPaneStyleProps.js +2 -1
- package/lib/cjs/components/proactivechatpanestateful/ProactiveChatPaneStateful.js +0 -1
- package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +157 -34
- package/lib/cjs/components/webchatcontainerstateful/common/DesignerChatAdapter.js +10 -0
- package/lib/cjs/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +117 -16
- package/lib/cjs/components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts.js +3 -0
- package/lib/cjs/components/webchatcontainerstateful/common/defaultProps/defaultWebChatContainerStatefulProps.js +2 -1
- package/lib/cjs/components/webchatcontainerstateful/common/defaultStyles/defaultAdaptiveCardStyles.js +5 -1
- package/lib/cjs/components/webchatcontainerstateful/common/defaultStyles/defaultWebChatStyles.js +2 -2
- package/lib/cjs/components/webchatcontainerstateful/common/utils/chatAdapterUtils.js +3 -1
- package/lib/cjs/components/webchatcontainerstateful/common/utils/citationA11y.js +195 -0
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +13 -2
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +160 -167
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +27 -8
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/attachmentMiddleware.js +2 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/attachments/AdaptiveCardAccessibilityWrapper.js +203 -0
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultAvatarTextStyles.js +1 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultSystemMessageStyles.js +8 -3
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultTimestampRetryStyles.js +8 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/NotDeliveredTimestamp.js +5 -13
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/attachmentSentAnnouncementMiddleware.js +81 -0
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/attachmentUploadValidatorMiddleware.js +29 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware.js +52 -8
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/notification/NotificationHandler.js +55 -1
- package/lib/cjs/contexts/common/LiveChatWidgetActionType.js +1 -0
- package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +17 -1
- package/lib/cjs/contexts/createReducer.js +15 -0
- package/lib/cjs/controller/componentController.js +13 -1
- package/lib/cjs/plugins/newMessageEventHandler.js +20 -3
- package/lib/esm/common/Constants.js +5 -0
- package/lib/esm/common/facades/FacadeChatSDK.js +236 -10
- package/lib/esm/common/telemetry/TelemetryConstants.js +14 -0
- package/lib/esm/common/telemetry/TelemetryManager.js +6 -1
- package/lib/esm/common/telemetry/loggers/appInsightsLogger.js +7 -7
- package/lib/esm/common/telemetry/sanitizeSasInPayload.js +75 -0
- package/lib/esm/common/utils/xssUtils.js +23 -51
- package/lib/esm/common/utils.js +99 -14
- package/lib/esm/components/citationpanestateful/CitationPaneStateful.js +8 -1
- package/lib/esm/components/confirmationpanestateful/ConfirmationPaneStateful.js +12 -1
- package/lib/esm/components/emailtranscriptpanestateful/EmailTranscriptPaneStateful.js +37 -14
- package/lib/esm/components/errorboundary/ErrorBoundary.js +4 -2
- package/lib/esm/components/livechatwidget/LiveChatWidget.js +9 -1
- package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +23 -6
- package/lib/esm/components/livechatwidget/common/ChatWidgetEvents.js +1 -0
- package/lib/esm/components/livechatwidget/common/PersistentConversationHandler.js +9 -0
- package/lib/esm/components/livechatwidget/common/authHelper.js +44 -4
- package/lib/esm/components/livechatwidget/common/createAdapter.js +3 -2
- package/lib/esm/components/livechatwidget/common/createMarkdown.js +98 -5
- package/lib/esm/components/livechatwidget/common/endChat.js +6 -0
- package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +186 -1
- package/lib/esm/components/livechatwidget/common/liveChatConfigUtils.js +33 -2
- package/lib/esm/components/livechatwidget/common/startChat.js +31 -14
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +125 -6
- package/lib/esm/components/postchatloadingpanestateful/PostChatLoadingPaneStateful.js +16 -4
- package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +7 -4
- package/lib/esm/components/prechatsurveypanestateful/PreChatSurveyPaneStateful.js +69 -3
- package/lib/esm/components/prechatsurveypanestateful/common/defaultStyles/defaultGeneralPreChatSurveyPaneStyleProps.js +2 -1
- package/lib/esm/components/proactivechatpanestateful/ProactiveChatPaneStateful.js +1 -2
- package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +158 -35
- package/lib/esm/components/webchatcontainerstateful/common/DesignerChatAdapter.js +10 -0
- package/lib/esm/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +117 -16
- package/lib/esm/components/webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts.js +3 -0
- package/lib/esm/components/webchatcontainerstateful/common/defaultProps/defaultWebChatContainerStatefulProps.js +2 -1
- package/lib/esm/components/webchatcontainerstateful/common/defaultStyles/defaultAdaptiveCardStyles.js +5 -1
- package/lib/esm/components/webchatcontainerstateful/common/defaultStyles/defaultWebChatStyles.js +2 -2
- package/lib/esm/components/webchatcontainerstateful/common/utils/chatAdapterUtils.js +3 -1
- package/lib/esm/components/webchatcontainerstateful/common/utils/citationA11y.js +188 -0
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +13 -2
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +160 -171
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +24 -6
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/attachmentMiddleware.js +2 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/attachments/AdaptiveCardAccessibilityWrapper.js +195 -0
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultAvatarTextStyles.js +1 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultSystemMessageStyles.js +8 -3
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultTimestampRetryStyles.js +8 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/NotDeliveredTimestamp.js +5 -13
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/attachmentSentAnnouncementMiddleware.js +74 -0
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/attachmentUploadValidatorMiddleware.js +29 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.js +1 -0
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/localizedStringsBotInitialsMiddleware.js +52 -8
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/notification/NotificationHandler.js +55 -1
- package/lib/esm/contexts/common/LiveChatWidgetActionType.js +1 -0
- package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +17 -1
- package/lib/esm/contexts/createReducer.js +15 -0
- package/lib/esm/controller/componentController.js +13 -1
- package/lib/esm/plugins/newMessageEventHandler.js +20 -3
- package/lib/types/common/Constants.d.ts +4 -0
- package/lib/types/common/facades/FacadeChatSDK.d.ts +29 -0
- package/lib/types/common/facades/types/IFacadeChatSDKInput.d.ts +3 -1
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +14 -2
- package/lib/types/common/telemetry/sanitizeSasInPayload.d.ts +24 -0
- package/lib/types/common/utils/xssUtils.d.ts +5 -21
- package/lib/types/common/utils.d.ts +12 -2
- package/lib/types/components/errorboundary/ErrorBoundary.d.ts +1 -1
- package/lib/types/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.d.ts +1 -0
- package/lib/types/components/livechatwidget/common/ChatWidgetEvents.d.ts +2 -1
- package/lib/types/components/livechatwidget/common/authHelper.d.ts +9 -2
- package/lib/types/components/livechatwidget/common/liveChatConfigUtils.d.ts +11 -0
- package/lib/types/components/livechatwidget/interfaces/IBotAuthActivitySubscriberOptionalParams.d.ts +1 -0
- package/lib/types/components/webchatcontainerstateful/common/utils/chatAdapterUtils.d.ts +1 -1
- package/lib/types/components/webchatcontainerstateful/common/utils/citationA11y.d.ts +1 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IAdaptiveCardStyles.d.ts +3 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IBotAuthConfig.d.ts +7 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.d.ts +1 -1
- package/lib/types/components/webchatcontainerstateful/interfaces/IWebChatContainerStatefulProps.d.ts +7 -0
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.d.ts +14 -38
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.d.ts +2 -0
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/attachments/AdaptiveCardAccessibilityWrapper.d.ts +18 -0
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/defaultStyles/defaultSystemMessageStyles.d.ts +3 -0
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/attachmentSentAnnouncementMiddleware.d.ts +12 -0
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/notification/NotificationHandler.d.ts +7 -0
- package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -0
- package/lib/types/contexts/common/ILiveChatWidgetLocalizedTexts.d.ts +17 -0
- package/lib/types/contexts/common/LiveChatWidgetActionType.d.ts +2 -1
- package/package.json +37 -9
|
@@ -7,70 +7,42 @@ exports.detectAndCleanXSS = void 0;
|
|
|
7
7
|
var _dompurify = _interopRequireDefault(require("dompurify"));
|
|
8
8
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
10
|
+
* Sanitizes text input and detects XSS attack patterns.
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* against various XSS techniques including script injection, event handler injection, style-based
|
|
15
|
-
* attacks, and encoded payloads.
|
|
12
|
+
* Sanitizes first with DOMPurify, then checks for malicious patterns in both
|
|
13
|
+
* the original and sanitized text to catch mutation XSS attacks.
|
|
16
14
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* - HTML event handlers (onmouseover, onclick, etc.)
|
|
20
|
-
* - Script tags (<script>)
|
|
21
|
-
* - CSS expression() functions
|
|
22
|
-
* - CSS url() functions
|
|
23
|
-
* - Position-based CSS attacks (position: fixed/absolute)
|
|
24
|
-
* - VBScript protocol URLs
|
|
25
|
-
* - Data URLs with HTML content
|
|
26
|
-
* - Fragment identifiers with escaped quotes
|
|
27
|
-
* - HTML entity-encoded angle brackets
|
|
28
|
-
*
|
|
29
|
-
* @param text - The input text to be analyzed and sanitized
|
|
30
|
-
* @returns An object containing:
|
|
31
|
-
* - cleanText: The sanitized version of the input text with all HTML tags and attributes removed
|
|
32
|
-
* - isXSSDetected: Boolean flag indicating whether potential XSS patterns were found in the original text
|
|
15
|
+
* @param text - Input text to sanitize
|
|
16
|
+
* @returns Object with cleanText (sanitized) and isXSSDetected flag
|
|
33
17
|
*/
|
|
34
18
|
const detectAndCleanXSS = text => {
|
|
35
|
-
//
|
|
36
|
-
const xssPatterns = [/javascript\s*:/gi,
|
|
37
|
-
// JavaScript protocol URLs (with optional spaces)
|
|
38
|
-
/vbscript\s*:/gi,
|
|
39
|
-
// VBScript protocol URLs (with optional spaces)
|
|
40
|
-
/on\w+\s*=/gi,
|
|
41
|
-
// HTML event handlers (onmouseover, onclick, onload, etc.)
|
|
42
|
-
/<\s*script/gi,
|
|
43
|
-
// Script tag opening (with optional spaces)
|
|
44
|
-
/expression\s*\(/gi,
|
|
45
|
-
// CSS expression() function (IE-specific)
|
|
46
|
-
/url\s*\(/gi,
|
|
47
|
-
// CSS url() function
|
|
48
|
-
/style\s*=.*position\s*:\s*fixed/gi,
|
|
49
|
-
// CSS position fixed attacks
|
|
50
|
-
/style\s*=.*position\s*:\s*absolute/gi,
|
|
51
|
-
// CSS position absolute attacks
|
|
52
|
-
/data\s*:\s*text\s*\/\s*html/gi,
|
|
53
|
-
// Data URLs containing HTML
|
|
54
|
-
/#.*\\"/gi,
|
|
55
|
-
// Fragment identifiers with escaped quotes
|
|
56
|
-
/>.*</gi // HTML entity-encoded angle brackets indicating tag structure
|
|
57
|
-
];
|
|
58
|
-
|
|
59
|
-
// Check if any XSS patterns are detected in the input text
|
|
60
|
-
const isXSSDetected = xssPatterns.some(pattern => pattern.test(text));
|
|
61
|
-
|
|
62
|
-
// Clean the text using DOMPurify with strict config
|
|
19
|
+
// Sanitize first to prevent mutation XSS (e.g., "s<iframe></iframe>tyle" → "style")
|
|
63
20
|
const cleanText = _dompurify.default.sanitize(text, {
|
|
64
21
|
ALLOWED_TAGS: [],
|
|
65
|
-
// No HTML tags allowed in title
|
|
66
22
|
ALLOWED_ATTR: [],
|
|
67
23
|
KEEP_CONTENT: true,
|
|
68
|
-
// Keep text content
|
|
69
24
|
ALLOW_DATA_ATTR: false,
|
|
70
25
|
ALLOW_UNKNOWN_PROTOCOLS: false,
|
|
71
26
|
SANITIZE_DOM: true,
|
|
72
27
|
FORCE_BODY: false
|
|
73
28
|
});
|
|
29
|
+
const contentChanged = text !== cleanText;
|
|
30
|
+
|
|
31
|
+
// Non-global regex patterns to avoid stateful .test() issues
|
|
32
|
+
const xssPatterns = [/javascript\s*:/i, /vbscript\s*:/i, /on\w+\s*=/i,
|
|
33
|
+
// Event handlers
|
|
34
|
+
/<\s*script/i, /<\s*iframe/i, /<\s*object/i, /<\s*embed/i, /<\s*svg/i, /expression\s*\(/i,
|
|
35
|
+
// IE CSS expressions
|
|
36
|
+
/style\s*=.*position\s*:\s*(fixed|absolute)/i, /data\s*:\s*text\s*\/\s*html/i, /#.*\\"/i, /&(lt|gt|#x3c|#60|#x3e|#62);/i,
|
|
37
|
+
// HTML entities
|
|
38
|
+
/&#x?[0-9a-f]+;.*</i, /\u003c.*\u003e/i,
|
|
39
|
+
// Unicode escapes
|
|
40
|
+
/src\s*=\s*["']?\s*javascript:/i, /href\s*=\s*["']?\s*javascript:/i];
|
|
41
|
+
const hasXSSPattern = xssPatterns.some(pattern => {
|
|
42
|
+
return pattern.test(text) || pattern.test(cleanText);
|
|
43
|
+
});
|
|
44
|
+
const hasHTMLStructure = /<[^>]+>/.test(text) && !/<[^>]+>/.test(cleanText);
|
|
45
|
+
const isXSSDetected = contentChanged || hasXSSPattern || hasHTMLStructure;
|
|
74
46
|
return {
|
|
75
47
|
cleanText,
|
|
76
48
|
isXSSDetected
|
package/lib/cjs/common/utils.js
CHANGED
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.getCustomEventValue = exports.getConversationDetailsCall = exports.getBroadcastChannelName = exports.formatTemplateString = exports.findParentFocusableElementsWithoutChildContainer = exports.findAllFocusableElement = exports.extractPreChatSurveyResponseValues = exports.escapeHtml = exports.debounceLeading = exports.createTimer = exports.createFileAndDownload = exports.checkContactIdError = exports.changeLanguageCodeFormatForWebChat = exports.addDelayInMs = void 0;
|
|
6
|
+
exports.getCustomEventValue = exports.getConversationDetailsCall = exports.getBroadcastChannelName = exports.formatTemplateString = exports.findParentFocusableElementsWithoutChildContainer = exports.findAllFocusableElement = exports.extractPreChatSurveyResponseValues = exports.escapeHtml = exports.debounceLeading = exports.createTimer = exports.createFileAndDownload = exports.checkContactIdError = exports.changeLanguageCodeFormatForWebChat = exports.announceMessageImmediately = exports.addDelayInMs = void 0;
|
|
7
7
|
exports.getDeviceType = getDeviceType;
|
|
8
8
|
exports.getWidgetEndChatEventName = exports.getWidgetCacheIdfromProps = exports.getWidgetCacheId = exports.getTimestampHourMinute = exports.getStateFromCache = exports.getLocaleDirection = exports.getIconText = exports.getDomain = void 0;
|
|
9
9
|
exports.isEndConversationDueToOverflowActivity = isEndConversationDueToOverflowActivity;
|
|
10
|
-
exports.
|
|
10
|
+
exports.parseAdaptiveCardPayload = exports.newGuid = exports.isValidCustomEvent = exports.isUndefinedOrEmpty = exports.isThisSessionPopout = exports.isNullOrUndefined = exports.isNullOrEmptyString = void 0;
|
|
11
|
+
exports.parseBooleanFromConfig = parseBooleanFromConfig;
|
|
12
|
+
exports.setTabIndices = exports.setOcUserAgent = exports.setFocusOnSendBox = exports.setFocusOnElement = exports.setAriaHiddenForSiblings = exports.preventFocusToMoveOutOfElement = exports.parseLowerCaseString = void 0;
|
|
11
13
|
var _Constants = require("./Constants");
|
|
12
14
|
var _TelemetryConstants = require("./telemetry/TelemetryConstants");
|
|
13
15
|
var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
|
|
@@ -83,28 +85,69 @@ exports.findAllFocusableElement = findAllFocusableElement;
|
|
|
83
85
|
const preventFocusToMoveOutOfElement = elementId => {
|
|
84
86
|
const container = document.getElementById(elementId);
|
|
85
87
|
if (!container) {
|
|
86
|
-
return;
|
|
88
|
+
return () => {/* no-op */};
|
|
87
89
|
}
|
|
88
90
|
const focusableElements = findAllFocusableElement(container);
|
|
89
91
|
if (!focusableElements) {
|
|
90
|
-
return;
|
|
92
|
+
return () => {/* no-op */};
|
|
91
93
|
}
|
|
92
94
|
const firstFocusableElement = focusableElements[0];
|
|
93
95
|
const lastFocusableElement = focusableElements[focusableElements.length - 1];
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
|
|
96
|
+
const cleanups = [];
|
|
97
|
+
if (firstFocusableElement === lastFocusableElement) {
|
|
98
|
+
const handler = e => {
|
|
99
|
+
if (e.key === _KeyCodes.KeyCodes.TAB && !e.shiftKey) {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
firstFocusableElement.focus();
|
|
102
|
+
} else if (e.key === _KeyCodes.KeyCodes.TAB && e.shiftKey) {
|
|
103
|
+
e.preventDefault();
|
|
104
|
+
firstFocusableElement.focus();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
firstFocusableElement.addEventListener("keydown", handler);
|
|
108
|
+
cleanups.push(() => firstFocusableElement.removeEventListener("keydown", handler));
|
|
109
|
+
} else {
|
|
110
|
+
const firstHandler = e => {
|
|
111
|
+
if (e.shiftKey && e.key === _KeyCodes.KeyCodes.TAB) {
|
|
112
|
+
e.preventDefault();
|
|
113
|
+
lastFocusableElement === null || lastFocusableElement === void 0 ? void 0 : lastFocusableElement.focus();
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
firstFocusableElement.addEventListener("keydown", firstHandler);
|
|
117
|
+
cleanups.push(() => firstFocusableElement.removeEventListener("keydown", firstHandler));
|
|
118
|
+
const lastHandler = e => {
|
|
119
|
+
if (!e.shiftKey && e.key === _KeyCodes.KeyCodes.TAB) {
|
|
120
|
+
e.preventDefault();
|
|
121
|
+
firstFocusableElement === null || firstFocusableElement === void 0 ? void 0 : firstFocusableElement.focus();
|
|
122
|
+
}
|
|
123
|
+
};
|
|
124
|
+
lastFocusableElement.addEventListener("keydown", lastHandler);
|
|
125
|
+
cleanups.push(() => lastFocusableElement.removeEventListener("keydown", lastHandler));
|
|
126
|
+
}
|
|
127
|
+
return () => cleanups.forEach(fn => fn());
|
|
106
128
|
};
|
|
107
129
|
exports.preventFocusToMoveOutOfElement = preventFocusToMoveOutOfElement;
|
|
130
|
+
const setAriaHiddenForSiblings = (elementId, shouldHide, stateMap) => {
|
|
131
|
+
const element = document.getElementById(elementId);
|
|
132
|
+
if (!(element !== null && element !== void 0 && element.parentElement)) return;
|
|
133
|
+
Array.from(element.parentElement.children).forEach(sibling => {
|
|
134
|
+
if (sibling !== element) {
|
|
135
|
+
if (shouldHide) {
|
|
136
|
+
stateMap.set(sibling, sibling.getAttribute("aria-hidden"));
|
|
137
|
+
sibling.setAttribute("aria-hidden", "true");
|
|
138
|
+
} else if (stateMap.has(sibling)) {
|
|
139
|
+
const original = stateMap.get(sibling);
|
|
140
|
+
if (original === null) {
|
|
141
|
+
sibling.removeAttribute("aria-hidden");
|
|
142
|
+
} else {
|
|
143
|
+
sibling.setAttribute("aria-hidden", original);
|
|
144
|
+
}
|
|
145
|
+
stateMap.delete(sibling);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
exports.setAriaHiddenForSiblings = setAriaHiddenForSiblings;
|
|
108
151
|
const setFocusOnSendBox = () => {
|
|
109
152
|
const sendBoxSelector = "textarea[data-id=\"webchat-sendbox-input\"]";
|
|
110
153
|
setFocusOnElement(sendBoxSelector);
|
|
@@ -115,6 +158,41 @@ const setFocusOnElement = selector => {
|
|
|
115
158
|
element === null || element === void 0 ? void 0 : element.focus();
|
|
116
159
|
};
|
|
117
160
|
exports.setFocusOnElement = setFocusOnElement;
|
|
161
|
+
const IMMEDIATE_ANNOUNCEMENT_REGION_ID = "oc-lcw-immediate-announcement";
|
|
162
|
+
|
|
163
|
+
// Announces a message to screen readers via an aria-live="assertive" region
|
|
164
|
+
// attached to document.body — outside the chat widget's DOM subtree — so the
|
|
165
|
+
// screen reader does not have to traverse chat content to reach it.
|
|
166
|
+
const announceMessageImmediately = message => {
|
|
167
|
+
if (!message || typeof document === "undefined") {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
let region = document.getElementById(IMMEDIATE_ANNOUNCEMENT_REGION_ID);
|
|
171
|
+
if (!region) {
|
|
172
|
+
region = document.createElement("div");
|
|
173
|
+
region.id = IMMEDIATE_ANNOUNCEMENT_REGION_ID;
|
|
174
|
+
region.setAttribute("aria-live", "assertive");
|
|
175
|
+
region.setAttribute("role", "alert");
|
|
176
|
+
region.setAttribute("aria-atomic", "true");
|
|
177
|
+
region.style.position = "absolute";
|
|
178
|
+
region.style.width = "1px";
|
|
179
|
+
region.style.height = "1px";
|
|
180
|
+
region.style.overflow = "hidden";
|
|
181
|
+
region.style.clip = "rect(0 0 0 0)";
|
|
182
|
+
region.style.clipPath = "inset(50%)";
|
|
183
|
+
region.style.whiteSpace = "nowrap";
|
|
184
|
+
document.body.appendChild(region);
|
|
185
|
+
}
|
|
186
|
+
region.textContent = "";
|
|
187
|
+
// Re-set on the next tick so screen readers detect the change even when
|
|
188
|
+
// the same message is announced twice in a row.
|
|
189
|
+
setTimeout(() => {
|
|
190
|
+
if (region) {
|
|
191
|
+
region.textContent = message;
|
|
192
|
+
}
|
|
193
|
+
}, 50);
|
|
194
|
+
};
|
|
195
|
+
exports.announceMessageImmediately = announceMessageImmediately;
|
|
118
196
|
const escapeHtml = inputString => {
|
|
119
197
|
const entityMap = {
|
|
120
198
|
"<": "<",
|
|
@@ -478,7 +556,7 @@ const setOcUserAgent = chatSDK => {
|
|
|
478
556
|
// eslint-disable-line @typescript-eslint/no-explicit-any
|
|
479
557
|
if ((_chatSDK$OCClient = chatSDK.OCClient) !== null && _chatSDK$OCClient !== void 0 && _chatSDK$OCClient.ocUserAgent && !((_chatSDK$OCClient2 = chatSDK.OCClient) !== null && _chatSDK$OCClient2 !== void 0 && _chatSDK$OCClient2.ocUserAgent.join(" ").includes("omnichannel-chat-widget/"))) {
|
|
480
558
|
try {
|
|
481
|
-
const version = require("
|
|
559
|
+
const version = require("../../package.json").version; // eslint-disable-line @typescript-eslint/no-var-requires
|
|
482
560
|
const userAgent = `omnichannel-chat-widget/${version}`;
|
|
483
561
|
chatSDK.OCClient.ocUserAgent = [userAgent, ...chatSDK.OCClient.ocUserAgent];
|
|
484
562
|
} catch (error) {
|
|
@@ -519,4 +597,15 @@ exports.getCustomEventValue = getCustomEventValue;
|
|
|
519
597
|
function isEndConversationDueToOverflowActivity(activity) {
|
|
520
598
|
var _activity$channelData, _activity$channelData2;
|
|
521
599
|
return (activity === null || activity === void 0 ? void 0 : (_activity$channelData = activity.channelData) === null || _activity$channelData === void 0 ? void 0 : _activity$channelData.tags) && Array.isArray(activity === null || activity === void 0 ? void 0 : (_activity$channelData2 = activity.channelData) === null || _activity$channelData2 === void 0 ? void 0 : _activity$channelData2.tags) && activity.channelData.tags.includes(_Constants.Constants.EndConversationDueToOverflow);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Parses a value that can be boolean or string ("true"/"false") into a boolean.
|
|
604
|
+
* Handles null/undefined by returning false.
|
|
605
|
+
*
|
|
606
|
+
* @param value - The value to parse (can be boolean, string, null, or undefined)
|
|
607
|
+
* @returns true if value is true or "true" (case-insensitive), false otherwise
|
|
608
|
+
*/
|
|
609
|
+
function parseBooleanFromConfig(value) {
|
|
610
|
+
return value === true || (value === null || value === void 0 ? void 0 : value.toString().toLowerCase()) === "true";
|
|
522
611
|
}
|
|
@@ -44,7 +44,7 @@ const CitationPaneStateful = props => {
|
|
|
44
44
|
|
|
45
45
|
// Initial focus pattern (mirrors ConfirmationPaneStateful): focus first focusable element (will re-attempt after visibility becomes true)
|
|
46
46
|
(0, _react.useEffect)(() => {
|
|
47
|
-
(0, _utils.preventFocusToMoveOutOfElement)(controlId);
|
|
47
|
+
const cleanup = (0, _utils.preventFocusToMoveOutOfElement)(controlId);
|
|
48
48
|
const focusableElements = (0, _utils.findAllFocusableElement)(`#${controlId}`);
|
|
49
49
|
requestAnimationFrame(() => {
|
|
50
50
|
if (focusableElements && focusableElements.length > 0 && focusableElements[0]) {
|
|
@@ -62,6 +62,13 @@ const CitationPaneStateful = props => {
|
|
|
62
62
|
Event: _TelemetryConstants.TelemetryEvent.UXCitationPaneCompleted,
|
|
63
63
|
ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
|
|
64
64
|
});
|
|
65
|
+
return () => {
|
|
66
|
+
// internal tracking: restore parent tab indices on unmount so focus
|
|
67
|
+
// can escape the widget even if the pane is dismissed by an
|
|
68
|
+
// external state change rather than a user button click.
|
|
69
|
+
(0, _utils.setTabIndices)(elements, initialTabIndexMap, true);
|
|
70
|
+
cleanup();
|
|
71
|
+
};
|
|
65
72
|
}, []);
|
|
66
73
|
|
|
67
74
|
// Retry focus once pane is actually visible (isReady) in case initial attempt occurred while wrapper was visibility:hidden
|
|
@@ -82,7 +82,7 @@ const ConfirmationPaneStateful = props => {
|
|
|
82
82
|
|
|
83
83
|
// Move focus to the first button
|
|
84
84
|
(0, _react.useEffect)(() => {
|
|
85
|
-
(0, _utils.preventFocusToMoveOutOfElement)(controlProps.id);
|
|
85
|
+
const cleanup = (0, _utils.preventFocusToMoveOutOfElement)(controlProps.id);
|
|
86
86
|
const focusableElements = (0, _utils.findAllFocusableElement)(`#${controlProps.id}`);
|
|
87
87
|
requestAnimationFrame(() => {
|
|
88
88
|
if (focusableElements && focusableElements.length > 0 && focusableElements[0]) {
|
|
@@ -100,6 +100,17 @@ const ConfirmationPaneStateful = props => {
|
|
|
100
100
|
Event: _TelemetryConstants.TelemetryEvent.UXConfirmationPaneCompleted,
|
|
101
101
|
ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
|
|
102
102
|
});
|
|
103
|
+
return () => {
|
|
104
|
+
// internal tracking: when the confirmation pane unmounts (page reload,
|
|
105
|
+
// parent state change, or any path that bypasses onConfirm /
|
|
106
|
+
// onCancel) the tab indices that were forced to -1 on sibling
|
|
107
|
+
// focusable elements must be restored, otherwise Tab order
|
|
108
|
+
// remains broken and focus can be trapped inside the widget.
|
|
109
|
+
// setTabIndices is a no-op when initialTabIndexMap is already
|
|
110
|
+
// empty (onConfirm / onCancel already restored).
|
|
111
|
+
(0, _utils.setTabIndices)(elements, initialTabIndexMap, true);
|
|
112
|
+
cleanup();
|
|
113
|
+
};
|
|
103
114
|
}, []);
|
|
104
115
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_DimLayer.DimLayer, {
|
|
105
116
|
brightness: (controlProps === null || controlProps === void 0 ? void 0 : controlProps.brightnessValueOnDim) ?? "0.2"
|
|
@@ -35,16 +35,23 @@ const EmailTranscriptPaneStateful = props => {
|
|
|
35
35
|
const [state, dispatch] = (0, _useChatContextStore.default)();
|
|
36
36
|
const [facadeChatSDK] = (0, _useFacadeChatSDKStore.default)();
|
|
37
37
|
const [initialEmail, setInitialEmail] = (0, _react.useState)("");
|
|
38
|
-
|
|
38
|
+
// restoreFocus=false is used on the submit path: the notification banner
|
|
39
|
+
// (success or error) takes focus via NotificationHandler.setFocusOnNotificationCloseButton,
|
|
40
|
+
// so an intermediate restore to the chat-widget shell would otherwise cause SRs to
|
|
41
|
+
// announce "Enter <widget>" in between the dialog and the banner.
|
|
42
|
+
const closeEmailTranscriptPane = function () {
|
|
43
|
+
let restoreFocus = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
|
|
39
44
|
dispatch({
|
|
40
45
|
type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_SHOW_EMAIL_TRANSCRIPT_PANE,
|
|
41
46
|
payload: false
|
|
42
47
|
});
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
+
if (restoreFocus) {
|
|
49
|
+
const previousFocusedElementId = state.appStates.previousElementIdOnFocusBeforeModalOpen;
|
|
50
|
+
if (previousFocusedElementId) {
|
|
51
|
+
(0, _utils.setFocusOnElement)("#" + previousFocusedElementId);
|
|
52
|
+
} else {
|
|
53
|
+
(0, _utils.setFocusOnSendBox)();
|
|
54
|
+
}
|
|
48
55
|
}
|
|
49
56
|
dispatch({
|
|
50
57
|
type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_PREVIOUS_FOCUSED_ELEMENT_ID,
|
|
@@ -55,23 +62,31 @@ const EmailTranscriptPaneStateful = props => {
|
|
|
55
62
|
const onSend = (0, _react.useCallback)(async email => {
|
|
56
63
|
var _state$domainStates;
|
|
57
64
|
const liveChatContext = state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.liveChatContext;
|
|
58
|
-
closeEmailTranscriptPane();
|
|
65
|
+
closeEmailTranscriptPane(false);
|
|
59
66
|
const chatTranscriptBody = {
|
|
60
67
|
emailAddress: email,
|
|
61
68
|
attachmentMessage: (props === null || props === void 0 ? void 0 : props.attachmentMessage) ?? "The following attachment was uploaded during the conversation:"
|
|
62
69
|
};
|
|
63
70
|
try {
|
|
64
|
-
var _state$domainStates2, _state$domainStates2$;
|
|
71
|
+
var _state$domainStates2, _state$domainStates2$, _state$domainStates3, _state$domainStates3$;
|
|
65
72
|
await (facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.emailLiveChatTranscript(chatTranscriptBody, {
|
|
66
73
|
liveChatContext
|
|
67
74
|
}));
|
|
68
|
-
|
|
75
|
+
const successMessage = (state === null || state === void 0 ? void 0 : (_state$domainStates2 = state.domainStates) === null || _state$domainStates2 === void 0 ? void 0 : (_state$domainStates2$ = _state$domainStates2.middlewareLocalizedTexts) === null || _state$domainStates2$ === void 0 ? void 0 : _state$domainStates2$.MIDDLEWARE_BANNER_FILE_EMAIL_ADDRESS_RECORDED_SUCCESS) ?? (_defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts === null || _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts === void 0 ? void 0 : _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_FILE_EMAIL_ADDRESS_RECORDED_SUCCESS);
|
|
76
|
+
// Announce from a live region at document.body level so the
|
|
77
|
+
// screen reader speaks the confirmation immediately, without
|
|
78
|
+
// traversing the chat transcript on the way to the banner.
|
|
79
|
+
// Prefix with the explicit state word so SR users hear the outcome
|
|
80
|
+
// (visual users already see a success icon on the banner).
|
|
81
|
+
const successSrPrefix = (state === null || state === void 0 ? void 0 : (_state$domainStates3 = state.domainStates) === null || _state$domainStates3 === void 0 ? void 0 : (_state$domainStates3$ = _state$domainStates3.middlewareLocalizedTexts) === null || _state$domainStates3$ === void 0 ? void 0 : _state$domainStates3$.MIDDLEWARE_SR_PREFIX_SUCCESS) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_SR_PREFIX_SUCCESS;
|
|
82
|
+
(0, _utils.announceMessageImmediately)(`${successSrPrefix}${successMessage}`);
|
|
83
|
+
_NotificationHandler.NotificationHandler.notifySuccess(_NotificationScenarios.NotificationScenarios.EmailAddressSaved, successMessage);
|
|
69
84
|
_TelemetryHelper.TelemetryHelper.logActionEventToAllTelemetry(_TelemetryConstants.LogLevel.INFO, {
|
|
70
85
|
Event: _TelemetryConstants.TelemetryEvent.EmailTranscriptSent,
|
|
71
86
|
Description: "Transcript sent to email successfully."
|
|
72
87
|
});
|
|
73
88
|
} catch (ex) {
|
|
74
|
-
var _state$
|
|
89
|
+
var _state$domainStates4, _state$domainStates4$, _state$domainStates5, _state$domainStates5$;
|
|
75
90
|
_TelemetryHelper.TelemetryHelper.logActionEventToAllTelemetry(_TelemetryConstants.LogLevel.ERROR, {
|
|
76
91
|
Event: _TelemetryConstants.TelemetryEvent.EmailTranscriptFailed,
|
|
77
92
|
Description: "Email transcript failed.",
|
|
@@ -79,8 +94,11 @@ const EmailTranscriptPaneStateful = props => {
|
|
|
79
94
|
exception: ex
|
|
80
95
|
}
|
|
81
96
|
});
|
|
82
|
-
const message = (0, _utils.formatTemplateString)((state === null || state === void 0 ? void 0 : (_state$
|
|
83
|
-
|
|
97
|
+
const message = (0, _utils.formatTemplateString)((state === null || state === void 0 ? void 0 : (_state$domainStates4 = state.domainStates) === null || _state$domainStates4 === void 0 ? void 0 : (_state$domainStates4$ = _state$domainStates4.middlewareLocalizedTexts) === null || _state$domainStates4$ === void 0 ? void 0 : _state$domainStates4$.MIDDLEWARE_BANNER_FILE_EMAIL_ADDRESS_RECORDED_ERROR) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_FILE_EMAIL_ADDRESS_RECORDED_ERROR, [email]);
|
|
98
|
+
const bannerMessage = (props === null || props === void 0 ? void 0 : props.bannerMessageOnError) ?? message;
|
|
99
|
+
const errorSrPrefix = (state === null || state === void 0 ? void 0 : (_state$domainStates5 = state.domainStates) === null || _state$domainStates5 === void 0 ? void 0 : (_state$domainStates5$ = _state$domainStates5.middlewareLocalizedTexts) === null || _state$domainStates5$ === void 0 ? void 0 : _state$domainStates5$.MIDDLEWARE_SR_PREFIX_ERROR) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_SR_PREFIX_ERROR;
|
|
100
|
+
(0, _utils.announceMessageImmediately)(`${errorSrPrefix}${bannerMessage}`);
|
|
101
|
+
_NotificationHandler.NotificationHandler.notifyError(_NotificationScenarios.NotificationScenarios.EmailTranscriptError, bannerMessage);
|
|
84
102
|
}
|
|
85
103
|
}, [props.attachmentMessage, props.bannerMessageOnError, facadeChatSDK, state.domainStates.liveChatContext]);
|
|
86
104
|
const controlProps = {
|
|
@@ -103,7 +121,7 @@ const EmailTranscriptPaneStateful = props => {
|
|
|
103
121
|
|
|
104
122
|
// Move focus to the first button
|
|
105
123
|
(0, _react.useEffect)(() => {
|
|
106
|
-
(0, _utils.preventFocusToMoveOutOfElement)(controlProps.id);
|
|
124
|
+
const cleanup = (0, _utils.preventFocusToMoveOutOfElement)(controlProps.id);
|
|
107
125
|
const focusableElements = (0, _utils.findAllFocusableElement)(`#${controlProps.id}`);
|
|
108
126
|
if (focusableElements) {
|
|
109
127
|
focusableElements[0].focus();
|
|
@@ -118,6 +136,11 @@ const EmailTranscriptPaneStateful = props => {
|
|
|
118
136
|
Event: _TelemetryConstants.TelemetryEvent.UXEmailTranscriptPaneCompleted,
|
|
119
137
|
ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
|
|
120
138
|
});
|
|
139
|
+
return () => {
|
|
140
|
+
// internal tracking: restore parent tab indices on unmount.
|
|
141
|
+
(0, _utils.setTabIndices)(elements, initialTabIndexMap, true);
|
|
142
|
+
cleanup();
|
|
143
|
+
};
|
|
121
144
|
}, [initialEmail]);
|
|
122
145
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_DimLayer.DimLayer, {
|
|
123
146
|
brightness: (controlProps === null || controlProps === void 0 ? void 0 : controlProps.brightnessValueOnDim) ?? "0.2"
|
|
@@ -19,11 +19,12 @@ function _possibleConstructorReturn(self, call) { if (call && (typeof call === "
|
|
|
19
19
|
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
|
|
20
20
|
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
|
|
21
21
|
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
|
|
22
|
+
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
22
23
|
const RenderChildrenFunction = _ref => {
|
|
23
24
|
let {
|
|
24
25
|
children
|
|
25
26
|
} = _ref;
|
|
26
|
-
return typeof children ===
|
|
27
|
+
return typeof children === "function" ? children() : children;
|
|
27
28
|
};
|
|
28
29
|
let ErrorBoundary = /*#__PURE__*/function (_Component) {
|
|
29
30
|
_inherits(ErrorBoundary, _Component);
|
|
@@ -35,8 +35,16 @@ const LiveChatWidget = props => {
|
|
|
35
35
|
throw new Error("chatConfig is required");
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
// Check configuration flags
|
|
38
39
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
|
-
const
|
|
40
|
+
const hasAuthClientFn = !!((_props$chatConfig = props.chatConfig) !== null && _props$chatConfig !== void 0 && (_props$chatConfig$Liv = _props$chatConfig.LiveChatConfigAuthSettings) !== null && _props$chatConfig$Liv !== void 0 && _props$chatConfig$Liv.msdyn_javascriptclientfunction);
|
|
41
|
+
const persistentChatEnabled = (0, _liveChatConfigUtils.isPersistentChatEnabled)((_props$chatConfig2 = props.chatConfig) === null || _props$chatConfig2 === void 0 ? void 0 : (_props$chatConfig2$Li = _props$chatConfig2.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig2$Li === void 0 ? void 0 : _props$chatConfig2$Li.msdyn_conversationmode);
|
|
42
|
+
|
|
43
|
+
// isAuthenticatedChat determines if FacadeChatSDK should require authentication:
|
|
44
|
+
// REGULAR AUTH FLOW (config-based):
|
|
45
|
+
// - Persistent chat enabled ? always authenticated
|
|
46
|
+
// - Auth settings exist ? authenticated from start
|
|
47
|
+
const isAuthenticatedChat = persistentChatEnabled || hasAuthClientFn;
|
|
40
48
|
if (!facadeChatSDK) {
|
|
41
49
|
var _props$mock;
|
|
42
50
|
setFacadeChatSDK(new _FacadeChatSDK.FacadeChatSDK({
|
package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js
CHANGED
|
@@ -44,7 +44,7 @@ const extractSasUrl = async attachment => {
|
|
|
44
44
|
}
|
|
45
45
|
return sasUrl;
|
|
46
46
|
};
|
|
47
|
-
const fetchBotAuthConfig = async (retries, interval) => {
|
|
47
|
+
const fetchBotAuthConfig = async (retries, interval, fallback) => {
|
|
48
48
|
_TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
|
|
49
49
|
Event: _TelemetryConstants.TelemetryEvent.SetBotAuthProviderFetchConfig
|
|
50
50
|
});
|
|
@@ -60,13 +60,23 @@ const fetchBotAuthConfig = async (retries, interval) => {
|
|
|
60
60
|
});
|
|
61
61
|
if (retries === 1) {
|
|
62
62
|
// Base Case
|
|
63
|
-
|
|
63
|
+
if (response !== undefined) {
|
|
64
|
+
return response;
|
|
65
|
+
}
|
|
66
|
+
if (fallback !== undefined) {
|
|
67
|
+
_TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.WARN, {
|
|
68
|
+
Event: _TelemetryConstants.TelemetryEvent.SetBotAuthProviderNotFound,
|
|
69
|
+
Description: `Failed to fetch bot auth config after maximum retries. Using fallback value: ${fallback}`
|
|
70
|
+
});
|
|
71
|
+
return fallback;
|
|
72
|
+
}
|
|
73
|
+
throw new Error("Failed to fetch bot auth config after maximum retries");
|
|
64
74
|
}
|
|
65
75
|
await delay(interval);
|
|
66
76
|
if (response !== undefined) {
|
|
67
77
|
return response;
|
|
68
78
|
}
|
|
69
|
-
return await fetchBotAuthConfig(--retries, interval);
|
|
79
|
+
return await fetchBotAuthConfig(--retries, interval, fallback);
|
|
70
80
|
};
|
|
71
81
|
let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
72
82
|
function BotAuthActivitySubscriber() {
|
|
@@ -76,6 +86,7 @@ let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
|
76
86
|
_defineProperty(this, "signInCardSeen", void 0);
|
|
77
87
|
_defineProperty(this, "fetchBotAuthConfigRetries", void 0);
|
|
78
88
|
_defineProperty(this, "fetchBotAuthConfigRetryInterval", void 0);
|
|
89
|
+
_defineProperty(this, "fallbackShowSignInCard", void 0);
|
|
79
90
|
this.signInCardSeen = new Set();
|
|
80
91
|
this.fetchBotAuthConfigRetries = 3;
|
|
81
92
|
this.fetchBotAuthConfigRetryInterval = 1000;
|
|
@@ -85,6 +96,11 @@ let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
|
85
96
|
if (optionalParams.fetchBotAuthConfigRetryInterval) {
|
|
86
97
|
this.fetchBotAuthConfigRetryInterval = optionalParams.fetchBotAuthConfigRetryInterval;
|
|
87
98
|
}
|
|
99
|
+
this.fallbackShowSignInCard = optionalParams.fallbackShowSignInCard;
|
|
100
|
+
_TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
|
|
101
|
+
Event: _TelemetryConstants.TelemetryEvent.SetBotAuthProviderFetchConfig,
|
|
102
|
+
Description: `BotAuthActivitySubscriber initialized with fallbackShowSignInCard: ${optionalParams.fallbackShowSignInCard}`
|
|
103
|
+
});
|
|
88
104
|
}
|
|
89
105
|
_createClass(BotAuthActivitySubscriber, [{
|
|
90
106
|
key: "applicable",
|
|
@@ -129,7 +145,7 @@ let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
|
129
145
|
_omnichannelChatComponents.BroadcastService.postMessage(event);
|
|
130
146
|
}
|
|
131
147
|
try {
|
|
132
|
-
const response = await fetchBotAuthConfig(this.fetchBotAuthConfigRetries, this.fetchBotAuthConfigRetryInterval);
|
|
148
|
+
const response = await fetchBotAuthConfig(this.fetchBotAuthConfigRetries, this.fetchBotAuthConfigRetryInterval, this.fallbackShowSignInCard);
|
|
133
149
|
if (response === false) {
|
|
134
150
|
_TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
|
|
135
151
|
Event: _TelemetryConstants.TelemetryEvent.SetBotAuthProviderHideCard
|
|
@@ -140,9 +156,10 @@ let BotAuthActivitySubscriber = /*#__PURE__*/function () {
|
|
|
140
156
|
});
|
|
141
157
|
return activity;
|
|
142
158
|
}
|
|
143
|
-
} catch {
|
|
159
|
+
} catch (e) {
|
|
144
160
|
_TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
|
|
145
|
-
Event: _TelemetryConstants.TelemetryEvent.SetBotAuthProviderNotFound
|
|
161
|
+
Event: _TelemetryConstants.TelemetryEvent.SetBotAuthProviderNotFound,
|
|
162
|
+
ExceptionDetails: e instanceof Error ? e.message : JSON.stringify(e)
|
|
146
163
|
});
|
|
147
164
|
//this is to ensure listener continues waiting for response
|
|
148
165
|
if (this.signInCardSeen.has(signInId)) {
|
|
@@ -10,6 +10,7 @@ var ChatWidgetEvents;
|
|
|
10
10
|
ChatWidgetEvents["FETCH_PERSISTENT_CHAT_HISTORY"] = "CHAT_WIDGET/FETCH_PERSISTENT_CHAT_HISTORY";
|
|
11
11
|
ChatWidgetEvents["NO_MORE_HISTORY_AVAILABLE"] = "CHAT_WIDGET/NO_MORE_HISTORY_AVAILABLE";
|
|
12
12
|
ChatWidgetEvents["HISTORY_LOAD_ERROR"] = "CHAT_WIDGET/HISTORY_LOAD_ERROR";
|
|
13
|
+
ChatWidgetEvents["HISTORY_BATCH_LOADED"] = "CHAT_WIDGET/HISTORY_BATCH_LOADED";
|
|
13
14
|
})(ChatWidgetEvents || (ChatWidgetEvents = {}));
|
|
14
15
|
var _default = ChatWidgetEvents;
|
|
15
16
|
exports.default = _default;
|
|
@@ -133,6 +133,12 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
|
|
|
133
133
|
}
|
|
134
134
|
const messagesDescOrder = (_ref = [...messages]) === null || _ref === void 0 ? void 0 : _ref.reverse();
|
|
135
135
|
this.processHistoryMessages(messagesDescOrder);
|
|
136
|
+
|
|
137
|
+
// Signal that a batch of history messages has been added to the store.
|
|
138
|
+
// LazyLoadActivity subscribes to this to apply scroll anchoring after render.
|
|
139
|
+
(0, _dispatchCustomEvent.default)(_ChatWidgetEvents.default.HISTORY_BATCH_LOADED, {
|
|
140
|
+
messageCount: messages.length
|
|
141
|
+
});
|
|
136
142
|
_TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
|
|
137
143
|
Event: _TelemetryConstants.TelemetryEvent.LCWPersistentHistoryPullCompleted,
|
|
138
144
|
Description: "History pull completed successfully",
|
|
@@ -241,6 +247,9 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
|
|
|
241
247
|
value: function processMessageToActivity(message) {
|
|
242
248
|
try {
|
|
243
249
|
const activity = (0, _convertPersistentChatHistoryMessageToActivity.default)(message);
|
|
250
|
+
if (!activity) {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
244
253
|
activity.id = activity.id || `activity-${this.count}`;
|
|
245
254
|
activity.channelData = {
|
|
246
255
|
...activity.channelData,
|