@qualified-salesforce/web 0.0.1-oidc-bootstrap → 0.1.1
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/CAPABILITY-REFERENCE.md +41 -0
- package/CHANGELOG.md +84 -0
- package/README.md +65 -0
- package/constants.generated.js +30 -2
- package/css/widget/multimodal_v2/index.split-css.panda.css +265 -47
- package/package.json +18 -4
- package/packs/widget/api/docking/viewport_lock.js +93 -2
- package/packs/widget/esm/index.d.ts +134 -0
- package/packs/widget/esm/index.js +18 -2
- package/packs/widget/esm/qualified.css +265 -47
- package/src/graphql-types.js +74 -1
- package/src/url.js +4 -1
- package/vendor/actioncable/connection.js +40 -3
- package/vendor/actioncable/connection_monitor.js +8 -0
- package/vendor/actioncable/consumer.js +7 -1
- package/vendor/actioncable/index.js +5 -2
- package/vendor/actioncable/sse_socket.js +262 -0
- package/widget/analytics.js +8 -0
- package/widget/api_handler/base_api_handler.js +24 -0
- package/widget/booker_outcome_tracker.js +58 -20
- package/widget/capabilities.js +190 -0
- package/widget/channel.js +38 -6
- package/widget/constants.generated.js +2 -1
- package/widget/multimodal_v2/components/AppLayout.js +1 -1
- package/widget/multimodal_v2/components/app/Foreground.js +10 -9
- package/widget/multimodal_v2/components/app/Input.js +8 -3
- package/widget/multimodal_v2/components/app/LightboxExperience.js +17 -3
- package/widget/multimodal_v2/components/app/Main.js +87 -31
- package/widget/multimodal_v2/components/app/MessengerButton.js +18 -1
- package/widget/multimodal_v2/components/chat/ChatInputForm.js +8 -6
- package/widget/multimodal_v2/components/chat/timeline/CalendarEventPickRenderer.js +2 -2
- package/widget/multimodal_v2/components/chat/timeline/PresentDeckRenderer.js +346 -170
- package/widget/multimodal_v2/components/chat/timeline/SystemRenderer.js +4 -7
- package/widget/multimodal_v2/components/decks/index.js +506 -52
- package/widget/multimodal_v2/components/helpers/content_click_payloads.js +67 -1
- package/widget/multimodal_v2/components/lightbox_gather/index.js +4 -4
- package/widget/multimodal_v2/components/meetings/MeetingBookerEntry.js +8 -1
- package/widget/multimodal_v2/components/meetings/MeetingOfferEmailStep.js +1 -1
- package/widget/multimodal_v2/components/meetings/MeetingSummaryRail.js +1 -1
- package/widget/multimodal_v2/components/meetings/MeetingTimeSelector.js +1 -1
- package/widget/multimodal_v2/components/multimodal/Controls.js +11 -3
- package/widget/multimodal_v2/components/multimodal/useMultimodal.js +19 -7
- package/widget/multimodal_v2/components/presentations/index.js +61 -0
- package/widget/multimodal_v2/constants.js +1 -1
- package/widget/multimodal_v2/images/icons.js +17 -1
- package/widget/multimodal_v2/index.panda.js +2 -2
- package/widget/multimodal_v2/locales/cs.js +8 -1
- package/widget/multimodal_v2/locales/da.js +8 -1
- package/widget/multimodal_v2/locales/de.js +8 -1
- package/widget/multimodal_v2/locales/en.js +8 -1
- package/widget/multimodal_v2/locales/en_AU.js +8 -1
- package/widget/multimodal_v2/locales/en_GB.js +8 -1
- package/widget/multimodal_v2/locales/es.js +8 -1
- package/widget/multimodal_v2/locales/es_LA.js +8 -1
- package/widget/multimodal_v2/locales/fi.js +8 -1
- package/widget/multimodal_v2/locales/fr.js +8 -1
- package/widget/multimodal_v2/locales/fr_CA.js +8 -1
- package/widget/multimodal_v2/locales/id.js +8 -1
- package/widget/multimodal_v2/locales/it.js +8 -1
- package/widget/multimodal_v2/locales/ja.js +8 -1
- package/widget/multimodal_v2/locales/ko.js +8 -1
- package/widget/multimodal_v2/locales/nb.js +8 -1
- package/widget/multimodal_v2/locales/nl.js +8 -1
- package/widget/multimodal_v2/locales/pl.js +8 -1
- package/widget/multimodal_v2/locales/pt_BR.js +8 -1
- package/widget/multimodal_v2/locales/ru.js +8 -1
- package/widget/multimodal_v2/locales/sv.js +8 -1
- package/widget/multimodal_v2/locales/th.js +8 -1
- package/widget/multimodal_v2/locales/tr.js +8 -1
- package/widget/multimodal_v2/locales/vi.js +8 -1
- package/widget/multimodal_v2/locales/zh_CN.js +8 -1
- package/widget/multimodal_v2/locales/zh_TW.js +8 -1
- package/widget/multimodal_v2/multimodal.js +5 -1
- package/widget/multimodal_v2/multimodal_channel.js +13 -8
- package/widget/multimodal_v2/signals/messages_signal.js +4 -0
- package/widget/multimodal_v2/stores/ai_conversation_store.js +6 -2
- package/widget/multimodal_v2/stores/artifact_store.js +352 -27
- package/widget/multimodal_v2/stores/call_store.js +40 -1
- package/widget/multimodal_v2/stores/call_ui_adapter.js +1 -1
- package/widget/multimodal_v2/stores/decks_store.js +405 -39
- package/widget/multimodal_v2/stores/meeting_store.js +15 -10
- package/widget/multimodal_v2/stores/presentation_ga_adapter.js +64 -0
- package/widget/multimodal_v2/stores/presentation_telemetry_store.js +556 -0
- package/widget/multimodal_v2/stores/presentations_store.js +1 -0
- package/widget/multimodal_v2/stores/root_store.js +157 -268
- package/widget/multimodal_v2/stores/screen_share_store.js +41 -21
- package/widget/multimodal_v2/stores/translation_store.js +9 -0
- package/widget/multimodal_v2/stores/ui_store.js +7 -7
- package/widget/multimodal_v2/stores/website_navigation_store.js +3 -1
- package/widget/multimodal_v2/text_turn_response_tracker.js +419 -0
- package/widget/multimodal_v2/types.js +21 -1
- package/widget/multimodal_v2/utils/locale.js +2 -1
- package/widget/multimodal_v2/utils/signals.js +35 -4
- package/widget/pardot_visitor.js +7 -1
- package/widget/server-logger.js +97 -2
- package/widget/tracker.js +69 -21
- package/widget/widget/page_mirror_factory.js +9 -1
- package/widget/widget/widget.js +29 -4
|
@@ -28,6 +28,72 @@
|
|
|
28
28
|
}
|
|
29
29
|
};
|
|
30
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* Canonical presentation-type labels, mirroring the server-side mapping in
|
|
33
|
+
* multimodal_sql_fragments.rb. Codegen only exports that mapping to the admin
|
|
34
|
+
* bundle, so the widget keeps this typed equivalent.
|
|
35
|
+
*/ const PRESENTATION_TYPE_LABELS = {
|
|
36
|
+
present_deck: "Slide Deck",
|
|
37
|
+
present_video: "Product Demo",
|
|
38
|
+
present_content: "Image"
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Payload for custEv_chatPresentationStart. Fires once when a presentation is
|
|
42
|
+
* initiated and becomes visible to the visitor.
|
|
43
|
+
*/ function buildCustEvChatPresentationStartPayload(param) {
|
|
44
|
+
let { conversationId, formJoinIDUnique = "", title, type, totalSlides, triggeredBy } = param;
|
|
45
|
+
return {
|
|
46
|
+
event: "custEv_chatPresentationStart",
|
|
47
|
+
chatExperience: "qualified",
|
|
48
|
+
nameCaptureCampaignId: "",
|
|
49
|
+
formJoinIDUnique,
|
|
50
|
+
conversationId,
|
|
51
|
+
presentation: {
|
|
52
|
+
title,
|
|
53
|
+
type,
|
|
54
|
+
totalSlides,
|
|
55
|
+
triggeredBy
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Payload for custEv_chatPresentationSlide. Fires once each time a slide becomes
|
|
61
|
+
* visible — whether Piper advances the deck or the visitor navigates manually.
|
|
62
|
+
*/ function buildCustEvChatPresentationSlidePayload(param) {
|
|
63
|
+
let { conversationId, formJoinIDUnique = "", title, type, slideTitle, slidePosition } = param;
|
|
64
|
+
return {
|
|
65
|
+
event: "custEv_chatPresentationSlide",
|
|
66
|
+
chatExperience: "qualified",
|
|
67
|
+
nameCaptureCampaignId: "",
|
|
68
|
+
formJoinIDUnique,
|
|
69
|
+
conversationId,
|
|
70
|
+
presentation: {
|
|
71
|
+
title,
|
|
72
|
+
type,
|
|
73
|
+
slideTitle,
|
|
74
|
+
slidePosition
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Payload for custEv_chatPresentationEnd. Fires once when a live presentation
|
|
80
|
+
* reaches any terminal lifecycle boundary.
|
|
81
|
+
*/ function buildCustEvChatPresentationEndPayload(param) {
|
|
82
|
+
let { conversationId, formJoinIDUnique = "", title, type, slidesShown, secondsWatched } = param;
|
|
83
|
+
return {
|
|
84
|
+
event: "custEv_chatPresentationEnd",
|
|
85
|
+
chatExperience: "qualified",
|
|
86
|
+
nameCaptureCampaignId: "",
|
|
87
|
+
formJoinIDUnique,
|
|
88
|
+
conversationId,
|
|
89
|
+
presentation: {
|
|
90
|
+
title,
|
|
91
|
+
type,
|
|
92
|
+
slidesShown,
|
|
93
|
+
secondsWatched
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
31
97
|
/** Payload for custEv_contentClick when a link in the widget is clicked (e.g. in a message body). */ function buildCustEvContentClickPayloadForLink(url, moduleName, clickedLinkText, conversationId) {
|
|
32
98
|
if (conversationId === void 0) conversationId = "";
|
|
33
99
|
return {
|
|
@@ -55,4 +121,4 @@
|
|
|
55
121
|
};
|
|
56
122
|
}
|
|
57
123
|
|
|
58
|
-
export { buildCustEvChatViewPayload, buildCustEvContentClickPayloadForLink, buildCustEvContentImpressionPayload };
|
|
124
|
+
export { PRESENTATION_TYPE_LABELS, buildCustEvChatPresentationEndPayload, buildCustEvChatPresentationSlidePayload, buildCustEvChatPresentationStartPayload, buildCustEvChatViewPayload, buildCustEvContentClickPayloadForLink, buildCustEvContentImpressionPayload };
|
|
@@ -43,7 +43,7 @@ function _extends() {
|
|
|
43
43
|
const LightboxGather = (param)=>{
|
|
44
44
|
let { rootStore } = param;
|
|
45
45
|
var _message_inputFields;
|
|
46
|
-
const {
|
|
46
|
+
const { effectiveIntlLocale, t } = rootStore.translationStore;
|
|
47
47
|
const fieldValues = signals_module_useSignal({});
|
|
48
48
|
const fieldErrors = signals_module_useSignal({});
|
|
49
49
|
const handleFieldChange = hooks_module_q((index, value)=>{
|
|
@@ -173,7 +173,7 @@ const LightboxGather = (param)=>{
|
|
|
173
173
|
"data-component-name": "LightboxGather.CalendarColumn",
|
|
174
174
|
children: /*#__PURE__*/ jsxRuntime_module_u(InertCalendarPlaceholder, {
|
|
175
175
|
t: t,
|
|
176
|
-
|
|
176
|
+
locale: effectiveIntlLocale.value
|
|
177
177
|
})
|
|
178
178
|
})
|
|
179
179
|
]
|
|
@@ -347,7 +347,7 @@ const previewHasPrev = signals_core_module_d(false);
|
|
|
347
347
|
const previewHasNext = signals_core_module_d(false);
|
|
348
348
|
const FAKE_SLOTS = generateFakeTimeSlots();
|
|
349
349
|
const InertCalendarPlaceholder = (param)=>{
|
|
350
|
-
let { t,
|
|
350
|
+
let { t, locale } = param;
|
|
351
351
|
const dayOfWeek = today.getDay();
|
|
352
352
|
const startOfWeek = new Date(today);
|
|
353
353
|
startOfWeek.setDate(today.getDate() - dayOfWeek);
|
|
@@ -378,7 +378,7 @@ const InertCalendarPlaceholder = (param)=>{
|
|
|
378
378
|
availableDateStrings: previewAvailableDates,
|
|
379
379
|
selectedDateString: previewSelectedDate,
|
|
380
380
|
onSelectDate: ()=>{},
|
|
381
|
-
locale:
|
|
381
|
+
locale: locale,
|
|
382
382
|
openDatePickerLabel: t("meetings.openDatePicker")
|
|
383
383
|
}),
|
|
384
384
|
/*#__PURE__*/ jsxRuntime_module_u(DayStripRow, {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsxRuntime_module_u } from "../../../../js/multimodal_v2.js";
|
|
2
|
+
import { getSentryClient } from "../../../widget/sentry.js";
|
|
2
3
|
import { CalendarResumeIcon } from "../../images/icons.js";
|
|
3
4
|
import "../../styled-system/jsx/index.js";
|
|
4
5
|
import { styled } from "../../styled-system/jsx/factory.js";
|
|
@@ -6,6 +7,7 @@ import { styled } from "../../styled-system/jsx/factory.js";
|
|
|
6
7
|
|
|
7
8
|
/** @jsxImportSource preact */
|
|
8
9
|
|
|
10
|
+
|
|
9
11
|
/**
|
|
10
12
|
* The meeting booker's presence in the chat timeline: a placeholder card that
|
|
11
13
|
* opens the booker in the artifact overlay, which is the only surface the booker
|
|
@@ -20,7 +22,12 @@ import { styled } from "../../styled-system/jsx/factory.js";
|
|
|
20
22
|
let { rootStore, message } = param;
|
|
21
23
|
const { t } = rootStore.translationStore;
|
|
22
24
|
const handleClick = ()=>{
|
|
23
|
-
|
|
25
|
+
rootStore.toggleMeetingBookerArtifact(message).catch((error)=>{
|
|
26
|
+
var _getSentryClient;
|
|
27
|
+
(_getSentryClient = getSentryClient({
|
|
28
|
+
project: "multimodal"
|
|
29
|
+
})) == null ? void 0 : _getSentryClient.captureException(error);
|
|
30
|
+
});
|
|
24
31
|
};
|
|
25
32
|
return /*#__PURE__*/ jsxRuntime_module_u(CardButton, {
|
|
26
33
|
"data-component-name": "MeetingBookerEntry.CardButton",
|
|
@@ -128,7 +128,7 @@ function useEmailStep(param) {
|
|
|
128
128
|
// Read infrequent values at the top (these rarely change)
|
|
129
129
|
const selectedTimeSlot = meetingStore.selectedTimeSlot.value;
|
|
130
130
|
const timeZone = meetingStore.timeZone.value;
|
|
131
|
-
const locale = meetingStore.rootStore.translationStore.
|
|
131
|
+
const locale = meetingStore.rootStore.translationStore.effectiveIntlLocale.value;
|
|
132
132
|
// Handlers - simple wrappers around store actions
|
|
133
133
|
const handleEmailChange = (e)=>{
|
|
134
134
|
const target = e.currentTarget;
|
|
@@ -73,7 +73,7 @@ import { styled } from "../../styled-system/jsx/factory.js";
|
|
|
73
73
|
const timeZone = meetingStore.timeZone.value;
|
|
74
74
|
const timeZoneLabel = (_ref2 = (_AVAILABLE_TIME_ZONES_find = AVAILABLE_TIME_ZONES.find((tz)=>tz.value === timeZone)) == null ? void 0 : _AVAILABLE_TIME_ZONES_find.label) != null ? _ref2 : timeZone;
|
|
75
75
|
const slot = meetingStore.selectedTimeSlot.value;
|
|
76
|
-
const locale = meetingStore.rootStore.translationStore.
|
|
76
|
+
const locale = meetingStore.rootStore.translationStore.effectiveIntlLocale.value;
|
|
77
77
|
const meta = /*#__PURE__*/ jsxRuntime_module_u(Meta, {
|
|
78
78
|
"data-component-name": "MeetingSummaryRail.Meta",
|
|
79
79
|
children: [
|
|
@@ -269,7 +269,7 @@ function useMeetingTimeSelector(param) {
|
|
|
269
269
|
displayedTimeSlotItems: meetingStore.displayedTimeSlotItems,
|
|
270
270
|
slotPageSize: meetingStore.slotPageSize,
|
|
271
271
|
layout,
|
|
272
|
-
locale: meetingStore.rootStore.translationStore.
|
|
272
|
+
locale: meetingStore.rootStore.translationStore.effectiveIntlLocale
|
|
273
273
|
},
|
|
274
274
|
handlers: {
|
|
275
275
|
handleSelectTimeSlot,
|
|
@@ -20,9 +20,17 @@ import { styled } from "../../styled-system/jsx/factory.js";
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
const Controls = (param)=>{
|
|
23
|
-
let { connectingStatus, conversationMode, mic, maximize, minimizeToCorner, endCall } = param;
|
|
24
|
-
|
|
23
|
+
let { connectingStatus, conversationMode, mic, maximize, minimizeToCorner, endCall, avatarProvider } = param;
|
|
24
|
+
var _ref;
|
|
25
|
+
return(// "Video Mode"/"Voice Mode" buttons regardless of the active mode (only
|
|
26
|
+
// aria-pressed/styling differ), so E2E can't tell modes apart by button
|
|
27
|
+
// visibility/text — it needs this explicit signal instead. On the
|
|
28
|
+
// Container (not gated behind conversationMode.visible) so it reads
|
|
29
|
+
// correctly even for a team where the toggle itself is hidden.
|
|
30
|
+
/*#__PURE__*/ jsxRuntime_module_u(Container, {
|
|
25
31
|
"data-component-name": "Controls.Container",
|
|
32
|
+
"data-avatar-provider": (_ref = avatarProvider == null ? void 0 : avatarProvider.value) != null ? _ref : undefined,
|
|
33
|
+
"data-conversation-mode": conversationMode.currentMode.value,
|
|
26
34
|
children: [
|
|
27
35
|
/*#__PURE__*/ jsxRuntime_module_u(utils_module_u, {
|
|
28
36
|
when: conversationMode.visible,
|
|
@@ -134,7 +142,7 @@ const Controls = (param)=>{
|
|
|
134
142
|
})
|
|
135
143
|
})
|
|
136
144
|
]
|
|
137
|
-
});
|
|
145
|
+
}));
|
|
138
146
|
};
|
|
139
147
|
const VIDEO_MODE_OPTIONS = [
|
|
140
148
|
{
|
|
@@ -72,11 +72,14 @@ function useVariant(rootStore, adapter) {
|
|
|
72
72
|
const maximizedState = rootStore.maximizedState.value;
|
|
73
73
|
const isMaximized = maximizedState === types_MaximizedState.MULTIMODAL && isOpened;
|
|
74
74
|
if (isMaximized) return "maximized";
|
|
75
|
-
const isMobileArtifact = isMobile.value && maximizedState === types_MaximizedState.ARTIFACT;
|
|
76
|
-
if (isMobileArtifact) return isOpened ? "pill" : "compact";
|
|
77
75
|
if (rootStore.displayMode.minimized.value && rootStore.conversationMode.video.value) return "compact";
|
|
78
76
|
const adapterState = adapter.value.state;
|
|
79
|
-
|
|
77
|
+
// A mobile video call takes over the screen -- unless the artifact is already
|
|
78
|
+
// doing that. Then the call floats in the bottom-right corner over it, exactly
|
|
79
|
+
// as it does in the closed state, and it gets there by resolving what the
|
|
80
|
+
// closed state resolves: the fall-through below, which is the compact tile for
|
|
81
|
+
// video and the pill for voice.
|
|
82
|
+
const isVideoInCall = isMobile.value && rootStore.conversationMode.video.value && maximizedState !== types_MaximizedState.ARTIFACT && (adapterState.isInCall.value || adapterState.isVideoLoading.value);
|
|
80
83
|
if (isVideoInCall) return "maximized";
|
|
81
84
|
if ((_rootStore_postCallSurveyStore_value = rootStore.postCallSurveyStore.value) == null ? void 0 : _rootStore_postCallSurveyStore_value.isActive.value) return "compact";
|
|
82
85
|
if (!isMaximized && (isVoiceMode || userHasIgnoredMultimodal && isOpened)) return "pill";
|
|
@@ -278,7 +281,13 @@ function useControlsConfig(rootStore, adapter, variant, visibility) {
|
|
|
278
281
|
return rootStore.conversationMode.video.value ? "compactInside" : "compactOutside";
|
|
279
282
|
});
|
|
280
283
|
// Computed signals for controls props
|
|
281
|
-
|
|
284
|
+
// A call taken with the artifact open on a phone is a small panel floating in the
|
|
285
|
+
// bottom-right corner over it (see the artifact rules in Main). The toggle is a
|
|
286
|
+
// two-option pill that would take most of that panel's width and change its shape
|
|
287
|
+
// underneath the visitor mid-call, so it stands down there for the same reason it
|
|
288
|
+
// stands down for a fullscreen call. The closed state parks a call in that corner
|
|
289
|
+
// too and needs no term of its own: the `minimized` check below already covers it.
|
|
290
|
+
const conversationModeVisible = useComputed(()=>rootStore.allowVoiceVideoToggle.value && !adapterState.isBlurredVideoActive.value && rootStore.maximizedState.value !== types_MaximizedState.MULTIMODAL && !(isMobile.value && rootStore.maximizedState.value === types_MaximizedState.ARTIFACT && (adapterState.isInCall.value || adapterState.isVideoLoading.value)) && !rootStore.displayMode.minimized.value);
|
|
282
291
|
const micIsOn = useComputed(()=>!adapterState.isMicMuted.value);
|
|
283
292
|
const micHasDevicesAvailable = useComputed(()=>adapterState.microphoneDevices.value.length > 0);
|
|
284
293
|
const micDevices = useComputed(()=>adapterState.microphoneDevices.value.map((d)=>({
|
|
@@ -318,7 +327,7 @@ function useControlsConfig(rootStore, adapter, variant, visibility) {
|
|
|
318
327
|
if (rootStore.displayMode.minimized.value) {
|
|
319
328
|
rootStore.setOpenedDisplayMode();
|
|
320
329
|
}
|
|
321
|
-
rootStore.
|
|
330
|
+
rootStore.endPresentationAndSetMaximizedState(types_MaximizedState.MULTIMODAL);
|
|
322
331
|
}
|
|
323
332
|
}
|
|
324
333
|
},
|
|
@@ -339,10 +348,13 @@ function useControlsConfig(rootStore, adapter, variant, visibility) {
|
|
|
339
348
|
endCall: {
|
|
340
349
|
visible: endCallVisible,
|
|
341
350
|
onClick: ()=>{
|
|
342
|
-
rootStore.
|
|
351
|
+
rootStore.endPresentationAndClearMaximizedState({
|
|
352
|
+
reason: "call_ended"
|
|
353
|
+
});
|
|
343
354
|
actions.endCall();
|
|
344
355
|
}
|
|
345
|
-
}
|
|
356
|
+
},
|
|
357
|
+
avatarProvider: rootStore.activeAvatarProvider
|
|
346
358
|
};
|
|
347
359
|
return {
|
|
348
360
|
visible: showControls,
|
|
@@ -8,6 +8,20 @@ import { styled } from "../../styled-system/jsx/factory.js";
|
|
|
8
8
|
|
|
9
9
|
/* provided dependency */ var presentations_setInterval = __webpack_require__(68034).LK;
|
|
10
10
|
/* provided dependency */ var presentations_clearInterval = __webpack_require__(68034).wm;
|
|
11
|
+
function _extends() {
|
|
12
|
+
_extends = Object.assign || function(target) {
|
|
13
|
+
for(var i = 1; i < arguments.length; i++){
|
|
14
|
+
var source = arguments[i];
|
|
15
|
+
for(var key in source){
|
|
16
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
17
|
+
target[key] = source[key];
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return target;
|
|
22
|
+
};
|
|
23
|
+
return _extends.apply(this, arguments);
|
|
24
|
+
}
|
|
11
25
|
|
|
12
26
|
/** @jsxImportSource preact */
|
|
13
27
|
|
|
@@ -165,6 +179,7 @@ function usePresentation(param) {
|
|
|
165
179
|
const isNewClip = video.dataset.clipKey !== clipKey;
|
|
166
180
|
if (isNewClip) {
|
|
167
181
|
video.dataset.clipKey = clipKey;
|
|
182
|
+
delete video.dataset.completedClipKey;
|
|
168
183
|
// Start at the first segment. segIndex tracks which segment is playing so timeupdate can chain
|
|
169
184
|
// to the next one at each segment's end.
|
|
170
185
|
video.dataset.segIndex = "0";
|
|
@@ -203,6 +218,44 @@ function usePresentation(param) {
|
|
|
203
218
|
video.addEventListener("seeked", handleReady);
|
|
204
219
|
video.addEventListener("loadeddata", handleReady);
|
|
205
220
|
video.addEventListener("playing", handleReady);
|
|
221
|
+
const reportPlaybackState = (overrides)=>{
|
|
222
|
+
if (overrides === void 0) overrides = {};
|
|
223
|
+
rootStore.presentationTelemetryStore.onDemoPlaybackState(pres.messageId, _extends({
|
|
224
|
+
playing: !video.paused,
|
|
225
|
+
buffering: !videoReady.peek(),
|
|
226
|
+
seeking: video.seeking
|
|
227
|
+
}, overrides));
|
|
228
|
+
};
|
|
229
|
+
const handlePlaying = ()=>reportPlaybackState({
|
|
230
|
+
playing: true,
|
|
231
|
+
buffering: false
|
|
232
|
+
});
|
|
233
|
+
const handlePause = ()=>reportPlaybackState({
|
|
234
|
+
playing: false
|
|
235
|
+
});
|
|
236
|
+
const handleWaiting = ()=>reportPlaybackState({
|
|
237
|
+
playing: false,
|
|
238
|
+
buffering: true
|
|
239
|
+
});
|
|
240
|
+
const handleSeeking = ()=>reportPlaybackState({
|
|
241
|
+
playing: false,
|
|
242
|
+
seeking: true
|
|
243
|
+
});
|
|
244
|
+
const handleSeeked = ()=>reportPlaybackState({
|
|
245
|
+
seeking: false
|
|
246
|
+
});
|
|
247
|
+
video.addEventListener("playing", handlePlaying);
|
|
248
|
+
video.addEventListener("pause", handlePause);
|
|
249
|
+
video.addEventListener("waiting", handleWaiting);
|
|
250
|
+
video.addEventListener("seeking", handleSeeking);
|
|
251
|
+
video.addEventListener("seeked", handleSeeked);
|
|
252
|
+
const reportNaturalCompletion = ()=>{
|
|
253
|
+
const finalSegment = segments.at(-1);
|
|
254
|
+
if (!finalSegment || !video.ended && video.currentTime < finalSegment.end) return;
|
|
255
|
+
if (video.dataset.completedClipKey === clipKey) return;
|
|
256
|
+
video.dataset.completedClipKey = clipKey;
|
|
257
|
+
rootStore.presentationTelemetryStore.onDemoNaturalCompletion(pres.messageId);
|
|
258
|
+
};
|
|
206
259
|
const handleTimeUpdate = ()=>{
|
|
207
260
|
var _video_dataset_segIndex;
|
|
208
261
|
// Publish the position so an interruption can tell the agent where it paused.
|
|
@@ -219,10 +272,12 @@ function usePresentation(param) {
|
|
|
219
272
|
video.currentTime = nextSegment.start;
|
|
220
273
|
} else if (!video.paused) {
|
|
221
274
|
video.pause();
|
|
275
|
+
reportNaturalCompletion();
|
|
222
276
|
}
|
|
223
277
|
}
|
|
224
278
|
};
|
|
225
279
|
video.addEventListener("timeupdate", handleTimeUpdate);
|
|
280
|
+
video.addEventListener("ended", reportNaturalCompletion);
|
|
226
281
|
// The visitor barged in — pause and freeze the frame. Otherwise keep playing.
|
|
227
282
|
if (stopped) {
|
|
228
283
|
if (!video.paused) video.pause();
|
|
@@ -239,9 +294,15 @@ function usePresentation(param) {
|
|
|
239
294
|
}
|
|
240
295
|
return ()=>{
|
|
241
296
|
video.removeEventListener("timeupdate", handleTimeUpdate);
|
|
297
|
+
video.removeEventListener("ended", reportNaturalCompletion);
|
|
242
298
|
video.removeEventListener("seeked", handleReady);
|
|
243
299
|
video.removeEventListener("loadeddata", handleReady);
|
|
244
300
|
video.removeEventListener("playing", handleReady);
|
|
301
|
+
video.removeEventListener("playing", handlePlaying);
|
|
302
|
+
video.removeEventListener("pause", handlePause);
|
|
303
|
+
video.removeEventListener("waiting", handleWaiting);
|
|
304
|
+
video.removeEventListener("seeking", handleSeeking);
|
|
305
|
+
video.removeEventListener("seeked", handleSeeked);
|
|
245
306
|
if (captureTimer !== null) presentations_clearInterval(captureTimer);
|
|
246
307
|
};
|
|
247
308
|
});
|
|
@@ -52,7 +52,7 @@ const WIDGET_VISIBLE_ATTRIBUTE = "q-widget-visible";
|
|
|
52
52
|
const MULTIMODAL_HOST_Z_INDEX = {
|
|
53
53
|
docked: 2147483640,
|
|
54
54
|
minimized: 2147483642,
|
|
55
|
-
expanded:
|
|
55
|
+
expanded: 2147483647,
|
|
56
56
|
maximized: 2147483647
|
|
57
57
|
};
|
|
58
58
|
// Mirrors backend `Message::Text::TEXT_SIZE_LIMIT` (app/models/message/text.rb), which
|
|
@@ -29,6 +29,22 @@ const PlayIcon = ()=>/*#__PURE__*/ jsxRuntime_module_u("svg", {
|
|
|
29
29
|
d: "M5 4.13C5 3.35 5.84 2.86 6.51 3.26L13.04 7.13C13.69 7.52 13.69 8.48 13.04 8.87L6.51 12.74C5.84 13.14 5 12.65 5 11.87V4.13Z"
|
|
30
30
|
})
|
|
31
31
|
});
|
|
32
|
+
/**
|
|
33
|
+
* Stacked lines, for the "N slides" badge on a deck's timeline card.
|
|
34
|
+
*/ const SlidesIcon = ()=>/*#__PURE__*/ jsxRuntime_module_u("svg", {
|
|
35
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
36
|
+
width: "12",
|
|
37
|
+
height: "12",
|
|
38
|
+
viewBox: "0 0 12 12",
|
|
39
|
+
fill: "none",
|
|
40
|
+
"aria-hidden": "true",
|
|
41
|
+
children: /*#__PURE__*/ jsxRuntime_module_u("path", {
|
|
42
|
+
d: "M1.5 2.5H10.5M1.5 6H8M1.5 9.5H6",
|
|
43
|
+
stroke: "currentColor",
|
|
44
|
+
strokeWidth: "1.5",
|
|
45
|
+
strokeLinecap: "round"
|
|
46
|
+
})
|
|
47
|
+
});
|
|
32
48
|
/**
|
|
33
49
|
* Microphone icon used in the "Speak now" button overlay on video preview.
|
|
34
50
|
*/ const SpeakNowMicIcon = ()=>/*#__PURE__*/ jsxRuntime_module_u("svg", {
|
|
@@ -579,4 +595,4 @@ var icons_CloseIcon = /* unused export */ undefined;
|
|
|
579
595
|
var icons_DoubleChatIcon = /* unused export */ undefined;
|
|
580
596
|
var icons_PinIcon = /* unused export */ undefined;
|
|
581
597
|
var icons_SoundwaveIcon = /* unused export */ undefined;
|
|
582
|
-
export { AlertIcon, ArrowRightIcon, CalendarIcon, CalendarResumeIcon, ChatBubbleIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronUpIcon, ClockIcon, CrossIcon, CursorIcon, ExpandIcon, GlobeIcon, LeftArrowIcon, MicIcon, MicOffIcon, MinimizeIcon, PinnedIcon, PipIcon, PlayIcon, RightArrowIcon, RotatePhoneIcon, SelectChevronIcon, SpeakNowMicIcon, SpinnerIcon, ThumbsDownIcon, ThumbsUpIcon, UpCaretIcon, WarningIcon, icons_CameraOffIcon as CameraOffIcon, icons_CameraOnIcon as CameraOnIcon, icons_CheckmarkIcon as CheckmarkIcon, icons_ChevronIcon as ChevronIcon, icons_CloseIcon as CloseIcon, icons_DoubleChatIcon as DoubleChatIcon, icons_PinIcon as PinIcon, icons_SoundwaveIcon as SoundwaveIcon };
|
|
598
|
+
export { AlertIcon, ArrowRightIcon, CalendarIcon, CalendarResumeIcon, ChatBubbleIcon, CheckCircleIcon, CheckIcon, ChevronDownIcon, ChevronUpIcon, ClockIcon, CrossIcon, CursorIcon, ExpandIcon, GlobeIcon, LeftArrowIcon, MicIcon, MicOffIcon, MinimizeIcon, PinnedIcon, PipIcon, PlayIcon, RightArrowIcon, RotatePhoneIcon, SelectChevronIcon, SlidesIcon, SpeakNowMicIcon, SpinnerIcon, ThumbsDownIcon, ThumbsUpIcon, UpCaretIcon, WarningIcon, icons_CameraOffIcon as CameraOffIcon, icons_CameraOnIcon as CameraOnIcon, icons_CheckmarkIcon as CheckmarkIcon, icons_ChevronIcon as ChevronIcon, icons_CloseIcon as CloseIcon, icons_DoubleChatIcon as DoubleChatIcon, icons_PinIcon as PinIcon, icons_SoundwaveIcon as SoundwaveIcon };
|