tuikit-atomicx-vue3 4.5.3 → 4.5.4
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/dist/baseComp/Input/InputH5.vue.d.ts +1 -1
- package/dist/baseComp/Input/InputPC.vue.d.ts +1 -1
- package/dist/baseComp/Input/InputWX.vue.d.ts +1 -1
- package/dist/baseComp/Input/index.d.ts +15 -15
- package/dist/components/BarrageInput/TextEditor/TextEditor.vue.d.ts +1 -1
- package/dist/components/BarrageInput/index.d.ts +6 -6
- package/dist/components/ChatSetting/SettingItem/SettingItem.vue.d.ts +2 -2
- package/dist/components/ContactList/index.d.ts +6 -6
- package/dist/components/ConversationList/ConversationList.vue.d.ts +190 -190
- package/dist/components/ConversationList/ConversationPreview/ConversationPreview.vue.d.ts +82 -82
- package/dist/components/ConversationList/ConversationPreview/ConversationPreviewUI.vue.d.ts +16 -16
- package/dist/components/ConversationList/ConversationSearch/ConversationSearch.vue.d.ts +36 -36
- package/dist/components/ConversationList/index.d.ts +416 -416
- package/dist/components/LiveView/PlayerControl/PlayerControl.js +145 -128
- package/dist/components/LiveView/PlayerControl/PlayerControlState.d.ts +6 -4
- package/dist/components/LiveView/PlayerControl/PlayerControlState.js +148 -122
- package/dist/components/LiveView/PlayerControl/utils/domHelpers.d.ts +2 -1
- package/dist/components/LiveView/PlayerControl/utils/domHelpers.js +7 -6
- package/dist/components/LiveView/i18n/en-US/index.d.ts +3 -0
- package/dist/components/LiveView/i18n/en-US/index.js +4 -1
- package/dist/components/LiveView/i18n/zh-CN/index.d.ts +3 -0
- package/dist/components/LiveView/i18n/zh-CN/index.js +4 -1
- package/dist/components/LiveView/index.js +78 -78
- package/dist/components/MessageInput/MessageInput.vue.d.ts +1 -1
- package/dist/components/MessageInput/TextEditor/TextEditor.vue.d.ts +1 -1
- package/dist/components/MessageInput/index.d.ts +30 -30
- package/dist/components/RoomParticipantList/useParticpantAction/useNameCardAction/index.d.ts +10 -2
- package/dist/components/Search/Search.vue.d.ts +12 -12
- package/dist/components/Search/index.d.ts +18 -18
- package/dist/components/StreamView/Layout/CustomLayout.vue.d.ts +2 -1
- package/dist/components/StreamView/Layout/FloatLayout.vue.d.ts +2 -1
- package/dist/components/StreamView/Layout/GridLayout.vue.d.ts +2 -1
- package/dist/components/StreamView/Layout/MeetingLayout.vue.d.ts +1 -1
- package/dist/components/StreamView/common/StreamList/index.vue.d.ts +1 -1
- package/dist/components/StreamView/common/StreamRegion/StreamRegionPC.vue.d.ts +2 -2
- package/dist/components/StreamView/index.d.ts +1 -1
- package/dist/components/StreamView/index.vue.d.ts +1 -1
- package/dist/hooks/useRoomEngine.d.ts +2 -2
- package/dist/hooks/useUserActions/index.d.ts +18 -2
- package/dist/hooks/useUserActions/useChangeNameCardAction/index.d.ts +9 -1
- package/dist/hooks/useUserActions/useKickUserAction.d.ts +9 -1
- package/dist/hooks/useUserActions/useTransferOwnerAction.d.ts +9 -1
- package/dist/hooks/useUserActions/useVideoAction.d.ts +9 -1
- package/dist/states/BarrageState/BarrageState.d.ts +2 -2
- package/dist/states/BattleState/BattleState.d.ts +5 -5
- package/dist/states/CoGuestState.d.ts +1 -1
- package/dist/states/LiveAudienceState.d.ts +4 -4
- package/dist/states/LiveListState/LiveListState.d.ts +2 -2
- package/dist/states/LiveSeatState/index.d.ts +6 -6
- package/dist/states/LiveSeatState/seatManager.d.ts +6 -6
- package/dist/states/SeatStore.d.ts +148 -16
- package/dist/states/UserState/userManager.d.ts +1 -1
- package/dist/styles/index.css +1 -1
- package/dist/subEntry/chat/chat.d.ts +457 -457
- package/dist/subEntry/live/server.d.ts +1 -1
- package/dist/subEntry/room/server.d.ts +1 -1
- package/package.json +3 -2
- package/src/components/LiveView/PlayerControl/PlayerControl.vue +39 -15
- package/src/components/LiveView/PlayerControl/PlayerControlState.ts +61 -18
- package/src/components/LiveView/PlayerControl/utils/domHelpers.ts +4 -4
- package/src/components/LiveView/i18n/en-US/index.ts +3 -0
- package/src/components/LiveView/i18n/zh-CN/index.ts +3 -0
- package/src/components/LiveView/index.vue +7 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tuikit-atomicx-vue3",
|
|
3
|
-
"version": "4.5.
|
|
3
|
+
"version": "4.5.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -35,6 +35,7 @@
|
|
|
35
35
|
"scripts": {
|
|
36
36
|
"dev": "vite build --watch",
|
|
37
37
|
"build": "vite build",
|
|
38
|
+
"build:local": "vite build",
|
|
38
39
|
"build:watch": "vite build --mode development -w",
|
|
39
40
|
"lint": "eslint .",
|
|
40
41
|
"check-chinese": "node scripts/check-chinese-simple.js",
|
|
@@ -55,7 +56,7 @@
|
|
|
55
56
|
"@tencentcloud/chat": "^3.5.8",
|
|
56
57
|
"@tencentcloud/chat-uikit-engine": "~2.5.7",
|
|
57
58
|
"@tencentcloud/tui-core": "latest",
|
|
58
|
-
"@tencentcloud/tuiroom-engine-js": "~3.5.
|
|
59
|
+
"@tencentcloud/tuiroom-engine-js": "~3.5.1",
|
|
59
60
|
"@tencentcloud/uikit-base-component-vue3": "1.3.2",
|
|
60
61
|
"vue": "^3.4.0"
|
|
61
62
|
},
|
|
@@ -10,14 +10,20 @@
|
|
|
10
10
|
]"
|
|
11
11
|
>
|
|
12
12
|
<div class="control-buttons">
|
|
13
|
-
<span
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
<span
|
|
14
|
+
v-if="!isSafari || !isTcPlayer"
|
|
15
|
+
class="control-btn play-pause-btn"
|
|
16
|
+
:class="{disabled: isPictureInPicture}"
|
|
17
|
+
:title="isPlaying ? t('Pause') : t('Play')"
|
|
18
|
+
@click="handlePlayPause"
|
|
19
|
+
>
|
|
20
|
+
<IconPause v-if="isPlaying" size="20" />
|
|
21
|
+
<IconPlay v-else size="20" />
|
|
16
22
|
</span>
|
|
17
|
-
<div class="center-controls"
|
|
23
|
+
<div class="center-controls" />
|
|
18
24
|
<div class="right-controls">
|
|
19
25
|
<MultiResolution />
|
|
20
|
-
<span class="control-btn audio-control-btn">
|
|
26
|
+
<span v-if="!isSafari || !isTcPlayer" class="control-btn audio-control-btn">
|
|
21
27
|
<AudioControl
|
|
22
28
|
class="audio-control-icon"
|
|
23
29
|
:icon-size="20"
|
|
@@ -29,6 +35,7 @@
|
|
|
29
35
|
</span>
|
|
30
36
|
<span
|
|
31
37
|
class="control-btn"
|
|
38
|
+
:class="{disabled: !isPlaying && !isPictureInPicture}"
|
|
32
39
|
:title="isPictureInPicture ? t('Exit Picture in Picture') : t('Picture in Picture')"
|
|
33
40
|
@click="handlePictureInPicture"
|
|
34
41
|
>
|
|
@@ -58,11 +65,10 @@ import {
|
|
|
58
65
|
TUIToast,
|
|
59
66
|
TOAST_TYPE,
|
|
60
67
|
} from '@tencentcloud/uikit-base-component-vue3';
|
|
61
|
-
import {
|
|
68
|
+
import { isMobile } from '../../../utils';
|
|
62
69
|
import AudioControl from './AudioControl.vue';
|
|
63
70
|
import MultiResolution from './MultiResolution.vue';
|
|
64
|
-
import {
|
|
65
|
-
import { waitForVideoMounted } from './utils/domHelpers';
|
|
71
|
+
import { usePlayerControlState } from './PlayerControlState';
|
|
66
72
|
|
|
67
73
|
const {
|
|
68
74
|
isMuted,
|
|
@@ -79,6 +85,8 @@ const {
|
|
|
79
85
|
setVolume,
|
|
80
86
|
setMute,
|
|
81
87
|
cleanup,
|
|
88
|
+
isSafari,
|
|
89
|
+
isTcPlayer,
|
|
82
90
|
} = usePlayerControlState();
|
|
83
91
|
|
|
84
92
|
const props = defineProps<{
|
|
@@ -93,6 +101,14 @@ const hideTimeout = ref<number | null>(null);
|
|
|
93
101
|
const AUTO_HIDE_DELAY = 3000; // ms
|
|
94
102
|
|
|
95
103
|
const handlePlayPause = () => {
|
|
104
|
+
if (isPictureInPicture.value) {
|
|
105
|
+
TUIToast({
|
|
106
|
+
type: TOAST_TYPE.WARNING,
|
|
107
|
+
message: t('Not allow to "Pause" in picture-in-picture mode'),
|
|
108
|
+
});
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
96
112
|
if (isPlaying.value) {
|
|
97
113
|
pause();
|
|
98
114
|
} else {
|
|
@@ -101,6 +117,14 @@ const handlePlayPause = () => {
|
|
|
101
117
|
};
|
|
102
118
|
|
|
103
119
|
const handlePictureInPicture = async () => {
|
|
120
|
+
if (!isPlaying.value && !isPictureInPicture.value) {
|
|
121
|
+
TUIToast({
|
|
122
|
+
type: TOAST_TYPE.WARNING,
|
|
123
|
+
message: t('Not allow to "Picture in Picture" in non-playing mode'),
|
|
124
|
+
});
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
104
128
|
let flag = false;
|
|
105
129
|
if (isPictureInPicture.value) {
|
|
106
130
|
flag = await exitPictureInPicture();
|
|
@@ -184,13 +208,9 @@ const removeParentMouseListener = () => {
|
|
|
184
208
|
const touchStartCoords = ref<{ x: number; y: number } | null>(null);
|
|
185
209
|
|
|
186
210
|
// Touch distance calculation
|
|
187
|
-
const calculateTouchDistance = (start: { x: number; y: number }, end: Touch) =>
|
|
188
|
-
return Math.sqrt(Math.pow(end.clientX - start.x, 2) + Math.pow(end.clientY - start.y, 2));
|
|
189
|
-
};
|
|
211
|
+
const calculateTouchDistance = (start: { x: number; y: number }, end: Touch) => Math.sqrt((end.clientX - start.x) ** 2 + (end.clientY - start.y) ** 2);
|
|
190
212
|
|
|
191
|
-
const isPlayerControlTarget = (target: Node) =>
|
|
192
|
-
return playerControlRef.value?.contains(target) || false;
|
|
193
|
-
};
|
|
213
|
+
const isPlayerControlTarget = (target: Node) => playerControlRef.value?.contains(target) || false;
|
|
194
214
|
|
|
195
215
|
const isLiveCoreViewTarget = (target: Node) => {
|
|
196
216
|
const container = document.getElementById('live-core-view-container');
|
|
@@ -224,7 +244,6 @@ const handleScreenTouchStart = (event: TouchEvent) => {
|
|
|
224
244
|
const handleScreenTouchMove = (event: TouchEvent) => {
|
|
225
245
|
if (playerControlRef.value && playerControlRef.value.contains(event.target as Node)) {
|
|
226
246
|
stopAutoHideControl();
|
|
227
|
-
return;
|
|
228
247
|
}
|
|
229
248
|
};
|
|
230
249
|
|
|
@@ -395,6 +414,11 @@ onBeforeUnmount(() => {
|
|
|
395
414
|
height: 20px;
|
|
396
415
|
fill: currentColor;
|
|
397
416
|
}
|
|
417
|
+
|
|
418
|
+
&.disabled {
|
|
419
|
+
cursor: not-allowed;
|
|
420
|
+
opacity: 0.4;
|
|
421
|
+
}
|
|
398
422
|
}
|
|
399
423
|
|
|
400
424
|
.play-pause-btn {
|
|
@@ -1,17 +1,20 @@
|
|
|
1
1
|
import type { Ref } from 'vue';
|
|
2
2
|
import { computed, ref, watch } from 'vue';
|
|
3
3
|
import { TUIVideoQuality } from '@tencentcloud/tuiroom-engine-js';
|
|
4
|
+
import { TUIMessageBox, useUIKit } from '@tencentcloud/uikit-base-component-vue3';
|
|
4
5
|
import useRoomEngine from '../../../hooks/useRoomEngine';
|
|
5
|
-
import { useLiveSeatState } from '../../../states/LiveSeatState';
|
|
6
6
|
import { useLiveListState } from '../../../states/LiveListState';
|
|
7
|
+
import { useLiveSeatState } from '../../../states/LiveSeatState';
|
|
7
8
|
import {
|
|
8
9
|
getDeviceType,
|
|
9
10
|
shouldRotateToLandscapeForFullscreen,
|
|
10
11
|
hadLandscapeRotationToUndo,
|
|
12
|
+
isSafariBrowser,
|
|
11
13
|
} from './utils/deviceDetection';
|
|
12
14
|
import {
|
|
13
15
|
DOMElementGetter,
|
|
14
16
|
EventListenerManager,
|
|
17
|
+
waitForVideoMounted,
|
|
15
18
|
} from './utils/domHelpers';
|
|
16
19
|
import {
|
|
17
20
|
FullscreenManager,
|
|
@@ -20,7 +23,7 @@ import {
|
|
|
20
23
|
StyleManager,
|
|
21
24
|
} from './utils/fullscreenManager';
|
|
22
25
|
import type {
|
|
23
|
-
FullscreenResult
|
|
26
|
+
FullscreenResult,
|
|
24
27
|
} from './utils/fullscreenManager';
|
|
25
28
|
|
|
26
29
|
// Player fill mode enum
|
|
@@ -48,6 +51,8 @@ export interface PlayerControlState {
|
|
|
48
51
|
isPictureInPicture: Ref<boolean>;
|
|
49
52
|
currentVolume: Ref<number>;
|
|
50
53
|
isMuted: Ref<boolean>;
|
|
54
|
+
isSafari: Ref<boolean>;
|
|
55
|
+
isTcPlayer: Ref<boolean>;
|
|
51
56
|
|
|
52
57
|
// Resolution state properties
|
|
53
58
|
resolutionList: Ref<Resolution[]>;
|
|
@@ -88,25 +93,21 @@ const VOLUME_CONSTANTS = {
|
|
|
88
93
|
MUTE_VOLUME: 0,
|
|
89
94
|
};
|
|
90
95
|
|
|
91
|
-
const TIMING_CONSTANTS = {
|
|
92
|
-
// Delay in milliseconds before resuming playback after leaving picture-in-picture
|
|
93
|
-
// Allows browser to handle state transitions naturally
|
|
94
|
-
PIP_RESUME_DELAY: 300,
|
|
95
|
-
};
|
|
96
|
-
|
|
97
96
|
const ARRAY_CONSTANTS = {
|
|
98
97
|
// Index of the first element in an array
|
|
99
98
|
FIRST_INDEX: 0,
|
|
100
99
|
};
|
|
101
100
|
|
|
102
101
|
// State management
|
|
103
|
-
const isPlaying = ref(
|
|
102
|
+
const isPlaying = ref(false);
|
|
104
103
|
const currentFillMode = ref<FillMode>(FillMode.CONTAIN);
|
|
105
104
|
const isFullscreen = ref(false);
|
|
106
105
|
const isLandscapeStyleMode = ref(false);
|
|
107
106
|
const isPictureInPicture = ref(false);
|
|
108
107
|
const currentVolume = ref(VOLUME_CONSTANTS.DEFAULT_VOLUME);
|
|
109
108
|
const isMuted = ref(false); // Mute state - synced across all rooms
|
|
109
|
+
const isSafari = ref(isSafariBrowser());
|
|
110
|
+
const isTcPlayer = ref(false);
|
|
110
111
|
|
|
111
112
|
// Internal storage for volume restoration (not reactive)
|
|
112
113
|
let restoreVolume = VOLUME_CONSTANTS.DEFAULT_VOLUME;
|
|
@@ -116,6 +117,7 @@ const resolutionList = ref<Resolution[]>([]);
|
|
|
116
117
|
const currentResolution = ref<Resolution | undefined>();
|
|
117
118
|
|
|
118
119
|
const roomEngine = useRoomEngine();
|
|
120
|
+
const { t } = useUIKit();
|
|
119
121
|
|
|
120
122
|
/**
|
|
121
123
|
* Player control state management hook
|
|
@@ -159,12 +161,31 @@ export function usePlayerControlState(): PlayerControlState {
|
|
|
159
161
|
};
|
|
160
162
|
|
|
161
163
|
const resume = async (): Promise<boolean> => withErrorHandling(async () => {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
164
|
+
try {
|
|
165
|
+
await roomEngine.instance?.callExperimentalAPI(JSON.stringify({
|
|
166
|
+
api: 'resume',
|
|
167
|
+
params: {},
|
|
168
|
+
}));
|
|
169
|
+
isPlaying.value = true;
|
|
170
|
+
return true;
|
|
171
|
+
} catch (error: any) {
|
|
172
|
+
// Handle browser autoplay policy restriction
|
|
173
|
+
if (error?.name === 'NotAllowedError' && (error?.message?.includes('user agent') || error?.message?.includes('denied permission'))) {
|
|
174
|
+
TUIMessageBox.alert({
|
|
175
|
+
content: t('Content is ready. Click the button to start playback'),
|
|
176
|
+
confirmText: t('Play'),
|
|
177
|
+
callback: async () => {
|
|
178
|
+
await roomEngine.instance?.callExperimentalAPI(JSON.stringify({
|
|
179
|
+
api: 'resume',
|
|
180
|
+
params: {},
|
|
181
|
+
}));
|
|
182
|
+
isPlaying.value = true;
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
throw error;
|
|
188
|
+
}
|
|
168
189
|
}, 'Resume playback', false);
|
|
169
190
|
|
|
170
191
|
const pause = async (): Promise<boolean> => withErrorHandling(async () => {
|
|
@@ -443,7 +464,6 @@ export function usePlayerControlState(): PlayerControlState {
|
|
|
443
464
|
|
|
444
465
|
const handleLeavePictureInPicture = () => {
|
|
445
466
|
isPictureInPicture.value = false;
|
|
446
|
-
setTimeout(resume, TIMING_CONSTANTS.PIP_RESUME_DELAY);
|
|
447
467
|
};
|
|
448
468
|
|
|
449
469
|
eventManager.addListener('enterpictureinpicture', video, 'enterpictureinpicture', handleEnterPictureInPicture);
|
|
@@ -462,19 +482,34 @@ export function usePlayerControlState(): PlayerControlState {
|
|
|
462
482
|
setupVideoEventListeners();
|
|
463
483
|
OrientationManager.addOrientationListener(orientationListenerId, handleOrientationChange);
|
|
464
484
|
|
|
485
|
+
const updateIsTcPlayer = async () => {
|
|
486
|
+
try {
|
|
487
|
+
await waitForVideoMounted();
|
|
488
|
+
} finally {
|
|
489
|
+
const hasTcPlayer = DOMElementGetter.hasTcPlayerElement();
|
|
490
|
+
if (hasTcPlayer !== isTcPlayer.value) {
|
|
491
|
+
isTcPlayer.value = hasTcPlayer;
|
|
492
|
+
console.log('[PlayerControl] isTcPlayer:', isTcPlayer.value);
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
};
|
|
496
|
+
|
|
465
497
|
watch(
|
|
466
498
|
() => currentLive.value?.liveId,
|
|
467
499
|
async (newLiveId) => {
|
|
468
500
|
if (newLiveId) {
|
|
469
501
|
isPlaying.value = true;
|
|
502
|
+
isPictureInPicture.value = false;
|
|
503
|
+
isFullscreen.value = false;
|
|
470
504
|
resolutionList.value = [];
|
|
471
505
|
currentResolution.value = undefined;
|
|
472
506
|
// When pulling a TRTC stream, this interface has a cache, but when using TCPlayer, there is no cache
|
|
473
507
|
await setVolume(currentVolume.value);
|
|
474
508
|
await initializeResolution(newLiveId, false);
|
|
509
|
+
updateIsTcPlayer();
|
|
475
510
|
|
|
476
511
|
// Print player control state after entering room
|
|
477
|
-
console.log('[PlayerControl] State after entering room:', {
|
|
512
|
+
console.log('[PlayerControl] State after entering room:', JSON.stringify({
|
|
478
513
|
isPlaying: isPlaying.value,
|
|
479
514
|
currentFillMode: currentFillMode.value,
|
|
480
515
|
isFullscreen: isFullscreen.value,
|
|
@@ -483,11 +518,17 @@ export function usePlayerControlState(): PlayerControlState {
|
|
|
483
518
|
currentVolume: currentVolume.value,
|
|
484
519
|
resolutionList: resolutionList.value,
|
|
485
520
|
currentResolution: currentResolution.value,
|
|
486
|
-
});
|
|
521
|
+
}));
|
|
487
522
|
}
|
|
488
523
|
},
|
|
489
524
|
);
|
|
490
525
|
|
|
526
|
+
watch(() => isPlaying.value, (newIsPlaying) => {
|
|
527
|
+
if (newIsPlaying) {
|
|
528
|
+
updateIsTcPlayer();
|
|
529
|
+
}
|
|
530
|
+
}, { immediate: true });
|
|
531
|
+
|
|
491
532
|
// Return interface implementation
|
|
492
533
|
return {
|
|
493
534
|
isPlaying,
|
|
@@ -499,6 +540,8 @@ export function usePlayerControlState(): PlayerControlState {
|
|
|
499
540
|
isMuted,
|
|
500
541
|
resolutionList,
|
|
501
542
|
currentResolution,
|
|
543
|
+
isSafari,
|
|
544
|
+
isTcPlayer,
|
|
502
545
|
resume,
|
|
503
546
|
pause,
|
|
504
547
|
requestFullscreen,
|
|
@@ -73,7 +73,8 @@ export class DOMElementGetter {
|
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
/**
|
|
76
|
-
* Validate if elements exist
|
|
76
|
+
* Validate if required elements exist for fullscreen
|
|
77
|
+
* Note: video element is optional because canvas rendering (TRTC SDK) doesn't use video
|
|
77
78
|
*/
|
|
78
79
|
static validateElements(elements: { container?: HTMLElement | null; view?: HTMLElement | null; video?: HTMLVideoElement | null }): {
|
|
79
80
|
isValid: boolean;
|
|
@@ -87,9 +88,8 @@ export class DOMElementGetter {
|
|
|
87
88
|
if (elements.view === null) {
|
|
88
89
|
missingElements.push('live-core-view');
|
|
89
90
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
}
|
|
91
|
+
// Video element is not required for fullscreen (canvas rendering works without it)
|
|
92
|
+
// Only required for picture-in-picture feature
|
|
93
93
|
|
|
94
94
|
return {
|
|
95
95
|
isValid: missingElements.length === 0,
|
|
@@ -10,6 +10,7 @@ export const resource = {
|
|
|
10
10
|
'Open Speaker': 'Open Speaker',
|
|
11
11
|
'Close Speaker': 'Close Speaker',
|
|
12
12
|
'The system does not support picture-in-picture mode': 'The system does not support picture-in-picture mode',
|
|
13
|
+
'Content is ready. Click the button to start playback': 'Content is ready. Click the button to start playback',
|
|
13
14
|
'co-Hosting': 'co-Hosting',
|
|
14
15
|
'In battle': 'In battle',
|
|
15
16
|
'360P': '360P',
|
|
@@ -17,4 +18,6 @@ export const resource = {
|
|
|
17
18
|
'720P': '720P',
|
|
18
19
|
'1080P': '1080P',
|
|
19
20
|
'Connecting': 'Connecting',
|
|
21
|
+
'Not allow to "Pause" in picture-in-picture mode': 'Not allow to "Pause" in picture-in-picture mode',
|
|
22
|
+
'Not allow to "Picture in Picture" in non-playing mode': 'Not allow to "Picture in Picture" in non-playing mode',
|
|
20
23
|
};
|
|
@@ -10,6 +10,7 @@ export const resource = {
|
|
|
10
10
|
'Open Speaker': '取消静音',
|
|
11
11
|
'Close Speaker': '静音',
|
|
12
12
|
'The system does not support picture-in-picture mode': '系统不支持画中画模式',
|
|
13
|
+
'Content is ready. Click the button to start playback': '画面已准备好,点击播放按钮开始播放',
|
|
13
14
|
'co-Hosting': '连线中',
|
|
14
15
|
'In battle': 'PK中',
|
|
15
16
|
'360P': '低清',
|
|
@@ -17,4 +18,6 @@ export const resource = {
|
|
|
17
18
|
'720P': '高清',
|
|
18
19
|
'1080P': '超清',
|
|
19
20
|
'Connecting': '连线中',
|
|
21
|
+
'Not allow to "Pause" in picture-in-picture mode': '画中画模式下不允许暂停操作',
|
|
22
|
+
'Not allow to "Picture in Picture" in non-playing mode': '暂停状态下不允许进入画中画模式',
|
|
20
23
|
};
|
|
@@ -67,7 +67,7 @@ import type { SeatInfo, SeatUserInfo } from '../../types';
|
|
|
67
67
|
import { isMobile } from '../../utils';
|
|
68
68
|
import { usePlayerControlState } from './PlayerControl';
|
|
69
69
|
|
|
70
|
-
const { isFullscreen, isLandscapeStyleMode } = usePlayerControlState();
|
|
70
|
+
const { isFullscreen, isLandscapeStyleMode, isPictureInPicture, exitPictureInPicture } = usePlayerControlState();
|
|
71
71
|
const { t } = useUIKit();
|
|
72
72
|
const { seatList, canvas, startPlayStream, stopPlayStream } = useLiveSeatState();
|
|
73
73
|
const { currentLive } = useLiveListState();
|
|
@@ -96,6 +96,9 @@ onMounted(async () => {
|
|
|
96
96
|
});
|
|
97
97
|
|
|
98
98
|
onBeforeUnmount(async () => {
|
|
99
|
+
if (isPictureInPicture.value) {
|
|
100
|
+
exitPictureInPicture();
|
|
101
|
+
}
|
|
99
102
|
isMounted.value = false;
|
|
100
103
|
await stopPlayStream();
|
|
101
104
|
isPlayedVideo.value = false;
|
|
@@ -248,8 +251,8 @@ function handleStreamListTransform() {
|
|
|
248
251
|
|
|
249
252
|
const streamViewStyle = computed(() => {
|
|
250
253
|
return {
|
|
251
|
-
width: `${Math.
|
|
252
|
-
height: `${Math.
|
|
254
|
+
width: `${Math.ceil(originStreamViewStyle.value.width) * originStreamViewStyle.value.scale}px`,
|
|
255
|
+
height: `${Math.ceil(originStreamViewStyle.value.height) * originStreamViewStyle.value.scale}px`,
|
|
253
256
|
transform: `translate(${originStreamViewStyle.value.transformX * originStreamViewStyle.value.scale}px, ${
|
|
254
257
|
originStreamViewStyle.value.transformY * originStreamViewStyle.value.scale
|
|
255
258
|
}px)`,
|
|
@@ -419,6 +422,7 @@ onBeforeUnmount(() => {
|
|
|
419
422
|
position: absolute;
|
|
420
423
|
top: 0;
|
|
421
424
|
left: 0;
|
|
425
|
+
overflow: hidden;
|
|
422
426
|
}
|
|
423
427
|
|
|
424
428
|
.live-core-ui {
|