@microsoft/omnichannel-chat-widget 1.8.4-main.424a580 → 1.8.4-main.4f09da2

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 (60) hide show
  1. package/README.md +27 -0
  2. package/lib/cjs/common/Constants.js +2 -0
  3. package/lib/cjs/common/telemetry/AppInsightsEvents.js +11 -5
  4. package/lib/cjs/common/telemetry/TelemetryConstants.js +2 -0
  5. package/lib/cjs/common/telemetry/TelemetryManager.js +10 -7
  6. package/lib/cjs/common/telemetry/loggers/appInsightsLogger.js +7 -7
  7. package/lib/cjs/common/utils.js +14 -1
  8. package/lib/cjs/components/errorboundary/ErrorBoundary.js +2 -1
  9. package/lib/cjs/components/livechatwidget/common/ChatWidgetEvents.js +1 -1
  10. package/lib/cjs/components/livechatwidget/common/PersistentConversationHandler.js +24 -21
  11. package/lib/cjs/components/livechatwidget/common/defaultProps/defaultPersistentChatHistoryProps.js +1 -2
  12. package/lib/cjs/components/livechatwidget/common/endChat.js +26 -9
  13. package/lib/cjs/components/livechatwidget/common/liveChatConfigUtils.js +36 -4
  14. package/lib/cjs/components/livechatwidget/common/registerTelemetryLoggers.js +3 -0
  15. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +103 -26
  16. package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +8 -6
  17. package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +26 -33
  18. package/lib/cjs/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +8 -2
  19. package/lib/cjs/components/webchatcontainerstateful/hooks/usePersistentChatHistory.js +1 -3
  20. package/lib/cjs/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.js +1 -0
  21. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +6 -7
  22. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +21 -1
  23. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/NotDeliveredTimestamp.js +2 -0
  24. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/citationsMiddleware.js +6 -1
  25. package/lib/esm/common/Constants.js +2 -0
  26. package/lib/esm/common/telemetry/AppInsightsEvents.js +11 -5
  27. package/lib/esm/common/telemetry/TelemetryConstants.js +2 -0
  28. package/lib/esm/common/telemetry/TelemetryManager.js +10 -7
  29. package/lib/esm/common/telemetry/loggers/appInsightsLogger.js +7 -7
  30. package/lib/esm/common/utils.js +11 -0
  31. package/lib/esm/components/errorboundary/ErrorBoundary.js +4 -2
  32. package/lib/esm/components/livechatwidget/common/ChatWidgetEvents.js +1 -1
  33. package/lib/esm/components/livechatwidget/common/PersistentConversationHandler.js +24 -21
  34. package/lib/esm/components/livechatwidget/common/defaultProps/defaultPersistentChatHistoryProps.js +1 -2
  35. package/lib/esm/components/livechatwidget/common/endChat.js +26 -9
  36. package/lib/esm/components/livechatwidget/common/liveChatConfigUtils.js +33 -2
  37. package/lib/esm/components/livechatwidget/common/registerTelemetryLoggers.js +3 -0
  38. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +103 -26
  39. package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +8 -6
  40. package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +27 -37
  41. package/lib/esm/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +8 -2
  42. package/lib/esm/components/webchatcontainerstateful/hooks/usePersistentChatHistory.js +1 -3
  43. package/lib/esm/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.js +1 -0
  44. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +6 -7
  45. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +21 -1
  46. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/NotDeliveredTimestamp.js +2 -0
  47. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.js +1 -0
  48. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/citationsMiddleware.js +6 -1
  49. package/lib/types/common/Constants.d.ts +2 -0
  50. package/lib/types/common/telemetry/TelemetryConstants.d.ts +2 -0
  51. package/lib/types/common/telemetry/interfaces/IInternalTelemetryData.d.ts +1 -0
  52. package/lib/types/common/utils.d.ts +9 -1
  53. package/lib/types/components/errorboundary/ErrorBoundary.d.ts +1 -1
  54. package/lib/types/components/livechatwidget/common/ChatWidgetEvents.d.ts +1 -1
  55. package/lib/types/components/livechatwidget/common/liveChatConfigUtils.d.ts +11 -0
  56. package/lib/types/components/livechatwidget/interfaces/IPersistentChatHistoryProps.d.ts +0 -1
  57. package/lib/types/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.d.ts +15 -0
  58. package/lib/types/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.d.ts +1 -2
  59. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.d.ts +1 -1
  60. package/package.json +2 -2
@@ -62,7 +62,7 @@ let LazyLoadHandler = /*#__PURE__*/function () {
62
62
 
63
63
  // Scroll operation state
64
64
  // Current scroll operation tracking
65
- // Prevents concurrent scroll operations
65
+ // Prevents concurrent scroll operations (public for event handlers)
66
66
 
67
67
  // Timeout and queue management
68
68
  // Tracks all setTimeout IDs for cleanup
@@ -934,6 +934,21 @@ const LazyLoadActivity = props => {
934
934
  setHasMoreHistory(false);
935
935
  };
936
936
 
937
+ // Event listener for HISTORY_LOAD_ERROR - hides banner temporarily without disabling future loads
938
+ const handleHistoryLoadError = () => {
939
+ // Temporarily hide the banner by pausing, but keep hasMoreHistory true to allow retry
940
+ LazyLoadHandler.paused = true;
941
+ LazyLoadHandler.pendingScrollAction = false;
942
+
943
+ // Re-enable after a delay to allow retry on next scroll
944
+ // Note: This timeout is intentionally not tracked as it's scoped to the component lifecycle
945
+ window.setTimeout(() => {
946
+ LazyLoadHandler.paused = false;
947
+ }, 2000); // 2 second delay before allowing retry
948
+
949
+ LazyLoadHandler.logLifecycleEvent(_TelemetryConstants.TelemetryEvent.LCWLazyLoadHistoryError, "History load error - will retry on next scroll");
950
+ };
951
+
937
952
  // Event listener for PersistentConversationReset to sync React state
938
953
  // This fixes the issue where banner doesn't appear in start chat + close chat + start chat sequence
939
954
  // by ensuring React state (hasMoreHistory) is synchronized with handler state when reset occurs
@@ -946,6 +961,9 @@ const LazyLoadActivity = props => {
946
961
  const eventBus = _SecureEventBus.default.getInstance();
947
962
  const unsubscribeNoMoreHistory = eventBus.subscribe(_ChatWidgetEvents.default.NO_MORE_HISTORY_AVAILABLE, handleNoMoreHistory);
948
963
 
964
+ // Add event listener for history load errors
965
+ const unsubscribeHistoryError = eventBus.subscribe(_ChatWidgetEvents.default.HISTORY_LOAD_ERROR, handleHistoryLoadError);
966
+
949
967
  // Add event listener for persistent conversation reset
950
968
  const resetSubscription = _omnichannelChatComponents.BroadcastService.getMessageByEventName(_TelemetryConstants.BroadcastEvent.PersistentConversationReset).subscribe(handlePersistentConversationReset);
951
969
 
@@ -962,6 +980,7 @@ const LazyLoadActivity = props => {
962
980
  // Still need to return cleanup function even after reset
963
981
  return () => {
964
982
  unsubscribeNoMoreHistory();
983
+ unsubscribeHistoryError();
965
984
  resetSubscription.unsubscribe();
966
985
  };
967
986
  }
@@ -1014,6 +1033,7 @@ const LazyLoadActivity = props => {
1014
1033
 
1015
1034
  // Remove event listeners
1016
1035
  unsubscribeNoMoreHistory();
1036
+ unsubscribeHistoryError();
1017
1037
  resetSubscription.unsubscribe();
1018
1038
  if (container) {
1019
1039
  container.removeEventListener("scroll", handleScroll);
@@ -17,6 +17,8 @@ var _useChatContextStore = _interopRequireDefault(require("../../../../../../hoo
17
17
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
18
18
  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
19
  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; }
20
+ /* eslint-disable @typescript-eslint/no-explicit-any */
21
+
20
22
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
21
23
  const NotDeliveredTimestamp = _ref => {
22
24
  var _state$domainStates$r, _state$domainStates$r2, _state$domainStates$r3, _state$domainStates$r4, _state$domainStates$m, _state$domainStates$m2;
@@ -32,7 +32,12 @@ const createCitationsMiddleware = (state, dispatch) => () => next => action => {
32
32
  const citations = (_gptFeedback$summariz = gptFeedback.summarizationOpenAIResponse) === null || _gptFeedback$summariz === void 0 ? void 0 : (_gptFeedback$summariz2 = _gptFeedback$summariz.result) === null || _gptFeedback$summariz2 === void 0 ? void 0 : _gptFeedback$summariz2.textCitations;
33
33
  // Rewrite inline citation labels in activity.text to match the global map keys
34
34
  const updatedText = replaceCitations(action.payload.activity.text, citations, messagePrefix);
35
- action.payload.activity.text = updatedText;
35
+
36
+ // Create new activity object to avoid mutation
37
+ action.payload.activity = {
38
+ ...action.payload.activity,
39
+ text: updatedText
40
+ };
36
41
  // Build a global citation map keyed by the prefixed citation id and
37
42
  // dispatch it to app state so the UI container can render citations.
38
43
  try {
@@ -136,6 +136,7 @@ _defineProperty(Constants, "customEventName", "customEventName");
136
136
  _defineProperty(Constants, "customEventValue", "customEventValue");
137
137
  _defineProperty(Constants, "Hidden", "Hidden");
138
138
  _defineProperty(Constants, "EndConversationDueToOverflow", "endconversationduetooverflow");
139
+ _defineProperty(Constants, "SkipSessionCloseForPersistentChatFlag", "skipSessionCloseForPersistentChat");
139
140
  export const Regex = (_class = /*#__PURE__*/_createClass(function Regex() {
140
141
  _classCallCheck(this, Regex);
141
142
  }), _defineProperty(_class, "EmailRegex", "^(?:[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-zA-Z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"[^\"\\\\]*(?:\\\\.[^\"\\\\]*)*\")@(?:[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]*[a-zA-Z0-9])?)*|\\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\])$"), _class);
@@ -345,6 +346,7 @@ _defineProperty(PrepareEndChatDescriptionConstants, "ConversationEndedBy", "Conv
345
346
  _defineProperty(PrepareEndChatDescriptionConstants, "PrepareEndChatError", "There's an error while preparing to end chat. Closing chat widget.");
346
347
  _defineProperty(PrepareEndChatDescriptionConstants, "WidgetLoadFailedAfterSessionInit", "SessionInit was successful, but widget load failed. Ending chat to avoid ghost chats in OC.");
347
348
  _defineProperty(PrepareEndChatDescriptionConstants, "InitiateEndChatReceived", "Received InitiateEndChat BroadcastEvent while conversation state is not Active. Ending chat.");
349
+ _defineProperty(PrepareEndChatDescriptionConstants, "InitiateEndChatReceivedActiveChat", "Received InitiateEndChat BroadcastEvent while conversation state is Active. Updating conversation states.");
348
350
  _defineProperty(PrepareEndChatDescriptionConstants, "EndChatReceivedFromOtherTabs", "Received EndChat BroadcastEvent from other tabs. Closing this chat.");
349
351
  _defineProperty(PrepareEndChatDescriptionConstants, "CustomerCloseChatOnFailureOrPostChat", "Customer is trying to close chat widget on start chat failure or post chat pane.");
350
352
  _defineProperty(PrepareEndChatDescriptionConstants, "CustomerCloseInactiveChat", "Chat was Inactive and customer is trying to close chat widget or refreshing the page.");
@@ -1,7 +1,10 @@
1
1
  export const AppInsightsEventMapping = {
2
2
  "LCWChatButtonClicked": "LCWChatButtonActionStarted",
3
- "PrechatSubmitted": "PrechatSubmitCompleted",
4
- "StartChatEventRecevied": "StartChatEventReceivedCompleted",
3
+ "UXLCWChatButtonLoadingStart": "LiveChatWidgetChatButtonLoadingStarted",
4
+ "UXLCWChatButtonLoadingCompleted": "LiveChatWidgetChatButtonLoadingCompleted",
5
+ "UXPrechatPaneStart": "PrechatSurveyStarted",
6
+ "UXPrechatPaneCompleted": "PrechatSurveyCompleted",
7
+ "PrechatSubmitted": "PrechatSurveySubmitCompleted",
5
8
  "EndChatEventReceived": "EndChatEventReceivedCompleted",
6
9
  "EmailTranscriptSent": "EmailTranscriptActionCompleted",
7
10
  "EmailTranscriptFailed": "EmailTranscriptActionFailed",
@@ -9,8 +12,6 @@ export const AppInsightsEventMapping = {
9
12
  "HeaderMinimizeButtonClicked": "MinimizeChatActionStarted",
10
13
  "DownloadTranscriptButtonClicked": "DownloadTranscriptActionStarted",
11
14
  "EmailTranscriptButtonClicked": "EmailTranscriptButtonActionStarted",
12
- "CustomerVoiceFormResponseSubmitted": "CustomerVoiceFormResponseSubmitCompleted",
13
- "StartProactiveChatEventReceived": "StartProactiveChatEventReceivedCompleted",
14
15
  "ProactiveChatRejected": "ProactiveChatTimeOutCompleted",
15
16
  "MessageSent": "MessageSentCompleted",
16
17
  "MessageReceived": "MessageReceivedCompleted",
@@ -19,5 +20,10 @@ export const AppInsightsEventMapping = {
19
20
  "CustomContextReceived": "CustomContextReceivedCompleted",
20
21
  "NewTokenValidationStarted": "AuthTokenValidationStarted",
21
22
  "NewTokenValidationCompleted": "AuthTokenValidationCompleted",
22
- "NewTokenValidationFailed": "AuthTokenValidationFailed"
23
+ "NewTokenValidationFailed": "AuthTokenValidationFailed",
24
+ "UXPostChatPaneStarted": "PostChatSurveyStarted",
25
+ "UXPostChatPaneCompleted": "PostChatSurveyCompleted",
26
+ "WidgetLoadStarted": "ChatSessionInitializationStarted",
27
+ "WidgetLoadComplete": "ChatSessionInitializationCompleted",
28
+ "WidgetLoadFailed": "ChatSessionInitializationFailed"
23
29
  };
@@ -300,6 +300,7 @@ export let TelemetryEvent;
300
300
  TelemetryEvent["LCWPersistentConversationHandlerInitialized"] = "LCWPersistentConversationHandlerInitialized";
301
301
  TelemetryEvent["LCWPersistentHistoryPullBlocked"] = "LCWPersistentHistoryPullBlocked";
302
302
  TelemetryEvent["LCWPersistentHistoryPullCompleted"] = "LCWPersistentHistoryPullCompleted";
303
+ TelemetryEvent["LCWPersistentHistoryReturnedNull"] = "LCWPersistentHistoryReturnedNull";
303
304
  TelemetryEvent["LCWLazyLoadInitializationStarted"] = "LCWLazyLoadInitializationStarted";
304
305
  TelemetryEvent["LCWLazyLoadContainerNotFound"] = "LCWLazyLoadContainerNotFound";
305
306
  TelemetryEvent["LCWLazyLoadInitializationCompleted"] = "LCWLazyLoadInitializationCompleted";
@@ -309,6 +310,7 @@ export let TelemetryEvent;
309
310
  TelemetryEvent["LCWLazyLoadActivityMounted"] = "LCWLazyLoadActivityMounted";
310
311
  TelemetryEvent["LCWLazyLoadReset"] = "LCWLazyLoadReset";
311
312
  TelemetryEvent["LCWLazyLoadNoMoreHistory"] = "LCWLazyLoadNoMoreHistory";
313
+ TelemetryEvent["LCWLazyLoadHistoryError"] = "LCWLazyLoadHistoryError";
312
314
  TelemetryEvent["LCWLazyLoadDestroyed"] = "LCWLazyLoadDestroyed";
313
315
  TelemetryEvent["SecureEventBusUnauthorizedDispatch"] = "SecureEventBusUnauthorizedDispatch";
314
316
  TelemetryEvent["SecureEventBusListenerError"] = "SecureEventBusListenerError";
@@ -41,7 +41,7 @@ export const RegisterLoggers = () => {
41
41
  loggers.push(consoleLogger());
42
42
  }
43
43
  if (((_TelemetryManager$Int9 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int9 === void 0 ? void 0 : (_TelemetryManager$Int10 = _TelemetryManager$Int9.telemetryConfig) === null || _TelemetryManager$Int10 === void 0 ? void 0 : _TelemetryManager$Int10.telemetryDisabled) === false) {
44
- var _TelemetryManager$Int11, _TelemetryManager$Int20, _TelemetryManager$Int21, _TelemetryManager$Int22, _TelemetryManager$Int23;
44
+ var _TelemetryManager$Int11, _TelemetryManager$Int20, _TelemetryManager$Int21, _TelemetryManager$Int22, _TelemetryManager$Int23, _TelemetryManager$Int24, _TelemetryManager$Int25, _TelemetryManager$Int26;
45
45
  if ((_TelemetryManager$Int11 = TelemetryManager.InternalTelemetryData) !== null && _TelemetryManager$Int11 !== void 0 && _TelemetryManager$Int11.ariaConfig) {
46
46
  var _TelemetryManager$Int12, _TelemetryManager$Int13, _TelemetryManager$Int14, _TelemetryManager$Int15, _TelemetryManager$Int16, _TelemetryManager$Int17, _TelemetryManager$Int18, _TelemetryManager$Int19;
47
47
  loggers.push(ariaTelemetryLogger(((_TelemetryManager$Int12 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int12 === void 0 ? void 0 : (_TelemetryManager$Int13 = _TelemetryManager$Int12.ariaConfig) === null || _TelemetryManager$Int13 === void 0 ? void 0 : _TelemetryManager$Int13.ariaTelemetryKey) ?? defaultAriaConfig.ariaTelemetryKey, ((_TelemetryManager$Int14 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int14 === void 0 ? void 0 : (_TelemetryManager$Int15 = _TelemetryManager$Int14.ariaConfig) === null || _TelemetryManager$Int15 === void 0 ? void 0 : _TelemetryManager$Int15.disableCookieUsage) ?? defaultAriaConfig.disableCookieUsage, ((_TelemetryManager$Int16 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int16 === void 0 ? void 0 : (_TelemetryManager$Int17 = _TelemetryManager$Int16.ariaConfig) === null || _TelemetryManager$Int17 === void 0 ? void 0 : _TelemetryManager$Int17.collectorUriForTelemetry) ?? defaultAriaConfig.collectorUriForTelemetry, ((_TelemetryManager$Int18 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int18 === void 0 ? void 0 : (_TelemetryManager$Int19 = _TelemetryManager$Int18.ariaConfig) === null || _TelemetryManager$Int19 === void 0 ? void 0 : _TelemetryManager$Int19.ariaTelemetryApplicationName) ?? defaultAriaConfig.ariaTelemetryApplicationName));
@@ -52,12 +52,15 @@ export const RegisterLoggers = () => {
52
52
  loggers.push(logger);
53
53
  });
54
54
  }
55
- if (((_TelemetryManager$Int22 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int22 === void 0 ? void 0 : (_TelemetryManager$Int23 = _TelemetryManager$Int22.appInsightsConfig) === null || _TelemetryManager$Int23 === void 0 ? void 0 : _TelemetryManager$Int23.appInsightsDisabled) === false) {
56
- var _TelemetryManager$Int24;
57
- if ((_TelemetryManager$Int24 = TelemetryManager.InternalTelemetryData) !== null && _TelemetryManager$Int24 !== void 0 && _TelemetryManager$Int24.appInsightsConfig.appInsightsKey) {
58
- var _TelemetryManager$Int25;
59
- loggers.push(appInsightsLogger((_TelemetryManager$Int25 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int25 === void 0 ? void 0 : _TelemetryManager$Int25.appInsightsConfig.appInsightsKey));
60
- }
55
+ const chatConfigAppInsightsKey = (_TelemetryManager$Int22 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int22 === void 0 ? void 0 : _TelemetryManager$Int22.chatConfigAppInsightsKey;
56
+ const appInsightsKeyFromUser = (_TelemetryManager$Int23 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int23 === void 0 ? void 0 : (_TelemetryManager$Int24 = _TelemetryManager$Int23.appInsightsConfig) === null || _TelemetryManager$Int24 === void 0 ? void 0 : _TelemetryManager$Int24.appInsightsKey;
57
+ // when chatConfig has AppInsightsInstrumentationKey
58
+ if (chatConfigAppInsightsKey) {
59
+ loggers.push(appInsightsLogger(chatConfigAppInsightsKey));
60
+ }
61
+ // when key set through appInsightsConfig
62
+ else if (appInsightsKeyFromUser && ((_TelemetryManager$Int25 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int25 === void 0 ? void 0 : (_TelemetryManager$Int26 = _TelemetryManager$Int25.appInsightsConfig) === null || _TelemetryManager$Int26 === void 0 ? void 0 : _TelemetryManager$Int26.appInsightsDisabled) === false) {
63
+ loggers.push(appInsightsLogger(appInsightsKeyFromUser));
61
64
  }
62
65
  }
63
66
  };
@@ -5,11 +5,11 @@ import { AppInsightsTelemetryMessage } from "../../Constants";
5
5
  import { AppInsightsEventMapping } from "../AppInsightsEvents";
6
6
  var AllowedKeys;
7
7
  (function (AllowedKeys) {
8
- AllowedKeys["OrganizationId"] = "OrganizationId";
9
- AllowedKeys["ConversationId"] = "LiveWorkItemId";
8
+ AllowedKeys["OrganizationId"] = "powerplatform.analytics.resource.organization.id";
9
+ AllowedKeys["ConversationId"] = "powerplatform.analytics.resource.id";
10
10
  AllowedKeys["ElapsedTimeInMilliseconds"] = "Duration";
11
- AllowedKeys["Description"] = "Description";
12
- AllowedKeys["ChannelId"] = "ChannelType";
11
+ AllowedKeys["Description"] = "omnichannel.description";
12
+ AllowedKeys["ChannelId"] = "omnichannel.channel.type";
13
13
  AllowedKeys["LCWRuntimeId"] = "ClientSessionId";
14
14
  })(AllowedKeys || (AllowedKeys = {}));
15
15
  let initializationPromise = null;
@@ -86,8 +86,8 @@ export const appInsightsLogger = appInsightsKey => {
86
86
  if (eventName) {
87
87
  const trackingEventName = getTrackingEventName(logLevel, eventName);
88
88
  const eventProperties = setEventProperties(trackingEventName, telemetryInfo);
89
- _logger.trackEvent({
90
- name: trackingEventName,
89
+ _logger.trackTrace({
90
+ message: trackingEventName,
91
91
  properties: eventProperties
92
92
  });
93
93
  }
@@ -133,7 +133,7 @@ export const appInsightsLogger = appInsightsKey => {
133
133
  // Additional properties
134
134
  eventProperties["ConversationStage"] = customProperties.ConversationStage ?? ConversationStage.CSREngagement;
135
135
  eventProperties["Scenario"] = "Conversation Diagnostics";
136
- eventProperties["OperationName"] = eventName.includes(": ") ? eventName.split(": ")[1] : eventName;
136
+ eventProperties["powerplatform.analytics.subscenario"] = eventName.includes(": ") ? eventName.split(": ")[1] : eventName;
137
137
  return eventProperties;
138
138
  }
139
139
  function getTrackingEventName(logLevel, eventName) {
@@ -474,4 +474,15 @@ export const getCustomEventValue = customEventPayload => {
474
474
  export function isEndConversationDueToOverflowActivity(activity) {
475
475
  var _activity$channelData, _activity$channelData2;
476
476
  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.EndConversationDueToOverflow);
477
+ }
478
+
479
+ /**
480
+ * Parses a value that can be boolean or string ("true"/"false") into a boolean.
481
+ * Handles null/undefined by returning false.
482
+ *
483
+ * @param value - The value to parse (can be boolean, string, null, or undefined)
484
+ * @returns true if value is true or "true" (case-insensitive), false otherwise
485
+ */
486
+ export function parseBooleanFromConfig(value) {
487
+ return value === true || (value === null || value === void 0 ? void 0 : value.toString().toLowerCase()) === "true";
477
488
  }
@@ -10,12 +10,14 @@ function _possibleConstructorReturn(self, call) { if (call && (typeof call === "
10
10
  function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
11
11
  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; } }
12
12
  function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
13
- import React, { Component } from 'react';
13
+ import React, { Component } from "react";
14
+
15
+ // eslint-disable-next-line @typescript-eslint/ban-types
14
16
  const RenderChildrenFunction = _ref => {
15
17
  let {
16
18
  children
17
19
  } = _ref;
18
- return typeof children === 'function' ? children() : children;
20
+ return typeof children === "function" ? children() : children;
19
21
  };
20
22
  let ErrorBoundary = /*#__PURE__*/function (_Component) {
21
23
  _inherits(ErrorBoundary, _Component);
@@ -3,6 +3,6 @@ var ChatWidgetEvents;
3
3
  ChatWidgetEvents["ADD_ACTIVITY"] = "CHAT_WIDGET/ADD_ACTIVITY";
4
4
  ChatWidgetEvents["FETCH_PERSISTENT_CHAT_HISTORY"] = "CHAT_WIDGET/FETCH_PERSISTENT_CHAT_HISTORY";
5
5
  ChatWidgetEvents["NO_MORE_HISTORY_AVAILABLE"] = "CHAT_WIDGET/NO_MORE_HISTORY_AVAILABLE";
6
- ChatWidgetEvents["HIDE_LOADING_BANNER"] = "CHAT_WIDGET/HIDE_LOADING_BANNER";
6
+ ChatWidgetEvents["HISTORY_LOAD_ERROR"] = "CHAT_WIDGET/HISTORY_LOAD_ERROR";
7
7
  })(ChatWidgetEvents || (ChatWidgetEvents = {}));
8
8
  export default ChatWidgetEvents;
@@ -30,7 +30,7 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
30
30
  _defineProperty(this, "facadeChatSDK", void 0);
31
31
  _defineProperty(this, "lastMessage", null);
32
32
  _defineProperty(this, "count", 0);
33
- _defineProperty(this, "pageSize", 4);
33
+ _defineProperty(this, "pageSize", defaultPersistentChatHistoryProps.pageSize);
34
34
  _defineProperty(this, "isCurrentlyPulling", false);
35
35
  _defineProperty(this, "pageTokenInTransitSet", new Set());
36
36
  _defineProperty(this, "resetEventListener", BroadcastService.getMessageByEventName(BroadcastEvent.PersistentConversationReset).subscribe(() => {
@@ -42,7 +42,7 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
42
42
  Event: TelemetryEvent.LCWPersistentConversationHandlerInitialized,
43
43
  Description: "PersistentConversationHandler initialized",
44
44
  CustomProperties: {
45
- pageSize: this.pageSize
45
+ pageSize: defaultPersistentChatHistoryProps.pageSize
46
46
  }
47
47
  });
48
48
  }
@@ -55,8 +55,8 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
55
55
  ...props
56
56
  };
57
57
 
58
- // if the props is not existent or is not anumber then default to 4
59
- this.pageSize = ((_this$appliedProps = this.appliedProps) === null || _this$appliedProps === void 0 ? void 0 : _this$appliedProps.pageSize) !== undefined && !isNaN(this.appliedProps.pageSize) ? this.appliedProps.pageSize : 4;
58
+ // if the props is not existent or is not a number then default to defaultPersistentChatHistoryProps.pageSize
59
+ this.pageSize = ((_this$appliedProps = this.appliedProps) === null || _this$appliedProps === void 0 ? void 0 : _this$appliedProps.pageSize) !== undefined && !isNaN(this.appliedProps.pageSize) ? this.appliedProps.pageSize : defaultPersistentChatHistoryProps.pageSize;
60
60
  }
61
61
  }, {
62
62
  key: "reset",
@@ -101,12 +101,23 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
101
101
  try {
102
102
  var _ref;
103
103
  const messages = await this.fetchHistoryMessages();
104
- if (messages === null || (messages === null || messages === void 0 ? void 0 : messages.length) === 0) {
104
+
105
+ // Handle error case - null indicates an error occurred
106
+ // Don't mark as last pull to allow retry on next attempt
107
+ if (messages == null) {
108
+ TelemetryHelper.logActionEvent(LogLevel.WARN, {
109
+ Event: TelemetryEvent.LCWPersistentHistoryReturnedNull,
110
+ Description: "History pull returned null - Possible error occurred, will retry on next scroll",
111
+ ElapsedTimeInMilliseconds: pullTimer.milliSecondsElapsed
112
+ });
113
+ return;
114
+ }
115
+
116
+ // Handle legitimate end of history - empty array
117
+ if (messages.length === 0) {
105
118
  this.isLastPull = true;
106
119
  // Dispatch event to notify UI that no more history is available
107
120
  dispatchCustomEvent(ChatWidgetEvents.NO_MORE_HISTORY_AVAILABLE);
108
- // Also hide the loading banner
109
- dispatchCustomEvent(ChatWidgetEvents.HIDE_LOADING_BANNER);
110
121
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
111
122
  Event: TelemetryEvent.LCWPersistentHistoryPullCompleted,
112
123
  Description: "History pull completed - no more messages",
@@ -116,9 +127,6 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
116
127
  }
117
128
  const messagesDescOrder = (_ref = [...messages]) === null || _ref === void 0 ? void 0 : _ref.reverse();
118
129
  this.processHistoryMessages(messagesDescOrder);
119
-
120
- // Dispatch event to hide the loading banner after messages are processed
121
- dispatchCustomEvent(ChatWidgetEvents.HIDE_LOADING_BANNER);
122
130
  TelemetryHelper.logActionEvent(LogLevel.INFO, {
123
131
  Event: TelemetryEvent.LCWPersistentHistoryPullCompleted,
124
132
  Description: "History pull completed successfully",
@@ -174,7 +182,6 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
174
182
  if (!this.shouldPull()) {
175
183
  // Dispatch event to ensure banner is hidden when no more pulls are needed
176
184
  dispatchCustomEvent(ChatWidgetEvents.NO_MORE_HISTORY_AVAILABLE);
177
- dispatchCustomEvent(ChatWidgetEvents.HIDE_LOADING_BANNER);
178
185
  return [];
179
186
  }
180
187
  const options = {
@@ -200,24 +207,20 @@ let PersistentConversationHandler = /*#__PURE__*/function () {
200
207
  this.isLastPull = true;
201
208
  // Dispatch event when we reach the end of available history
202
209
  dispatchCustomEvent(ChatWidgetEvents.NO_MORE_HISTORY_AVAILABLE);
203
- // Also hide the loading banner
204
- dispatchCustomEvent(ChatWidgetEvents.HIDE_LOADING_BANNER);
205
210
  return [];
206
211
  }
207
- dispatchCustomEvent(ChatWidgetEvents.HIDE_LOADING_BANNER);
208
212
  return messages;
209
213
  } catch (error) {
210
214
  TelemetryHelper.logSDKEvent(LogLevel.ERROR, {
211
215
  Event: TelemetryEvent.FetchPersistentChatHistoryFailed,
212
216
  ExceptionDetails: error
213
217
  });
214
- this.isLastPull = true;
215
- this.pageToken = null;
216
- // Dispatch event when there's an error to stop loading banner
217
- dispatchCustomEvent(ChatWidgetEvents.NO_MORE_HISTORY_AVAILABLE);
218
- // Also hide the loading banner
219
- dispatchCustomEvent(ChatWidgetEvents.HIDE_LOADING_BANNER);
220
- return [];
218
+
219
+ // On error, dispatch HISTORY_LOAD_ERROR to hide loading banner without marking conversation as ended
220
+ // This allows recovery on the next attempt (e.g., transient network errors)
221
+ // Return null to distinguish error from legitimate empty history
222
+ dispatchCustomEvent(ChatWidgetEvents.HISTORY_LOAD_ERROR);
223
+ return null;
221
224
  }
222
225
  }
223
226
  }, {
@@ -1,6 +1,5 @@
1
1
  export const defaultPersistentChatHistoryProps = {
2
- persistentChatHistoryEnabled: true,
3
- pageSize: 4,
2
+ pageSize: 10,
4
3
  dividerActivityStyle: {
5
4
  border: "1px solid rgb(96, 94, 92, 0.5)",
6
5
  margin: "10px 20%"
@@ -6,6 +6,8 @@ import { BroadcastService } from "@microsoft/omnichannel-chat-components";
6
6
  import { ConversationState } from "../../../contexts/common/ConversationState";
7
7
  import { LazyLoadHandler } from "../../webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity";
8
8
  import { LiveChatWidgetActionType } from "../../../contexts/common/LiveChatWidgetActionType";
9
+ import { NotificationHandler } from "../../webchatcontainerstateful/webchatcontroller/notification/NotificationHandler";
10
+ import { NotificationScenarios } from "../../webchatcontainerstateful/webchatcontroller/enums/NotificationScenarios";
9
11
  import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
10
12
  import { TelemetryManager } from "../../../common/telemetry/TelemetryManager";
11
13
  import { WebChatStoreLoader } from "../../webchatcontainerstateful/webchatcontroller/WebChatStoreLoader";
@@ -195,6 +197,18 @@ const endChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWeb
195
197
  facadeChatSDK.destroy();
196
198
  }
197
199
  }
200
+
201
+ //moving logic below to before processing skipCloseChat logic to avoid race conditions of postMessage for endChatEvent for other tabs vs postMessage for CloseChat
202
+ //TODO: clarify if this postMessageToOtherTab actually works in production.
203
+ if (postMessageToOtherTab) {
204
+ const endChatEventName = await getEndChatEventName(facadeChatSDK, props);
205
+ BroadcastService.postMessage({
206
+ eventName: endChatEventName,
207
+ payload: {
208
+ runtimeId: TelemetryManager.InternalTelemetryData.lcwRuntimeId
209
+ }
210
+ });
211
+ }
198
212
  if (!skipCloseChat) {
199
213
  try {
200
214
  var _props$webChatContain;
@@ -234,17 +248,17 @@ const endChat = async (props, facadeChatSDK, state, dispatch, setAdapter, setWeb
234
248
  });
235
249
  closeChatWidget(dispatch, setWebChatStyles, props);
236
250
  facadeChatSDK.destroy();
251
+
252
+ //always post the close chat event after chat closed and cleanup completed
253
+ BroadcastService.postMessage({
254
+ eventName: BroadcastEvent.CloseChat
255
+ });
256
+ TelemetryHelper.logActionEvent(LogLevel.INFO, {
257
+ Event: TelemetryEvent.CloseChatCall,
258
+ Description: "Broadcasted close chat event"
259
+ });
237
260
  }
238
261
  }
239
- if (postMessageToOtherTab) {
240
- const endChatEventName = await getEndChatEventName(facadeChatSDK, props);
241
- BroadcastService.postMessage({
242
- eventName: endChatEventName,
243
- payload: {
244
- runtimeId: TelemetryManager.InternalTelemetryData.lcwRuntimeId
245
- }
246
- });
247
- }
248
262
  };
249
263
  export const callingStateCleanUp = dispatch => {
250
264
  dispatch({
@@ -322,6 +336,9 @@ export const closeChatStateCleanUp = dispatch => {
322
336
  payload: {}
323
337
  });
324
338
 
339
+ // Dismiss the chat disconnect notification banner if it was shown
340
+ NotificationHandler.dismissNotification(NotificationScenarios.ChatDisconnect);
341
+
325
342
  // Clear live chat context only if chat widget is fully closed to support transcript calls after sessionclose is called
326
343
  dispatch({
327
344
  type: LiveChatWidgetActionType.SET_LIVE_CHAT_CONTEXT,
@@ -1,11 +1,13 @@
1
+ import { isNullOrUndefined, parseBooleanFromConfig } from "../../../common/utils";
1
2
  import { ConversationMode } from "../../../common/Constants";
2
- import { isNullOrUndefined } from "../../../common/utils";
3
3
  export const isPostChatSurveyEnabled = async facadeChatSDK => {
4
4
  var _chatConfig$LiveWSAnd;
5
5
  const chatConfig = await facadeChatSDK.getLiveChatConfig();
6
6
  const postChatEnabled = (_chatConfig$LiveWSAnd = chatConfig.LiveWSAndLiveChatEngJoin) === null || _chatConfig$LiveWSAnd === void 0 ? void 0 : _chatConfig$LiveWSAnd.msdyn_postconversationsurveyenable.toString().toLowerCase();
7
7
  return postChatEnabled === "true";
8
8
  };
9
+
10
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
11
  export const getPostChatSurveyConfig = async facadeChatSDK => {
10
12
  var _chatConfig$LiveWSAnd2, _chatConfig$LiveWSAnd3, _chatConfig$LiveWSAnd4, _chatConfig$LiveWSAnd5, _chatConfig$LiveWSAnd6, _chatConfig$LiveWSAnd7, _chatConfig$LiveWSAnd8, _chatConfig$LiveWSAnd9, _chatConfig$LiveWSAnd10;
11
13
  const chatConfig = await facadeChatSDK.getLiveChatConfig();
@@ -26,5 +28,34 @@ export const isPersistentChatEnabled = conversationMode => {
26
28
  if (isNullOrUndefined(conversationMode)) {
27
29
  return false;
28
30
  }
29
- return (conversationMode === null || conversationMode === void 0 ? void 0 : conversationMode.toString().toLowerCase()) === ConversationMode.Persistent;
31
+ return (conversationMode === null || conversationMode === void 0 ? void 0 : conversationMode.toString()) === ConversationMode.Persistent;
32
+ };
33
+
34
+ /**
35
+ * Determines if persistent chat history should be loaded based on all required conditions.
36
+ *
37
+ * @param extendedChatConfig - The extended chat configuration object
38
+ * @returns true if ALL conditions are met:
39
+ * 1. Conversation mode must be Persistent ("192350001")
40
+ * 2. History is enabled in admin config (msdyn_enablepersistentchatpreviousconversations)
41
+ * 3. History is enabled via feature flag (lcwPersistentChatHistoryEnabled)
42
+ */
43
+ export const shouldLoadPersistentChatHistory = extendedChatConfig => {
44
+ var _extendedChatConfig$L, _extendedChatConfig$L2, _extendedChatConfig$L3;
45
+ // CRITICAL: First check if conversation mode is persistent
46
+ // Only persistent mode ("192350001") should allow history loading
47
+ const isPersistentChatEnabledForWidget = isPersistentChatEnabled(extendedChatConfig === null || extendedChatConfig === void 0 ? void 0 : (_extendedChatConfig$L = extendedChatConfig.LiveWSAndLiveChatEngJoin) === null || _extendedChatConfig$L === void 0 ? void 0 : _extendedChatConfig$L.msdyn_conversationmode);
48
+ if (!isPersistentChatEnabledForWidget) {
49
+ return false;
50
+ }
51
+
52
+ // Check if history is enabled in admin config (handles both boolean and string "true"/"false")
53
+ const isHistoryEnabledInConfig = parseBooleanFromConfig(extendedChatConfig === null || extendedChatConfig === void 0 ? void 0 : (_extendedChatConfig$L2 = extendedChatConfig.LiveWSAndLiveChatEngJoin) === null || _extendedChatConfig$L2 === void 0 ? void 0 : _extendedChatConfig$L2.msdyn_enablepersistentchatpreviousconversations);
54
+ if (!isHistoryEnabledInConfig) {
55
+ return false;
56
+ }
57
+
58
+ // Check if history is enabled via feature flag (handles both boolean and string "true"/"false")
59
+ const isHistoryEnabledViaFCB = parseBooleanFromConfig(extendedChatConfig === null || extendedChatConfig === void 0 ? void 0 : (_extendedChatConfig$L3 = extendedChatConfig.LcwFcbConfiguration) === null || _extendedChatConfig$L3 === void 0 ? void 0 : _extendedChatConfig$L3.lcwPersistentChatHistoryEnabled);
60
+ return isHistoryEnabledViaFCB;
30
61
  };
@@ -24,7 +24,10 @@ export const registerTelemetryLoggers = (props, dispatch) => {
24
24
  appInsightsConfig: Object.assign({}, defaultAppInsightsConfig, props.appInsightsConfig)
25
25
  };
26
26
  if (props.chatConfig) {
27
+ var _props$chatConfig$Liv;
27
28
  telemetryData = TelemetryHelper.addChatConfigDataToTelemetry(props === null || props === void 0 ? void 0 : props.chatConfig, telemetryData);
29
+ //store AppInsights instrumentation key from chatConfig if present
30
+ telemetryData.chatConfigAppInsightsKey = (_props$chatConfig$Liv = props.chatConfig.LiveWSAndLiveChatEngJoin) === null || _props$chatConfig$Liv === void 0 ? void 0 : _props$chatConfig$Liv.AppInsightsInstrumentationKey;
28
31
  }
29
32
  if (!((_props$chatSDK = props.chatSDK) !== null && _props$chatSDK !== void 0 && (_props$chatSDK$omnich = _props$chatSDK.omnichannelConfig) !== null && _props$chatSDK$omnich !== void 0 && _props$chatSDK$omnich.orgId) || ((_props$chatSDK2 = props.chatSDK) === null || _props$chatSDK2 === void 0 ? void 0 : (_props$chatSDK2$omnic = _props$chatSDK2.omnichannelConfig) === null || _props$chatSDK2$omnic === void 0 ? void 0 : _props$chatSDK2$omnic.orgId.trim().length) === 0) {
30
33
  throw new Error("orgId is undefined in ChatSDK");