@microsoft/omnichannel-chat-widget 1.8.2-main.e3c1d40 → 1.8.2-main.fc93d3d

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/README.md +2 -0
  2. package/lib/cjs/common/Constants.js +9 -1
  3. package/lib/cjs/components/draggable/DraggableChatWidget.js +16 -1
  4. package/lib/cjs/components/livechatwidget/common/endChat.js +18 -7
  5. package/lib/cjs/components/livechatwidget/common/initWebChatComposer.js +29 -1
  6. package/lib/cjs/components/livechatwidget/common/liveChatConfigUtils.js +18 -1
  7. package/lib/cjs/components/livechatwidget/common/renderSurveyHelpers.js +31 -7
  8. package/lib/cjs/components/livechatwidget/common/setPostChatContextAndLoadSurvey.js +15 -2
  9. package/lib/cjs/components/livechatwidget/common/startChat.js +5 -3
  10. package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +22 -11
  11. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.js +4 -3
  12. package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/conversationEndMiddleware.js +12 -6
  13. package/lib/cjs/contexts/common/LiveChatWidgetActionType.js +3 -1
  14. package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +3 -1
  15. package/lib/cjs/contexts/createReducer.js +30 -0
  16. package/lib/cjs/controller/componentController.js +2 -2
  17. package/lib/cjs/firstresponselatency/util.js +52 -27
  18. package/lib/cjs/plugins/newMessageEventHandler.js +12 -6
  19. package/lib/esm/common/Constants.js +7 -0
  20. package/lib/esm/components/draggable/DraggableChatWidget.js +16 -1
  21. package/lib/esm/components/livechatwidget/common/endChat.js +18 -7
  22. package/lib/esm/components/livechatwidget/common/initWebChatComposer.js +29 -1
  23. package/lib/esm/components/livechatwidget/common/liveChatConfigUtils.js +16 -0
  24. package/lib/esm/components/livechatwidget/common/renderSurveyHelpers.js +33 -9
  25. package/lib/esm/components/livechatwidget/common/setPostChatContextAndLoadSurvey.js +16 -3
  26. package/lib/esm/components/livechatwidget/common/startChat.js +5 -3
  27. package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +22 -11
  28. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.js +4 -4
  29. package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/conversationEndMiddleware.js +12 -6
  30. package/lib/esm/contexts/common/LiveChatWidgetActionType.js +3 -1
  31. package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +3 -1
  32. package/lib/esm/contexts/createReducer.js +30 -0
  33. package/lib/esm/controller/componentController.js +2 -2
  34. package/lib/esm/firstresponselatency/util.js +49 -25
  35. package/lib/esm/plugins/newMessageEventHandler.js +12 -6
  36. package/lib/types/common/Constants.d.ts +6 -0
  37. package/lib/types/components/livechatwidget/common/liveChatConfigUtils.d.ts +1 -0
  38. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.d.ts +1 -1
  39. package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/conversationEndMiddleware.d.ts +1 -1
  40. package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +2 -0
  41. package/lib/types/contexts/common/LiveChatWidgetActionType.d.ts +3 -1
  42. package/lib/types/firstresponselatency/util.d.ts +17 -0
  43. package/lib/types/plugins/newMessageEventHandler.d.ts +1 -1
  44. package/package.json +3 -3
@@ -611,12 +611,15 @@ export const LiveChatWidgetStateful = props => {
611
611
  payload: null
612
612
  });
613
613
  if ("participantsRemoved" in event && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta5 = inMemoryState.appStates) === null || _inMemoryState$appSta5 === void 0 ? void 0 : _inMemoryState$appSta5.conversationState) === ConversationState.Active) {
614
- setWebChatStyles(styles => {
615
- return {
616
- ...styles,
617
- hideSendBox: true
618
- };
619
- });
614
+ var _inMemoryState$appSta6;
615
+ if ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta6 = inMemoryState.appStates) === null || _inMemoryState$appSta6 === void 0 ? void 0 : _inMemoryState$appSta6.isConversationalSurveyEnabled) === false) {
616
+ setWebChatStyles(styles => {
617
+ return {
618
+ ...styles,
619
+ hideSendBox: true
620
+ };
621
+ });
622
+ }
620
623
  TelemetryHelper.logSDKEvent(LogLevel.INFO, {
621
624
  Event: TelemetryEvent.ParticipantsRemovedEvent,
622
625
  Description: "Participants removed event received."
@@ -712,7 +715,15 @@ export const LiveChatWidgetStateful = props => {
712
715
  endChat(props, facadeChatSDK, state, dispatch, setAdapter, setWebChatStyles, adapter, false, false, true);
713
716
  return;
714
717
  }
715
- if ((state === null || state === void 0 ? void 0 : (_state$appStates12 = state.appStates) === null || _state$appStates12 === void 0 ? void 0 : _state$appStates12.conversationEndedBy) === ConversationEndEntity.Agent || (state === null || state === void 0 ? void 0 : (_state$appStates13 = state.appStates) === null || _state$appStates13 === void 0 ? void 0 : _state$appStates13.conversationEndedBy) === ConversationEndEntity.Bot) {
718
+ const inMemoryState = executeReducer(state, {
719
+ type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
720
+ payload: null
721
+ });
722
+ let isConversationalSurveyEnabled = state.appStates.isConversationalSurveyEnabled;
723
+
724
+ // In conversational survey, we need to check post chat survey logics before we set ConversationState to InActive
725
+ // Hence setting ConversationState to InActive will be done later in the post chat flows
726
+ if (!isConversationalSurveyEnabled && ((state === null || state === void 0 ? void 0 : (_state$appStates12 = state.appStates) === null || _state$appStates12 === void 0 ? void 0 : _state$appStates12.conversationEndedBy) === ConversationEndEntity.Agent || (state === null || state === void 0 ? void 0 : (_state$appStates13 = state.appStates) === null || _state$appStates13 === void 0 ? void 0 : _state$appStates13.conversationEndedBy) === ConversationEndEntity.Bot)) {
716
727
  dispatch({
717
728
  type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
718
729
  payload: ConversationState.InActive
@@ -753,13 +764,13 @@ export const LiveChatWidgetStateful = props => {
753
764
 
754
765
  // Handle Chat disconnect cases
755
766
  useEffect(() => {
756
- var _inMemoryState$appSta6;
767
+ var _inMemoryState$appSta7;
757
768
  const inMemoryState = executeReducer(state, {
758
769
  type: LiveChatWidgetActionType.GET_IN_MEMORY_STATE,
759
770
  payload: null
760
771
  });
761
772
  handleChatDisconnect(props, inMemoryState, setWebChatStyles);
762
- const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta6 = inMemoryState.appStates) === null || _inMemoryState$appSta6 === void 0 ? void 0 : _inMemoryState$appSta6.chatDisconnectEventReceived;
773
+ const chatDisconnectState = inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta7 = inMemoryState.appStates) === null || _inMemoryState$appSta7 === void 0 ? void 0 : _inMemoryState$appSta7.chatDisconnectEventReceived;
763
774
  if (chatDisconnectState && adapter) {
764
775
  try {
765
776
  adapter.end();
@@ -887,8 +898,8 @@ export const LiveChatWidgetStateful = props => {
887
898
  margin-left: .25em;
888
899
  }
889
900
  ${(sendBoxTextArea === null || sendBoxTextArea === void 0 ? void 0 : sendBoxTextArea.minHeight) && `
890
- textarea.webchat__send-box-text-box__html-text-area {
891
- min-height: ${sendBoxTextArea === null || sendBoxTextArea === void 0 ? void 0 : sendBoxTextArea.minHeight};
901
+ .webchat__auto-resize-textarea.webchat__send-box-text-box__text-area {
902
+ min-height: ${sendBoxTextArea === null || sendBoxTextArea === void 0 ? void 0 : sendBoxTextArea.minHeight} !important;
892
903
  }`}
893
904
  `), /*#__PURE__*/React.createElement(DraggableChatWidget, chatWidgetDraggableConfig, /*#__PURE__*/React.createElement(Composer, _extends({}, webChatProps, {
894
905
  userID: userID,
@@ -7,15 +7,14 @@
7
7
  import { Constants } from "../../../../../common/Constants";
8
8
  import { DeliveryMode } from "@microsoft/omnichannel-chat-sdk";
9
9
  import { WebChatActionType } from "../../enums/WebChatActionType";
10
-
11
10
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
12
- const channelDataMiddleware = _ref => {
11
+ const channelDataMiddleware = addConversationalSurveyTagsCallback => _ref => {
13
12
  let {
14
13
  dispatch
15
14
  } = _ref;
16
15
  return next => action => {
17
- var _action$payload, _action$payload$activ;
18
- if ((action === null || action === void 0 ? void 0 : action.type) === WebChatActionType.DIRECT_LINE_POST_ACTIVITY_PENDING && action !== null && action !== void 0 && (_action$payload = action.payload) !== null && _action$payload !== void 0 && (_action$payload$activ = _action$payload.activity) !== null && _action$payload$activ !== void 0 && _action$payload$activ.channelData) {
16
+ var _action, _action2, _action2$payload, _action2$payload$acti;
17
+ if (((_action = action) === null || _action === void 0 ? void 0 : _action.type) === WebChatActionType.DIRECT_LINE_POST_ACTIVITY_PENDING && (_action2 = action) !== null && _action2 !== void 0 && (_action2$payload = _action2.payload) !== null && _action2$payload !== void 0 && (_action2$payload$acti = _action2$payload.activity) !== null && _action2$payload$acti !== void 0 && _action2$payload$acti.channelData) {
19
18
  const channelIdTag = `${Constants.channelIdKey}${Constants.ChannelId}`;
20
19
  const customerMessageTag = `${Constants.CustomerTag}`;
21
20
  if (action.payload.activity.channelData.tags) {
@@ -29,6 +28,7 @@ const channelDataMiddleware = _ref => {
29
28
  action.payload.activity.channelData.tags = [channelIdTag];
30
29
  action.payload.activity.channelData.tags.push(customerMessageTag);
31
30
  }
31
+ action = addConversationalSurveyTagsCallback(action);
32
32
  action.payload.activity.channelData.metadata = {
33
33
  deliveryMode: DeliveryMode.Bridged
34
34
  };
@@ -11,27 +11,33 @@ import { MessageTypes } from "../../enums/MessageType";
11
11
  import { WebChatActionType } from "../../enums/WebChatActionType";
12
12
 
13
13
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
14
- const createConversationEndMiddleware = conversationEndCallback => _ref => {
14
+ const createConversationEndMiddleware = (conversationEndCallback, startConversationalSurveyCallback, endConversationalSurveyCallback) => _ref => {
15
15
  let {
16
16
  dispatch
17
17
  } = _ref;
18
18
  return next => action => {
19
19
  var _action$payload;
20
20
  if ((action === null || action === void 0 ? void 0 : action.type) == WebChatActionType.DIRECT_LINE_INCOMING_ACTIVITY && (_action$payload = action.payload) !== null && _action$payload !== void 0 && _action$payload.activity) {
21
- var _activity$from2, _activity$channelData7, _activity$channelData8;
21
+ var _activity$from2, _activity$channelData17, _activity$channelData18;
22
22
  const activity = action.payload.activity;
23
23
  if (activity.channelId === "ACS_CHANNEL") {
24
24
  var _activity$from;
25
25
  if (((_activity$from = activity.from) === null || _activity$from === void 0 ? void 0 : _activity$from.role) === DirectLineSenderRole.Bot) {
26
- var _activity$channelData, _activity$channelData2, _activity$channelData3, _activity$channelData4, _activity$channelData5, _activity$channelData6;
26
+ var _activity$channelData, _activity$channelData2, _activity$channelData3, _activity$channelData4, _activity$channelData5, _activity$channelData6, _activity$channelData7, _activity$channelData8, _activity$channelData9, _activity$channelData10, _activity$channelData11, _activity$channelData12, _activity$channelData13, _activity$channelData14, _activity$channelData15, _activity$channelData16;
27
27
  if ((_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && (_activity$channelData2 = _activity$channelData.tags) !== null && _activity$channelData2 !== void 0 && _activity$channelData2.includes(Constants.systemMessageTag) && ((_activity$channelData3 = activity.channelData) !== null && _activity$channelData3 !== void 0 && (_activity$channelData4 = _activity$channelData3.tags) !== null && _activity$channelData4 !== void 0 && _activity$channelData4.includes(Constants.agentEndConversationMessageTag) || (_activity$channelData5 = activity.channelData) !== null && _activity$channelData5 !== void 0 && (_activity$channelData6 = _activity$channelData5.tags) !== null && _activity$channelData6 !== void 0 && _activity$channelData6.includes(Constants.supervisorForceCloseMessageTag))) {
28
28
  conversationEndCallback();
29
29
  }
30
+ if ((_activity$channelData7 = activity.channelData) !== null && _activity$channelData7 !== void 0 && (_activity$channelData8 = _activity$channelData7.tags) !== null && _activity$channelData8 !== void 0 && _activity$channelData8.includes(Constants.systemMessageTag) && ((_activity$channelData9 = activity.channelData) !== null && _activity$channelData9 !== void 0 && (_activity$channelData10 = _activity$channelData9.tags) !== null && _activity$channelData10 !== void 0 && _activity$channelData10.includes(Constants.startConversationalSurveyMessageTag) || (_activity$channelData11 = activity.channelData) !== null && _activity$channelData11 !== void 0 && (_activity$channelData12 = _activity$channelData11.tags) !== null && _activity$channelData12 !== void 0 && _activity$channelData12.includes(Constants.startConversationalSurveyMessageTag))) {
31
+ startConversationalSurveyCallback();
32
+ }
33
+ if ((_activity$channelData13 = activity.channelData) !== null && _activity$channelData13 !== void 0 && (_activity$channelData14 = _activity$channelData13.tags) !== null && _activity$channelData14 !== void 0 && _activity$channelData14.includes(Constants.systemMessageTag) && (_activity$channelData15 = activity.channelData) !== null && _activity$channelData15 !== void 0 && (_activity$channelData16 = _activity$channelData15.tags) !== null && _activity$channelData16 !== void 0 && _activity$channelData16.includes(Constants.endConversationalSurveyMessageTag)) {
34
+ endConversationalSurveyCallback();
35
+ }
30
36
  }
31
- } else if (((_activity$from2 = activity.from) === null || _activity$from2 === void 0 ? void 0 : _activity$from2.role) === DirectLineSenderRole.Channel && ((_activity$channelData7 = activity.channelData) === null || _activity$channelData7 === void 0 ? void 0 : _activity$channelData7.type) === MessageTypes.Thread && (_activity$channelData8 = activity.channelData) !== null && _activity$channelData8 !== void 0 && _activity$channelData8.properties) {
32
- var _activity$channelData9, _activity$channelData10, _activity$channelData11, _activity$channelData12;
37
+ } else if (((_activity$from2 = activity.from) === null || _activity$from2 === void 0 ? void 0 : _activity$from2.role) === DirectLineSenderRole.Channel && ((_activity$channelData17 = activity.channelData) === null || _activity$channelData17 === void 0 ? void 0 : _activity$channelData17.type) === MessageTypes.Thread && (_activity$channelData18 = activity.channelData) !== null && _activity$channelData18 !== void 0 && _activity$channelData18.properties) {
38
+ var _activity$channelData19, _activity$channelData20, _activity$channelData21, _activity$channelData22;
33
39
  // IC3
34
- if (((_activity$channelData9 = activity.channelData) === null || _activity$channelData9 === void 0 ? void 0 : (_activity$channelData10 = _activity$channelData9.properties) === null || _activity$channelData10 === void 0 ? void 0 : _activity$channelData10.isdeleted) === Constants.truePascal || !((_activity$channelData11 = activity.channelData) !== null && _activity$channelData11 !== void 0 && (_activity$channelData12 = _activity$channelData11.properties) !== null && _activity$channelData12 !== void 0 && _activity$channelData12.containsExternalEntitiesListeningAll)) {
40
+ if (((_activity$channelData19 = activity.channelData) === null || _activity$channelData19 === void 0 ? void 0 : (_activity$channelData20 = _activity$channelData19.properties) === null || _activity$channelData20 === void 0 ? void 0 : _activity$channelData20.isdeleted) === Constants.truePascal || !((_activity$channelData21 = activity.channelData) !== null && _activity$channelData21 !== void 0 && (_activity$channelData22 = _activity$channelData21.properties) !== null && _activity$channelData22 !== void 0 && _activity$channelData22.containsExternalEntitiesListeningAll)) {
35
41
  conversationEndCallback();
36
42
  }
37
43
  }
@@ -45,5 +45,7 @@ export let LiveChatWidgetActionType;
45
45
  LiveChatWidgetActionType[LiveChatWidgetActionType["SET_SURVEY_MODE"] = 42] = "SET_SURVEY_MODE";
46
46
  LiveChatWidgetActionType[LiveChatWidgetActionType["SET_CONFIRMATION_STATE"] = 43] = "SET_CONFIRMATION_STATE";
47
47
  LiveChatWidgetActionType[LiveChatWidgetActionType["SET_POST_CHAT_PARTICIPANT_TYPE"] = 44] = "SET_POST_CHAT_PARTICIPANT_TYPE";
48
- LiveChatWidgetActionType[LiveChatWidgetActionType["GET_IN_MEMORY_STATE"] = 45] = "GET_IN_MEMORY_STATE";
48
+ LiveChatWidgetActionType[LiveChatWidgetActionType["SET_CONVERSATIONAL_SURVEY_ENABLED"] = 45] = "SET_CONVERSATIONAL_SURVEY_ENABLED";
49
+ LiveChatWidgetActionType[LiveChatWidgetActionType["SET_CONVERSATIONAL_SURVEY_DISPLAY"] = 46] = "SET_CONVERSATIONAL_SURVEY_DISPLAY";
50
+ LiveChatWidgetActionType[LiveChatWidgetActionType["GET_IN_MEMORY_STATE"] = 47] = "GET_IN_MEMORY_STATE";
49
51
  })(LiveChatWidgetActionType || (LiveChatWidgetActionType = {}));
@@ -77,7 +77,9 @@ export const getLiveChatWidgetContextInitialState = props => {
77
77
  conversationEndedBy: ConversationEndEntity.NotSet,
78
78
  chatDisconnectEventReceived: false,
79
79
  selectedSurveyMode: null,
80
- postChatParticipantType: undefined
80
+ postChatParticipantType: undefined,
81
+ isConversationalSurvey: false,
82
+ isConversationalSurveyEnabled: false
81
83
  },
82
84
  uiStates: {
83
85
  showConfirmationPane: false,
@@ -648,6 +648,36 @@ const reducer = (state, action) => {
648
648
  postChatParticipantType: action.payload
649
649
  }
650
650
  };
651
+ case LiveChatWidgetActionType.SET_CONVERSATIONAL_SURVEY_ENABLED:
652
+ inMemory = {
653
+ ...inMemory,
654
+ appStates: {
655
+ ...inMemory.appStates,
656
+ isConversationalSurveyEnabled: action.payload
657
+ }
658
+ };
659
+ return {
660
+ ...state,
661
+ appStates: {
662
+ ...state.appStates,
663
+ isConversationalSurveyEnabled: action.payload
664
+ }
665
+ };
666
+ case LiveChatWidgetActionType.SET_CONVERSATIONAL_SURVEY_DISPLAY:
667
+ inMemory = {
668
+ ...inMemory,
669
+ appStates: {
670
+ ...inMemory.appStates,
671
+ isConversationalSurvey: action.payload
672
+ }
673
+ };
674
+ return {
675
+ ...state,
676
+ appStates: {
677
+ ...state.appStates,
678
+ isConversationalSurvey: action.payload
679
+ }
680
+ };
651
681
  case LiveChatWidgetActionType.GET_IN_MEMORY_STATE:
652
682
  return inMemory;
653
683
  default:
@@ -17,7 +17,7 @@ export const shouldShowEmailTranscriptPane = state => {
17
17
  return state.uiStates.showEmailTranscriptPane;
18
18
  };
19
19
  export const shouldShowWebChatContainer = state => {
20
- return !state.appStates.isMinimized && state.appStates.conversationState === ConversationState.Active || state.appStates.conversationState === ConversationState.InActive;
20
+ return !state.appStates.isMinimized && state.appStates.conversationState === ConversationState.Active || state.appStates.conversationState === ConversationState.InActive || state.appStates.conversationState === ConversationState.Postchat && state.appStates.isConversationalSurveyEnabled && state.appStates.isConversationalSurvey;
21
21
  };
22
22
  export const shouldShowLoadingPane = state => {
23
23
  return !state.appStates.isMinimized && state.appStates.conversationState === ConversationState.Loading;
@@ -42,7 +42,7 @@ export const shouldShowConfirmationPane = state => {
42
42
  return state.uiStates.showConfirmationPane;
43
43
  };
44
44
  export const shouldShowPostChatSurveyPane = state => {
45
- return state.appStates.conversationState === ConversationState.Postchat;
45
+ return state.appStates.conversationState === ConversationState.Postchat && !state.appStates.isConversationalSurvey;
46
46
  };
47
47
  export const shouldShowCallingContainer = state => {
48
48
  return state.appStates.conversationState === ConversationState.Active && state.appStates.e2vvEnabled;
@@ -1,35 +1,59 @@
1
1
  import { ScenarioType } from "./Constants";
2
2
  import { Constants } from "../common/Constants";
3
+ /**
4
+ * Determines whether a given activity is a historical message.
5
+ *
6
+ * This function checks if the activity is a message type and uses a combination
7
+ * of legacy tags and timestamp-based logic to determine if the message is historical.
8
+ *
9
+ * @param {IActivity} activity - The activity object to evaluate.
10
+ * @param {number} startTime - The start time (in milliseconds since epoch) to compare against.
11
+ * @returns {boolean} - Returns true if the activity is a historical message, false otherwise.
12
+ *
13
+ * Logic:
14
+ * - If the activity type is not a message, it is not historical.
15
+ * - If the activity contains a legacy history message tag, it is considered historical.
16
+ * - Otherwise, the function extracts a timestamp from the activity ID using `extractTimestampFromId`.
17
+ * - If the ID is valid and the timestamp is older than the start time, the message is historical.
18
+ */
3
19
  export const isHistoryMessage = (activity, startTime) => {
4
- try {
5
- if ((activity === null || activity === void 0 ? void 0 : activity.type) === Constants.message) {
6
- var _activity$channelData, _activity$channelData2;
7
- // this is an old piece of code, probably no longer relevant
8
- if (activity !== null && activity !== void 0 && (_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && (_activity$channelData2 = _activity$channelData.tags) !== null && _activity$channelData2 !== void 0 && _activity$channelData2.includes(Constants.historyMessageTag)) return true;
20
+ var _activity$channelData, _activity$channelData2;
21
+ // Only process message activities
22
+ if ((activity === null || activity === void 0 ? void 0 : activity.type) !== Constants.message) {
23
+ return false;
24
+ }
9
25
 
10
- // Id is an epoch time in milliseconds , in utc format, for some reason is in a string format
11
- if (activity !== null && activity !== void 0 && activity.id) {
12
- /// activity.id is an string that contains epoch time in milliseconds
13
- const activityId = parseInt(activity === null || activity === void 0 ? void 0 : activity.id);
26
+ // Legacy check for history message tag
27
+ if (activity !== null && activity !== void 0 && (_activity$channelData = activity.channelData) !== null && _activity$channelData !== void 0 && (_activity$channelData2 = _activity$channelData.tags) !== null && _activity$channelData2 !== void 0 && _activity$channelData2.includes(Constants.historyMessageTag)) {
28
+ return true;
29
+ }
30
+ const activityId = extractTimestampFromId(activity);
31
+ const isValidId = !isNaN(activityId) && activityId > 0;
32
+ const isOlderThanStartTime = activityId < startTime;
33
+ const isHistoryById = isValidId && isOlderThanStartTime;
34
+ return isHistoryById;
35
+ };
36
+ export const extractTimestampFromId = activity => {
37
+ const id = (activity === null || activity === void 0 ? void 0 : activity.id) ?? "";
14
38
 
15
- // if the activity id is not a number, we default to new message
16
- if (isNaN(activityId)) {
17
- return false;
18
- }
39
+ // Helper function to get timestamp fallback
40
+ const getTimestampFallback = () => {
41
+ const timestamp = new Date((activity === null || activity === void 0 ? void 0 : activity.timestamp) ?? "").getTime();
42
+ return isNaN(timestamp) ? 0 : timestamp;
43
+ };
19
44
 
20
- // if the activity id is less than the start time, it means that the message is a history message
21
- if (activityId < startTime) {
22
- return true;
23
- }
24
- }
25
- // anything else will be considered a new message
26
- return false;
27
- }
28
- } catch (e) {
29
- // if there is an error in parsing the activity id, we will consider it a new message
30
- console.error("Error in parsing activity id: ", e);
45
+ // Check if ID looks like a UUID (contains dashes or is very long)
46
+ const UUID_LENGTH_THRESHOLD = 13; // Threshold to distinguish UUIDs from epoch timestamps
47
+ if (id.includes("-") || id.length > UUID_LENGTH_THRESHOLD) {
48
+ // Likely UUID, use timestamp instead
49
+ return getTimestampFallback();
50
+ }
51
+ const activityId = parseInt(id);
52
+ // if activity id is not a number, then we use timestamp field
53
+ if (isNaN(activityId)) {
54
+ return getTimestampFallback();
31
55
  }
32
- return false;
56
+ return activityId;
33
57
  };
34
58
  export const buildMessagePayload = (activity, userId) => {
35
59
  var _text, _text2, _activity$channelData3, _activity$from;
@@ -6,13 +6,13 @@ import { Constants } from "../common/Constants";
6
6
  import { FirstResponseLatencyTracker } from "../firstresponselatency/FirstResponseLatencyTracker";
7
7
  import { TelemetryHelper } from "../common/telemetry/TelemetryHelper";
8
8
  import { TelemetryManager } from "../common/telemetry/TelemetryManager";
9
- export const createOnNewAdapterActivityHandler = (chatId, userId) => {
9
+ export const createOnNewAdapterActivityHandler = (chatId, userId, startTime) => {
10
10
  // Hooking the message tracker in the listener, a bit invasive but easier to control.
11
11
  const firstResponseLatencyTracker = new FirstResponseLatencyTracker();
12
12
  // epoch time in utc for when start to listen.
13
13
  // We dont longer have a mechanism to know if a message is history or new, so any message older than the time we start listening will be considered a history message.
14
14
  // this is a workaround for the fact that we dont have a way to identify if a message is history or new, and it will provide consistency across different scenarios
15
- const startTime = new Date().getTime();
15
+
16
16
  let isHistoryMessageReceivedEventRaised = false;
17
17
  const onNewAdapterActivityHandler = activity => {
18
18
  raiseMessageEvent(activity);
@@ -35,6 +35,7 @@ export const createOnNewAdapterActivityHandler = (chatId, userId) => {
35
35
  });
36
36
  };
37
37
  const systemMessageStrategy = activity => {
38
+ var _TelemetryManager$Int3;
38
39
  const payload = buildMessagePayload(activity, userId);
39
40
  payload.messageType = Constants.systemMessageTag;
40
41
  if (isHistoryMessage(activity, startTime)) {
@@ -42,6 +43,11 @@ export const createOnNewAdapterActivityHandler = (chatId, userId) => {
42
43
  historyMessageStrategy(polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int2 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int2 === void 0 ? void 0 : _TelemetryManager$Int2.conversationId));
43
44
  return;
44
45
  }
46
+ const newMessageReceivedEvent = {
47
+ eventName: BroadcastEvent.NewMessageReceived,
48
+ payload: polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int3 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int3 === void 0 ? void 0 : _TelemetryManager$Int3.conversationId)
49
+ };
50
+ BroadcastService.postMessage(newMessageReceivedEvent);
45
51
  TelemetryHelper.logActionEventToAllTelemetry(LogLevel.INFO, {
46
52
  Event: TelemetryEvent.SystemMessageReceived,
47
53
  Description: "System message received"
@@ -77,20 +83,20 @@ export const createOnNewAdapterActivityHandler = (chatId, userId) => {
77
83
  return true;
78
84
  };
79
85
  const receivedMessageStrategy = activity => {
80
- var _TelemetryManager$Int4;
86
+ var _TelemetryManager$Int5;
81
87
  if (!isValidMessage(activity)) return;
82
88
  const isHistoryMessageReceived = isHistoryMessage(activity, startTime);
83
89
  const payload = buildMessagePayload(activity, userId);
84
90
  payload.messageType = Constants.userMessageTag;
85
91
  if (isHistoryMessageReceived) {
86
- var _TelemetryManager$Int3;
87
- historyMessageStrategy(polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int3 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int3 === void 0 ? void 0 : _TelemetryManager$Int3.conversationId));
92
+ var _TelemetryManager$Int4;
93
+ historyMessageStrategy(polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int4 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int4 === void 0 ? void 0 : _TelemetryManager$Int4.conversationId));
88
94
  return;
89
95
  }
90
96
  firstResponseLatencyTracker.stopClock(payload);
91
97
  const newMessageReceivedEvent = {
92
98
  eventName: BroadcastEvent.NewMessageReceived,
93
- payload: polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int4 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int4 === void 0 ? void 0 : _TelemetryManager$Int4.conversationId)
99
+ payload: polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int5 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int5 === void 0 ? void 0 : _TelemetryManager$Int5.conversationId)
94
100
  };
95
101
  BroadcastService.postMessage(newMessageReceivedEvent);
96
102
  TelemetryHelper.logActionEventToAllTelemetry(LogLevel.INFO, {
@@ -7,6 +7,9 @@ export declare class Constants {
7
7
  static readonly historyMessageTag = "history";
8
8
  static readonly agentEndConversationMessageTag = "agentendconversation";
9
9
  static readonly supervisorForceCloseMessageTag = "supervisorforceclosedconversation";
10
+ static readonly endConversationalSurveyMessageTag = "endconversationalsurvey";
11
+ static readonly startConversationalSurveyMessageTag = "startconversationalsurvey";
12
+ static readonly c2ConversationalSurveyMessageTag = "c2conversationalsurvey";
10
13
  static readonly receivedMessageClassName = "ms_lcw_webchat_received_message";
11
14
  static readonly sentMessageClassName = "ms_lcw_webchat_sent_message";
12
15
  static readonly webchatChannelId = "webchat";
@@ -180,6 +183,9 @@ export declare enum ConversationMode {
180
183
  Regular = "192350000",
181
184
  Persistent = "192350001"
182
185
  }
186
+ export declare enum SurveyProvider {
187
+ MicrosoftCopilotStudio = "600990001"
188
+ }
183
189
  export declare enum LiveWorkItemState {
184
190
  Active = "Active",
185
191
  Closed = "Closed",
@@ -1,3 +1,4 @@
1
1
  import { FacadeChatSDK } from "../../../common/facades/FacadeChatSDK";
2
2
  export declare const isPostChatSurveyEnabled: (facadeChatSDK: FacadeChatSDK) => Promise<boolean>;
3
+ export declare const getPostChatSurveyConfig: (facadeChatSDK: FacadeChatSDK) => Promise<any>;
3
4
  export declare const isPersistentChatEnabled: (conversationMode: string | undefined) => boolean;
@@ -4,7 +4,7 @@
4
4
  * Adds necessary tags if not present so that the rendering middlewares can process them later.
5
5
  ******/
6
6
  import { IWebChatAction } from "../../../interfaces/IWebChatAction";
7
- declare const channelDataMiddleware: ({ dispatch }: {
7
+ declare const channelDataMiddleware: (addConversationalSurveyTagsCallback: any) => ({ dispatch }: {
8
8
  dispatch: any;
9
9
  }) => (next: any) => (action: IWebChatAction) => any;
10
10
  export default channelDataMiddleware;
@@ -5,7 +5,7 @@
5
5
  * The callback is then invoked to hide the send box (by default).
6
6
  ******/
7
7
  import { IWebChatAction } from "../../../interfaces/IWebChatAction";
8
- declare const createConversationEndMiddleware: (conversationEndCallback: any) => ({ dispatch }: {
8
+ declare const createConversationEndMiddleware: (conversationEndCallback: any, startConversationalSurveyCallback: any, endConversationalSurveyCallback: any) => ({ dispatch }: {
9
9
  dispatch: any;
10
10
  }) => (next: any) => (action: IWebChatAction) => any;
11
11
  export default createConversationEndMiddleware;
@@ -48,6 +48,8 @@ export interface ILiveChatWidgetContext {
48
48
  chatDisconnectEventReceived: boolean;
49
49
  selectedSurveyMode: string | null;
50
50
  postChatParticipantType: undefined | ParticipantType;
51
+ isConversationalSurvey: boolean;
52
+ isConversationalSurveyEnabled: boolean;
51
53
  };
52
54
  uiStates: {
53
55
  showConfirmationPane: boolean;
@@ -44,5 +44,7 @@ export declare enum LiveChatWidgetActionType {
44
44
  SET_SURVEY_MODE = 42,
45
45
  SET_CONFIRMATION_STATE = 43,
46
46
  SET_POST_CHAT_PARTICIPANT_TYPE = 44,
47
- GET_IN_MEMORY_STATE = 45
47
+ SET_CONVERSATIONAL_SURVEY_ENABLED = 45,
48
+ SET_CONVERSATIONAL_SURVEY_DISPLAY = 46,
49
+ GET_IN_MEMORY_STATE = 47
48
50
  }
@@ -1,6 +1,23 @@
1
1
  import { MessagePayload, ScenarioType, TrackingMessage } from "./Constants";
2
2
  import { IActivity } from "botframework-directlinejs";
3
+ /**
4
+ * Determines whether a given activity is a historical message.
5
+ *
6
+ * This function checks if the activity is a message type and uses a combination
7
+ * of legacy tags and timestamp-based logic to determine if the message is historical.
8
+ *
9
+ * @param {IActivity} activity - The activity object to evaluate.
10
+ * @param {number} startTime - The start time (in milliseconds since epoch) to compare against.
11
+ * @returns {boolean} - Returns true if the activity is a historical message, false otherwise.
12
+ *
13
+ * Logic:
14
+ * - If the activity type is not a message, it is not historical.
15
+ * - If the activity contains a legacy history message tag, it is considered historical.
16
+ * - Otherwise, the function extracts a timestamp from the activity ID using `extractTimestampFromId`.
17
+ * - If the ID is valid and the timestamp is older than the start time, the message is historical.
18
+ */
3
19
  export declare const isHistoryMessage: (activity: IActivity, startTime: number) => boolean;
20
+ export declare const extractTimestampFromId: (activity: IActivity) => number;
4
21
  export declare const buildMessagePayload: (activity: IActivity, userId: string) => MessagePayload;
5
22
  export declare const polyfillMessagePayloadForEvent: (activity: IActivity, payload: MessagePayload, conversationId?: string) => MessagePayload;
6
23
  export declare const getScenarioType: (activity: IActivity) => ScenarioType;
@@ -1,2 +1,2 @@
1
1
  import { IActivity } from "botframework-directlinejs";
2
- export declare const createOnNewAdapterActivityHandler: (chatId: string, userId: string) => (activity: IActivity) => void;
2
+ export declare const createOnNewAdapterActivityHandler: (chatId: string, userId: string, startTime: number) => (activity: IActivity) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/omnichannel-chat-widget",
3
- "version": "1.8.2-main.e3c1d40",
3
+ "version": "1.8.2-main.fc93d3d",
4
4
  "description": "Microsoft Omnichannel Chat Widget",
5
5
  "main": "lib/cjs/index.js",
6
6
  "types": "lib/types/index.d.ts",
@@ -121,8 +121,8 @@
121
121
  "build:umd": "webpack --config ./webpack.umd.config.cjs",
122
122
  "verify": "yarn install && yarn build-storybook && yarn test:all && yarn build && yarn storybook",
123
123
  "testpack": "yarn build && yarn pack",
124
- "build-sample": "yarn build && webpack --config ./webpack.config.cjs",
125
- "build-sample:dev": "yarn build && webpack --config ./webpack.dev.config.cjs",
124
+ "build-sample": "yarn build && cross-env NODE_OPTIONS=--openssl-legacy-provider webpack --config ./webpack.config.cjs",
125
+ "build-sample:dev": "yarn build && cross-env NODE_OPTIONS=--openssl-legacy-provider webpack --config ./webpack.dev.config.cjs",
126
126
  "test:visual:build": "yarn build-storybook && yarn test:visual",
127
127
  "lint": "yarn eslint . --max-warnings=0",
128
128
  "prepush": "yarn lint && yarn danger:prepush",