@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
|
@@ -43,10 +43,6 @@ import { createTimer } from "../../../../../../common/utils";
|
|
|
43
43
|
import dispatchCustomEvent from "../../../../../../common/utils/dispatchCustomEvent";
|
|
44
44
|
import SecureEventBus from "../../../../../../common/utils/SecureEventBus";
|
|
45
45
|
|
|
46
|
-
/*
|
|
47
|
-
* Interface defining the state of a scroll operation
|
|
48
|
-
* Used to track and verify scroll actions for reliability
|
|
49
|
-
*/
|
|
50
46
|
/**
|
|
51
47
|
* LazyLoadHandler - Static class managing all lazy loading functionality
|
|
52
48
|
*
|
|
@@ -83,8 +79,10 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
83
79
|
// Temporary disable flag
|
|
84
80
|
// The intersection observer instance
|
|
85
81
|
|
|
86
|
-
// Scroll
|
|
87
|
-
//
|
|
82
|
+
// Scroll anchoring state (height-delta approach)
|
|
83
|
+
// scrollHeight before content loads
|
|
84
|
+
// scrollTop before content loads
|
|
85
|
+
// Tracks if the first batch has loaded
|
|
88
86
|
// Prevents concurrent scroll operations (public for event handlers)
|
|
89
87
|
|
|
90
88
|
// Timeout and queue management
|
|
@@ -128,6 +126,7 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
128
126
|
key: "directReset",
|
|
129
127
|
value: function directReset() {
|
|
130
128
|
LazyLoadHandler.resetPending = true;
|
|
129
|
+
LazyLoadHandler.initialLoadComplete = false; // New session — next batch is an initial load
|
|
131
130
|
LazyLoadHandler.setHasMoreHistoryAvailable(true);
|
|
132
131
|
LazyLoadHandler.unmount();
|
|
133
132
|
}
|
|
@@ -431,16 +430,15 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
431
430
|
|
|
432
431
|
/**
|
|
433
432
|
* Main lazy load trigger handler
|
|
434
|
-
*
|
|
433
|
+
*
|
|
435
434
|
* This is the core method that executes when the trigger element becomes visible.
|
|
436
435
|
* It coordinates the entire lazy loading process:
|
|
437
|
-
*
|
|
436
|
+
*
|
|
438
437
|
* 1. Sets flags to prevent concurrent operations
|
|
439
|
-
* 2.
|
|
440
|
-
* 3.
|
|
441
|
-
*
|
|
442
|
-
*
|
|
443
|
-
* Timing: Uses 300ms delay to allow content loading before scroll adjustment
|
|
438
|
+
* 2. Captures scroll state BEFORE content loads (for height-delta anchoring)
|
|
439
|
+
* 3. Dispatches event to fetch more chat history
|
|
440
|
+
*
|
|
441
|
+
* Scroll anchoring is triggered by HISTORY_BATCH_LOADED event (not a blind timeout).
|
|
444
442
|
*/
|
|
445
443
|
}, {
|
|
446
444
|
key: "handleLazyLoadTrigger",
|
|
@@ -454,138 +452,60 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
454
452
|
LazyLoadHandler.pendingScrollAction = true; // Block new scroll actions
|
|
455
453
|
LazyLoadHandler.paused = true; // Pause intersection observer
|
|
456
454
|
|
|
455
|
+
// Capture scroll geometry BEFORE new content loads — used for height-delta anchoring
|
|
456
|
+
const {
|
|
457
|
+
container,
|
|
458
|
+
isScrollable
|
|
459
|
+
} = LazyLoadHandler.findScrollContainer();
|
|
460
|
+
if (container && isScrollable) {
|
|
461
|
+
LazyLoadHandler.preLoadScrollHeight = container.scrollHeight;
|
|
462
|
+
LazyLoadHandler.preLoadScrollTop = container.scrollTop;
|
|
463
|
+
}
|
|
464
|
+
LazyLoadHandler.logLifecycleEvent(TelemetryEvent.LCWLazyLoadTriggerFired, "Lazy load trigger fired — fetching history");
|
|
465
|
+
|
|
457
466
|
// Dispatch custom event to trigger chat history fetching
|
|
458
|
-
// This event is handled by other parts of the chat system
|
|
459
467
|
dispatchCustomEvent(ChatWidgetEvents.FETCH_PERSISTENT_CHAT_HISTORY);
|
|
460
|
-
|
|
461
|
-
// Wait for content to load before performing scroll adjustment
|
|
462
|
-
// 200ms provides good balance between responsiveness and content loading
|
|
463
|
-
const timeoutId = window.setTimeout(() => {
|
|
464
|
-
LazyLoadHandler.retryTimeouts.delete(timeoutId);
|
|
465
|
-
LazyLoadHandler.executeReliableScroll();
|
|
466
|
-
}, 200); // Reduced from 300ms to 200ms for faster response
|
|
467
|
-
LazyLoadHandler.retryTimeouts.add(timeoutId);
|
|
468
468
|
}
|
|
469
469
|
|
|
470
470
|
/**
|
|
471
|
-
*
|
|
472
|
-
*
|
|
473
|
-
*
|
|
474
|
-
*
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
* 4. Initiates the scroll attempt process
|
|
478
|
-
*
|
|
479
|
-
* If no suitable container is found, schedules a retry.
|
|
471
|
+
* Applies height-delta scroll anchoring after new history content is prepended.
|
|
472
|
+
*
|
|
473
|
+
* When content is added above the viewport, the browser keeps scrollTop constant
|
|
474
|
+
* but the content shifts down — making the viewport drift upward.
|
|
475
|
+
* Fix: scrollTop = savedScrollTop + (newScrollHeight - savedScrollHeight)
|
|
476
|
+
* This keeps the user looking at the same content they had before.
|
|
480
477
|
*/
|
|
481
478
|
}, {
|
|
482
|
-
key: "
|
|
483
|
-
value: function
|
|
484
|
-
// Guard: Don't execute scroll if no more history is available
|
|
485
|
-
if (!LazyLoadHandler.hasMoreHistoryAvailable) {
|
|
486
|
-
LazyLoadHandler.finishScrollAction();
|
|
487
|
-
return;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
// Find container using multiple fallback strategies
|
|
479
|
+
key: "applyScrollAnchor",
|
|
480
|
+
value: function applyScrollAnchor() {
|
|
491
481
|
const {
|
|
492
482
|
container,
|
|
493
483
|
isScrollable
|
|
494
484
|
} = LazyLoadHandler.findScrollContainer();
|
|
495
485
|
if (!container || !isScrollable) {
|
|
496
|
-
LazyLoadHandler.scheduleScrollRetry();
|
|
497
|
-
return;
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
// Calculate scroll positions
|
|
501
|
-
const initialScrollTop = container.scrollTop;
|
|
502
|
-
const targetScrollTop = initialScrollTop + 35; // 35px down to maintain position
|
|
503
|
-
|
|
504
|
-
// Set up scroll state for tracking and retries
|
|
505
|
-
LazyLoadHandler.scrollState = {
|
|
506
|
-
container,
|
|
507
|
-
initialScrollTop,
|
|
508
|
-
targetScrollTop,
|
|
509
|
-
attemptCount: 0,
|
|
510
|
-
maxAttempts: 5 // Allow up to 5 retry attempts
|
|
511
|
-
};
|
|
512
|
-
|
|
513
|
-
// Begin the scroll attempt process
|
|
514
|
-
LazyLoadHandler.attemptScroll();
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Attempts to perform scroll with verification and retry logic
|
|
519
|
-
*
|
|
520
|
-
* This method implements a sophisticated scroll system:
|
|
521
|
-
*
|
|
522
|
-
* 1. Uses requestAnimationFrame for smooth execution
|
|
523
|
-
* 2. Performs the scroll operation
|
|
524
|
-
* 3. Verifies scroll actually occurred (5px tolerance)
|
|
525
|
-
* 4. Retries with exponential backoff if failed
|
|
526
|
-
* 5. Continues operation after max attempts
|
|
527
|
-
*
|
|
528
|
-
* The two-frame approach ensures scroll is applied and then verified
|
|
529
|
-
* after the browser has had time to process the scroll change.
|
|
530
|
-
*/
|
|
531
|
-
}, {
|
|
532
|
-
key: "attemptScroll",
|
|
533
|
-
value: function attemptScroll() {
|
|
534
|
-
// Guard: Don't attempt scroll if no more history is available
|
|
535
|
-
if (!LazyLoadHandler.hasMoreHistoryAvailable) {
|
|
536
486
|
LazyLoadHandler.finishScrollAction();
|
|
537
487
|
return;
|
|
538
488
|
}
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
489
|
+
const newScrollHeight = container.scrollHeight;
|
|
490
|
+
const heightDelta = newScrollHeight - LazyLoadHandler.preLoadScrollHeight;
|
|
491
|
+
if (heightDelta > 0) {
|
|
492
|
+
container.scrollTop = LazyLoadHandler.preLoadScrollTop + heightDelta;
|
|
542
493
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
// Perform scroll using requestAnimationFrame for smooth execution
|
|
554
|
-
// Frame 1: Apply the scroll
|
|
555
|
-
requestAnimationFrame(() => {
|
|
556
|
-
// Double-check history availability before applying scroll
|
|
557
|
-
if (!LazyLoadHandler.hasMoreHistoryAvailable) {
|
|
558
|
-
LazyLoadHandler.finishScrollAction();
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
if (container) {
|
|
562
|
-
container.scrollTop = targetScrollTop;
|
|
563
|
-
}
|
|
564
|
-
|
|
565
|
-
// Frame 2: Verify scroll occurred after browser has processed the change
|
|
566
|
-
requestAnimationFrame(() => {
|
|
567
|
-
// Triple-check history availability before verification
|
|
568
|
-
if (!LazyLoadHandler.hasMoreHistoryAvailable) {
|
|
569
|
-
LazyLoadHandler.finishScrollAction();
|
|
570
|
-
return;
|
|
571
|
-
}
|
|
572
|
-
const actualScrollTop = container ? container.scrollTop : 0;
|
|
573
|
-
const scrollSucceeded = Math.abs(actualScrollTop - targetScrollTop) < 5; // 5px tolerance for success
|
|
574
|
-
|
|
575
|
-
if (scrollSucceeded) {
|
|
576
|
-
LazyLoadHandler.finishScrollAction();
|
|
577
|
-
} else if (attemptCount < maxAttempts) {
|
|
578
|
-
// Retry with exponential backoff (100ms * attempt number)
|
|
579
|
-
const timeoutId = window.setTimeout(() => {
|
|
580
|
-
LazyLoadHandler.retryTimeouts.delete(timeoutId);
|
|
581
|
-
LazyLoadHandler.attemptScroll();
|
|
582
|
-
}, 100 * attemptCount); // Exponential backoff
|
|
583
|
-
LazyLoadHandler.retryTimeouts.add(timeoutId);
|
|
584
|
-
} else {
|
|
585
|
-
LazyLoadHandler.finishScrollAction();
|
|
494
|
+
try {
|
|
495
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
496
|
+
Event: TelemetryEvent.LCWLazyLoadScrollAnchorApplied,
|
|
497
|
+
Description: "Scroll anchor applied after history batch",
|
|
498
|
+
CustomProperties: {
|
|
499
|
+
heightDelta,
|
|
500
|
+
preLoadScrollHeight: LazyLoadHandler.preLoadScrollHeight,
|
|
501
|
+
newScrollHeight,
|
|
502
|
+
newScrollTop: container.scrollTop
|
|
586
503
|
}
|
|
587
504
|
});
|
|
588
|
-
}
|
|
505
|
+
} catch {
|
|
506
|
+
// Silent fail — don't break scroll anchoring for telemetry issues
|
|
507
|
+
}
|
|
508
|
+
LazyLoadHandler.finishScrollAction();
|
|
589
509
|
}
|
|
590
510
|
|
|
591
511
|
/**
|
|
@@ -599,7 +519,6 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
599
519
|
key: "finishScrollAction",
|
|
600
520
|
value: function finishScrollAction() {
|
|
601
521
|
// Clean up scroll tracking state
|
|
602
|
-
LazyLoadHandler.scrollState = null;
|
|
603
522
|
LazyLoadHandler.pendingScrollAction = false;
|
|
604
523
|
|
|
605
524
|
// Schedule unpause and reset with delay for content stabilization
|
|
@@ -611,33 +530,9 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
611
530
|
LazyLoadHandler.retryTimeouts.add(timeoutId);
|
|
612
531
|
}
|
|
613
532
|
|
|
614
|
-
/**
|
|
615
|
-
* Schedules retry for failed scroll operations
|
|
616
|
-
*
|
|
617
|
-
* Used when scroll container is not available or scrollable.
|
|
618
|
-
* Provides a longer delay to allow container to become ready.
|
|
619
|
-
*/
|
|
620
|
-
}, {
|
|
621
|
-
key: "scheduleScrollRetry",
|
|
622
|
-
value: function scheduleScrollRetry() {
|
|
623
|
-
// Don't schedule retry if no more history is available
|
|
624
|
-
if (!LazyLoadHandler.hasMoreHistoryAvailable) {
|
|
625
|
-
LazyLoadHandler.finishScrollAction();
|
|
626
|
-
return;
|
|
627
|
-
}
|
|
628
|
-
const timeoutId = window.setTimeout(() => {
|
|
629
|
-
LazyLoadHandler.retryTimeouts.delete(timeoutId);
|
|
630
|
-
// Only retry if we're still in a pending scroll action state and have more history
|
|
631
|
-
if (LazyLoadHandler.pendingScrollAction && LazyLoadHandler.hasMoreHistoryAvailable) {
|
|
632
|
-
LazyLoadHandler.executeReliableScroll();
|
|
633
|
-
}
|
|
634
|
-
}, 1000); // 1 second delay for container readiness
|
|
635
|
-
LazyLoadHandler.retryTimeouts.add(timeoutId);
|
|
636
|
-
}
|
|
637
|
-
|
|
638
533
|
/**
|
|
639
534
|
* Schedules observer reset for next lazy load cycle
|
|
640
|
-
*
|
|
535
|
+
*
|
|
641
536
|
* After a lazy load operation completes, the observer needs to be reset
|
|
642
537
|
* to detect the next time the user scrolls to the top.
|
|
643
538
|
*/
|
|
@@ -755,7 +650,7 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
755
650
|
}, {
|
|
756
651
|
key: "moveScrollDown",
|
|
757
652
|
value: function moveScrollDown() {
|
|
758
|
-
LazyLoadHandler.
|
|
653
|
+
LazyLoadHandler.applyScrollAnchor();
|
|
759
654
|
}
|
|
760
655
|
|
|
761
656
|
/**
|
|
@@ -795,6 +690,9 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
795
690
|
}, {
|
|
796
691
|
key: "handleNoMoreHistoryAvailable",
|
|
797
692
|
value: function handleNoMoreHistoryAvailable() {
|
|
693
|
+
if (!LazyLoadHandler.initialLoadComplete) {
|
|
694
|
+
LazyLoadHandler.initialLoadComplete = true;
|
|
695
|
+
}
|
|
798
696
|
LazyLoadHandler.setHasMoreHistoryAvailable(false);
|
|
799
697
|
LazyLoadHandler.paused = true;
|
|
800
698
|
LazyLoadHandler.pendingScrollAction = false; // Reset this to prevent stuck states
|
|
@@ -812,9 +710,6 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
812
710
|
LazyLoadHandler.observer.disconnect();
|
|
813
711
|
LazyLoadHandler.observer = null;
|
|
814
712
|
}
|
|
815
|
-
|
|
816
|
-
// Clear scroll state
|
|
817
|
-
LazyLoadHandler.scrollState = null;
|
|
818
713
|
}
|
|
819
714
|
|
|
820
715
|
/**
|
|
@@ -836,6 +731,8 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
836
731
|
LazyLoadHandler.setHasMoreHistoryAvailable(true); // Reset history availability flag
|
|
837
732
|
LazyLoadHandler.initializationQueue = []; // Clear action queue
|
|
838
733
|
LazyLoadHandler.resetPending = false; // Clear pending reset flag
|
|
734
|
+
// Note: initialLoadComplete is NOT reset here — it persists across observer cycles.
|
|
735
|
+
// It's only reset on new chat sessions (directReset / PersistentConversationReset).
|
|
839
736
|
|
|
840
737
|
// Reinitialize with faster timing for better responsiveness
|
|
841
738
|
const timeoutId = window.setTimeout(() => {
|
|
@@ -875,8 +772,9 @@ let LazyLoadHandler = /*#__PURE__*/function () {
|
|
|
875
772
|
LazyLoadHandler.initialized = false;
|
|
876
773
|
LazyLoadHandler.paused = false;
|
|
877
774
|
LazyLoadHandler.pendingScrollAction = false;
|
|
878
|
-
LazyLoadHandler.scrollState = null;
|
|
879
775
|
LazyLoadHandler.isReady = false;
|
|
776
|
+
LazyLoadHandler.preLoadScrollHeight = 0;
|
|
777
|
+
LazyLoadHandler.preLoadScrollTop = 0;
|
|
880
778
|
LazyLoadHandler.initializationQueue = [];
|
|
881
779
|
// Note: Don't reset resetPending here as it needs to persist across unmount/mount cycles
|
|
882
780
|
}
|
|
@@ -925,7 +823,9 @@ _defineProperty(LazyLoadHandler, "targetId", "lazy-load-trigger-element");
|
|
|
925
823
|
_defineProperty(LazyLoadHandler, "initialized", false);
|
|
926
824
|
_defineProperty(LazyLoadHandler, "paused", false);
|
|
927
825
|
_defineProperty(LazyLoadHandler, "observer", null);
|
|
928
|
-
_defineProperty(LazyLoadHandler, "
|
|
826
|
+
_defineProperty(LazyLoadHandler, "preLoadScrollHeight", 0);
|
|
827
|
+
_defineProperty(LazyLoadHandler, "preLoadScrollTop", 0);
|
|
828
|
+
_defineProperty(LazyLoadHandler, "initialLoadComplete", false);
|
|
929
829
|
_defineProperty(LazyLoadHandler, "pendingScrollAction", false);
|
|
930
830
|
_defineProperty(LazyLoadHandler, "retryTimeouts", new Set());
|
|
931
831
|
_defineProperty(LazyLoadHandler, "resetPending", false);
|
|
@@ -933,6 +833,7 @@ _defineProperty(LazyLoadHandler, "initTimer", createTimer());
|
|
|
933
833
|
_defineProperty(LazyLoadHandler, "resetEventListener", BroadcastService.getMessageByEventName(BroadcastEvent.PersistentConversationReset).subscribe(() => {
|
|
934
834
|
LazyLoadHandler.logLifecycleEvent(TelemetryEvent.LCWLazyLoadReset, "LazyLoad reset triggered");
|
|
935
835
|
LazyLoadHandler.resetPending = true;
|
|
836
|
+
LazyLoadHandler.initialLoadComplete = false; // New session — next batch is an initial load
|
|
936
837
|
LazyLoadHandler.setHasMoreHistoryAvailable(true); // Reset this immediately so activityMiddleware doesn't block rendering
|
|
937
838
|
LazyLoadHandler.unmount(); // Clean up current state immediately
|
|
938
839
|
}));
|
|
@@ -956,19 +857,11 @@ const LazyLoadActivity = props => {
|
|
|
956
857
|
setHasMoreHistory(false);
|
|
957
858
|
};
|
|
958
859
|
|
|
959
|
-
// Event listener for HISTORY_LOAD_ERROR
|
|
860
|
+
// Event listener for HISTORY_LOAD_ERROR — dismiss banner on any error
|
|
960
861
|
const handleHistoryLoadError = () => {
|
|
961
|
-
|
|
962
|
-
LazyLoadHandler.
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
// Re-enable after a delay to allow retry on next scroll
|
|
966
|
-
// Note: This timeout is intentionally not tracked as it's scoped to the component lifecycle
|
|
967
|
-
window.setTimeout(() => {
|
|
968
|
-
LazyLoadHandler.paused = false;
|
|
969
|
-
}, 2000); // 2 second delay before allowing retry
|
|
970
|
-
|
|
971
|
-
LazyLoadHandler.logLifecycleEvent(TelemetryEvent.LCWLazyLoadHistoryError, "History load error - will retry on next scroll");
|
|
862
|
+
LazyLoadHandler.logLifecycleEvent(TelemetryEvent.LCWLazyLoadHistoryError, `History load error - dismissing banner. initialLoadComplete: ${LazyLoadHandler.initialLoadComplete}`);
|
|
863
|
+
LazyLoadHandler.handleNoMoreHistoryAvailable();
|
|
864
|
+
setHasMoreHistory(false);
|
|
972
865
|
};
|
|
973
866
|
|
|
974
867
|
// Event listener for PersistentConversationReset to sync React state
|
|
@@ -979,6 +872,97 @@ const LazyLoadActivity = props => {
|
|
|
979
872
|
setHasMoreHistory(true);
|
|
980
873
|
};
|
|
981
874
|
|
|
875
|
+
// Event listener for HISTORY_BATCH_LOADED — applies scroll anchoring after batch is processed
|
|
876
|
+
const handleBatchLoaded = () => {
|
|
877
|
+
LazyLoadHandler.logLifecycleEvent(TelemetryEvent.LCWLazyLoadBatchReceived, `Batch received — initialLoadComplete: ${LazyLoadHandler.initialLoadComplete}`);
|
|
878
|
+
if (!LazyLoadHandler.initialLoadComplete) {
|
|
879
|
+
// Initial load: use the same height-delta scroll anchoring as subsequent loads.
|
|
880
|
+
// This keeps the user at their current position while history is prepended above.
|
|
881
|
+
LazyLoadHandler.initialLoadComplete = true;
|
|
882
|
+
LazyLoadHandler.pendingScrollAction = false;
|
|
883
|
+
try {
|
|
884
|
+
const {
|
|
885
|
+
container
|
|
886
|
+
} = LazyLoadHandler.findScrollContainer();
|
|
887
|
+
if (container) {
|
|
888
|
+
const savedScrollTop = container.scrollTop;
|
|
889
|
+
const savedScrollHeight = container.scrollHeight;
|
|
890
|
+
|
|
891
|
+
// Freeze viewport while React renders new content above
|
|
892
|
+
container.style.overflow = "hidden";
|
|
893
|
+
let framesRemaining = 6;
|
|
894
|
+
const anchorScroll = () => {
|
|
895
|
+
const newScrollHeight = container.scrollHeight;
|
|
896
|
+
const heightDelta = newScrollHeight - savedScrollHeight;
|
|
897
|
+
if (heightDelta > 0) {
|
|
898
|
+
container.scrollTop = savedScrollTop + heightDelta;
|
|
899
|
+
}
|
|
900
|
+
framesRemaining--;
|
|
901
|
+
if (framesRemaining > 0) {
|
|
902
|
+
requestAnimationFrame(anchorScroll);
|
|
903
|
+
} else {
|
|
904
|
+
container.style.overflow = "";
|
|
905
|
+
LazyLoadHandler.paused = false;
|
|
906
|
+
LazyLoadHandler.scheduleReset();
|
|
907
|
+
}
|
|
908
|
+
};
|
|
909
|
+
requestAnimationFrame(anchorScroll);
|
|
910
|
+
} else {
|
|
911
|
+
LazyLoadHandler.paused = false;
|
|
912
|
+
LazyLoadHandler.scheduleReset();
|
|
913
|
+
}
|
|
914
|
+
} catch {
|
|
915
|
+
LazyLoadHandler.paused = false;
|
|
916
|
+
LazyLoadHandler.scheduleReset();
|
|
917
|
+
}
|
|
918
|
+
LazyLoadHandler.logLifecycleEvent(TelemetryEvent.LCWLazyLoadInitialLoadComplete, "Initial history load complete — scroll anchored to current position");
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
// Pagination: apply height-delta scroll anchoring repeatedly across frames.
|
|
922
|
+
//
|
|
923
|
+
// react-scroll-to-bottom uses useEffect + rAF to auto-scroll to bottom when new content
|
|
924
|
+
// arrives. This fires at unpredictable timing relative to our callbacks, so a single
|
|
925
|
+
// scrollTop assignment gets overridden intermittently.
|
|
926
|
+
//
|
|
927
|
+
// Fix: re-apply the correct scrollTop across several animation frames. After a few frames,
|
|
928
|
+
// react-scroll-to-bottom detects the user is NOT at the bottom (sticky=false) and stops
|
|
929
|
+
// auto-scrolling. We also temporarily freeze overflow to prevent visible flicker.
|
|
930
|
+
try {
|
|
931
|
+
const {
|
|
932
|
+
container
|
|
933
|
+
} = LazyLoadHandler.findScrollContainer();
|
|
934
|
+
if (container) {
|
|
935
|
+
// Re-capture scrollTop — user may have scrolled during the API fetch
|
|
936
|
+
const savedScrollTop = container.scrollTop;
|
|
937
|
+
const savedScrollHeight = LazyLoadHandler.preLoadScrollHeight;
|
|
938
|
+
|
|
939
|
+
// Freeze viewport to prevent visible flicker between competing scroll positions
|
|
940
|
+
container.style.overflow = "hidden";
|
|
941
|
+
let framesRemaining = 6; // ~100ms at 60fps — enough for react-scroll-to-bottom to settle
|
|
942
|
+
const anchorScroll = () => {
|
|
943
|
+
const newScrollHeight = container.scrollHeight;
|
|
944
|
+
const heightDelta = newScrollHeight - savedScrollHeight;
|
|
945
|
+
if (heightDelta > 0) {
|
|
946
|
+
container.scrollTop = savedScrollTop + heightDelta;
|
|
947
|
+
}
|
|
948
|
+
framesRemaining--;
|
|
949
|
+
if (framesRemaining > 0) {
|
|
950
|
+
requestAnimationFrame(anchorScroll);
|
|
951
|
+
} else {
|
|
952
|
+
// All frames applied — restore overflow and finish
|
|
953
|
+
container.style.overflow = "";
|
|
954
|
+
LazyLoadHandler.finishScrollAction();
|
|
955
|
+
}
|
|
956
|
+
};
|
|
957
|
+
requestAnimationFrame(anchorScroll);
|
|
958
|
+
} else {
|
|
959
|
+
LazyLoadHandler.finishScrollAction();
|
|
960
|
+
}
|
|
961
|
+
} catch {
|
|
962
|
+
LazyLoadHandler.finishScrollAction();
|
|
963
|
+
}
|
|
964
|
+
};
|
|
965
|
+
|
|
982
966
|
// Add secure event listener for no more history signal
|
|
983
967
|
const eventBus = SecureEventBus.getInstance();
|
|
984
968
|
const unsubscribeNoMoreHistory = eventBus.subscribe(ChatWidgetEvents.NO_MORE_HISTORY_AVAILABLE, handleNoMoreHistory);
|
|
@@ -986,6 +970,9 @@ const LazyLoadActivity = props => {
|
|
|
986
970
|
// Add event listener for history load errors
|
|
987
971
|
const unsubscribeHistoryError = eventBus.subscribe(ChatWidgetEvents.HISTORY_LOAD_ERROR, handleHistoryLoadError);
|
|
988
972
|
|
|
973
|
+
// Add event listener for history batch loaded
|
|
974
|
+
const unsubscribeBatchLoaded = eventBus.subscribe(ChatWidgetEvents.HISTORY_BATCH_LOADED, handleBatchLoaded);
|
|
975
|
+
|
|
989
976
|
// Add event listener for persistent conversation reset
|
|
990
977
|
const resetSubscription = BroadcastService.getMessageByEventName(BroadcastEvent.PersistentConversationReset).subscribe(handlePersistentConversationReset);
|
|
991
978
|
|
|
@@ -1003,6 +990,7 @@ const LazyLoadActivity = props => {
|
|
|
1003
990
|
return () => {
|
|
1004
991
|
unsubscribeNoMoreHistory();
|
|
1005
992
|
unsubscribeHistoryError();
|
|
993
|
+
unsubscribeBatchLoaded();
|
|
1006
994
|
resetSubscription.unsubscribe();
|
|
1007
995
|
};
|
|
1008
996
|
}
|
|
@@ -1056,6 +1044,7 @@ const LazyLoadActivity = props => {
|
|
|
1056
1044
|
// Remove event listeners
|
|
1057
1045
|
unsubscribeNoMoreHistory();
|
|
1058
1046
|
unsubscribeHistoryError();
|
|
1047
|
+
unsubscribeBatchLoaded();
|
|
1059
1048
|
resetSubscription.unsubscribe();
|
|
1060
1049
|
if (container) {
|
|
1061
1050
|
container.removeEventListener("scroll", handleScroll);
|
|
@@ -124,7 +124,7 @@ export const createActivityMiddleware = (renderMarkdown, systemMessageStyleProps
|
|
|
124
124
|
if (isTagIncluded(card, Constants.conversationDividerTag)) {
|
|
125
125
|
const conversationDividerLabel = (localizedTexts === null || localizedTexts === void 0 ? void 0 : localizedTexts.CONVERSATION_DIVIDER_ARIA_LABEL) || defaultMiddlewareLocalizedTexts.CONVERSATION_DIVIDER_ARIA_LABEL;
|
|
126
126
|
// Pass the computed localized text to the divider component
|
|
127
|
-
return /*#__PURE__*/React.createElement(ConversationDividerActivity, {
|
|
127
|
+
return () => /*#__PURE__*/React.createElement(ConversationDividerActivity, {
|
|
128
128
|
dividerActivityAriaLabel: conversationDividerLabel
|
|
129
129
|
});
|
|
130
130
|
}
|
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
import { Constants } from "../../../../../common/Constants";
|
|
8
8
|
import { DeliveryMode } from "@microsoft/omnichannel-chat-sdk";
|
|
9
9
|
import { WebChatActionType } from "../../enums/WebChatActionType";
|
|
10
|
+
|
|
10
11
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unused-vars
|
|
11
12
|
const channelDataMiddleware = addConversationalSurveyTagsCallback => _ref => {
|
|
12
13
|
let {
|
|
@@ -50,4 +50,5 @@ export let LiveChatWidgetActionType;
|
|
|
50
50
|
LiveChatWidgetActionType[LiveChatWidgetActionType["SET_CONVERSATIONAL_SURVEY_DISPLAY"] = 47] = "SET_CONVERSATIONAL_SURVEY_DISPLAY";
|
|
51
51
|
LiveChatWidgetActionType[LiveChatWidgetActionType["GET_IN_MEMORY_STATE"] = 48] = "GET_IN_MEMORY_STATE";
|
|
52
52
|
LiveChatWidgetActionType[LiveChatWidgetActionType["SET_BOT_AVATAR_INITIALS"] = 49] = "SET_BOT_AVATAR_INITIALS";
|
|
53
|
+
LiveChatWidgetActionType[LiveChatWidgetActionType["SET_USER_AUTHENTICATED"] = 50] = "SET_USER_AUTHENTICATED";
|
|
53
54
|
})(LiveChatWidgetActionType || (LiveChatWidgetActionType = {}));
|
|
@@ -38,6 +38,10 @@ export const getLiveChatWidgetContextInitialState = props => {
|
|
|
38
38
|
if (!initialStateFromCache.domainStates.botAvatarInitials) {
|
|
39
39
|
initialStateFromCache.domainStates.botAvatarInitials = defaultWebChatStyles.botAvatarInitials;
|
|
40
40
|
}
|
|
41
|
+
// Default isUserAuthenticated to false if not present in cache
|
|
42
|
+
if (initialStateFromCache.appStates.isUserAuthenticated === undefined) {
|
|
43
|
+
initialStateFromCache.appStates.isUserAuthenticated = false;
|
|
44
|
+
}
|
|
41
45
|
return initialStateFromCache;
|
|
42
46
|
}
|
|
43
47
|
const LiveChatWidgetContextInitialState = {
|
|
@@ -87,7 +91,8 @@ export const getLiveChatWidgetContextInitialState = props => {
|
|
|
87
91
|
selectedSurveyMode: null,
|
|
88
92
|
postChatParticipantType: undefined,
|
|
89
93
|
isConversationalSurvey: false,
|
|
90
|
-
isConversationalSurveyEnabled: false
|
|
94
|
+
isConversationalSurveyEnabled: false,
|
|
95
|
+
isUserAuthenticated: false
|
|
91
96
|
},
|
|
92
97
|
uiStates: {
|
|
93
98
|
showConfirmationPane: false,
|
|
@@ -708,6 +708,21 @@ const reducer = (state, action) => {
|
|
|
708
708
|
isConversationalSurvey: action.payload
|
|
709
709
|
}
|
|
710
710
|
};
|
|
711
|
+
case LiveChatWidgetActionType.SET_USER_AUTHENTICATED:
|
|
712
|
+
inMemory = {
|
|
713
|
+
...inMemory,
|
|
714
|
+
appStates: {
|
|
715
|
+
...inMemory.appStates,
|
|
716
|
+
isUserAuthenticated: action.payload
|
|
717
|
+
}
|
|
718
|
+
};
|
|
719
|
+
return {
|
|
720
|
+
...state,
|
|
721
|
+
appStates: {
|
|
722
|
+
...state.appStates,
|
|
723
|
+
isUserAuthenticated: action.payload
|
|
724
|
+
}
|
|
725
|
+
};
|
|
711
726
|
case LiveChatWidgetActionType.GET_IN_MEMORY_STATE:
|
|
712
727
|
return inMemory;
|
|
713
728
|
default:
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ConversationState } from "../contexts/common/ConversationState";
|
|
2
|
+
import { shouldLoadPersistentChatHistory } from "../components/livechatwidget/common/liveChatConfigUtils";
|
|
2
3
|
export const shouldShowChatButton = state => {
|
|
3
4
|
var _state$appStates;
|
|
4
5
|
return (state.appStates.isMinimized || state.appStates.conversationState === ConversationState.Closed) && (state === null || state === void 0 ? void 0 : (_state$appStates = state.appStates) === null || _state$appStates === void 0 ? void 0 : _state$appStates.hideStartChatButton) === false; // Do not show chat button in case of popout
|
|
@@ -17,7 +18,18 @@ export const shouldShowEmailTranscriptPane = state => {
|
|
|
17
18
|
return state.uiStates.showEmailTranscriptPane;
|
|
18
19
|
};
|
|
19
20
|
export const shouldShowWebChatContainer = state => {
|
|
20
|
-
|
|
21
|
+
var _state$domainStates;
|
|
22
|
+
const extendedChatConfig = state === null || state === void 0 ? void 0 : (_state$domainStates = state.domainStates) === null || _state$domainStates === void 0 ? void 0 : _state$domainStates.liveChatConfig;
|
|
23
|
+
const persistentHistoryEnabled = shouldLoadPersistentChatHistory(extendedChatConfig);
|
|
24
|
+
const isActiveOrInactive = state.appStates.conversationState === ConversationState.Active || state.appStates.conversationState === ConversationState.InActive;
|
|
25
|
+
const isPostchatSurvey = state.appStates.conversationState === ConversationState.Postchat && state.appStates.isConversationalSurveyEnabled && state.appStates.isConversationalSurvey;
|
|
26
|
+
if (persistentHistoryEnabled) {
|
|
27
|
+
// Keep WebChat in DOM even when minimized (CSS hides it via visibility)
|
|
28
|
+
// This preserves scroll position across minimize/maximize cycles
|
|
29
|
+
return isActiveOrInactive || isPostchatSurvey;
|
|
30
|
+
}
|
|
31
|
+
// Original behavior - hide WebChat when minimized
|
|
32
|
+
return !state.appStates.isMinimized && (isActiveOrInactive || isPostchatSurvey);
|
|
21
33
|
};
|
|
22
34
|
export const shouldShowLoadingPane = state => {
|
|
23
35
|
return !state.appStates.isMinimized && state.appStates.conversationState === ConversationState.Loading;
|
|
@@ -14,6 +14,8 @@ export const createOnNewAdapterActivityHandler = (chatId, userId, startTime) =>
|
|
|
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
15
|
|
|
16
16
|
let isHistoryMessageReceivedEventRaised = false;
|
|
17
|
+
let isInQueue = false;
|
|
18
|
+
let agentJoinLogged = false;
|
|
17
19
|
const onNewAdapterActivityHandler = activity => {
|
|
18
20
|
raiseMessageEvent(activity);
|
|
19
21
|
};
|
|
@@ -35,9 +37,14 @@ export const createOnNewAdapterActivityHandler = (chatId, userId, startTime) =>
|
|
|
35
37
|
});
|
|
36
38
|
};
|
|
37
39
|
const systemMessageStrategy = activity => {
|
|
38
|
-
var _TelemetryManager$Int3;
|
|
40
|
+
var _activity$channelData, _activity$channelData2, _TelemetryManager$Int3;
|
|
39
41
|
const payload = buildMessagePayload(activity, userId);
|
|
40
42
|
payload.messageType = Constants.systemMessageTag;
|
|
43
|
+
|
|
44
|
+
// Track queue entry for agent-join detection
|
|
45
|
+
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.queuePositionMessageTag)) {
|
|
46
|
+
isInQueue = true;
|
|
47
|
+
}
|
|
41
48
|
if (isHistoryMessage(activity, startTime)) {
|
|
42
49
|
var _TelemetryManager$Int2;
|
|
43
50
|
historyMessageStrategy(polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int2 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int2 === void 0 ? void 0 : _TelemetryManager$Int2.conversationId));
|
|
@@ -70,11 +77,11 @@ export const createOnNewAdapterActivityHandler = (chatId, userId, startTime) =>
|
|
|
70
77
|
}
|
|
71
78
|
};
|
|
72
79
|
const isValidMessage = activity => {
|
|
73
|
-
var _activity$
|
|
80
|
+
var _activity$channelData3, _activity$channelData4, _activity$channelData5;
|
|
74
81
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
75
82
|
const messageHasNoText = !(activity !== null && activity !== void 0 && activity.text);
|
|
76
83
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
77
|
-
const messageHasNoTags = !(activity !== null && activity !== void 0 && activity.channelData) || !(activity !== null && activity !== void 0 && (_activity$
|
|
84
|
+
const messageHasNoTags = !(activity !== null && activity !== void 0 && activity.channelData) || !(activity !== null && activity !== void 0 && (_activity$channelData3 = activity.channelData) !== null && _activity$channelData3 !== void 0 && _activity$channelData3.tags) || (activity === null || activity === void 0 ? void 0 : (_activity$channelData4 = activity.channelData) === null || _activity$channelData4 === void 0 ? void 0 : (_activity$channelData5 = _activity$channelData4.tags) === null || _activity$channelData5 === void 0 ? void 0 : _activity$channelData5.length) === 0;
|
|
78
85
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
79
86
|
const messageHasNoAttachments = !(activity !== null && activity !== void 0 && activity.attachments) || (activity === null || activity === void 0 ? void 0 : activity.attachments.length) === 0;
|
|
80
87
|
if (messageHasNoTags && messageHasNoText && messageHasNoAttachments) {
|
|
@@ -96,6 +103,16 @@ export const createOnNewAdapterActivityHandler = (chatId, userId, startTime) =>
|
|
|
96
103
|
historyMessageStrategy(polyfillMessagePayloadForEvent(activity, payload, (_TelemetryManager$Int4 = TelemetryManager.InternalTelemetryData) === null || _TelemetryManager$Int4 === void 0 ? void 0 : _TelemetryManager$Int4.conversationId));
|
|
97
104
|
return;
|
|
98
105
|
}
|
|
106
|
+
|
|
107
|
+
// Log agent joining when first non-history message is received after queue
|
|
108
|
+
if (isInQueue && !agentJoinLogged) {
|
|
109
|
+
agentJoinLogged = true;
|
|
110
|
+
isInQueue = false;
|
|
111
|
+
TelemetryHelper.logActionEvent(LogLevel.INFO, {
|
|
112
|
+
Event: TelemetryEvent.AgentJoinedConversation,
|
|
113
|
+
Description: "First message received from agent after queue"
|
|
114
|
+
});
|
|
115
|
+
}
|
|
99
116
|
firstResponseLatencyTracker.stopClock(payload);
|
|
100
117
|
const newMessageReceivedEvent = {
|
|
101
118
|
eventName: BroadcastEvent.NewMessageReceived,
|
|
@@ -58,6 +58,8 @@ export declare class Constants {
|
|
|
58
58
|
static readonly videoMediaRegex: RegExp;
|
|
59
59
|
static readonly chromeSupportedInlineMediaRegex: RegExp;
|
|
60
60
|
static readonly firefoxSupportedInlineMediaRegex: RegExp;
|
|
61
|
+
static readonly AdaptiveCardType = "adaptivecard";
|
|
62
|
+
static readonly SuggestedActionsType = "suggestedactions";
|
|
61
63
|
static readonly CallAdded = "callAdded";
|
|
62
64
|
static readonly LocalVideoStreamAdded = "localVideoStreamAdded";
|
|
63
65
|
static readonly LocalVideoStreamRemoved = "localVideoStreamRemoved";
|