@microsoft/omnichannel-chat-widget 1.7.7-main.bdac0a6 → 1.7.8-main.270960e

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.
Files changed (44) hide show
  1. package/lib/cjs/common/Constants.js +1 -0
  2. package/lib/cjs/common/facades/FacadeChatSDK.js +2 -1
  3. package/lib/cjs/common/telemetry/TelemetryConstants.js +2 -0
  4. package/lib/cjs/common/utils.js +14 -2
  5. package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  6. package/lib/cjs/components/livechatwidget/common/authHelper.js +15 -0
  7. package/lib/cjs/components/livechatwidget/common/createInternetConnectionChangeHandler.js +10 -4
  8. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +14 -8
  9. package/lib/cjs/components/ooohpanestateful/OOOHPaneStateful.js +4 -0
  10. package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +15 -0
  11. package/lib/cjs/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +28 -0
  12. package/lib/cjs/components/prechatsurveypanestateful/PreChatSurveyPaneStateful.js +10 -5
  13. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +13 -1
  14. package/lib/cjs/components/webchatcontainerstateful/common/defaultStyles/defaultWebChatStyles.js +1 -1
  15. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +15 -2
  16. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.js +6 -2
  17. package/lib/cjs/plugins/createChatTranscript.js +9 -5
  18. package/lib/cjs/plugins/newMessageEventHandler.js +2 -2
  19. package/lib/esm/common/Constants.js +1 -0
  20. package/lib/esm/common/facades/FacadeChatSDK.js +2 -1
  21. package/lib/esm/common/telemetry/TelemetryConstants.js +2 -0
  22. package/lib/esm/common/utils.js +11 -1
  23. package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +4 -1
  24. package/lib/esm/components/livechatwidget/common/authHelper.js +15 -0
  25. package/lib/esm/components/livechatwidget/common/createInternetConnectionChangeHandler.js +10 -4
  26. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +14 -8
  27. package/lib/esm/components/ooohpanestateful/OOOHPaneStateful.js +4 -0
  28. package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +15 -0
  29. package/lib/esm/components/postchatsurveypanestateful/common/isValidSurveyUrl.js +21 -0
  30. package/lib/esm/components/prechatsurveypanestateful/PreChatSurveyPaneStateful.js +10 -5
  31. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +15 -3
  32. package/lib/esm/components/webchatcontainerstateful/common/defaultStyles/defaultWebChatStyles.js +1 -1
  33. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/DeliveredTimestamp.js +15 -2
  34. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/htmlTextMiddleware.js +6 -2
  35. package/lib/esm/plugins/createChatTranscript.js +9 -5
  36. package/lib/esm/plugins/newMessageEventHandler.js +2 -2
  37. package/lib/types/common/Constants.d.ts +1 -0
  38. package/lib/types/common/facades/FacadeChatSDK.d.ts +1 -1
  39. package/lib/types/common/telemetry/TelemetryConstants.d.ts +2 -0
  40. package/lib/types/common/telemetry/TelemetryHelper.d.ts +1 -0
  41. package/lib/types/common/utils.d.ts +1 -0
  42. package/lib/types/components/postchatsurveypanestateful/common/isValidSurveyUrl.d.ts +2 -0
  43. package/lib/types/components/webchatcontainerstateful/interfaces/IWebChatContainerStatefulProps.d.ts +1 -0
  44. package/package.json +2 -2
@@ -132,6 +132,7 @@ class HtmlClassNames {}
132
132
  exports.HtmlClassNames = HtmlClassNames;
133
133
  _defineProperty(HtmlClassNames, "webChatBannerCloseButton", "webchat__toast__dismissButton");
134
134
  _defineProperty(HtmlClassNames, "webChatBannerExpandButton", "webchat__toaster__expandIcon");
135
+ _defineProperty(HtmlClassNames, "webChatHistoryContainer", "webchat__basic-transcript");
135
136
  class HtmlElementSelectors {}
136
137
  exports.HtmlElementSelectors = HtmlElementSelectors;
137
138
  _defineProperty(HtmlElementSelectors, "sendBoxSelector", "textarea[data-id=\"webchat-sendbox-input\"]");
@@ -149,6 +149,7 @@ class FacadeChatSDK {
149
149
  }
150
150
  }
151
151
  async tokenRing() {
152
+ var _this$chatSDK$chatSDK;
152
153
  if (this.disableReauthentication === true) {
153
154
  // facade feature is disabled, so we are bypassing the re authentication and let it fail.
154
155
  return {
@@ -176,7 +177,7 @@ class FacadeChatSDK {
176
177
  message: "Token is valid"
177
178
  };
178
179
  }
179
- if (this.getAuthToken === undefined) {
180
+ if (this.getAuthToken === undefined && ((_this$chatSDK$chatSDK = this.chatSDK.chatSDKConfig) === null || _this$chatSDK$chatSDK === void 0 ? void 0 : _this$chatSDK$chatSDK.getAuthToken) === undefined) {
180
181
  _TelemetryHelper.TelemetryHelper.logFacadeChatSDKEvent(_TelemetryConstants.LogLevel.ERROR, {
181
182
  Event: _TelemetryConstants.TelemetryEvent.NewTokenFailed,
182
183
  Description: "GetAuthToken function is not present",
@@ -219,6 +219,8 @@ exports.TelemetryEvent = TelemetryEvent;
219
219
  TelemetryEvent["PostChatContextCallFailed"] = "PostChatContextCallFailed";
220
220
  TelemetryEvent["PostChatSurveyLoadingPaneLoaded"] = "PostChatSurveyLoadingPaneLoaded";
221
221
  TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
222
+ TelemetryEvent["PostChatSurveyUrlValidationCompleted"] = "PostChatSurveyUrlValidationCompleted";
223
+ TelemetryEvent["PostChatSurveyUrlValidationFailed"] = "PostChatSurveyUrlValidationFailed";
222
224
  TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
223
225
  TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
224
226
  TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
@@ -3,7 +3,9 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.setTabIndices = exports.setOcUserAgent = exports.setFocusOnSendBox = exports.setFocusOnElement = exports.preventFocusToMoveOutOfElement = exports.parseLowerCaseString = exports.parseAdaptiveCardPayload = exports.newGuid = exports.isUndefinedOrEmpty = exports.isThisSessionPopout = exports.isNullOrUndefined = exports.isNullOrEmptyString = exports.getWidgetEndChatEventName = exports.getWidgetCacheIdfromProps = exports.getWidgetCacheId = exports.getTimestampHourMinute = exports.getStateFromCache = exports.getLocaleDirection = exports.getIconText = exports.getDomain = 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.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;
7
+ exports.getDeviceType = getDeviceType;
8
+ exports.setTabIndices = exports.setOcUserAgent = exports.setFocusOnSendBox = exports.setFocusOnElement = exports.preventFocusToMoveOutOfElement = exports.parseLowerCaseString = exports.parseAdaptiveCardPayload = exports.newGuid = exports.isUndefinedOrEmpty = exports.isThisSessionPopout = exports.isNullOrUndefined = exports.isNullOrEmptyString = exports.getWidgetEndChatEventName = exports.getWidgetCacheIdfromProps = exports.getWidgetCacheId = exports.getTimestampHourMinute = exports.getStateFromCache = exports.getLocaleDirection = exports.getIconText = exports.getDomain = void 0;
7
9
  var _Constants = require("./Constants");
8
10
  var _TelemetryConstants = require("./telemetry/TelemetryConstants");
9
11
  var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
@@ -479,4 +481,14 @@ const setOcUserAgent = chatSDK => {
479
481
  }
480
482
  }
481
483
  };
482
- exports.setOcUserAgent = setOcUserAgent;
484
+ exports.setOcUserAgent = setOcUserAgent;
485
+ function getDeviceType() {
486
+ const userAgent = navigator.userAgent.toLowerCase();
487
+ if (/android/.test(userAgent)) {
488
+ return "android";
489
+ } else if (/iphone|ipad|ipod/.test(userAgent)) {
490
+ return "ios";
491
+ } else {
492
+ return "standard";
493
+ }
494
+ }
@@ -7,6 +7,7 @@ exports.BotAuthActivitySubscriber = void 0;
7
7
  var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components");
8
8
  var _TelemetryConstants = require("../../../../common/telemetry/TelemetryConstants");
9
9
  var _TelemetryHelper = require("../../../../common/telemetry/TelemetryHelper");
10
+ var _TelemetryManager = require("../../../../common/telemetry/TelemetryManager");
10
11
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
12
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
12
13
  function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
@@ -87,6 +88,7 @@ class BotAuthActivitySubscriber {
87
88
  return (activity === null || activity === void 0 ? void 0 : (_activity$attachments = activity.attachments) === null || _activity$attachments === void 0 ? void 0 : _activity$attachments.length) > 0 && activity.attachments[0] && supportedSignInCardContentTypes.indexOf(activity.attachments[0].contentType) >= 0;
88
89
  }
89
90
  async apply(activity) {
91
+ var _TelemetryManager$Int;
90
92
  this.observer.next(false); // Hides card
91
93
  const attachment = activity.attachments[0];
92
94
  const signInUrl = attachment.content.buttons[0].value;
@@ -106,7 +108,8 @@ class BotAuthActivitySubscriber {
106
108
  const event = {
107
109
  eventName: _TelemetryConstants.BroadcastEvent.SigninCardReceived,
108
110
  payload: {
109
- sasUrl
111
+ sasUrl,
112
+ conversationId: (_TelemetryManager$Int = _TelemetryManager.TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId
110
113
  }
111
114
  };
112
115
  if (!sasUrl) {
@@ -18,6 +18,7 @@ const getAuthClientFunction = chatConfig => {
18
18
  };
19
19
  exports.getAuthClientFunction = getAuthClientFunction;
20
20
  const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
21
+ var _chatSDK$chatSDKConfi;
21
22
  const authClientFunction = getAuthClientFunction(chatConfig);
22
23
  if (getAuthToken && authClientFunction) {
23
24
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
@@ -41,6 +42,20 @@ const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
41
42
  });
42
43
  throw new Error(_Constants.WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
43
44
  }
45
+ } else if (chatSDK !== null && chatSDK !== void 0 && (_chatSDK$chatSDKConfi = chatSDK.chatSDKConfig) !== null && _chatSDK$chatSDKConfi !== void 0 && _chatSDK$chatSDKConfi.getAuthToken) {
46
+ var _chatSDK$chatSDKConfi2;
47
+ const token = await ((_chatSDK$chatSDKConfi2 = chatSDK.chatSDKConfig) === null || _chatSDK$chatSDKConfi2 === void 0 ? void 0 : _chatSDK$chatSDKConfi2.getAuthToken());
48
+ if ((0, _utils.isNullOrEmptyString)(token)) {
49
+ _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.ERROR, {
50
+ Event: _TelemetryConstants.TelemetryEvent.ReceivedNullOrEmptyToken,
51
+ Description: "getAuthToken in chat SDK returns empty string"
52
+ });
53
+ throw new Error(_Constants.WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
54
+ }
55
+ return {
56
+ "result": true,
57
+ token
58
+ };
44
59
  }
45
60
  return {
46
61
  "result": false,
@@ -11,6 +11,8 @@ var _NotificationHandler = require("../../webchatcontainerstateful/webchatcontro
11
11
  var _NotificationScenarios = require("../../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios");
12
12
  var _TelemetryHelper = require("../../../common/telemetry/TelemetryHelper");
13
13
  var _defaultMiddlewareLocalizedTexts = require("../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts");
14
+ var _createReducer = require("../../../contexts/createReducer");
15
+ var _LiveChatWidgetActionType = require("../../../contexts/common/LiveChatWidgetActionType");
14
16
  const isInternetConnected = async () => {
15
17
  try {
16
18
  const response = await fetch(_Constants.Constants.internetConnectionTestUrl);
@@ -23,18 +25,22 @@ const isInternetConnected = async () => {
23
25
  const createInternetConnectionChangeHandler = async state => {
24
26
  const handler = async () => {
25
27
  const connected = await isInternetConnected();
28
+ const inMemoryState = (0, _createReducer.executeReducer)(state, {
29
+ type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
30
+ payload: null
31
+ });
26
32
  if (!connected) {
27
- var _state$domainStates, _state$domainStates$m;
33
+ var _inMemoryState$domain, _inMemoryState$domain2;
28
34
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.WARN, {
29
35
  Event: _TelemetryConstants.TelemetryEvent.NetworkDisconnected
30
36
  });
31
- _NotificationHandler.NotificationHandler.notifyError(_NotificationScenarios.NotificationScenarios.InternetConnection, (state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : (_state$domainStates$m = _state$domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION);
37
+ _NotificationHandler.NotificationHandler.notifyError(_NotificationScenarios.NotificationScenarios.InternetConnection, (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$domain = inMemoryState.domainStates) === null || _inMemoryState$domain === void 0 ? void 0 : (_inMemoryState$domain2 = _inMemoryState$domain.middlewareLocalizedTexts) === null || _inMemoryState$domain2 === void 0 ? void 0 : _inMemoryState$domain2.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION);
32
38
  } else {
33
- var _state$domainStates2, _state$domainStates2$;
39
+ var _inMemoryState$domain3, _inMemoryState$domain4;
34
40
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.WARN, {
35
41
  Event: _TelemetryConstants.TelemetryEvent.NetworkReconnected
36
42
  });
37
- _NotificationHandler.NotificationHandler.notifySuccess(_NotificationScenarios.NotificationScenarios.InternetConnection, (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_INTERNET_BACK_ONLINE) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE);
43
+ _NotificationHandler.NotificationHandler.notifySuccess(_NotificationScenarios.NotificationScenarios.InternetConnection, (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$domain3 = inMemoryState.domainStates) === null || _inMemoryState$domain3 === void 0 ? void 0 : (_inMemoryState$domain4 = _inMemoryState$domain3.middlewareLocalizedTexts) === null || _inMemoryState$domain4 === void 0 ? void 0 : _inMemoryState$domain4.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE);
38
44
  _omnichannelChatComponents.BroadcastService.postMessage({
39
45
  eventName: _TelemetryConstants.BroadcastEvent.NetworkReconnected
40
46
  });
@@ -417,7 +417,7 @@ const LiveChatWidgetStateful = props => {
417
417
 
418
418
  // Start chat from SDK Event
419
419
  _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.StartChat).subscribe(msg => {
420
- var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3, _inMemoryState$appSta4, _inMemoryState$appSta5;
420
+ var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3;
421
421
  // If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
422
422
  if (typeof (props === null || props === void 0 ? void 0 : (_props$chatConfig5 = props.chatConfig) === null || _props$chatConfig5 === void 0 ? void 0 : (_props$chatConfig5$Li = _props$chatConfig5.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig5$Li === void 0 ? void 0 : _props$chatConfig5$Li.OutOfOperatingHours) === "string" && (props === null || props === void 0 ? void 0 : (_props$chatConfig6 = props.chatConfig) === null || _props$chatConfig6 === void 0 ? void 0 : (_props$chatConfig6$Li = _props$chatConfig6.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig6$Li === void 0 ? void 0 : _props$chatConfig6$Li.OutOfOperatingHours.toLowerCase()) === "true") {
423
423
  (state === null || state === void 0 ? void 0 : state.appStates.isMinimized) && dispatch({
@@ -455,8 +455,14 @@ const LiveChatWidgetStateful = props => {
455
455
  });
456
456
  inMemoryState.domainStates.customContext = msg === null || msg === void 0 ? void 0 : (_msg$payload9 = msg.payload) === null || _msg$payload9 === void 0 ? void 0 : _msg$payload9.customContext;
457
457
 
458
- // Only initiate new chat if widget runtime state is one of the followings
459
- if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === _ConversationState.ConversationState.Closed || ((_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.conversationState) === _ConversationState.ConversationState.InActive || ((_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === _ConversationState.ConversationState.Postchat) {
458
+ /*
459
+ * If the conversation is in closed state then we start a new chat,
460
+ * else if the conversation is in active state then we maximize the chat
461
+ * If the conversation is in inactive or postchat state then we maximize the chat.
462
+ *
463
+ * To start a new chat, it needs to be called via the close button or close chat via SDK.
464
+ **/
465
+ if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === _ConversationState.ConversationState.Closed) {
460
466
  _omnichannelChatComponents.BroadcastService.postMessage({
461
467
  eventName: _TelemetryConstants.BroadcastEvent.ChatInitiated
462
468
  });
@@ -465,7 +471,7 @@ const LiveChatWidgetStateful = props => {
465
471
  }
466
472
 
467
473
  // If minimized, maximize the chat
468
- if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.isMinimized) === true) {
474
+ if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.isMinimized) === true) {
469
475
  var _inMemoryState$domain, _inMemoryState$domain2, _inMemoryState$domain3, _inMemoryState$domain4;
470
476
  dispatch({
471
477
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_MINIMIZED,
@@ -593,12 +599,12 @@ const LiveChatWidgetStateful = props => {
593
599
  disablePolling: true
594
600
  });
595
601
  facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
596
- var _inMemoryState$appSta6;
602
+ var _inMemoryState$appSta4;
597
603
  const inMemoryState = (0, _createReducer.executeReducer)(state, {
598
604
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
599
605
  payload: null
600
606
  });
601
- if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta6 = inMemoryState.appStates) === null || _inMemoryState$appSta6 === void 0 ? void 0 : _inMemoryState$appSta6.conversationState) === _ConversationState.ConversationState.Active) {
607
+ if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === _ConversationState.ConversationState.Active) {
602
608
  setWebChatStyles(styles => {
603
609
  return {
604
610
  ...styles,
@@ -741,13 +747,13 @@ const LiveChatWidgetStateful = props => {
741
747
 
742
748
  // Handle Chat disconnect cases
743
749
  (0, _react2.useEffect)(() => {
744
- var _inMemoryState$appSta7;
750
+ var _inMemoryState$appSta5;
745
751
  const inMemoryState = (0, _createReducer.executeReducer)(state, {
746
752
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
747
753
  payload: null
748
754
  });
749
755
  (0, _chatDisconnectHelper.handleChatDisconnect)(props, inMemoryState, setWebChatStyles);
750
- const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta7 = inMemoryState.appStates) === null || _inMemoryState$appSta7 === void 0 ? void 0 : _inMemoryState$appSta7.chatDisconnectEventReceived;
756
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
751
757
  if (chatDisconnectState && adapter) {
752
758
  try {
753
759
  adapter.end();
@@ -11,6 +11,7 @@ var _omnichannelChatComponents = require("@microsoft/omnichannel-chat-components
11
11
  var _TelemetryHelper = require("../../common/telemetry/TelemetryHelper");
12
12
  var _defaultgeneralOOOHPaneStyleProps = require("./common/defaultStyleProps/defaultgeneralOOOHPaneStyleProps");
13
13
  var _useChatContextStore = _interopRequireDefault(require("../../hooks/useChatContextStore"));
14
+ var _dompurify = _interopRequireDefault(require("dompurify"));
14
15
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
16
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
16
17
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -49,6 +50,9 @@ const OutOfOfficeHoursPaneStateful = props => {
49
50
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
50
51
  });
51
52
  }, []);
53
+ if (controlProps !== null && controlProps !== void 0 && controlProps.titleText) {
54
+ controlProps.titleText = _dompurify.default.sanitize(controlProps.titleText);
55
+ }
52
56
  return /*#__PURE__*/_react.default.createElement(_omnichannelChatComponents.OutOfOfficeHoursPane, {
53
57
  componentOverrides: props.componentOverrides,
54
58
  controlProps: controlProps,
@@ -14,6 +14,7 @@ var _TelemetryHelper = require("../../common/telemetry/TelemetryHelper");
14
14
  var _defaultgeneralPostChatSurveyPaneStyleProps = require("./common/defaultStyleProps/defaultgeneralPostChatSurveyPaneStyleProps");
15
15
  var _utils = require("../../common/utils");
16
16
  var _useChatContextStore = _interopRequireDefault(require("../../hooks/useChatContextStore"));
17
+ var _isValidSurveyUrl = _interopRequireDefault(require("./common/isValidSurveyUrl"));
17
18
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
19
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
20
  function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
@@ -54,6 +55,20 @@ const PostChatSurveyPaneStateful = props => {
54
55
  surveyURL: ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.surveyURL) ?? surveyInviteLink,
55
56
  ...props.controlProps
56
57
  };
58
+ if (controlProps.surveyURL) {
59
+ if (!(0, _isValidSurveyUrl.default)(controlProps.surveyURL)) {
60
+ _TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.ERROR, {
61
+ Event: _TelemetryConstants.TelemetryEvent.PostChatSurveyUrlValidationFailed,
62
+ Description: `${controlProps.surveyURL} is not a valid Survey URL`
63
+ });
64
+ controlProps.surveyURL = "";
65
+ } else {
66
+ _TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
67
+ Event: _TelemetryConstants.TelemetryEvent.PostChatSurveyUrlValidationCompleted,
68
+ Description: `${controlProps.surveyURL} is a valid Survey URL`
69
+ });
70
+ }
71
+ }
57
72
 
58
73
  // Move focus to the first button
59
74
  (0, _react.useEffect)(() => {
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.default = void 0;
7
+ var _utils = require("../../../common/utils");
8
+ const validRootDomains = ["microsoft.com", "microsoft.us", "appsplatform.us", "powervirtualagents.cn"];
9
+ const isValidSurveyUrl = url => {
10
+ if ((0, _utils.isNullOrEmptyString)(url)) {
11
+ return false;
12
+ }
13
+ try {
14
+ const objectUrl = new URL(url);
15
+ if (!objectUrl.origin || objectUrl.origin === "null") {
16
+ return false;
17
+ }
18
+ const validDomain = validRootDomains.find(domain => objectUrl.origin.endsWith(domain));
19
+ if (validDomain) {
20
+ return true;
21
+ }
22
+ } catch (error) {
23
+ return false;
24
+ }
25
+ return false;
26
+ };
27
+ var _default = isValidSurveyUrl;
28
+ exports.default = _default;
@@ -145,11 +145,6 @@ const PreChatSurveyPaneStateful = props => {
145
145
  }
146
146
  }
147
147
  }
148
- // Move focus to the first button
149
- const firstElement = (0, _utils.findAllFocusableElement)(`#${controlProps.id}`);
150
- if (firstElement && firstElement[0]) {
151
- firstElement[0].focus();
152
- }
153
148
  _TelemetryHelper.TelemetryHelper.logLoadingEvent(_TelemetryConstants.LogLevel.INFO, {
154
149
  Event: _TelemetryConstants.TelemetryEvent.PrechatSurveyLoaded
155
150
  });
@@ -158,6 +153,16 @@ const PreChatSurveyPaneStateful = props => {
158
153
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
159
154
  });
160
155
  }, []);
156
+
157
+ // Set focus to the first element
158
+ (0, _react.useEffect)(() => {
159
+ if (!state.appStates.isMinimized) {
160
+ const firstElement = (0, _utils.findAllFocusableElement)(`#${controlProps.id}`);
161
+ if (firstElement && firstElement[0]) {
162
+ firstElement[0].focus();
163
+ }
164
+ }
165
+ }, [state.appStates.isMinimized]);
161
166
  return /*#__PURE__*/_react.default.createElement(_omnichannelChatComponents.PreChatSurveyPane, {
162
167
  controlProps: controlProps,
163
168
  styleProps: styleProps
@@ -83,7 +83,12 @@ const WebChatContainerStateful = props => {
83
83
  };
84
84
  (0, _react2.useEffect)(() => {
85
85
  var _props$webChatContain, _props$webChatContain2;
86
- (0, _utils.setFocusOnSendBox)();
86
+ if ((0, _utils.getDeviceType)() !== "standard" && (webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.webChatHistoryMobileAccessibilityLabel) !== undefined) {
87
+ const chatHistoryElement = document.querySelector(`.${_Constants.HtmlClassNames.webChatHistoryContainer}`);
88
+ if (chatHistoryElement) {
89
+ chatHistoryElement.setAttribute(_Constants.HtmlAttributeNames.ariaLabel, webChatContainerProps.webChatHistoryMobileAccessibilityLabel);
90
+ }
91
+ }
87
92
  dispatch({
88
93
  type: _LiveChatWidgetActionType.LiveChatWidgetActionType.SET_RENDERING_MIDDLEWARE_PROPS,
89
94
  payload: webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.renderingMiddlewareProps
@@ -164,6 +169,13 @@ const WebChatContainerStateful = props => {
164
169
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
165
170
  });
166
171
  }, []);
172
+
173
+ // Set focus to the sendbox
174
+ (0, _react2.useEffect)(() => {
175
+ if (!state.appStates.isMinimized) {
176
+ (0, _utils.setFocusOnSendBox)();
177
+ }
178
+ }, [state.appStates.isMinimized]);
167
179
  return /*#__PURE__*/_react2.default.createElement(_react2.default.Fragment, null, /*#__PURE__*/_react2.default.createElement("style", null, `
168
180
  .webchat__stacked-layout__content .ac-pushButton {
169
181
  cursor: pointer;
@@ -60,6 +60,6 @@ const defaultWebChatStyles = {
60
60
  "</3": "💔",
61
61
  "<\\3": "💔"
62
62
  },
63
- uploadMultiple: false
63
+ sendAttachmentOn: "attach"
64
64
  };
65
65
  exports.defaultWebChatStyles = defaultWebChatStyles;
@@ -31,15 +31,28 @@ const DeliveredTimestamp = _ref => {
31
31
  timestamp
32
32
  }
33
33
  } = args;
34
+ const getTimeElement = timestamp => {
35
+ const timeString = (0, _utils.getTimestampHourMinute)(timestamp);
36
+ const isAmPmFormat = timeString.toLowerCase().includes("am") || timeString.toLowerCase().includes("pm");
37
+
38
+ // For clients that use languages that are written right-to-left, but still use AM/PM time format, we need to
39
+ // make sure the "rtl" direction doesn't produce "PM 1:23", but remains "1:23 PM"
40
+ if (dir === "rtl" && isAmPmFormat) {
41
+ return /*#__PURE__*/_react.default.createElement("span", {
42
+ dir: "ltr"
43
+ }, (0, _utils.getTimestampHourMinute)(timestamp));
44
+ }
45
+ return timeString;
46
+ };
34
47
  return /*#__PURE__*/_react.default.createElement(_react2.Stack, {
35
48
  style: contentStyles,
36
49
  dir: dir
37
50
  }, role === _DirectLineSenderRole.DirectLineSenderRole.Bot && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
38
51
  dir: dir,
39
52
  "aria-hidden": "false"
40
- }, name, " - ", (0, _utils.getTimestampHourMinute)(timestamp))), role === _DirectLineSenderRole.DirectLineSenderRole.User && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
53
+ }, name, " - ", getTimeElement(timestamp))), role === _DirectLineSenderRole.DirectLineSenderRole.User && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement("span", {
41
54
  "aria-hidden": "false",
42
55
  dir: dir
43
- }, " ", (0, _utils.getTimestampHourMinute)(timestamp), " - ", ((_state$domainStates$m = state.domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_MESSAGE_DELIVERED) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_MESSAGE_DELIVERED)));
56
+ }, " ", getTimeElement(timestamp), " - ", ((_state$domainStates$m = state.domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_MESSAGE_DELIVERED) ?? _defaultMiddlewareLocalizedTexts.defaultMiddlewareLocalizedTexts.MIDDLEWARE_MESSAGE_DELIVERED)));
44
57
  };
45
58
  exports.DeliveredTimestamp = DeliveredTimestamp;
@@ -41,6 +41,7 @@ const convertTextToHtmlNode = text => {
41
41
 
42
42
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
43
  const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
44
+ var _htmlNode$tagName;
44
45
  const htmlNode = convertTextToHtmlNode(text);
45
46
  const aNodes = htmlNode.getElementsByTagName(_Constants.HtmlAttributeNames.aTagName);
46
47
  if ((aNodes === null || aNodes === void 0 ? void 0 : aNodes.length) > 0) {
@@ -70,8 +71,6 @@ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
70
71
  }
71
72
  }
72
73
  }
73
-
74
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
74
  action = (0, _simpleUpdateIn.default)(action, [_Constants.Constants.payload, _Constants.Constants.activity, _Constants.Constants.text], () => htmlNode.innerHTML);
76
75
  } catch (e) {
77
76
  let errorMessage = "Failed to apply action: ";
@@ -89,6 +88,11 @@ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
89
88
  });
90
89
  }
91
90
  }
91
+
92
+ // if empty div tag after sanitization
93
+ if (((_htmlNode$tagName = htmlNode.tagName) === null || _htmlNode$tagName === void 0 ? void 0 : _htmlNode$tagName.toLowerCase()) === _Constants.HtmlAttributeNames.div && htmlNode.children.length === 0 && htmlNode.innerHTML.trim() === "") {
94
+ action = (0, _simpleUpdateIn.default)(action, [_Constants.Constants.payload, _Constants.Constants.activity, _Constants.Constants.text], () => "");
95
+ }
92
96
  return action;
93
97
  };
94
98
 
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = void 0;
7
7
  var _utils = require("../common/utils");
8
8
  var _defaultLibraryScripts = _interopRequireDefault(require("../components/footerstateful/downloadtranscriptstateful/common/defaultLibraryScripts"));
9
+ var _dompurify = _interopRequireDefault(require("dompurify"));
9
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
10
11
  function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
11
12
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
@@ -172,7 +173,7 @@ class TranscriptHTMLBuilder {
172
173
  <script>
173
174
  class Translator {
174
175
  static convertTranscriptMessageToActivity(message) {
175
- const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
176
+ const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences, amsreferences} = message;
176
177
 
177
178
  //it's required to convert the id to a number, otherwise the webchat will not render the messages in the correct order
178
179
  // if the OrginalMessageId is not present, we can use the id as the sequence id, which is always present.
@@ -219,7 +220,7 @@ class TranscriptHTMLBuilder {
219
220
  }
220
221
 
221
222
  // Attachments
222
- if (amsReferences && amsMetadata) {
223
+ if ((amsReferences || amsreferences) && amsMetadata) {
223
224
  const metadata = JSON.parse(amsMetadata);
224
225
  const { fileName } = metadata[0];
225
226
  const text = \`${this.attachmentMessage}\${fileName}\`;
@@ -243,7 +244,7 @@ class TranscriptHTMLBuilder {
243
244
  // Message
244
245
  if (content) {
245
246
  // Adaptive card formatting
246
- if (content.includes('"text"') && content.includes('"attachments"') && content.includes('"suggestedActions"')) {
247
+ if (content.includes('"attachments"') || content.includes('"suggestedActions"')) {
247
248
  try {
248
249
  const partialActivity = JSON.parse(content);
249
250
  return {
@@ -674,12 +675,15 @@ const createChatTranscript = async function (transcript, facadeChatSDK) {
674
675
  reader.readAsDataURL(blob);
675
676
  });
676
677
  };
677
- let messages = transcriptMessages;
678
+ let messages = transcriptMessages.filter(message => {
679
+ message.content = _dompurify.default.sanitize(message.content);
680
+ return message;
681
+ });
678
682
  if (renderAttachments) {
679
683
  messages = await Promise.all(transcriptMessages.map(async message => {
680
684
  // eslint-disable-line @typescript-eslint/no-explicit-any
681
685
  const {
682
- amsReferences,
686
+ amsReferences = message.amsreferences,
683
687
  amsMetadata
684
688
  } = message;
685
689
  if (amsReferences && amsMetadata) {
@@ -89,7 +89,7 @@ const createOnNewAdapterActivityHandler = (chatId, userId) => {
89
89
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
90
90
  Event: _TelemetryConstants.TelemetryEvent.MessageReceived,
91
91
  Description: "New message received",
92
- Data: payload
92
+ CustomProperties: payload
93
93
  });
94
94
  } else {
95
95
  if (!isHistoryMessageReceivedEventRasied) {
@@ -97,7 +97,7 @@ const createOnNewAdapterActivityHandler = (chatId, userId) => {
97
97
  _TelemetryHelper.TelemetryHelper.logActionEvent(_TelemetryConstants.LogLevel.INFO, {
98
98
  Event: _TelemetryConstants.TelemetryEvent.RehydrateMessageReceived,
99
99
  Description: "History message received",
100
- Data: payload
100
+ CustomProperties: payload
101
101
  });
102
102
  }
103
103
  }
@@ -122,6 +122,7 @@ _defineProperty(HtmlIdNames, "MSLiveChatWidget", "MSLiveChatWidget");
122
122
  export class HtmlClassNames {}
123
123
  _defineProperty(HtmlClassNames, "webChatBannerCloseButton", "webchat__toast__dismissButton");
124
124
  _defineProperty(HtmlClassNames, "webChatBannerExpandButton", "webchat__toaster__expandIcon");
125
+ _defineProperty(HtmlClassNames, "webChatHistoryContainer", "webchat__basic-transcript");
125
126
  export class HtmlElementSelectors {}
126
127
  _defineProperty(HtmlElementSelectors, "sendBoxSelector", "textarea[data-id=\"webchat-sendbox-input\"]");
127
128
  export class HtmlAttributeNames {}
@@ -143,6 +143,7 @@ export class FacadeChatSDK {
143
143
  }
144
144
  }
145
145
  async tokenRing() {
146
+ var _this$chatSDK$chatSDK;
146
147
  if (this.disableReauthentication === true) {
147
148
  // facade feature is disabled, so we are bypassing the re authentication and let it fail.
148
149
  return {
@@ -170,7 +171,7 @@ export class FacadeChatSDK {
170
171
  message: "Token is valid"
171
172
  };
172
173
  }
173
- if (this.getAuthToken === undefined) {
174
+ if (this.getAuthToken === undefined && ((_this$chatSDK$chatSDK = this.chatSDK.chatSDKConfig) === null || _this$chatSDK$chatSDK === void 0 ? void 0 : _this$chatSDK$chatSDK.getAuthToken) === undefined) {
174
175
  TelemetryHelper.logFacadeChatSDKEvent(LogLevel.ERROR, {
175
176
  Event: TelemetryEvent.NewTokenFailed,
176
177
  Description: "GetAuthToken function is not present",
@@ -213,6 +213,8 @@ export let TelemetryEvent;
213
213
  TelemetryEvent["PostChatContextCallFailed"] = "PostChatContextCallFailed";
214
214
  TelemetryEvent["PostChatSurveyLoadingPaneLoaded"] = "PostChatSurveyLoadingPaneLoaded";
215
215
  TelemetryEvent["PostChatSurveyLoaded"] = "PostChatSurveyLoaded";
216
+ TelemetryEvent["PostChatSurveyUrlValidationCompleted"] = "PostChatSurveyUrlValidationCompleted";
217
+ TelemetryEvent["PostChatSurveyUrlValidationFailed"] = "PostChatSurveyUrlValidationFailed";
216
218
  TelemetryEvent["ChatDisconnectThreadEventReceived"] = "ChatDisconnectThreadEventReceived";
217
219
  TelemetryEvent["HiddenAdaptiveCardMessageReceived"] = "HiddenAdaptiveCardMessageReceived";
218
220
  TelemetryEvent["EndingAdapterAfterDisconnectionError"] = "EndingAdapterAfterDisconnectionError";
@@ -440,4 +440,14 @@ export const setOcUserAgent = chatSDK => {
440
440
  console.warn(error);
441
441
  }
442
442
  }
443
- };
443
+ };
444
+ export function getDeviceType() {
445
+ const userAgent = navigator.userAgent.toLowerCase();
446
+ if (/android/.test(userAgent)) {
447
+ return "android";
448
+ } else if (/iphone|ipad|ipod/.test(userAgent)) {
449
+ return "ios";
450
+ } else {
451
+ return "standard";
452
+ }
453
+ }
@@ -6,6 +6,7 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
6
6
  import { BroadcastService } from "@microsoft/omnichannel-chat-components";
7
7
  import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../../../common/telemetry/TelemetryConstants";
8
8
  import { TelemetryHelper } from "../../../../common/telemetry/TelemetryHelper";
9
+ import { TelemetryManager } from "../../../../common/telemetry/TelemetryManager";
9
10
  const supportedSignInCardContentTypes = ["application/vnd.microsoft.card.signin", "application/vnd.microsoft.card.oauth"];
10
11
  const botOauthUrlRegex = /[\S]+.botframework.com\/api\/oauth\/signin\?signin=([\S]+)/;
11
12
  const delay = t => new Promise(resolve => setTimeout(resolve, t));
@@ -83,6 +84,7 @@ export class BotAuthActivitySubscriber {
83
84
  return (activity === null || activity === void 0 ? void 0 : (_activity$attachments = activity.attachments) === null || _activity$attachments === void 0 ? void 0 : _activity$attachments.length) > 0 && activity.attachments[0] && supportedSignInCardContentTypes.indexOf(activity.attachments[0].contentType) >= 0;
84
85
  }
85
86
  async apply(activity) {
87
+ var _TelemetryManager$Int;
86
88
  this.observer.next(false); // Hides card
87
89
  const attachment = activity.attachments[0];
88
90
  const signInUrl = attachment.content.buttons[0].value;
@@ -102,7 +104,8 @@ export class BotAuthActivitySubscriber {
102
104
  const event = {
103
105
  eventName: BroadcastEvent.SigninCardReceived,
104
106
  payload: {
105
- sasUrl
107
+ sasUrl,
108
+ conversationId: (_TelemetryManager$Int = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int === void 0 ? void 0 : _TelemetryManager$Int.conversationId
106
109
  }
107
110
  };
108
111
  if (!sasUrl) {
@@ -11,6 +11,7 @@ const getAuthClientFunction = chatConfig => {
11
11
  return authClientFunction;
12
12
  };
13
13
  const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
14
+ var _chatSDK$chatSDKConfi;
14
15
  const authClientFunction = getAuthClientFunction(chatConfig);
15
16
  if (getAuthToken && authClientFunction) {
16
17
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
@@ -34,6 +35,20 @@ const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
34
35
  });
35
36
  throw new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
36
37
  }
38
+ } else if (chatSDK !== null && chatSDK !== void 0 && (_chatSDK$chatSDKConfi = chatSDK.chatSDKConfig) !== null && _chatSDK$chatSDKConfi !== void 0 && _chatSDK$chatSDKConfi.getAuthToken) {
39
+ var _chatSDK$chatSDKConfi2;
40
+ const token = await ((_chatSDK$chatSDKConfi2 = chatSDK.chatSDKConfig) === null || _chatSDK$chatSDKConfi2 === void 0 ? void 0 : _chatSDK$chatSDKConfi2.getAuthToken());
41
+ if (isNullOrEmptyString(token)) {
42
+ TelemetryHelper.logActionEvent(LogLevel.ERROR, {
43
+ Event: TelemetryEvent.ReceivedNullOrEmptyToken,
44
+ Description: "getAuthToken in chat SDK returns empty string"
45
+ });
46
+ throw new Error(WidgetLoadCustomErrorString.AuthenticationFailedErrorString);
47
+ }
48
+ return {
49
+ "result": true,
50
+ token
51
+ };
37
52
  }
38
53
  return {
39
54
  "result": false,
@@ -5,6 +5,8 @@ import { NotificationHandler } from "../../webchatcontainerstateful/webchatcontr
5
5
  import { NotificationScenarios } from "../../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios";
6
6
  import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
7
7
  import { defaultMiddlewareLocalizedTexts } from "../../webchatcontainerstateful/common/defaultProps/defaultMiddlewareLocalizedTexts";
8
+ import { executeReducer } from "../../../contexts/createReducer";
9
+ import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
8
10
  const isInternetConnected = async () => {
9
11
  try {
10
12
  const response = await fetch(Constants.internetConnectionTestUrl);
@@ -17,18 +19,22 @@ const isInternetConnected = async () => {
17
19
  export const createInternetConnectionChangeHandler = async state => {
18
20
  const handler = async () => {
19
21
  const connected = await isInternetConnected();
22
+ const inMemoryState = executeReducer(state, {
23
+ type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
24
+ payload: null
25
+ });
20
26
  if (!connected) {
21
- var _state$domainStates, _state$domainStates$m;
27
+ var _inMemoryState$domain, _inMemoryState$domain2;
22
28
  TelemetryHelper.logActionEvent(LogLevel.WARN, {
23
29
  Event: TelemetryEvent.NetworkDisconnected
24
30
  });
25
- NotificationHandler.notifyError(NotificationScenarios.InternetConnection, (state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : (_state$domainStates$m = _state$domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION);
31
+ NotificationHandler.notifyError(NotificationScenarios.InternetConnection, (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$domain = inMemoryState.domainStates) === null || _inMemoryState$domain === void 0 ? void 0 : (_inMemoryState$domain2 = _inMemoryState$domain.middlewareLocalizedTexts) === null || _inMemoryState$domain2 === void 0 ? void 0 : _inMemoryState$domain2.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_NO_INTERNET_CONNECTION);
26
32
  } else {
27
- var _state$domainStates2, _state$domainStates2$;
33
+ var _inMemoryState$domain3, _inMemoryState$domain4;
28
34
  TelemetryHelper.logActionEvent(LogLevel.WARN, {
29
35
  Event: TelemetryEvent.NetworkReconnected
30
36
  });
31
- NotificationHandler.notifySuccess(NotificationScenarios.InternetConnection, (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_INTERNET_BACK_ONLINE) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE);
37
+ NotificationHandler.notifySuccess(NotificationScenarios.InternetConnection, (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$domain3 = inMemoryState.domainStates) === null || _inMemoryState$domain3 === void 0 ? void 0 : (_inMemoryState$domain4 = _inMemoryState$domain3.middlewareLocalizedTexts) === null || _inMemoryState$domain4 === void 0 ? void 0 : _inMemoryState$domain4.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_BANNER_INTERNET_BACK_ONLINE);
32
38
  BroadcastService.postMessage({
33
39
  eventName: BroadcastEvent.NetworkReconnected
34
40
  });
@@ -409,7 +409,7 @@ export const LiveChatWidgetStateful = props => {
409
409
 
410
410
  // Start chat from SDK Event
411
411
  BroadcastService.getMessageByEventName(BroadcastEvent.StartChat).subscribe(msg => {
412
- var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3, _inMemoryState$appSta4, _inMemoryState$appSta5;
412
+ var _props$chatConfig5, _props$chatConfig5$Li, _props$chatConfig6, _props$chatConfig6$Li, _msg$payload5, _msg$payload6, _msg$payload7, _msg$payload9, _inMemoryState$appSta2, _inMemoryState$appSta3;
413
413
  // If chat is out of operating hours chat widget sets the conversation state to OutOfOffice.
414
414
  if (typeof (props === null || props === void 0 ? void 0 : (_props$chatConfig5 = props.chatConfig) === null || _props$chatConfig5 === void 0 ? void 0 : (_props$chatConfig5$Li = _props$chatConfig5.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig5$Li === void 0 ? void 0 : _props$chatConfig5$Li.OutOfOperatingHours) === "string" && (props === null || props === void 0 ? void 0 : (_props$chatConfig6 = props.chatConfig) === null || _props$chatConfig6 === void 0 ? void 0 : (_props$chatConfig6$Li = _props$chatConfig6.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig6$Li === void 0 ? void 0 : _props$chatConfig6$Li.OutOfOperatingHours.toLowerCase()) === "true") {
415
415
  (state === null || state === void 0 ? void 0 : state.appStates.isMinimized) && dispatch({
@@ -447,8 +447,14 @@ export const LiveChatWidgetStateful = props => {
447
447
  });
448
448
  inMemoryState.domainStates.customContext = msg === null || msg === void 0 ? void 0 : (_msg$payload9 = msg.payload) === null || _msg$payload9 === void 0 ? void 0 : _msg$payload9.customContext;
449
449
 
450
- // Only initiate new chat if widget runtime state is one of the followings
451
- if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === ConversationState.Closed || ((_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.conversationState) === ConversationState.InActive || ((_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === ConversationState.Postchat) {
450
+ /*
451
+ * If the conversation is in closed state then we start a new chat,
452
+ * else if the conversation is in active state then we maximize the chat
453
+ * If the conversation is in inactive or postchat state then we maximize the chat.
454
+ *
455
+ * To start a new chat, it needs to be called via the close button or close chat via SDK.
456
+ **/
457
+ if (((_inMemoryState$appSta2 = inMemoryState.appStates) === null || _inMemoryState$appSta2 === void 0 ? void 0 : _inMemoryState$appSta2.conversationState) === ConversationState.Closed) {
452
458
  BroadcastService.postMessage({
453
459
  eventName: BroadcastEvent.ChatInitiated
454
460
  });
@@ -457,7 +463,7 @@ export const LiveChatWidgetStateful = props => {
457
463
  }
458
464
 
459
465
  // If minimized, maximize the chat
460
- if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.isMinimized) === true) {
466
+ if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta3 = inMemoryState.appStates) === null || _inMemoryState$appSta3 === void 0 ? void 0 : _inMemoryState$appSta3.isMinimized) === true) {
461
467
  var _inMemoryState$domain, _inMemoryState$domain2, _inMemoryState$domain3, _inMemoryState$domain4;
462
468
  dispatch({
463
469
  type: LiveChatWidgetActionType.SET_MINIMIZED,
@@ -585,12 +591,12 @@ export const LiveChatWidgetStateful = props => {
585
591
  disablePolling: true
586
592
  });
587
593
  facadeChatSDK === null || facadeChatSDK === void 0 ? void 0 : facadeChatSDK.onAgentEndSession(event => {
588
- var _inMemoryState$appSta6;
594
+ var _inMemoryState$appSta4;
589
595
  const inMemoryState = executeReducer(state, {
590
596
  type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
591
597
  payload: null
592
598
  });
593
- if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta6 = inMemoryState.appStates) === null || _inMemoryState$appSta6 === void 0 ? void 0 : _inMemoryState$appSta6.conversationState) === ConversationState.Active) {
599
+ if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta4 = inMemoryState.appStates) === null || _inMemoryState$appSta4 === void 0 ? void 0 : _inMemoryState$appSta4.conversationState) === ConversationState.Active) {
594
600
  setWebChatStyles(styles => {
595
601
  return {
596
602
  ...styles,
@@ -733,13 +739,13 @@ export const LiveChatWidgetStateful = props => {
733
739
 
734
740
  // Handle Chat disconnect cases
735
741
  useEffect(() => {
736
- var _inMemoryState$appSta7;
742
+ var _inMemoryState$appSta5;
737
743
  const inMemoryState = executeReducer(state, {
738
744
  type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
739
745
  payload: null
740
746
  });
741
747
  handleChatDisconnect(props, inMemoryState, setWebChatStyles);
742
- const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta7 = inMemoryState.appStates) === null || _inMemoryState$appSta7 === void 0 ? void 0 : _inMemoryState$appSta7.chatDisconnectEventReceived;
748
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.chatDisconnectEventReceived;
743
749
  if (chatDisconnectState && adapter) {
744
750
  try {
745
751
  adapter.end();
@@ -5,6 +5,7 @@ import { OutOfOfficeHoursPane } from "@microsoft/omnichannel-chat-components";
5
5
  import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
6
6
  import { defaultGeneralStyleProps } from "./common/defaultStyleProps/defaultgeneralOOOHPaneStyleProps";
7
7
  import useChatContextStore from "../../hooks/useChatContextStore";
8
+ import DOMPurify from "dompurify";
8
9
  let uiTimer;
9
10
  export const OutOfOfficeHoursPaneStateful = props => {
10
11
  var _props$styleProps;
@@ -40,6 +41,9 @@ export const OutOfOfficeHoursPaneStateful = props => {
40
41
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
41
42
  });
42
43
  }, []);
44
+ if (controlProps !== null && controlProps !== void 0 && controlProps.titleText) {
45
+ controlProps.titleText = DOMPurify.sanitize(controlProps.titleText);
46
+ }
43
47
  return /*#__PURE__*/React.createElement(OutOfOfficeHoursPane, {
44
48
  componentOverrides: props.componentOverrides,
45
49
  controlProps: controlProps,
@@ -8,6 +8,7 @@ import { TelemetryHelper } from "../../common/telemetry/TelemetryHelper";
8
8
  import { defaultGeneralPostChatSurveyPaneStyleProps } from "./common/defaultStyleProps/defaultgeneralPostChatSurveyPaneStyleProps";
9
9
  import { findAllFocusableElement } from "../../common/utils";
10
10
  import useChatContextStore from "../../hooks/useChatContextStore";
11
+ import isValidSurveyUrl from "./common/isValidSurveyUrl";
11
12
  const generateSurveyInviteLink = function (surveyInviteLink, isEmbed, locale, compact) {
12
13
  let showMultiLingual = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false;
13
14
  const surveyLink = `${surveyInviteLink}
@@ -45,6 +46,20 @@ export const PostChatSurveyPaneStateful = props => {
45
46
  surveyURL: ((_props$controlProps = props.controlProps) === null || _props$controlProps === void 0 ? void 0 : _props$controlProps.surveyURL) ?? surveyInviteLink,
46
47
  ...props.controlProps
47
48
  };
49
+ if (controlProps.surveyURL) {
50
+ if (!isValidSurveyUrl(controlProps.surveyURL)) {
51
+ TelemetryHelper.logLoadingEvent(LogLevel.ERROR, {
52
+ Event: TelemetryEvent.PostChatSurveyUrlValidationFailed,
53
+ Description: `${controlProps.surveyURL} is not a valid Survey URL`
54
+ });
55
+ controlProps.surveyURL = "";
56
+ } else {
57
+ TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
58
+ Event: TelemetryEvent.PostChatSurveyUrlValidationCompleted,
59
+ Description: `${controlProps.surveyURL} is a valid Survey URL`
60
+ });
61
+ }
62
+ }
48
63
 
49
64
  // Move focus to the first button
50
65
  useEffect(() => {
@@ -0,0 +1,21 @@
1
+ import { isNullOrEmptyString } from "../../../common/utils";
2
+ const validRootDomains = ["microsoft.com", "microsoft.us", "appsplatform.us", "powervirtualagents.cn"];
3
+ const isValidSurveyUrl = url => {
4
+ if (isNullOrEmptyString(url)) {
5
+ return false;
6
+ }
7
+ try {
8
+ const objectUrl = new URL(url);
9
+ if (!objectUrl.origin || objectUrl.origin === "null") {
10
+ return false;
11
+ }
12
+ const validDomain = validRootDomains.find(domain => objectUrl.origin.endsWith(domain));
13
+ if (validDomain) {
14
+ return true;
15
+ }
16
+ } catch (error) {
17
+ return false;
18
+ }
19
+ return false;
20
+ };
21
+ export default isValidSurveyUrl;
@@ -136,11 +136,6 @@ export const PreChatSurveyPaneStateful = props => {
136
136
  }
137
137
  }
138
138
  }
139
- // Move focus to the first button
140
- const firstElement = findAllFocusableElement(`#${controlProps.id}`);
141
- if (firstElement && firstElement[0]) {
142
- firstElement[0].focus();
143
- }
144
139
  TelemetryHelper.logLoadingEvent(LogLevel.INFO, {
145
140
  Event: TelemetryEvent.PrechatSurveyLoaded
146
141
  });
@@ -149,6 +144,16 @@ export const PreChatSurveyPaneStateful = props => {
149
144
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
150
145
  });
151
146
  }, []);
147
+
148
+ // Set focus to the first element
149
+ useEffect(() => {
150
+ if (!state.appStates.isMinimized) {
151
+ const firstElement = findAllFocusableElement(`#${controlProps.id}`);
152
+ if (firstElement && firstElement[0]) {
153
+ firstElement[0].focus();
154
+ }
155
+ }
156
+ }, [state.appStates.isMinimized]);
152
157
  return /*#__PURE__*/React.createElement(PreChatSurveyPane, {
153
158
  controlProps: controlProps,
154
159
  styleProps: styleProps
@@ -3,10 +3,10 @@
3
3
  import { Stack } from "@fluentui/react";
4
4
  import { LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
5
5
  import React, { useEffect } from "react";
6
- import { createTimer, setFocusOnSendBox } from "../../common/utils";
6
+ import { createTimer, getDeviceType, setFocusOnSendBox } from "../../common/utils";
7
7
  import { BotMagicCodeStore } from "./webchatcontroller/BotMagicCodeStore";
8
8
  import { Components } from "botframework-webchat";
9
- import { Constants } from "../../common/Constants";
9
+ import { Constants, HtmlAttributeNames, HtmlClassNames } from "../../common/Constants";
10
10
  import { LiveChatWidgetActionType } from "../../contexts/common/LiveChatWidgetActionType";
11
11
  import { NotificationHandler } from "./webchatcontroller/notification/NotificationHandler";
12
12
  import { NotificationScenarios } from "./webchatcontroller/enums/NotificationScenarios";
@@ -75,7 +75,12 @@ export const WebChatContainerStateful = props => {
75
75
  };
76
76
  useEffect(() => {
77
77
  var _props$webChatContain, _props$webChatContain2;
78
- setFocusOnSendBox();
78
+ if (getDeviceType() !== "standard" && (webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.webChatHistoryMobileAccessibilityLabel) !== undefined) {
79
+ const chatHistoryElement = document.querySelector(`.${HtmlClassNames.webChatHistoryContainer}`);
80
+ if (chatHistoryElement) {
81
+ chatHistoryElement.setAttribute(HtmlAttributeNames.ariaLabel, webChatContainerProps.webChatHistoryMobileAccessibilityLabel);
82
+ }
83
+ }
79
84
  dispatch({
80
85
  type: LiveChatWidgetActionType.SET_RENDERING_MIDDLEWARE_PROPS,
81
86
  payload: webChatContainerProps === null || webChatContainerProps === void 0 ? void 0 : webChatContainerProps.renderingMiddlewareProps
@@ -156,6 +161,13 @@ export const WebChatContainerStateful = props => {
156
161
  ElapsedTimeInMilliseconds: uiTimer.milliSecondsElapsed
157
162
  });
158
163
  }, []);
164
+
165
+ // Set focus to the sendbox
166
+ useEffect(() => {
167
+ if (!state.appStates.isMinimized) {
168
+ setFocusOnSendBox();
169
+ }
170
+ }, [state.appStates.isMinimized]);
159
171
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("style", null, `
160
172
  .webchat__stacked-layout__content .ac-pushButton {
161
173
  cursor: pointer;
@@ -54,5 +54,5 @@ export const defaultWebChatStyles = {
54
54
  "</3": "💔",
55
55
  "<\\3": "💔"
56
56
  },
57
- uploadMultiple: false
57
+ sendAttachmentOn: "attach"
58
58
  };
@@ -25,14 +25,27 @@ export const DeliveredTimestamp = _ref => {
25
25
  timestamp
26
26
  }
27
27
  } = args;
28
+ const getTimeElement = timestamp => {
29
+ const timeString = getTimestampHourMinute(timestamp);
30
+ const isAmPmFormat = timeString.toLowerCase().includes("am") || timeString.toLowerCase().includes("pm");
31
+
32
+ // For clients that use languages that are written right-to-left, but still use AM/PM time format, we need to
33
+ // make sure the "rtl" direction doesn't produce "PM 1:23", but remains "1:23 PM"
34
+ if (dir === "rtl" && isAmPmFormat) {
35
+ return /*#__PURE__*/React.createElement("span", {
36
+ dir: "ltr"
37
+ }, getTimestampHourMinute(timestamp));
38
+ }
39
+ return timeString;
40
+ };
28
41
  return /*#__PURE__*/React.createElement(Stack, {
29
42
  style: contentStyles,
30
43
  dir: dir
31
44
  }, role === DirectLineSenderRole.Bot && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
32
45
  dir: dir,
33
46
  "aria-hidden": "false"
34
- }, name, " - ", getTimestampHourMinute(timestamp))), role === DirectLineSenderRole.User && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
47
+ }, name, " - ", getTimeElement(timestamp))), role === DirectLineSenderRole.User && /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("span", {
35
48
  "aria-hidden": "false",
36
49
  dir: dir
37
- }, " ", getTimestampHourMinute(timestamp), " - ", ((_state$domainStates$m = state.domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_MESSAGE_DELIVERED) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_MESSAGE_DELIVERED)));
50
+ }, " ", getTimeElement(timestamp), " - ", ((_state$domainStates$m = state.domainStates.middlewareLocalizedTexts) === null || _state$domainStates$m === void 0 ? void 0 : _state$domainStates$m.MIDDLEWARE_MESSAGE_DELIVERED) ?? defaultMiddlewareLocalizedTexts.MIDDLEWARE_MESSAGE_DELIVERED)));
38
51
  };
@@ -35,6 +35,7 @@ const convertTextToHtmlNode = text => {
35
35
 
36
36
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
37
  const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
38
+ var _htmlNode$tagName;
38
39
  const htmlNode = convertTextToHtmlNode(text);
39
40
  const aNodes = htmlNode.getElementsByTagName(HtmlAttributeNames.aTagName);
40
41
  if ((aNodes === null || aNodes === void 0 ? void 0 : aNodes.length) > 0) {
@@ -64,8 +65,6 @@ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
64
65
  }
65
66
  }
66
67
  }
67
-
68
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
68
  action = updateIn(action, [Constants.payload, Constants.activity, Constants.text], () => htmlNode.innerHTML);
70
69
  } catch (e) {
71
70
  let errorMessage = "Failed to apply action: ";
@@ -83,6 +82,11 @@ const processHTMLText = (action, text, honorsTargetInHTMLLinks) => {
83
82
  });
84
83
  }
85
84
  }
85
+
86
+ // if empty div tag after sanitization
87
+ if (((_htmlNode$tagName = htmlNode.tagName) === null || _htmlNode$tagName === void 0 ? void 0 : _htmlNode$tagName.toLowerCase()) === HtmlAttributeNames.div && htmlNode.children.length === 0 && htmlNode.innerHTML.trim() === "") {
88
+ action = updateIn(action, [Constants.payload, Constants.activity, Constants.text], () => "");
89
+ }
86
90
  return action;
87
91
  };
88
92
 
@@ -5,6 +5,7 @@ function _toPrimitive(input, hint) { if (typeof input !== "object" || input ===
5
5
 
6
6
  import { createFileAndDownload } from "../common/utils";
7
7
  import defaultLibraryScripts from "../components/footerstateful/downloadtranscriptstateful/common/defaultLibraryScripts";
8
+ import DOMPurify from "dompurify";
8
9
  class TranscriptHTMLBuilder {
9
10
  // eslint-disable-line @typescript-eslint/no-explicit-any
10
11
 
@@ -167,7 +168,7 @@ class TranscriptHTMLBuilder {
167
168
  <script>
168
169
  class Translator {
169
170
  static convertTranscriptMessageToActivity(message) {
170
- const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences} = message;
171
+ const {created, OriginalMessageId, id, isControlMessage, content, tags, from, attachments, amsMetadata, amsReferences, amsreferences} = message;
171
172
 
172
173
  //it's required to convert the id to a number, otherwise the webchat will not render the messages in the correct order
173
174
  // if the OrginalMessageId is not present, we can use the id as the sequence id, which is always present.
@@ -214,7 +215,7 @@ class TranscriptHTMLBuilder {
214
215
  }
215
216
 
216
217
  // Attachments
217
- if (amsReferences && amsMetadata) {
218
+ if ((amsReferences || amsreferences) && amsMetadata) {
218
219
  const metadata = JSON.parse(amsMetadata);
219
220
  const { fileName } = metadata[0];
220
221
  const text = \`${this.attachmentMessage}\${fileName}\`;
@@ -238,7 +239,7 @@ class TranscriptHTMLBuilder {
238
239
  // Message
239
240
  if (content) {
240
241
  // Adaptive card formatting
241
- if (content.includes('"text"') && content.includes('"attachments"') && content.includes('"suggestedActions"')) {
242
+ if (content.includes('"attachments"') || content.includes('"suggestedActions"')) {
242
243
  try {
243
244
  const partialActivity = JSON.parse(content);
244
245
  return {
@@ -669,12 +670,15 @@ const createChatTranscript = async function (transcript, facadeChatSDK) {
669
670
  reader.readAsDataURL(blob);
670
671
  });
671
672
  };
672
- let messages = transcriptMessages;
673
+ let messages = transcriptMessages.filter(message => {
674
+ message.content = DOMPurify.sanitize(message.content);
675
+ return message;
676
+ });
673
677
  if (renderAttachments) {
674
678
  messages = await Promise.all(transcriptMessages.map(async message => {
675
679
  // eslint-disable-line @typescript-eslint/no-explicit-any
676
680
  const {
677
- amsReferences,
681
+ amsReferences = message.amsreferences,
678
682
  amsMetadata
679
683
  } = message;
680
684
  if (amsReferences && amsMetadata) {
@@ -83,7 +83,7 @@ export const createOnNewAdapterActivityHandler = (chatId, userId) => {
83
83
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
84
84
  Event: TelemetryEvent.MessageReceived,
85
85
  Description: "New message received",
86
- Data: payload
86
+ CustomProperties: payload
87
87
  });
88
88
  } else {
89
89
  if (!isHistoryMessageReceivedEventRasied) {
@@ -91,7 +91,7 @@ export const createOnNewAdapterActivityHandler = (chatId, userId) => {
91
91
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
92
92
  Event: TelemetryEvent.RehydrateMessageReceived,
93
93
  Description: "History message received",
94
- Data: payload
94
+ CustomProperties: payload
95
95
  });
96
96
  }
97
97
  }
@@ -104,6 +104,7 @@ export declare class HtmlIdNames {
104
104
  export declare class HtmlClassNames {
105
105
  static readonly webChatBannerCloseButton = "webchat__toast__dismissButton";
106
106
  static readonly webChatBannerExpandButton = "webchat__toaster__expandIcon";
107
+ static readonly webChatHistoryContainer = "webchat__basic-transcript";
107
108
  }
108
109
  export declare class HtmlElementSelectors {
109
110
  static readonly sendBoxSelector = "textarea[data-id=\"webchat-sendbox-input\"]";
@@ -57,7 +57,7 @@ export declare class FacadeChatSDK {
57
57
  getCallingToken(): Promise<string>;
58
58
  getMessages(): Promise<IMessage[] | OmnichannelMessage[] | undefined>;
59
59
  getDataMaskingRules(): Promise<MaskingRules>;
60
- sendMessage(message: ChatSDKMessage): Promise<void>;
60
+ sendMessage(message: ChatSDKMessage): Promise<void | OmnichannelMessage>;
61
61
  onNewMessage(onNewMessageCallback: CallableFunction, optionalParams?: OnNewMessageOptionalParams): Promise<void>;
62
62
  sendTypingEvent(): Promise<void>;
63
63
  onTypingEvent(onTypingEventCallback: CallableFunction): Promise<void>;
@@ -206,6 +206,8 @@ export declare enum TelemetryEvent {
206
206
  PostChatContextCallFailed = "PostChatContextCallFailed",
207
207
  PostChatSurveyLoadingPaneLoaded = "PostChatSurveyLoadingPaneLoaded",
208
208
  PostChatSurveyLoaded = "PostChatSurveyLoaded",
209
+ PostChatSurveyUrlValidationCompleted = "PostChatSurveyUrlValidationCompleted",
210
+ PostChatSurveyUrlValidationFailed = "PostChatSurveyUrlValidationFailed",
209
211
  ChatDisconnectThreadEventReceived = "ChatDisconnectThreadEventReceived",
210
212
  HiddenAdaptiveCardMessageReceived = "HiddenAdaptiveCardMessageReceived",
211
213
  EndingAdapterAfterDisconnectionError = "EndingAdapterAfterDisconnectionError",
@@ -12,6 +12,7 @@ export interface TelemetryEventWrapper {
12
12
  ExceptionDetails?: any;
13
13
  ElapsedTimeInMilliseconds?: number;
14
14
  Data?: any;
15
+ CustomProperties?: any;
15
16
  }
16
17
  export declare class TelemetryHelper {
17
18
  static callId: string;
@@ -46,3 +46,4 @@ export declare const createFileAndDownload: (fileName: string, blobData: string,
46
46
  export declare const formatTemplateString: (templateMessage: string, values: any) => string;
47
47
  export declare const parseLowerCaseString: (property: string | boolean | undefined) => string;
48
48
  export declare const setOcUserAgent: (chatSDK: any) => void;
49
+ export declare function getDeviceType(): string;
@@ -0,0 +1,2 @@
1
+ declare const isValidSurveyUrl: (url: string) => boolean;
2
+ export default isValidSurveyUrl;
@@ -24,4 +24,5 @@ export interface IWebChatContainerStatefulProps {
24
24
  hyperlinkTextOverride?: boolean;
25
25
  adaptiveCardStyles?: IAdaptiveCardStyles;
26
26
  sendBoxTextBox?: ISendBox;
27
+ webChatHistoryMobileAccessibilityLabel?: string;
27
28
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.7.7-main.bdac0a6",
3
+ "version": "1.7.8-main.270960e",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -78,7 +78,7 @@
78
78
  "dependencies": {
79
79
  "@azure/core-tracing": "^1.2.0",
80
80
  "@microsoft/omnichannel-chat-components": "1.1.8",
81
- "@microsoft/omnichannel-chat-sdk": "^1.10.15",
81
+ "@microsoft/omnichannel-chat-sdk": "^1.10.17",
82
82
  "@opentelemetry/api": "^1.9.0",
83
83
  "abort-controller-es5": "^2.0.1",
84
84
  "dompurify": "^3.2.4",