@microsoft/omnichannel-chat-widget 1.8.4-main.cbab5fc → 1.8.4-main.cd79f08
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -3
- package/lib/cjs/common/Constants.js +2 -0
- package/lib/cjs/common/facades/FacadeChatSDK.js +235 -9
- package/lib/cjs/common/telemetry/TelemetryConstants.js +13 -0
- package/lib/cjs/common/telemetry/loggers/appInsightsLogger.js +7 -7
- package/lib/cjs/common/utils/xssUtils.js +23 -51
- package/lib/cjs/common/utils.js +15 -2
- package/lib/cjs/components/errorboundary/ErrorBoundary.js +2 -1
- package/lib/cjs/components/livechatwidget/LiveChatWidget.js +9 -1
- package/lib/cjs/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +23 -6
- package/lib/cjs/components/livechatwidget/common/ChatWidgetEvents.js +1 -0
- package/lib/cjs/components/livechatwidget/common/PersistentConversationHandler.js +9 -0
- package/lib/cjs/components/livechatwidget/common/authHelper.js +44 -4
- package/lib/cjs/components/livechatwidget/common/createAdapter.js +3 -2
- package/lib/cjs/components/livechatwidget/common/liveChatConfigUtils.js +36 -4
- package/lib/cjs/components/livechatwidget/common/startChat.js +31 -14
- package/lib/cjs/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +62 -2
- package/lib/cjs/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +6 -4
- package/lib/cjs/components/proactivechatpanestateful/ProactiveChatPaneStateful.js +0 -1
- package/lib/cjs/components/webchatcontainerstateful/WebChatContainerStateful.js +42 -27
- package/lib/cjs/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +117 -16
- package/lib/cjs/components/webchatcontainerstateful/common/defaultStyles/defaultAdaptiveCardStyles.js +3 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +13 -2
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +160 -167
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +1 -1
- package/lib/cjs/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/NotDeliveredTimestamp.js +2 -0
- package/lib/cjs/contexts/common/LiveChatWidgetActionType.js +1 -0
- package/lib/cjs/contexts/common/LiveChatWidgetContextInitialState.js +6 -1
- package/lib/cjs/contexts/createReducer.js +15 -0
- package/lib/cjs/controller/componentController.js +13 -1
- package/lib/cjs/plugins/newMessageEventHandler.js +20 -3
- package/lib/esm/common/Constants.js +2 -0
- package/lib/esm/common/facades/FacadeChatSDK.js +236 -10
- package/lib/esm/common/telemetry/TelemetryConstants.js +13 -0
- package/lib/esm/common/telemetry/loggers/appInsightsLogger.js +7 -7
- package/lib/esm/common/utils/xssUtils.js +23 -51
- package/lib/esm/common/utils.js +12 -1
- package/lib/esm/components/errorboundary/ErrorBoundary.js +4 -2
- package/lib/esm/components/livechatwidget/LiveChatWidget.js +9 -1
- package/lib/esm/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.js +23 -6
- package/lib/esm/components/livechatwidget/common/ChatWidgetEvents.js +1 -0
- package/lib/esm/components/livechatwidget/common/PersistentConversationHandler.js +9 -0
- package/lib/esm/components/livechatwidget/common/authHelper.js +44 -4
- package/lib/esm/components/livechatwidget/common/createAdapter.js +3 -2
- package/lib/esm/components/livechatwidget/common/liveChatConfigUtils.js +33 -2
- package/lib/esm/components/livechatwidget/common/startChat.js +31 -14
- package/lib/esm/components/livechatwidget/livechatwidgetstateful/LiveChatWidgetStateful.js +62 -2
- package/lib/esm/components/postchatsurveypanestateful/PostChatSurveyPaneStateful.js +6 -4
- package/lib/esm/components/proactivechatpanestateful/ProactiveChatPaneStateful.js +1 -2
- package/lib/esm/components/webchatcontainerstateful/WebChatContainerStateful.js +43 -28
- package/lib/esm/components/webchatcontainerstateful/common/activityConverters/convertPersistentChatHistoryMessageToActivity.js +117 -16
- package/lib/esm/components/webchatcontainerstateful/common/defaultStyles/defaultAdaptiveCardStyles.js +3 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/WebChatEventSubscribers.js +13 -2
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.js +160 -171
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activityMiddleware.js +1 -1
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/timestamps/NotDeliveredTimestamp.js +2 -0
- package/lib/esm/components/webchatcontainerstateful/webchatcontroller/middlewares/storemiddlewares/channelDataMiddleware.js +1 -0
- package/lib/esm/contexts/common/LiveChatWidgetActionType.js +1 -0
- package/lib/esm/contexts/common/LiveChatWidgetContextInitialState.js +6 -1
- package/lib/esm/contexts/createReducer.js +15 -0
- package/lib/esm/controller/componentController.js +13 -1
- package/lib/esm/plugins/newMessageEventHandler.js +20 -3
- package/lib/types/common/Constants.d.ts +2 -0
- package/lib/types/common/facades/FacadeChatSDK.d.ts +29 -0
- package/lib/types/common/facades/types/IFacadeChatSDKInput.d.ts +3 -1
- package/lib/types/common/telemetry/TelemetryConstants.d.ts +13 -2
- package/lib/types/common/utils/xssUtils.d.ts +5 -21
- package/lib/types/common/utils.d.ts +9 -1
- package/lib/types/components/errorboundary/ErrorBoundary.d.ts +1 -1
- package/lib/types/components/livechatwidget/common/ActivitySubscriber/BotAuthActivitySubscriber.d.ts +1 -0
- package/lib/types/components/livechatwidget/common/ChatWidgetEvents.d.ts +2 -1
- package/lib/types/components/livechatwidget/common/authHelper.d.ts +9 -2
- package/lib/types/components/livechatwidget/common/liveChatConfigUtils.d.ts +11 -0
- package/lib/types/components/livechatwidget/interfaces/IBotAuthActivitySubscriberOptionalParams.d.ts +1 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IAdaptiveCardStyles.d.ts +2 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IBotAuthConfig.d.ts +7 -0
- package/lib/types/components/webchatcontainerstateful/interfaces/IExtendedChatConffig.d.ts +1 -1
- package/lib/types/components/webchatcontainerstateful/webchatcontroller/middlewares/renderingmiddlewares/activities/LazyLoadActivity.d.ts +14 -38
- package/lib/types/contexts/common/ILiveChatWidgetContext.d.ts +1 -0
- package/lib/types/contexts/common/LiveChatWidgetActionType.d.ts +2 -1
- package/package.json +15 -6
|
@@ -2,6 +2,17 @@ import { LogLevel, TelemetryEvent } from "../../../common/telemetry/TelemetryCon
|
|
|
2
2
|
import { TelemetryHelper } from "../../../common/telemetry/TelemetryHelper";
|
|
3
3
|
import { WidgetLoadCustomErrorString } from "../../../common/Constants";
|
|
4
4
|
import { isNullOrEmptyString } from "../../../common/utils";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Check if mid-auth is enabled based on chatConfig.
|
|
8
|
+
* Mid-auth flag lives under LiveWSAndLiveChatEngJoin.msdyn_authenticatedsigninoptional.
|
|
9
|
+
*/
|
|
10
|
+
const isMidAuthEnabled = chatConfig => {
|
|
11
|
+
var _chatConfig$LiveWSAnd, _value$toString, _value$toString$call$, _value$toString$call;
|
|
12
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
13
|
+
const value = chatConfig === null || chatConfig === void 0 ? void 0 : (_chatConfig$LiveWSAnd = chatConfig.LiveWSAndLiveChatEngJoin) === null || _chatConfig$LiveWSAnd === void 0 ? void 0 : _chatConfig$LiveWSAnd.msdyn_authenticatedsigninoptional;
|
|
14
|
+
return (value === null || value === void 0 ? void 0 : (_value$toString = value.toString) === null || _value$toString === void 0 ? void 0 : (_value$toString$call$ = (_value$toString$call = _value$toString.call(value)).toLowerCase) === null || _value$toString$call$ === void 0 ? void 0 : _value$toString$call$.call(_value$toString$call)) === "true";
|
|
15
|
+
};
|
|
5
16
|
const getAuthClientFunction = chatConfig => {
|
|
6
17
|
let authClientFunction = undefined;
|
|
7
18
|
if (chatConfig !== null && chatConfig !== void 0 && chatConfig.LiveChatConfigAuthSettings) {
|
|
@@ -12,12 +23,17 @@ const getAuthClientFunction = chatConfig => {
|
|
|
12
23
|
};
|
|
13
24
|
const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
|
|
14
25
|
var _chatSDK$chatSDKConfi;
|
|
26
|
+
const midAuthEnabled = isMidAuthEnabled(chatConfig);
|
|
15
27
|
const authClientFunction = getAuthClientFunction(chatConfig);
|
|
16
28
|
if (getAuthToken && authClientFunction) {
|
|
17
29
|
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
18
30
|
Event: TelemetryEvent.GetAuthTokenCalled
|
|
19
31
|
});
|
|
20
|
-
|
|
32
|
+
|
|
33
|
+
// Only pass isMidAuthEnabled option when mid-auth is enabled.
|
|
34
|
+
const token = midAuthEnabled ? await getAuthToken(authClientFunction, {
|
|
35
|
+
isMidAuthEnabled: midAuthEnabled
|
|
36
|
+
}) : await getAuthToken(authClientFunction);
|
|
21
37
|
if (!isNullOrEmptyString(token)) {
|
|
22
38
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
39
|
chatSDK.setAuthTokenProvider(async () => {
|
|
@@ -28,8 +44,21 @@ const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
|
|
|
28
44
|
"token": token
|
|
29
45
|
};
|
|
30
46
|
} else {
|
|
31
|
-
//
|
|
32
|
-
//
|
|
47
|
+
// For mid-auth scenarios, empty token means "user not signed in" - this is expected behavior.
|
|
48
|
+
// Return result: true with empty token so caller can decide to proceed unauthenticated.
|
|
49
|
+
if (midAuthEnabled) {
|
|
50
|
+
// Expected behavior for mid-auth: user not signed in
|
|
51
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
52
|
+
Event: TelemetryEvent.GetAuthTokenCalled,
|
|
53
|
+
Description: "Mid-auth: token provider returned empty; user not signed in"
|
|
54
|
+
});
|
|
55
|
+
return {
|
|
56
|
+
"result": true,
|
|
57
|
+
"token": null
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// For non-mid-auth scenarios, empty token is an error
|
|
33
62
|
TelemetryHelper.logActionEvent(LogLevel.ERROR, {
|
|
34
63
|
Event: TelemetryEvent.ReceivedNullOrEmptyToken
|
|
35
64
|
});
|
|
@@ -39,6 +68,17 @@ const handleAuthentication = async (chatSDK, chatConfig, getAuthToken) => {
|
|
|
39
68
|
var _chatSDK$chatSDKConfi2;
|
|
40
69
|
const token = await ((_chatSDK$chatSDKConfi2 = chatSDK.chatSDKConfig) === null || _chatSDK$chatSDKConfi2 === void 0 ? void 0 : _chatSDK$chatSDKConfi2.getAuthToken());
|
|
41
70
|
if (isNullOrEmptyString(token)) {
|
|
71
|
+
// For mid-auth scenarios, empty token from SDK's getAuthToken is also expected
|
|
72
|
+
if (midAuthEnabled) {
|
|
73
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
74
|
+
Event: TelemetryEvent.GetAuthTokenCalled,
|
|
75
|
+
Description: "Mid-auth: SDK getAuthToken returned empty; user not signed in"
|
|
76
|
+
});
|
|
77
|
+
return {
|
|
78
|
+
"result": true,
|
|
79
|
+
"token": null
|
|
80
|
+
};
|
|
81
|
+
}
|
|
42
82
|
TelemetryHelper.logActionEvent(LogLevel.ERROR, {
|
|
43
83
|
Event: TelemetryEvent.ReceivedNullOrEmptyToken,
|
|
44
84
|
Description: "getAuthToken in chat SDK returns empty string"
|
|
@@ -66,4 +106,4 @@ const removeAuthTokenProvider = chatSDK => {
|
|
|
66
106
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
67
107
|
chatSDK.authenticatedUserToken = null;
|
|
68
108
|
};
|
|
69
|
-
export { getAuthClientFunction, handleAuthentication, removeAuthTokenProvider };
|
|
109
|
+
export { getAuthClientFunction, handleAuthentication, removeAuthTokenProvider, isMidAuthEnabled };
|
|
@@ -39,10 +39,11 @@ export const createAdapter = async (facadeChatSDK, props) => {
|
|
|
39
39
|
//so far, there is no need to convert to the shim adapter when using visual tests
|
|
40
40
|
const isMocked = facadeChatSDK.getChatSDK() instanceof MockChatSDK;
|
|
41
41
|
if (isMocked !== true) {
|
|
42
|
-
var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4;
|
|
42
|
+
var _props$webChatContain, _props$webChatContain2, _props$webChatContain3, _props$webChatContain4, _props$webChatContain5, _props$webChatContain6;
|
|
43
43
|
const botAuthActivitySubscriberOptionalParams = {
|
|
44
44
|
fetchBotAuthConfigRetries: (props === null || props === void 0 ? void 0 : (_props$webChatContain = props.webChatContainerProps) === null || _props$webChatContain === void 0 ? void 0 : (_props$webChatContain2 = _props$webChatContain.botAuthConfig) === null || _props$webChatContain2 === void 0 ? void 0 : _props$webChatContain2.fetchBotAuthConfigRetries) || defaultBotAuthConfig.fetchBotAuthConfigRetries,
|
|
45
|
-
fetchBotAuthConfigRetryInterval: (props === null || props === void 0 ? void 0 : (_props$webChatContain3 = props.webChatContainerProps) === null || _props$webChatContain3 === void 0 ? void 0 : (_props$webChatContain4 = _props$webChatContain3.botAuthConfig) === null || _props$webChatContain4 === void 0 ? void 0 : _props$webChatContain4.fetchBotAuthConfigRetryInterval) || defaultBotAuthConfig.fetchBotAuthConfigRetryInterval
|
|
45
|
+
fetchBotAuthConfigRetryInterval: (props === null || props === void 0 ? void 0 : (_props$webChatContain3 = props.webChatContainerProps) === null || _props$webChatContain3 === void 0 ? void 0 : (_props$webChatContain4 = _props$webChatContain3.botAuthConfig) === null || _props$webChatContain4 === void 0 ? void 0 : _props$webChatContain4.fetchBotAuthConfigRetryInterval) || defaultBotAuthConfig.fetchBotAuthConfigRetryInterval,
|
|
46
|
+
fallbackShowSignInCard: props === null || props === void 0 ? void 0 : (_props$webChatContain5 = props.webChatContainerProps) === null || _props$webChatContain5 === void 0 ? void 0 : (_props$webChatContain6 = _props$webChatContain5.botAuthConfig) === null || _props$webChatContain6 === void 0 ? void 0 : _props$webChatContain6.fallbackShowSignInCard
|
|
46
47
|
};
|
|
47
48
|
adapter = new ChatAdapterShim(adapter);
|
|
48
49
|
adapter.addSubscriber(new AddActivitySubscriber());
|
|
@@ -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()
|
|
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
|
};
|
|
@@ -14,6 +14,7 @@ import { createAdapter } from "./createAdapter";
|
|
|
14
14
|
import { createOnNewAdapterActivityHandler } from "../../../plugins/newMessageEventHandler";
|
|
15
15
|
import { createTrackingForFirstMessage } from "../../../firstresponselatency/FirstMessageTrackerFromBot";
|
|
16
16
|
import { isPersistentChatEnabled } from "./liveChatConfigUtils";
|
|
17
|
+
import { isMidAuthEnabled } from "./authHelper";
|
|
17
18
|
import { setPostChatContextAndLoadSurvey } from "./setPostChatContextAndLoadSurvey";
|
|
18
19
|
import { shouldSetPreChatIfPersistentChat } from "./persistentChatHelper";
|
|
19
20
|
import { updateTelemetryData } from "./updateSessionDataForTelemetry";
|
|
@@ -59,7 +60,7 @@ const prepareStartChat = async (props, facadeChatSDK, state, dispatch, setAdapte
|
|
|
59
60
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
60
61
|
const setPreChatAndInitiateChat = async (facadeChatSDK, dispatch, setAdapter, isProactiveChat, proactiveChatEnablePrechatState, state, props) => {
|
|
61
62
|
var _props$preChatSurveyP, _props$preChatSurveyP2, _props$controlProps, _state$domainStates, _state$domainStates$l, _state$domainStates$l2, _state$appStates2;
|
|
62
|
-
//
|
|
63
|
+
// Reset before loading prechat to avoid starting chat with previous requestId
|
|
63
64
|
if ((state === null || state === void 0 ? void 0 : state.appStates.conversationState) === ConversationState.Closed) {
|
|
64
65
|
// Preventive reset to avoid starting chat with previous requestId which could potentially cause problems
|
|
65
66
|
chatSDKStateCleanUp(facadeChatSDK.getChatSDK());
|
|
@@ -192,7 +193,7 @@ const initStartChat = async (facadeChatSDK, dispatch, setAdapter, state, props,
|
|
|
192
193
|
});
|
|
193
194
|
}
|
|
194
195
|
try {
|
|
195
|
-
var _window$Microsoft, _window$Microsoft$Dyn, _window$Microsoft$Dyn2, _window$Microsoft$Dyn3;
|
|
196
|
+
var _window$Microsoft, _window$Microsoft$Dyn, _window$Microsoft$Dyn2, _window$Microsoft$Dyn3, _state$domainStates8;
|
|
196
197
|
// Set custom context params
|
|
197
198
|
await setCustomContextParams(state, props);
|
|
198
199
|
const defaultOptionalParams = {
|
|
@@ -201,9 +202,25 @@ const initStartChat = async (facadeChatSDK, dispatch, setAdapter, state, props,
|
|
|
201
202
|
portalContactId: (_window$Microsoft = window.Microsoft) === null || _window$Microsoft === void 0 ? void 0 : (_window$Microsoft$Dyn = _window$Microsoft.Dynamic365) === null || _window$Microsoft$Dyn === void 0 ? void 0 : (_window$Microsoft$Dyn2 = _window$Microsoft$Dyn.Portal) === null || _window$Microsoft$Dyn2 === void 0 ? void 0 : (_window$Microsoft$Dyn3 = _window$Microsoft$Dyn2.User) === null || _window$Microsoft$Dyn3 === void 0 ? void 0 : _window$Microsoft$Dyn3.contactId
|
|
202
203
|
};
|
|
203
204
|
const startChatOptionalParams = Object.assign({}, params, optionalParams, defaultOptionalParams);
|
|
205
|
+
|
|
206
|
+
// MID-AUTH: Add wasAuthenticated flag for reconnect scenarios
|
|
207
|
+
// Tells FacadeChatSDK whether the previous session was authenticated
|
|
208
|
+
// Used to detect auth transitions (Auth->Unauth) and decide whether to call authenticateChat
|
|
209
|
+
const midAuthEnabled = isMidAuthEnabled(state === null || state === void 0 ? void 0 : (_state$domainStates8 = state.domainStates) === null || _state$domainStates8 === void 0 ? void 0 : _state$domainStates8.liveChatConfig);
|
|
210
|
+
if (midAuthEnabled) {
|
|
211
|
+
var _state$appStates4, _persistedState$appSt;
|
|
212
|
+
const isUserAuthenticated = (state === null || state === void 0 ? void 0 : (_state$appStates4 = state.appStates) === null || _state$appStates4 === void 0 ? void 0 : _state$appStates4.isUserAuthenticated) === true || (persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$appSt = persistedState.appStates) === null || _persistedState$appSt === void 0 ? void 0 : _persistedState$appSt.isUserAuthenticated) === true;
|
|
213
|
+
startChatOptionalParams.wasAuthenticated = isUserAuthenticated;
|
|
214
|
+
}
|
|
215
|
+
|
|
204
216
|
// startTime is used to determine if a message is history or new, better to be set before creating the adapter to get bandwidth
|
|
205
217
|
const startTime = new Date().getTime();
|
|
206
218
|
createTrackingForFirstMessage();
|
|
219
|
+
|
|
220
|
+
// FacadeChatSDK.startChat() handles:
|
|
221
|
+
// 1. tokenRing() - checks authentication, calls handleAuthentication() if needed
|
|
222
|
+
// 2. Mid-auth: If no token, sets deferInitialAuth=true for unauthenticated flow
|
|
223
|
+
// 3. Mid-auth: On reconnect with valid token, calls authenticateChat to upgrade conversation
|
|
207
224
|
await facadeChatSDK.startChat(startChatOptionalParams);
|
|
208
225
|
logStartChatComplete();
|
|
209
226
|
isStartChatSuccessful = true;
|
|
@@ -290,15 +307,15 @@ const createAdapterAndSubscribe = async (facadeChatSDK, dispatch, setAdapter, st
|
|
|
290
307
|
};
|
|
291
308
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
292
309
|
const canConnectToExistingChat = async (props, facadeChatSDK, state, dispatch, setAdapter) => {
|
|
293
|
-
var _state$
|
|
310
|
+
var _state$appStates5, _persistedState$domai6, _persistedState$appSt2;
|
|
294
311
|
// By pass this function in case of popout chat
|
|
295
|
-
if ((state === null || state === void 0 ? void 0 : (_state$
|
|
312
|
+
if ((state === null || state === void 0 ? void 0 : (_state$appStates5 = state.appStates) === null || _state$appStates5 === void 0 ? void 0 : _state$appStates5.hideStartChatButton) === true) {
|
|
296
313
|
return false;
|
|
297
314
|
}
|
|
298
315
|
const persistedState = getStateFromCache(getWidgetCacheIdfromProps(props));
|
|
299
316
|
|
|
300
317
|
//Connect to only active chat session
|
|
301
|
-
if (persistedState && !isUndefinedOrEmpty(persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$domai6 = persistedState.domainStates) === null || _persistedState$domai6 === void 0 ? void 0 : _persistedState$domai6.liveChatContext) && (persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$
|
|
318
|
+
if (persistedState && !isUndefinedOrEmpty(persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$domai6 = persistedState.domainStates) === null || _persistedState$domai6 === void 0 ? void 0 : _persistedState$domai6.liveChatContext) && (persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$appSt2 = persistedState.appStates) === null || _persistedState$appSt2 === void 0 ? void 0 : _persistedState$appSt2.conversationState) === ConversationState.Active) {
|
|
302
319
|
var _persistedState$domai7;
|
|
303
320
|
dispatch({
|
|
304
321
|
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
@@ -315,11 +332,11 @@ const canConnectToExistingChat = async (props, facadeChatSDK, state, dispatch, s
|
|
|
315
332
|
|
|
316
333
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
317
334
|
const setCustomContextParams = async (state, props) => {
|
|
318
|
-
var _state$
|
|
319
|
-
if (state !== null && state !== void 0 && (_state$
|
|
320
|
-
var _state$
|
|
335
|
+
var _state$domainStates9, _persistedState$domai8;
|
|
336
|
+
if (state !== null && state !== void 0 && (_state$domainStates9 = state.domainStates) !== null && _state$domainStates9 !== void 0 && _state$domainStates9.customContext) {
|
|
337
|
+
var _state$domainStates10;
|
|
321
338
|
optionalParams = Object.assign({}, optionalParams, {
|
|
322
|
-
customContext: JSON.parse(JSON.stringify(state === null || state === void 0 ? void 0 : (_state$
|
|
339
|
+
customContext: JSON.parse(JSON.stringify(state === null || state === void 0 ? void 0 : (_state$domainStates10 = state.domainStates) === null || _state$domainStates10 === void 0 ? void 0 : _state$domainStates10.customContext))
|
|
323
340
|
});
|
|
324
341
|
return;
|
|
325
342
|
}
|
|
@@ -352,9 +369,9 @@ const canStartPopoutChat = async props => {
|
|
|
352
369
|
}
|
|
353
370
|
popoutWidgetInstanceId = getWidgetCacheIdfromProps(props, true);
|
|
354
371
|
if (!isNullOrEmptyString(popoutWidgetInstanceId)) {
|
|
355
|
-
var _persistedState$domai9, _persistedState$
|
|
372
|
+
var _persistedState$domai9, _persistedState$appSt3;
|
|
356
373
|
const persistedState = getStateFromCache(popoutWidgetInstanceId);
|
|
357
|
-
if (persistedState && !isUndefinedOrEmpty(persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$domai9 = persistedState.domainStates) === null || _persistedState$domai9 === void 0 ? void 0 : _persistedState$domai9.liveChatContext) && (persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$
|
|
374
|
+
if (persistedState && !isUndefinedOrEmpty(persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$domai9 = persistedState.domainStates) === null || _persistedState$domai9 === void 0 ? void 0 : _persistedState$domai9.liveChatContext) && (persistedState === null || persistedState === void 0 ? void 0 : (_persistedState$appSt3 = persistedState.appStates) === null || _persistedState$appSt3 === void 0 ? void 0 : _persistedState$appSt3.conversationState) === ConversationState.Active) {
|
|
358
375
|
// Initiate popout chat
|
|
359
376
|
BroadcastService.postMessage({
|
|
360
377
|
eventName: BroadcastEvent.InitiateStartChatInPopoutMode
|
|
@@ -367,9 +384,9 @@ const canStartPopoutChat = async props => {
|
|
|
367
384
|
|
|
368
385
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
369
386
|
const checkIfConversationStillValid = async (facadeChatSDK, dispatch, state) => {
|
|
370
|
-
var _state$
|
|
371
|
-
const requestIdFromCache = (_state$
|
|
372
|
-
const liveChatContext = state === null || state === void 0 ? void 0 : (_state$
|
|
387
|
+
var _state$domainStates11, _state$domainStates12, _state$domainStates13;
|
|
388
|
+
const requestIdFromCache = (_state$domainStates11 = state.domainStates) === null || _state$domainStates11 === void 0 ? void 0 : (_state$domainStates12 = _state$domainStates11.liveChatContext) === null || _state$domainStates12 === void 0 ? void 0 : _state$domainStates12.requestId;
|
|
389
|
+
const liveChatContext = state === null || state === void 0 ? void 0 : (_state$domainStates13 = state.domainStates) === null || _state$domainStates13 === void 0 ? void 0 : _state$domainStates13.liveChatContext;
|
|
373
390
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
374
391
|
let conversationDetails = undefined;
|
|
375
392
|
// Preserve current requestId
|
|
@@ -50,6 +50,7 @@ import { initConfirmationPropsComposer } from "../common/initConfirmationPropsCo
|
|
|
50
50
|
import { initWebChatComposer } from "../common/initWebChatComposer";
|
|
51
51
|
import { registerBroadcastServiceForStorage } from "../../../common/storage/default/defaultCacheManager";
|
|
52
52
|
import { setPostChatContextAndLoadSurvey } from "../common/setPostChatContextAndLoadSurvey";
|
|
53
|
+
import { shouldLoadPersistentChatHistory } from "../common/liveChatConfigUtils";
|
|
53
54
|
import { startProactiveChat } from "../common/startProactiveChat";
|
|
54
55
|
import useChatAdapterStore from "../../../hooks/useChatAdapterStore";
|
|
55
56
|
import useChatContextStore from "../../../hooks/useChatContextStore";
|
|
@@ -728,7 +729,15 @@ export const LiveChatWidgetStateful = props => {
|
|
|
728
729
|
if (state.appStates.isMinimized) {
|
|
729
730
|
ActivityStreamHandler.cork();
|
|
730
731
|
} else {
|
|
731
|
-
|
|
732
|
+
var _state$domainStates4;
|
|
733
|
+
const extendedChatConfig = state === null || state === void 0 ? void 0 : (_state$domainStates4 = state.domainStates) === null || _state$domainStates4 === void 0 ? void 0 : _state$domainStates4.liveChatConfig;
|
|
734
|
+
if (shouldLoadPersistentChatHistory(extendedChatConfig)) {
|
|
735
|
+
requestAnimationFrame(() => {
|
|
736
|
+
setTimeout(() => ActivityStreamHandler.uncork(), 500);
|
|
737
|
+
});
|
|
738
|
+
} else {
|
|
739
|
+
setTimeout(() => ActivityStreamHandler.uncork(), 500);
|
|
740
|
+
}
|
|
732
741
|
}
|
|
733
742
|
}, [state.appStates.isMinimized]);
|
|
734
743
|
|
|
@@ -806,7 +815,7 @@ export const LiveChatWidgetStateful = props => {
|
|
|
806
815
|
|
|
807
816
|
// In conversational survey, we need to check post chat survey logics before we set ConversationState to InActive
|
|
808
817
|
// Hence setting ConversationState to InActive will be done later in the post chat flows
|
|
809
|
-
if (!isConversationalSurveyEnabled && (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta12 = inMemoryState.appStates) === null || _inMemoryState$appSta12 === void 0 ? void 0 : _inMemoryState$appSta12.conversationEndedBy) === ConversationEndEntity.Agent || (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta13 = inMemoryState.appStates) === null || _inMemoryState$appSta13 === void 0 ? void 0 : _inMemoryState$appSta13.conversationEndedBy) === ConversationEndEntity.Bot) {
|
|
818
|
+
if (!isConversationalSurveyEnabled && ((inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta12 = inMemoryState.appStates) === null || _inMemoryState$appSta12 === void 0 ? void 0 : _inMemoryState$appSta12.conversationEndedBy) === ConversationEndEntity.Agent || (inMemoryState === null || inMemoryState === void 0 ? void 0 : (_inMemoryState$appSta13 = inMemoryState.appStates) === null || _inMemoryState$appSta13 === void 0 ? void 0 : _inMemoryState$appSta13.conversationEndedBy) === ConversationEndEntity.Bot)) {
|
|
810
819
|
dispatch({
|
|
811
820
|
type: LiveChatWidgetActionType.SET_CONVERSATION_STATE,
|
|
812
821
|
payload: ConversationState.InActive
|
|
@@ -867,6 +876,37 @@ export const LiveChatWidgetStateful = props => {
|
|
|
867
876
|
}
|
|
868
877
|
}, [state.appStates.chatDisconnectEventReceived]);
|
|
869
878
|
|
|
879
|
+
// Auth state change listeners (broadcast by FacadeChatSDK.startChat())
|
|
880
|
+
useEffect(() => {
|
|
881
|
+
const authSucceededSub = BroadcastService.getMessageByEventName(BroadcastEvent.MidConversationAuthSucceeded).subscribe(msg => {
|
|
882
|
+
var _msg$payload15;
|
|
883
|
+
if (msg !== null && msg !== void 0 && (_msg$payload15 = msg.payload) !== null && _msg$payload15 !== void 0 && _msg$payload15.isAuthenticated) {
|
|
884
|
+
// Only store boolean flag, NOT the token - token is managed by FacadeChatSDK
|
|
885
|
+
dispatch({
|
|
886
|
+
type: LiveChatWidgetActionType.SET_USER_AUTHENTICATED,
|
|
887
|
+
payload: true
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
});
|
|
891
|
+
|
|
892
|
+
// Auth reset: only update the boolean flag here.
|
|
893
|
+
// We do NOT clear widget state/cache/adapter because this fires DURING startChat(),
|
|
894
|
+
// which will handle state transitions. FacadeChatSDK has already cleared SDK internals.
|
|
895
|
+
const authResetSub = BroadcastService.getMessageByEventName(BroadcastEvent.MidConversationAuthReset).subscribe(msg => {
|
|
896
|
+
var _msg$payload16;
|
|
897
|
+
if ((msg === null || msg === void 0 ? void 0 : (_msg$payload16 = msg.payload) === null || _msg$payload16 === void 0 ? void 0 : _msg$payload16.isAuthenticated) === false) {
|
|
898
|
+
dispatch({
|
|
899
|
+
type: LiveChatWidgetActionType.SET_USER_AUTHENTICATED,
|
|
900
|
+
payload: false
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
return () => {
|
|
905
|
+
authSucceededSub.unsubscribe();
|
|
906
|
+
authResetSub.unsubscribe();
|
|
907
|
+
};
|
|
908
|
+
}, [dispatch]);
|
|
909
|
+
|
|
870
910
|
// if props state gets updates we need to update the renderingMiddlewareProps in the state
|
|
871
911
|
useEffect(() => {
|
|
872
912
|
var _props$webChatContain16;
|
|
@@ -885,6 +925,25 @@ export const LiveChatWidgetStateful = props => {
|
|
|
885
925
|
}
|
|
886
926
|
});
|
|
887
927
|
}, []);
|
|
928
|
+
|
|
929
|
+
// Reliable browser close detection via visibilitychange + sendBeacon
|
|
930
|
+
// visibilitychange fires while the page is still alive (unlike beforeunload),
|
|
931
|
+
// so telemetry calls complete reliably. False positives (tab switch, minimize)
|
|
932
|
+
// are filtered in Kusto by checking if this is the last event in the session.
|
|
933
|
+
useEffect(() => {
|
|
934
|
+
const handleVisibilityChange = () => {
|
|
935
|
+
if (document.visibilityState === "hidden" && state.appStates.conversationState === ConversationState.Active) {
|
|
936
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
937
|
+
Event: TelemetryEvent.BrowserTabHidden,
|
|
938
|
+
Description: "Browser tab hidden during active conversation"
|
|
939
|
+
});
|
|
940
|
+
}
|
|
941
|
+
};
|
|
942
|
+
document.addEventListener("visibilitychange", handleVisibilityChange);
|
|
943
|
+
return () => {
|
|
944
|
+
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
945
|
+
};
|
|
946
|
+
}, [state.appStates.conversationState]);
|
|
888
947
|
const initiateEndChatOnBrowserUnload = () => {
|
|
889
948
|
var _DataStoreManager$cli;
|
|
890
949
|
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
@@ -955,6 +1014,7 @@ export const LiveChatWidgetStateful = props => {
|
|
|
955
1014
|
// React to dynamic bot avatar initials updates from context
|
|
956
1015
|
useEffect(() => {
|
|
957
1016
|
if (state.domainStates.botAvatarInitials && state.domainStates.botAvatarInitials !== webChatStyles.botAvatarInitials) {
|
|
1017
|
+
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
|
|
958
1018
|
setWebChatStyles(styles => ({
|
|
959
1019
|
...styles,
|
|
960
1020
|
botAvatarInitials: state.domainStates.botAvatarInitials
|
|
@@ -22,7 +22,7 @@ const generateSurveyInviteLink = function (surveyInviteLink, isEmbed, locale, co
|
|
|
22
22
|
return `${surveyInviteLink}&${surveyLinkParams.toString()}`;
|
|
23
23
|
};
|
|
24
24
|
export const PostChatSurveyPaneStateful = props => {
|
|
25
|
-
var _props$styleProps, _state$appStates, _props$controlProps;
|
|
25
|
+
var _props$styleProps, _state$appStates, _state$domainStates$p, _props$controlProps;
|
|
26
26
|
useEffect(() => {
|
|
27
27
|
uiTimer = createTimer();
|
|
28
28
|
TelemetryHelper.logLoadingEventToAllTelemetry(LogLevel.INFO, {
|
|
@@ -39,13 +39,15 @@ export const PostChatSurveyPaneStateful = props => {
|
|
|
39
39
|
});
|
|
40
40
|
let surveyInviteLink = "";
|
|
41
41
|
const surveyMode = (state === null || state === void 0 ? void 0 : (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.selectedSurveyMode) === PostChatSurveyMode.Embed;
|
|
42
|
-
if (state.domainStates.postChatContext.botSurveyInviteLink &&
|
|
42
|
+
if ((_state$domainStates$p = state.domainStates.postChatContext) !== null && _state$domainStates$p !== void 0 && _state$domainStates$p.botSurveyInviteLink &&
|
|
43
43
|
// Bot survey enabled
|
|
44
44
|
state.appStates.postChatParticipantType === ParticipantType.Bot) {
|
|
45
|
+
var _state$domainStates$p2, _state$domainStates$p3;
|
|
45
46
|
// Only Bot has engaged
|
|
46
|
-
surveyInviteLink = generateSurveyInviteLink(state.domainStates.postChatContext.botSurveyInviteLink, surveyMode, state.domainStates.postChatContext.botFormsProLocale, props.isCustomerVoiceSurveyCompact ?? true, props.customerVoiceSurveyCorrelationId || "");
|
|
47
|
+
surveyInviteLink = generateSurveyInviteLink((_state$domainStates$p2 = state.domainStates.postChatContext) === null || _state$domainStates$p2 === void 0 ? void 0 : _state$domainStates$p2.botSurveyInviteLink, surveyMode, (_state$domainStates$p3 = state.domainStates.postChatContext) === null || _state$domainStates$p3 === void 0 ? void 0 : _state$domainStates$p3.botFormsProLocale, props.isCustomerVoiceSurveyCompact ?? true, props.customerVoiceSurveyCorrelationId || "");
|
|
47
48
|
} else {
|
|
48
|
-
|
|
49
|
+
var _state$domainStates$p4, _state$domainStates$p5;
|
|
50
|
+
surveyInviteLink = generateSurveyInviteLink((_state$domainStates$p4 = state.domainStates.postChatContext) === null || _state$domainStates$p4 === void 0 ? void 0 : _state$domainStates$p4.surveyInviteLink, surveyMode, (_state$domainStates$p5 = state.domainStates.postChatContext) === null || _state$domainStates$p5 === void 0 ? void 0 : _state$domainStates$p5.formsProLocale, props.isCustomerVoiceSurveyCompact ?? true, props.customerVoiceSurveyCorrelationId || "");
|
|
49
51
|
}
|
|
50
52
|
if (props.copilotSurveyContext) {
|
|
51
53
|
surveyInviteLink = `${surveyInviteLink}&mcs_additionalcontext=${JSON.stringify(props.copilotSurveyContext)}`;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BroadcastEvent, LogLevel, TelemetryEvent } from "../../common/telemetry/TelemetryConstants";
|
|
2
2
|
import React, { useEffect, useState } from "react";
|
|
3
|
-
import { createTimer
|
|
3
|
+
import { createTimer } from "../../common/utils";
|
|
4
4
|
import { BroadcastService } from "@microsoft/omnichannel-chat-components";
|
|
5
5
|
import { Constants } from "../../common/Constants";
|
|
6
6
|
import { ConversationState } from "../../contexts/common/ConversationState";
|
|
@@ -114,7 +114,6 @@ export const ProactiveChatPaneStateful = props => {
|
|
|
114
114
|
bodyTitleText: state.appStates.proactiveChatStates.proactiveChatBodyTitle ? state.appStates.proactiveChatStates.proactiveChatBodyTitle : proactiveChatProps === null || proactiveChatProps === void 0 ? void 0 : (_proactiveChatProps$c = proactiveChatProps.controlProps) === null || _proactiveChatProps$c === void 0 ? void 0 : _proactiveChatProps$c.bodyTitleText
|
|
115
115
|
};
|
|
116
116
|
useEffect(() => {
|
|
117
|
-
setFocusOnElement(document.getElementById(controlProps.id + "-startbutton"));
|
|
118
117
|
TelemetryTimers.ProactiveChatScreenTimer = createTimer();
|
|
119
118
|
const timeoutEvent = setTimeout(() => {
|
|
120
119
|
handleProactiveChatInviteTimeout();
|