@webitel/ui-sdk 26.4.78 → 26.6.2
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 +10 -0
- package/dist/{contacts-eFuSbv3m.js → contacts-DuiejYmg.js} +1551 -802
- package/dist/{index-CaY0ocAF.js → index-D_Bvqjjy.js} +1 -1
- package/dist/{index-TiiXs7ZO.js → index-ofJZWfBt.js} +1 -1
- package/dist/{install-Bd5HfFTV.js → install-rysuPEjF.js} +38 -38
- package/dist/{isObject-BV09j4E1.js → isObject-C5JdCKnH.js} +1 -1
- package/dist/ui-sdk.css +1 -1
- package/dist/ui-sdk.js +1 -1
- package/dist/ui-sdk.umd.cjs +187 -188
- package/dist/{useVidstackSrc-BGxC2kR5.js → useVidstackSrc-C6hUWIuE.js} +1 -1
- package/dist/{vidstack-Bq6c3Bam-jeTFOXk6.js → vidstack-Bq6c3Bam-D6M5GPTI.js} +3 -3
- package/dist/{vidstack-D2pY00kU-I-LJsKk8.js → vidstack-D2pY00kU-CRo5Kvyt.js} +3 -3
- package/dist/{vidstack-DDXt6fpN-W_Ix9vbH.js → vidstack-DDXt6fpN-QgRuASyL.js} +2 -2
- package/dist/{vidstack-D_-9AA6_-27F2Mv_5.js → vidstack-D_-9AA6_-BQB6UUD-.js} +2 -2
- package/dist/{vidstack-DqAw8m9J-BxfLqlFs.js → vidstack-DqAw8m9J-0B90hhJB.js} +1 -1
- package/dist/{vidstack-audio-CvjDPPuQ.js → vidstack-audio-BML-tyCz.js} +2 -2
- package/dist/{vidstack-dash-rV4ryZh2.js → vidstack-dash-BwVTHD5j.js} +4 -4
- package/dist/{vidstack-google-cast-Cb8t34m4.js → vidstack-google-cast-CvoUE_Qj.js} +4 -4
- package/dist/{vidstack-hls-C2zZ7COz.js → vidstack-hls-BgbWYqKl.js} +4 -4
- package/dist/{vidstack-video-DzItbHtm.js → vidstack-video-D6tVAa-p.js} +3 -3
- package/dist/{vidstack-vimeo-BpKsHwp4.js → vidstack-vimeo-CMino7JB.js} +4 -4
- package/dist/{vidstack-youtube--6zpNJz6.js → vidstack-youtube-DLE3pyNu.js} +3 -3
- package/dist/{wt-action-bar-Df57KUsc.js → wt-action-bar-BwAQUnPp.js} +1 -1
- package/dist/{wt-button-select-ymdOC5NH.js → wt-button-select-D8-D18E4.js} +1 -1
- package/dist/{wt-call-media-action-D4CP3oZl.js → wt-call-media-action-B-AEoxjt.js} +1 -1
- package/dist/{wt-chat-emoji-CUjHxdzV.js → wt-chat-emoji-D_4QMhH7.js} +2 -2
- package/dist/{wt-confirm-dialog-CNwpPdgE.js → wt-confirm-dialog-BQVImEga.js} +1 -1
- package/dist/{wt-context-menu-CToKHamf.js → wt-context-menu-CfvdB5Xl.js} +1 -1
- package/dist/{wt-copy-action-Dd0tVB7g.js → wt-copy-action-CIa3ImHz.js} +1 -1
- package/dist/{wt-datepicker-B7sKwJlh.js → wt-datepicker-CEoYduIo.js} +1 -1
- package/dist/{wt-display-chip-items-IGBh7VMV.js → wt-display-chip-items-CD6E8917.js} +1 -1
- package/dist/{wt-dual-panel-CqN6YB0F.js → wt-dual-panel-Cm2oe8sF.js} +1 -1
- package/dist/{wt-dummy-OrcannPM.js → wt-dummy-DHdJccrG.js} +1 -1
- package/dist/{wt-error-page-BMpoQdQl.js → wt-error-page-Rt-F9oVv.js} +1 -1
- package/dist/{wt-expansion-card-DEDM3Znr.js → wt-expansion-card-v7GFQBoJ.js} +1 -1
- package/dist/{wt-expansion-panel-YCSPf-eq.js → wt-expansion-panel-DSsY-KFR.js} +1 -1
- package/dist/{wt-filters-panel-wrapper-Ck2bF7qg.js → wt-filters-panel-wrapper-Cr9dYYnT.js} +1 -1
- package/dist/{wt-galleria-CNDkujRu.js → wt-galleria-C2aburQk.js} +1 -1
- package/dist/{wt-inline-add-panel-BSEdS7eW.js → wt-inline-add-panel-BaDP2TC1.js} +1 -1
- package/dist/{wt-navigation-menu-igJBYaxO.js → wt-navigation-menu-B_R8-_Bk.js} +1 -1
- package/dist/{wt-notifications-bar-C0M5LC4G.js → wt-notifications-bar-CfoCOojR.js} +2 -2
- package/dist/{wt-pagination-BXDqQ9YV.js → wt-pagination-DW7KL87c.js} +1 -1
- package/dist/{wt-player-A13mN2qk.js → wt-player-Be2YAJcQ.js} +2 -2
- package/dist/{wt-screen-recordings-action-BQPS--RV.js → wt-screen-recordings-action-BJBx9KXM.js} +1 -1
- package/dist/{wt-search-bar-Cvt_urUF.js → wt-search-bar-BT5d_LDB.js} +1 -1
- package/dist/{wt-selection-popup-CcAfc6T6.js → wt-selection-popup-DK6oLjfk.js} +1 -1
- package/dist/{wt-send-message-popup-pN9zzJpT.js → wt-send-message-popup-C8oG1Kxc.js} +3 -3
- package/dist/{wt-start-page-DaotE9Vi.js → wt-start-page-BcV-IdG_.js} +1 -1
- package/dist/{wt-status-select-Dhw-c6FB.js → wt-status-select-BcrdWJ9m.js} +1 -1
- package/dist/{wt-stepper-DyM6hf_l.js → wt-stepper-B_ny-IQN.js} +1 -1
- package/dist/{wt-table-Do6tizZl.js → wt-table-BX5kDXje.js} +1 -1
- package/dist/{wt-table-actions-Stm_KC06.js → wt-table-actions-Cvk2_NUG.js} +1 -1
- package/dist/{wt-table-column-select-DaGMSlL1.js → wt-table-column-select-CPacgsbN.js} +2 -2
- package/dist/{wt-tabs-CTv4GgX8.js → wt-tabs-wcnQfMfj.js} +1 -1
- package/dist/{wt-tags-input-DJhQrEdL.js → wt-tags-input-CPO80nnI.js} +2 -2
- package/dist/{wt-timepicker-98DhU-ME.js → wt-timepicker-DbdcOXYa.js} +1 -1
- package/dist/{wt-tree-CfkLw1SI.js → wt-tree-CLs3S4Av.js} +2 -2
- package/dist/{wt-tree-table-DDyxMFbz.js → wt-tree-table-DtNIE08B.js} +1 -1
- package/dist/{wt-type-extension-value-input-B2CwLd8p.js → wt-type-extension-value-input-CjJ8_xRU.js} +3 -3
- package/dist/{wt-vidstack-player-BduaN7w2.js → wt-vidstack-player-DmD7s58v.js} +900 -882
- package/package.json +10 -2
- package/src/components/wt-vidstack-player/wt-vidstack-player.vue +47 -3
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/bridgeCustomElements.ts +32 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/copyStyles.ts +18 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/domTraversal.ts +16 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/index.ts +1 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/mediaCollection.ts +13 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/mediaPlayback.ts +22 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/mediaSnapshot.ts +43 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/playbackRetry.ts +81 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/useDocumentPiP.ts +146 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/usePiPResizeObserver.ts +30 -0
- package/src/modules/CallSession/modules/VideoCall/composables/useReceiverLiveStream.ts +64 -0
- package/src/modules/CallSession/modules/VideoCall/types/types.ts +17 -0
- package/src/modules/CallSession/modules/VideoCall/video-call.vue +170 -18
- package/types/components/wt-vidstack-player/wt-vidstack-player.vue.d.ts +3 -1
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/bridgeCustomElements.d.ts +1 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/copyStyles.d.ts +1 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/domTraversal.d.ts +1 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/index.d.ts +1 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/mediaCollection.d.ts +2 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/mediaPlayback.d.ts +3 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/mediaSnapshot.d.ts +16 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/playbackRetry.d.ts +24 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/useDocumentPiP.d.ts +8 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/usePiPResizeObserver.d.ts +6 -0
- package/types/modules/CallSession/modules/VideoCall/composables/useReceiverLiveStream.d.ts +49 -0
- package/types/modules/CallSession/modules/VideoCall/types/types.d.ts +14 -0
- package/types/modules/CallSession/modules/VideoCall/video-call.vue.d.ts +6 -4
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<wt-vidstack-player
|
|
3
|
-
|
|
4
|
-
:
|
|
5
|
-
|
|
3
|
+
ref="playerRef"
|
|
4
|
+
:class="[
|
|
5
|
+
!props.static && !isPiP && `video-call-position--${props.position}`,
|
|
6
|
+
isPiP && 'video-call--pip',
|
|
7
|
+
]"
|
|
8
|
+
:hide-video-display-panel="isPiP || props.hideVideoDisplayPanel"
|
|
9
|
+
:size="isPiP ? ComponentSize.MD : props.size"
|
|
6
10
|
:stream="mainStream"
|
|
7
|
-
:static="props.static"
|
|
11
|
+
:static="isPiP || props.static"
|
|
8
12
|
:username="props.username"
|
|
9
13
|
:hide-controls-panel="props.hideControlsPanel"
|
|
10
14
|
:mirror-video="!showSenderScreen"
|
|
@@ -26,6 +30,17 @@
|
|
|
26
30
|
<template #content="{ size: innerSize }">
|
|
27
31
|
<slot :size="innerSize" name="content" />
|
|
28
32
|
|
|
33
|
+
<div
|
|
34
|
+
v-if="isPiP && props['receiver:mic:enabled'] === false"
|
|
35
|
+
class="video-call--pip__mic-indicator"
|
|
36
|
+
>
|
|
37
|
+
<wt-icon
|
|
38
|
+
:size="ComponentSize.SM"
|
|
39
|
+
icon="mic-muted"
|
|
40
|
+
color="on-dark"
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
43
|
+
|
|
29
44
|
<slot v-if="!mainStream" :size="innerSize" name="overlay">
|
|
30
45
|
<div class="video-call-overlay">
|
|
31
46
|
<div
|
|
@@ -72,6 +87,7 @@
|
|
|
72
87
|
<screenshot-box
|
|
73
88
|
:size="innerSize"
|
|
74
89
|
:src="props['screenshot:src']"
|
|
90
|
+
:style="pipContentSizeStyle"
|
|
75
91
|
@close="emit(`action:${VideoCallAction.CloseScreenshot}`)"
|
|
76
92
|
@zoom="emit(`action:${VideoCallAction.ZoomScreenshot}`)"
|
|
77
93
|
/>
|
|
@@ -91,6 +107,7 @@
|
|
|
91
107
|
<template v-else-if="showSenderScreen">
|
|
92
108
|
<wt-vidstack-player
|
|
93
109
|
:class="`video-call-sender--${innerSize}`"
|
|
110
|
+
:style="pipContentSizeStyle"
|
|
94
111
|
:stream="props['sender:stream']"
|
|
95
112
|
autoplay
|
|
96
113
|
class="video-call-sender"
|
|
@@ -133,6 +150,7 @@
|
|
|
133
150
|
@[VideoCallAction.Settings]="(payload, options) => emit(emitKeys[VideoCallAction.Settings], payload, options)"
|
|
134
151
|
@[VideoCallAction.Chat]="(payload, options) => emit(emitKeys[VideoCallAction.Chat], payload, options)"
|
|
135
152
|
@[VideoCallAction.Hangup]="(payload, options) => emit(emitKeys[VideoCallAction.Hangup], payload, options)"
|
|
153
|
+
|
|
136
154
|
/>
|
|
137
155
|
</template>
|
|
138
156
|
</wt-vidstack-player>
|
|
@@ -143,9 +161,8 @@
|
|
|
143
161
|
lang="ts"
|
|
144
162
|
>
|
|
145
163
|
import { WtVidstackPlayer } from '@webitel/ui-sdk/components';
|
|
146
|
-
import { computed, onBeforeUnmount, ref, watch } from 'vue';
|
|
164
|
+
import { computed, isRef, onBeforeUnmount, type Ref, ref, watch } from 'vue';
|
|
147
165
|
import { useI18n } from 'vue-i18n';
|
|
148
|
-
|
|
149
166
|
import { WtIcon } from '../../../../components';
|
|
150
167
|
import {
|
|
151
168
|
RecordingIndicator,
|
|
@@ -156,6 +173,8 @@ import { ComponentSize, WtApplication } from '../../../../enums';
|
|
|
156
173
|
import { convertDuration } from '../../../../scripts';
|
|
157
174
|
import type { ResultCallbacks } from '../../../../types';
|
|
158
175
|
import type { ScreenshotStatus } from '../../types';
|
|
176
|
+
import { useDocumentPiP } from './composables/useDocumentPiP';
|
|
177
|
+
import { useReceiverLiveStream } from './composables/useReceiverLiveStream';
|
|
159
178
|
import { VideoCallAction } from './enums/VideoCallAction.enum';
|
|
160
179
|
|
|
161
180
|
const props = withDefaults(
|
|
@@ -187,6 +206,9 @@ const props = withDefaults(
|
|
|
187
206
|
hideVideoDisplayPanel?: boolean;
|
|
188
207
|
hideAvatar?: boolean;
|
|
189
208
|
resizable?: boolean;
|
|
209
|
+
hideSenderOnHold?: boolean;
|
|
210
|
+
|
|
211
|
+
isPipMode?: boolean;
|
|
190
212
|
|
|
191
213
|
actions: VideoCallAction[];
|
|
192
214
|
username?: string;
|
|
@@ -256,6 +278,61 @@ const emitKeys = {
|
|
|
256
278
|
|
|
257
279
|
const { t } = useI18n();
|
|
258
280
|
|
|
281
|
+
const playerRef = ref<InstanceType<typeof WtVidstackPlayer> | null>(null);
|
|
282
|
+
|
|
283
|
+
/** `defineExpose({ rootEl })` on `WtVidstackPlayer` passes a Ref — DOM is ready after stream + Vidstack upgrade. */
|
|
284
|
+
const getVideoCallPlayerHostElement = (): HTMLElement | null => {
|
|
285
|
+
const inst = playerRef.value as unknown as {
|
|
286
|
+
rootEl?: HTMLElement | Ref<HTMLElement | null> | null;
|
|
287
|
+
$el?: HTMLElement | null;
|
|
288
|
+
} | null;
|
|
289
|
+
if (!inst) return null;
|
|
290
|
+
const rootEl = inst.rootEl;
|
|
291
|
+
const exposedElement = isRef(rootEl) ? rootEl.value : (rootEl ?? null);
|
|
292
|
+
return exposedElement ?? inst.$el ?? null;
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const { isPiP, enterPiP, onPiPResize } = useDocumentPiP(
|
|
296
|
+
getVideoCallPlayerHostElement,
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* @author @Oleksandr Palionnyi
|
|
301
|
+
*
|
|
302
|
+
* [WTEL-9414](https://webitel.atlassian.net/browse/WTEL-9414)
|
|
303
|
+
*
|
|
304
|
+
* Sender preview dimensions relative to the main player, taken from Figma design (256×171 / 1366×912).
|
|
305
|
+
* https://webitel.atlassian.net/browse/WTEL-9542?focusedCommentId=754891
|
|
306
|
+
*/
|
|
307
|
+
const SENDER_WIDTH_RATIO = 256 / 1366;
|
|
308
|
+
const SENDER_ASPECT_RATIO = 171 / 256;
|
|
309
|
+
|
|
310
|
+
const pipContentSize = ref<{
|
|
311
|
+
width: number;
|
|
312
|
+
height: number;
|
|
313
|
+
} | null>(null);
|
|
314
|
+
|
|
315
|
+
onPiPResize((rect) => {
|
|
316
|
+
const width = rect.width * SENDER_WIDTH_RATIO;
|
|
317
|
+
pipContentSize.value = {
|
|
318
|
+
width,
|
|
319
|
+
height: width * SENDER_ASPECT_RATIO,
|
|
320
|
+
};
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
watch(isPiP, (active) => {
|
|
324
|
+
if (!active) pipContentSize.value = null;
|
|
325
|
+
});
|
|
326
|
+
|
|
327
|
+
const pipContentSizeStyle = computed(() => {
|
|
328
|
+
if (!pipContentSize.value) return '';
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
width: `${pipContentSize.value.width}px`,
|
|
332
|
+
height: `${pipContentSize.value.height}px`,
|
|
333
|
+
};
|
|
334
|
+
});
|
|
335
|
+
|
|
259
336
|
const receiverStream = computed(() => props['receiver:stream']);
|
|
260
337
|
const senderStream = computed(() => props['sender:stream']);
|
|
261
338
|
|
|
@@ -290,6 +367,12 @@ const bothStreamsAvailable = computed(
|
|
|
290
367
|
() => !!receiverStream.value && !!senderStream.value,
|
|
291
368
|
);
|
|
292
369
|
|
|
370
|
+
const receiverStreamLiveForMain = useReceiverLiveStream(
|
|
371
|
+
receiverStream,
|
|
372
|
+
receiverVideoEnabled,
|
|
373
|
+
isOnHold,
|
|
374
|
+
);
|
|
375
|
+
|
|
293
376
|
const showReceiverOverlay = computed(
|
|
294
377
|
() =>
|
|
295
378
|
(!receiverStream.value &&
|
|
@@ -320,13 +403,22 @@ const mainStream = computed(() => {
|
|
|
320
403
|
return senderStream.value;
|
|
321
404
|
}
|
|
322
405
|
|
|
323
|
-
return
|
|
406
|
+
return receiverStreamLiveForMain.value ?? senderStream.value;
|
|
324
407
|
});
|
|
325
408
|
|
|
326
409
|
const showSenderScreen = computed(() => {
|
|
327
|
-
if (
|
|
328
|
-
|
|
329
|
-
|
|
410
|
+
if (isOnHold.value) {
|
|
411
|
+
return (
|
|
412
|
+
!props.hideSenderOnHold && !!senderStream.value && !!receiverStream.value
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
if (!bothStreamsAvailable.value) {
|
|
416
|
+
return false;
|
|
417
|
+
}
|
|
418
|
+
if (!receiverVideoEnabled.value) {
|
|
419
|
+
return true;
|
|
420
|
+
}
|
|
421
|
+
return receiverStreamLiveForMain.value != null;
|
|
330
422
|
});
|
|
331
423
|
|
|
332
424
|
const showSenderMutedScreen = computed(() => {
|
|
@@ -363,8 +455,36 @@ watch(
|
|
|
363
455
|
},
|
|
364
456
|
);
|
|
365
457
|
|
|
458
|
+
/**
|
|
459
|
+
* @author @Oleksandr Palionnyi
|
|
460
|
+
*
|
|
461
|
+
* [WTEL-9414](https://webitel.atlassian.net/browse/WTEL-9414)
|
|
462
|
+
*
|
|
463
|
+
* Document PiP: call `requestWindow()` only when `mainStream` and a usable player host exist.
|
|
464
|
+
* `flush: 'post'` runs after DOM updates so Vidstack / WC upgrade can finish before we read `rootEl`.
|
|
465
|
+
* Stop the watcher only once `enterPiP` succeeds (`isPiP`), so gesture/API failures can retry on later ticks.
|
|
466
|
+
*/
|
|
467
|
+
const stopAutoDocumentPiP = watch(
|
|
468
|
+
[
|
|
469
|
+
mainStream,
|
|
470
|
+
playerRef,
|
|
471
|
+
],
|
|
472
|
+
async () => {
|
|
473
|
+
if (!props.isPipMode) return;
|
|
474
|
+
if (!mainStream.value || !playerRef.value || isPiP.value) return;
|
|
475
|
+
if (!getVideoCallPlayerHostElement()) return;
|
|
476
|
+
await enterPiP();
|
|
477
|
+
if (isPiP.value) stopAutoDocumentPiP();
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
flush: 'post',
|
|
481
|
+
immediate: true,
|
|
482
|
+
},
|
|
483
|
+
);
|
|
484
|
+
|
|
366
485
|
onBeforeUnmount(() => {
|
|
367
486
|
stopHoldTimer();
|
|
487
|
+
stopAutoDocumentPiP();
|
|
368
488
|
});
|
|
369
489
|
|
|
370
490
|
const receiverVideoMutedIconSizes = {
|
|
@@ -385,6 +505,46 @@ const senderVideoMutedIconSizes = {
|
|
|
385
505
|
flex: 0 0 auto;
|
|
386
506
|
}
|
|
387
507
|
|
|
508
|
+
.video-call--pip.wt-vidstack-player {
|
|
509
|
+
position: fixed;
|
|
510
|
+
top: 0;
|
|
511
|
+
right: 0;
|
|
512
|
+
bottom: 0;
|
|
513
|
+
left: 0;
|
|
514
|
+
width: 100%;
|
|
515
|
+
height: 100%;
|
|
516
|
+
max-width: 100%;
|
|
517
|
+
max-height: 100%;
|
|
518
|
+
border-radius: 0;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
.video-call--pip :deep(.wt-vidstack-player__player:not(.video-call-sender *)),
|
|
522
|
+
.video-call--pip :deep(.wt-vidstack-player__provider:not(.video-call-sender *)),
|
|
523
|
+
.video-call--pip :deep(.wt-vidstack-player:not(.video-call-sender)),
|
|
524
|
+
.video-call--pip :deep(video:not(.video-call-sender *)) {
|
|
525
|
+
border-radius: 0;
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
.video-call--pip__mic-indicator {
|
|
529
|
+
display: flex;
|
|
530
|
+
align-items: center;
|
|
531
|
+
justify-content: center;
|
|
532
|
+
position: absolute;
|
|
533
|
+
top: var(--spacing-sm);
|
|
534
|
+
left: var(--spacing-sm);
|
|
535
|
+
z-index: 1;
|
|
536
|
+
padding: var(--spacing-xs);
|
|
537
|
+
background: var(--p-player-head-line-hover-background);
|
|
538
|
+
border-radius: var(--p-player-wrapper-sm-border-radius);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/* Placeholder occupies original layout space while element lives in PiP window */
|
|
542
|
+
.video-call--pip-active {
|
|
543
|
+
background: var(--p-player-wrapper-background, #000);
|
|
544
|
+
border-radius: inherit;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
|
|
388
548
|
.video-call-position--left-bottom.wt-vidstack-player--sm {
|
|
389
549
|
top: unset;
|
|
390
550
|
bottom: var(--spacing-sm);
|
|
@@ -533,10 +693,6 @@ const senderVideoMutedIconSizes = {
|
|
|
533
693
|
height: var(--p-player-cam-preview-sm-height);
|
|
534
694
|
}
|
|
535
695
|
|
|
536
|
-
.video-call-sender--md :deep(video) {
|
|
537
|
-
border-radius: var(--p-player-cam-preview-md-border-radius);
|
|
538
|
-
}
|
|
539
|
-
|
|
540
696
|
.video-call-sender--md.video-call-sender--muted {
|
|
541
697
|
border-radius: var(--p-player-cam-preview-md-border-radius);
|
|
542
698
|
}
|
|
@@ -549,10 +705,6 @@ const senderVideoMutedIconSizes = {
|
|
|
549
705
|
height: var(--p-player-cam-preview-md-height);
|
|
550
706
|
}
|
|
551
707
|
|
|
552
|
-
.video-call-sender--lg :deep(video) {
|
|
553
|
-
border-radius: var(--p-player-cam-preview-lg-border-radius);
|
|
554
|
-
}
|
|
555
|
-
|
|
556
708
|
.video-call-sender--lg.video-call-sender--muted {
|
|
557
709
|
border-radius: var(--p-player-cam-preview-lg-border-radius);
|
|
558
710
|
}
|
|
@@ -34,7 +34,9 @@ type __VLS_Slots = {} & {
|
|
|
34
34
|
} & {
|
|
35
35
|
content?: (props: typeof __VLS_32) => any;
|
|
36
36
|
};
|
|
37
|
-
declare const __VLS_base: import("vue").DefineComponent<Props, {
|
|
37
|
+
declare const __VLS_base: import("vue").DefineComponent<Props, {
|
|
38
|
+
rootEl: Readonly<import("vue").ShallowRef<HTMLElement>>;
|
|
39
|
+
}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
|
|
38
40
|
close: () => any;
|
|
39
41
|
"change-size": (args_0: ComponentSize) => any;
|
|
40
42
|
}, string, import("vue").PublicProps, Readonly<Props> & Readonly<{
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const bridgeCustomElements: (root: Element, targetWindow: Window) => void;
|
package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/copyStyles.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const copyStyles: (targetWindow: Window) => void;
|
package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/domTraversal.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const domTraversal: (root: Element | ShadowRoot, visit: (el: Element) => void) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useDocumentPiP } from './useDocumentPiP';
|
package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/mediaSnapshot.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author @PalonnyiOleksandr
|
|
3
|
+
*
|
|
4
|
+
* [WTEL-9414](https://webitel.atlassian.net/browse/WTEL-9414)
|
|
5
|
+
*
|
|
6
|
+
* Snapshot utilities for media elements inside Document PiP window.
|
|
7
|
+
* `snapshotMedia` captures current muted state and srcObject of all media
|
|
8
|
+
* elements, then forces mute to prevent autoplay policy violations.
|
|
9
|
+
* `restoreMedia` reverts muted state and re-attaches lost streams.
|
|
10
|
+
* `restoreStreams` re-attaches srcObject without touching muted state,
|
|
11
|
+
* used during playback retry polling.
|
|
12
|
+
*/
|
|
13
|
+
import type { MediaSnapshot } from '../../types/types';
|
|
14
|
+
export declare const snapshotMedia: (root: Element, snapshot: MediaSnapshot[]) => void;
|
|
15
|
+
export declare const restoreMedia: (snapshot: MediaSnapshot[]) => void;
|
|
16
|
+
export declare const restoreStreams: (snapshot: MediaSnapshot[]) => void;
|
package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/playbackRetry.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @author @PalonnyiOleksandr
|
|
3
|
+
*
|
|
4
|
+
* [WTEL-9414](https://webitel.atlassian.net/browse/WTEL-9414)
|
|
5
|
+
*
|
|
6
|
+
* Polling retry mechanism for media playback inside Document PiP window.
|
|
7
|
+
* Restores streams from snapshot, mutes and plays all media elements until
|
|
8
|
+
* all are ready or the timeout expires. Triggers vidstack playback after an
|
|
9
|
+
* initial delay and re-kicks it periodically when any element stays stalled,
|
|
10
|
+
* throttled to once per 1500 ms to avoid redundant calls.
|
|
11
|
+
*
|
|
12
|
+
* Background: browsers block autoplay until the user interacts with the page,
|
|
13
|
+
* which caused the video to freeze after opening PiP. Since the video must
|
|
14
|
+
* play immediately without any extra clicks, this retry loop works around that
|
|
15
|
+
* by muting elements (which bypasses the autoplay restriction) and
|
|
16
|
+
* re-attempting playback until all media is running.
|
|
17
|
+
*
|
|
18
|
+
* link to explanation - https://webitel.atlassian.net/browse/WTEL-9414?focusedCommentId=754533
|
|
19
|
+
*/
|
|
20
|
+
import type { MediaSnapshot } from '../../types/types';
|
|
21
|
+
export declare const createPlaybackRetry: (snapshot: MediaSnapshot[]) => {
|
|
22
|
+
retryPlayback: (root: Element, durationMs?: number) => void;
|
|
23
|
+
stopPlaybackRetry: () => void;
|
|
24
|
+
};
|
package/types/modules/CallSession/modules/VideoCall/composables/useDocumentPiP/useDocumentPiP.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export declare function useDocumentPiP(getElement: () => HTMLElement | null | undefined): {
|
|
2
|
+
isPiP: import("vue").Ref<boolean, boolean>;
|
|
3
|
+
isSupported: import("vue").ComputedRef<boolean>;
|
|
4
|
+
enterPiP: (width?: number, height?: number) => Promise<void>;
|
|
5
|
+
exitPiP: () => void;
|
|
6
|
+
armFirstGestureResume: (w?: Window) => void;
|
|
7
|
+
onPiPResize: (callback: import("../../types/types").PiPResizeCallback) => () => boolean;
|
|
8
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PiPResizeCallback } from '../../types/types';
|
|
2
|
+
export declare function usePiPResizeObserver(): {
|
|
3
|
+
startPiPResizeObserver: (element: HTMLElement) => void;
|
|
4
|
+
stopPiPResizeObserver: () => void;
|
|
5
|
+
onPiPResize: (callback: PiPResizeCallback) => () => boolean;
|
|
6
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type ComputedRef } from 'vue';
|
|
2
|
+
/**
|
|
3
|
+
* Tracks whether the receiver's stream has a live video track.
|
|
4
|
+
* Reacts to track additions, unmute, and ended events on the stream.
|
|
5
|
+
* Returns null when stream is absent, video is disabled, or call is on hold.
|
|
6
|
+
*/
|
|
7
|
+
export declare function useReceiverLiveStream(receiverStream: ComputedRef<MediaStream | null | undefined>, videoEnabled: ComputedRef<boolean | undefined>, isOnHold: ComputedRef<boolean>): import("vue").Ref<{
|
|
8
|
+
readonly active: boolean;
|
|
9
|
+
readonly id: string;
|
|
10
|
+
onaddtrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any;
|
|
11
|
+
onremovetrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any;
|
|
12
|
+
addTrack: (track: MediaStreamTrack) => void;
|
|
13
|
+
clone: () => MediaStream;
|
|
14
|
+
getAudioTracks: () => MediaStreamTrack[];
|
|
15
|
+
getTrackById: (trackId: string) => MediaStreamTrack | null;
|
|
16
|
+
getTracks: () => MediaStreamTrack[];
|
|
17
|
+
getVideoTracks: () => MediaStreamTrack[];
|
|
18
|
+
removeTrack: (track: MediaStreamTrack) => void;
|
|
19
|
+
addEventListener: {
|
|
20
|
+
<K extends keyof MediaStreamEventMap>(type: K, listener: (this: MediaStream, ev: MediaStreamEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
|
21
|
+
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
|
22
|
+
};
|
|
23
|
+
removeEventListener: {
|
|
24
|
+
<K extends keyof MediaStreamEventMap>(type: K, listener: (this: MediaStream, ev: MediaStreamEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
|
25
|
+
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
|
26
|
+
};
|
|
27
|
+
dispatchEvent: (event: Event) => boolean;
|
|
28
|
+
}, MediaStream | {
|
|
29
|
+
readonly active: boolean;
|
|
30
|
+
readonly id: string;
|
|
31
|
+
onaddtrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any;
|
|
32
|
+
onremovetrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any;
|
|
33
|
+
addTrack: (track: MediaStreamTrack) => void;
|
|
34
|
+
clone: () => MediaStream;
|
|
35
|
+
getAudioTracks: () => MediaStreamTrack[];
|
|
36
|
+
getTrackById: (trackId: string) => MediaStreamTrack | null;
|
|
37
|
+
getTracks: () => MediaStreamTrack[];
|
|
38
|
+
getVideoTracks: () => MediaStreamTrack[];
|
|
39
|
+
removeTrack: (track: MediaStreamTrack) => void;
|
|
40
|
+
addEventListener: {
|
|
41
|
+
<K extends keyof MediaStreamEventMap>(type: K, listener: (this: MediaStream, ev: MediaStreamEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
|
42
|
+
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
|
43
|
+
};
|
|
44
|
+
removeEventListener: {
|
|
45
|
+
<K extends keyof MediaStreamEventMap>(type: K, listener: (this: MediaStream, ev: MediaStreamEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
|
46
|
+
(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
|
47
|
+
};
|
|
48
|
+
dispatchEvent: (event: Event) => boolean;
|
|
49
|
+
}>;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type DocumentPiPWindow = Window & typeof globalThis & {
|
|
2
|
+
documentPictureInPicture: {
|
|
3
|
+
requestWindow: (opts: {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
}) => Promise<Window>;
|
|
7
|
+
};
|
|
8
|
+
};
|
|
9
|
+
export type MediaSnapshot = {
|
|
10
|
+
el: HTMLMediaElement;
|
|
11
|
+
muted: boolean;
|
|
12
|
+
srcObject: MediaStream | null;
|
|
13
|
+
};
|
|
14
|
+
export type PiPResizeCallback = (rect: DOMRectReadOnly) => void;
|
|
@@ -23,21 +23,23 @@ type __VLS_Props = {
|
|
|
23
23
|
hideVideoDisplayPanel?: boolean;
|
|
24
24
|
hideAvatar?: boolean;
|
|
25
25
|
resizable?: boolean;
|
|
26
|
+
hideSenderOnHold?: boolean;
|
|
27
|
+
isPipMode?: boolean;
|
|
26
28
|
actions: VideoCallAction[];
|
|
27
29
|
username?: string;
|
|
28
30
|
'actions:settings:pressed'?: boolean;
|
|
29
31
|
'actions:settings:disabled'?: boolean;
|
|
30
32
|
'actions:chat:pressed'?: boolean;
|
|
31
33
|
};
|
|
32
|
-
declare var
|
|
34
|
+
declare var __VLS_18: {
|
|
33
35
|
size: ComponentSize;
|
|
34
|
-
},
|
|
36
|
+
}, __VLS_25: {
|
|
35
37
|
size: ComponentSize;
|
|
36
38
|
};
|
|
37
39
|
type __VLS_Slots = {} & {
|
|
38
|
-
content?: (props: typeof
|
|
40
|
+
content?: (props: typeof __VLS_18) => any;
|
|
39
41
|
} & {
|
|
40
|
-
overlay?: (props: typeof
|
|
42
|
+
overlay?: (props: typeof __VLS_25) => any;
|
|
41
43
|
};
|
|
42
44
|
declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
|
|
43
45
|
"change-size": (size: ComponentSize) => any;
|