tuikit-atomicx-vue3 3.3.1 → 3.3.2-beta.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/dist/components/ChatSetting/GroupChatSetting/GroupActions/GroupActions.js +1 -4
- package/dist/components/ChatSetting/GroupChatSetting/GroupChatSetting.js +1 -2
- package/dist/components/ChatSetting/GroupChatSetting/GroupManagement/GroupManagement.js +1 -2
- package/dist/components/ContactList/ContactInfo/GroupInfo/GroupInfo.js +1 -2
- package/dist/components/ConversationList/ConversationCreate/ConversationCreate.js +1 -2
- package/dist/components/ConversationList/ConversationSearch/ConversationSearch.js +0 -1
- package/dist/components/LiveCoreView/PlayerControl/AudioControl.js +251 -0
- package/dist/components/LiveCoreView/PlayerControl/AudioControl.vue.d.ts +38 -0
- package/dist/components/LiveCoreView/PlayerControl/PlayerControl.js +271 -0
- package/dist/components/LiveCoreView/PlayerControl/PlayerControl.vue.d.ts +2 -0
- package/dist/components/LiveCoreView/PlayerControl/PlayerControlState.d.ts +27 -0
- package/dist/components/LiveCoreView/PlayerControl/PlayerControlState.js +407 -0
- package/dist/components/LiveCoreView/PlayerControl/index.d.ts +3 -0
- package/dist/components/LiveCoreView/PlayerControl/index.js +8 -0
- package/dist/components/LiveCoreView/PlayerControl/utils/deviceDetection.d.ts +85 -0
- package/dist/components/LiveCoreView/PlayerControl/utils/deviceDetection.js +129 -0
- package/dist/components/LiveCoreView/PlayerControl/utils/domHelpers.d.ts +75 -0
- package/dist/components/LiveCoreView/PlayerControl/utils/domHelpers.js +120 -0
- package/dist/components/LiveCoreView/PlayerControl/utils/fullscreenManager.d.ts +120 -0
- package/dist/components/LiveCoreView/PlayerControl/utils/fullscreenManager.js +311 -0
- package/dist/components/LiveCoreView/i18n/en-US/index.d.ts +9 -0
- package/dist/components/LiveCoreView/i18n/en-US/index.js +10 -1
- package/dist/components/LiveCoreView/i18n/zh-CN/index.d.ts +9 -0
- package/dist/components/LiveCoreView/i18n/zh-CN/index.js +10 -1
- package/dist/components/LiveCoreView/index.js +23 -3
- package/dist/styles/index.css +302 -30
- package/package.json +2 -2
- package/src/components/ChatSetting/GroupChatSetting/GroupActions/GroupActions.vue +0 -3
- package/src/components/ChatSetting/GroupChatSetting/GroupChatSetting.vue +0 -1
- package/src/components/ChatSetting/GroupChatSetting/GroupManagement/GroupManagement.vue +0 -1
- package/src/components/ContactList/ContactInfo/GroupInfo/GroupInfo.vue +0 -1
- package/src/components/ConversationList/ConversationCreate/ConversationCreate.vue +0 -1
- package/src/components/ConversationList/ConversationSearch/ConversationSearch.vue +0 -1
- package/src/components/LiveCoreView/PlayerControl/AudioControl.vue +456 -0
- package/src/components/LiveCoreView/PlayerControl/PlayerControl.module.scss +52 -0
- package/src/components/LiveCoreView/PlayerControl/PlayerControl.vue +429 -0
- package/src/components/LiveCoreView/PlayerControl/PlayerControlState.ts +599 -0
- package/src/components/LiveCoreView/PlayerControl/index.ts +3 -0
- package/src/components/LiveCoreView/PlayerControl/utils/deviceDetection.ts +234 -0
- package/src/components/LiveCoreView/PlayerControl/utils/domHelpers.ts +145 -0
- package/src/components/LiveCoreView/PlayerControl/utils/fullscreenManager.ts +417 -0
- package/src/components/LiveCoreView/i18n/en-US/index.ts +9 -0
- package/src/components/LiveCoreView/i18n/zh-CN/index.ts +9 -0
- package/src/components/LiveCoreView/index.vue +13 -2
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fullscreen management utility module
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { DeviceType } from './deviceDetection';
|
|
6
|
+
|
|
7
|
+
// Screen orientation type
|
|
8
|
+
export type ScreenOrientation = 'landscape' | 'portrait';
|
|
9
|
+
|
|
10
|
+
// Fullscreen mode type
|
|
11
|
+
export enum FullscreenMode {
|
|
12
|
+
STANDARD = 'standard', // Standard API fullscreen
|
|
13
|
+
CSS_SIMULATED = 'simulated' // CSS simulated fullscreen
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// CSS class name constants
|
|
17
|
+
export const CSS_CLASSES = {
|
|
18
|
+
FULLSCREEN: 'fullscreen-mode',
|
|
19
|
+
FULLSCREEN_PORTRAIT: 'fullscreen-mode-portrait',
|
|
20
|
+
LANDSCAPE: 'landscape-mode',
|
|
21
|
+
} as const;
|
|
22
|
+
|
|
23
|
+
// Fullscreen operation result
|
|
24
|
+
export interface FullscreenResult {
|
|
25
|
+
success: boolean;
|
|
26
|
+
mode: FullscreenMode;
|
|
27
|
+
shouldRotateToLandscape: boolean;
|
|
28
|
+
error?: Error;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Style management class
|
|
33
|
+
*/
|
|
34
|
+
export class StyleManager {
|
|
35
|
+
/**
|
|
36
|
+
* Apply fullscreen styles
|
|
37
|
+
*/
|
|
38
|
+
static applyFullscreenStyles(element: HTMLElement, isPortrait = false): void {
|
|
39
|
+
const className = isPortrait ? CSS_CLASSES.FULLSCREEN_PORTRAIT : CSS_CLASSES.FULLSCREEN;
|
|
40
|
+
element.classList.add(className);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Remove fullscreen styles
|
|
45
|
+
*/
|
|
46
|
+
static removeFullscreenStyles(element: HTMLElement): void {
|
|
47
|
+
element.classList.remove(CSS_CLASSES.FULLSCREEN);
|
|
48
|
+
element.classList.remove(CSS_CLASSES.FULLSCREEN_PORTRAIT);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Apply landscape styles
|
|
53
|
+
*/
|
|
54
|
+
static applyLandscapeStyles(element: HTMLElement): void {
|
|
55
|
+
element.classList.add(CSS_CLASSES.LANDSCAPE);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Remove landscape styles
|
|
60
|
+
*/
|
|
61
|
+
static removeLandscapeStyles(element: HTMLElement): void {
|
|
62
|
+
element.classList.remove(CSS_CLASSES.LANDSCAPE);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Smart landscape style adjustment - determine if CSS rotation is needed based on current device orientation
|
|
67
|
+
*/
|
|
68
|
+
static smartApplyLandscapeStyles(element: HTMLElement, currentOrientation: 'portrait' | 'landscape' | 'unknown'): void {
|
|
69
|
+
// If device is already in landscape orientation, no need to apply CSS rotation
|
|
70
|
+
if (currentOrientation === 'landscape') {
|
|
71
|
+
this.removeLandscapeStyles(element);
|
|
72
|
+
} else {
|
|
73
|
+
// When device is in portrait, need CSS rotation to display landscape content
|
|
74
|
+
this.applyLandscapeStyles(element);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Screen orientation management class
|
|
81
|
+
*/
|
|
82
|
+
export class OrientationManager {
|
|
83
|
+
private static orientationListeners: Map<string, (orientation: 'portrait' | 'landscape' | 'unknown') => void> = new Map();
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Request screen orientation
|
|
87
|
+
*/
|
|
88
|
+
static async requestOrientation(orientation: ScreenOrientation): Promise<boolean> {
|
|
89
|
+
try {
|
|
90
|
+
// Prioritize Screen Orientation API
|
|
91
|
+
if (screen.orientation && (screen.orientation as any).lock) {
|
|
92
|
+
await (screen.orientation as any).lock(orientation);
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Use webkit prefixed API as fallback
|
|
97
|
+
if ((screen.orientation as any).webkitLockOrientation) {
|
|
98
|
+
const result = (screen.orientation as any).webkitLockOrientation(orientation);
|
|
99
|
+
return !!result;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return false;
|
|
103
|
+
} catch (error) {
|
|
104
|
+
console.warn(`Screen orientation setting failed (${orientation}):`, error);
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Unlock screen orientation
|
|
111
|
+
*/
|
|
112
|
+
static async unlockOrientation(): Promise<boolean> {
|
|
113
|
+
try {
|
|
114
|
+
if (screen.orientation && (screen.orientation as any).unlock) {
|
|
115
|
+
(screen.orientation as any).unlock();
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
} catch (error) {
|
|
120
|
+
console.warn('Failed to unlock screen orientation:', error);
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Get current orientation
|
|
127
|
+
*/
|
|
128
|
+
static getCurrentOrientation(): 'portrait' | 'landscape' | 'unknown' {
|
|
129
|
+
// First try the standard Screen Orientation API
|
|
130
|
+
if (screen.orientation) {
|
|
131
|
+
const angle = screen.orientation.angle;
|
|
132
|
+
const type = screen.orientation.type;
|
|
133
|
+
|
|
134
|
+
// Check orientation type first (more reliable)
|
|
135
|
+
if (type.includes('portrait')) {
|
|
136
|
+
return 'portrait';
|
|
137
|
+
} else if (type.includes('landscape')) {
|
|
138
|
+
return 'landscape';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Fallback to angle-based detection
|
|
142
|
+
if (angle === 0 || angle === 180) {
|
|
143
|
+
return 'portrait';
|
|
144
|
+
} else if (angle === 90 || angle === 270) {
|
|
145
|
+
return 'landscape';
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Fallback to window dimensions
|
|
150
|
+
if (window.innerHeight > window.innerWidth) {
|
|
151
|
+
return 'portrait';
|
|
152
|
+
} else if (window.innerWidth > window.innerHeight) {
|
|
153
|
+
return 'landscape';
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return 'unknown';
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Add orientation change listener
|
|
161
|
+
*/
|
|
162
|
+
static addOrientationListener(id: string, callback: (orientation: 'portrait' | 'landscape' | 'unknown') => void): void {
|
|
163
|
+
this.orientationListeners.set(id, callback);
|
|
164
|
+
|
|
165
|
+
// If this is the first listener, set up global listening
|
|
166
|
+
if (this.orientationListeners.size === 1) {
|
|
167
|
+
this.setupGlobalOrientationListener();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Remove orientation change listener
|
|
173
|
+
*/
|
|
174
|
+
static removeOrientationListener(id: string): void {
|
|
175
|
+
this.orientationListeners.delete(id);
|
|
176
|
+
|
|
177
|
+
// If no more listeners, clean up global listening
|
|
178
|
+
if (this.orientationListeners.size === 0) {
|
|
179
|
+
this.cleanupGlobalOrientationListener();
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Setup global orientation listening
|
|
185
|
+
*/
|
|
186
|
+
private static setupGlobalOrientationListener(): void {
|
|
187
|
+
const handleOrientationChange = () => {
|
|
188
|
+
const currentOrientation = this.getCurrentOrientation();
|
|
189
|
+
console.log('Orientation change detected:', currentOrientation);
|
|
190
|
+
|
|
191
|
+
// Notify all listeners
|
|
192
|
+
this.orientationListeners.forEach((callback) => {
|
|
193
|
+
try {
|
|
194
|
+
callback(currentOrientation);
|
|
195
|
+
} catch (error) {
|
|
196
|
+
console.error('Orientation change callback execution failed:', error);
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
// Listen to multiple orientation change events
|
|
202
|
+
window.addEventListener('orientationchange', handleOrientationChange);
|
|
203
|
+
window.addEventListener('resize', handleOrientationChange);
|
|
204
|
+
|
|
205
|
+
// Also listen to Screen Orientation API if supported
|
|
206
|
+
if (screen.orientation) {
|
|
207
|
+
screen.orientation.addEventListener('change', handleOrientationChange);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Save cleanup function reference
|
|
211
|
+
(this as any)._cleanupOrientationListeners = () => {
|
|
212
|
+
window.removeEventListener('orientationchange', handleOrientationChange);
|
|
213
|
+
window.removeEventListener('resize', handleOrientationChange);
|
|
214
|
+
if (screen.orientation) {
|
|
215
|
+
screen.orientation.removeEventListener('change', handleOrientationChange);
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/**
|
|
221
|
+
* Cleanup global orientation listening
|
|
222
|
+
*/
|
|
223
|
+
private static cleanupGlobalOrientationListener(): void {
|
|
224
|
+
if ((this as any)._cleanupOrientationListeners) {
|
|
225
|
+
(this as any)._cleanupOrientationListeners();
|
|
226
|
+
delete (this as any)._cleanupOrientationListeners;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Fullscreen API management class
|
|
233
|
+
*/
|
|
234
|
+
export class FullscreenAPI {
|
|
235
|
+
/**
|
|
236
|
+
* Request standard fullscreen
|
|
237
|
+
*/
|
|
238
|
+
static async requestFullscreen(element: HTMLElement): Promise<boolean> {
|
|
239
|
+
try {
|
|
240
|
+
if (element.requestFullscreen) {
|
|
241
|
+
await element.requestFullscreen();
|
|
242
|
+
} else if ((element as any).webkitRequestFullscreen) {
|
|
243
|
+
await (element as any).webkitRequestFullscreen();
|
|
244
|
+
} else if ((element as any).mozRequestFullScreen) {
|
|
245
|
+
await (element as any).mozRequestFullScreen();
|
|
246
|
+
} else if ((element as any).msRequestFullscreen) {
|
|
247
|
+
await (element as any).msRequestFullscreen();
|
|
248
|
+
} else {
|
|
249
|
+
return false;
|
|
250
|
+
}
|
|
251
|
+
return true;
|
|
252
|
+
} catch (error) {
|
|
253
|
+
console.error('Standard fullscreen request failed:', error);
|
|
254
|
+
return false;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* Exit standard fullscreen
|
|
260
|
+
*/
|
|
261
|
+
static async exitFullscreen(): Promise<boolean> {
|
|
262
|
+
try {
|
|
263
|
+
if (document.exitFullscreen) {
|
|
264
|
+
await document.exitFullscreen();
|
|
265
|
+
} else if ((document as any).webkitExitFullscreen) {
|
|
266
|
+
await (document as any).webkitExitFullscreen();
|
|
267
|
+
} else if ((document as any).mozCancelFullScreen) {
|
|
268
|
+
await (document as any).mozCancelFullScreen();
|
|
269
|
+
} else if ((document as any).msExitFullscreen) {
|
|
270
|
+
await (document as any).msExitFullscreen();
|
|
271
|
+
} else {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
return true;
|
|
275
|
+
} catch (error) {
|
|
276
|
+
console.error('Exit standard fullscreen failed:', error);
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Check if currently in fullscreen state
|
|
283
|
+
*/
|
|
284
|
+
static isCurrentlyFullscreen(): boolean {
|
|
285
|
+
return !!document.fullscreenElement;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Main fullscreen manager class
|
|
291
|
+
*/
|
|
292
|
+
export class FullscreenManager {
|
|
293
|
+
/**
|
|
294
|
+
* Smart fullscreen request
|
|
295
|
+
* Choose the best fullscreen method based on device type and support
|
|
296
|
+
*/
|
|
297
|
+
static async requestFullscreen(
|
|
298
|
+
containerElement: HTMLElement,
|
|
299
|
+
viewElement: HTMLElement,
|
|
300
|
+
deviceType: DeviceType,
|
|
301
|
+
isPortraitStream: boolean,
|
|
302
|
+
shouldRotateToLandscape: boolean
|
|
303
|
+
): Promise<FullscreenResult> {
|
|
304
|
+
// iOS devices or devices that don't support standard fullscreen use CSS simulation
|
|
305
|
+
if (!this.isFullscreenSupported(containerElement)) {
|
|
306
|
+
return this.requestCSSFullscreen(viewElement, isPortraitStream, shouldRotateToLandscape);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// Other devices try standard fullscreen
|
|
310
|
+
return this.requestStandardFullscreen(containerElement, viewElement, shouldRotateToLandscape);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* Smart fullscreen exit
|
|
315
|
+
*/
|
|
316
|
+
static async exitFullscreen(
|
|
317
|
+
viewElement: HTMLElement,
|
|
318
|
+
deviceType: DeviceType,
|
|
319
|
+
hadLandscapeRotation: boolean
|
|
320
|
+
): Promise<FullscreenResult> {
|
|
321
|
+
// Remove CSS styles
|
|
322
|
+
StyleManager.removeFullscreenStyles(viewElement);
|
|
323
|
+
StyleManager.removeLandscapeStyles(viewElement);
|
|
324
|
+
|
|
325
|
+
// Other devices try to exit standard fullscreen
|
|
326
|
+
const success = await FullscreenAPI.exitFullscreen();
|
|
327
|
+
if (hadLandscapeRotation) {
|
|
328
|
+
await OrientationManager.unlockOrientation();
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
return {
|
|
332
|
+
success,
|
|
333
|
+
mode: success ? FullscreenMode.STANDARD : FullscreenMode.CSS_SIMULATED,
|
|
334
|
+
shouldRotateToLandscape: hadLandscapeRotation
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* CSS simulated fullscreen
|
|
340
|
+
*/
|
|
341
|
+
private static async requestCSSFullscreen(
|
|
342
|
+
element: HTMLElement,
|
|
343
|
+
isPortraitStream: boolean,
|
|
344
|
+
shouldRotateToLandscape: boolean
|
|
345
|
+
): Promise<FullscreenResult> {
|
|
346
|
+
try {
|
|
347
|
+
// Apply fullscreen styles
|
|
348
|
+
StyleManager.applyFullscreenStyles(element, isPortraitStream);
|
|
349
|
+
|
|
350
|
+
// Handle landscape rotation
|
|
351
|
+
if (shouldRotateToLandscape) {
|
|
352
|
+
const orientationSuccess = await OrientationManager.requestOrientation('landscape');
|
|
353
|
+
if (!orientationSuccess) {
|
|
354
|
+
// Use smart style adjustment based on current device orientation
|
|
355
|
+
const currentOrientation = OrientationManager.getCurrentOrientation();
|
|
356
|
+
StyleManager.smartApplyLandscapeStyles(element, currentOrientation);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
return { success: true, mode: FullscreenMode.CSS_SIMULATED, shouldRotateToLandscape };
|
|
361
|
+
} catch (error) {
|
|
362
|
+
return {
|
|
363
|
+
success: false,
|
|
364
|
+
mode: FullscreenMode.CSS_SIMULATED,
|
|
365
|
+
shouldRotateToLandscape,
|
|
366
|
+
error: error as Error
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Standard API fullscreen
|
|
373
|
+
*/
|
|
374
|
+
private static async requestStandardFullscreen(
|
|
375
|
+
containerElement: HTMLElement,
|
|
376
|
+
viewElement: HTMLElement,
|
|
377
|
+
shouldRotateToLandscape: boolean
|
|
378
|
+
): Promise<FullscreenResult> {
|
|
379
|
+
try {
|
|
380
|
+
const success = await FullscreenAPI.requestFullscreen(containerElement);
|
|
381
|
+
if (!success) {
|
|
382
|
+
return { success: false, mode: FullscreenMode.STANDARD, shouldRotateToLandscape };
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Handle landscape rotation
|
|
386
|
+
if (shouldRotateToLandscape) {
|
|
387
|
+
const orientationSuccess = await OrientationManager.requestOrientation('landscape');
|
|
388
|
+
if (!orientationSuccess) {
|
|
389
|
+
// Use smart style adjustment based on current device orientation
|
|
390
|
+
const currentOrientation = OrientationManager.getCurrentOrientation();
|
|
391
|
+
StyleManager.smartApplyLandscapeStyles(viewElement, currentOrientation);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
return { success: true, mode: FullscreenMode.STANDARD, shouldRotateToLandscape };
|
|
396
|
+
} catch (error) {
|
|
397
|
+
return {
|
|
398
|
+
success: false,
|
|
399
|
+
mode: FullscreenMode.STANDARD,
|
|
400
|
+
shouldRotateToLandscape,
|
|
401
|
+
error: error as Error
|
|
402
|
+
};
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Check if fullscreen is supported
|
|
408
|
+
*/
|
|
409
|
+
private static isFullscreenSupported(element: HTMLElement): boolean {
|
|
410
|
+
return !!(
|
|
411
|
+
element.requestFullscreen ||
|
|
412
|
+
(element as any).webkitRequestFullscreen ||
|
|
413
|
+
(element as any).mozRequestFullScreen ||
|
|
414
|
+
(element as any).msRequestFullscreen
|
|
415
|
+
);
|
|
416
|
+
}
|
|
417
|
+
}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export const resource = {
|
|
2
2
|
'No video': 'No video',
|
|
3
3
|
'Waiting for connection': 'Waiting for connection',
|
|
4
|
+
'Play': 'Play',
|
|
5
|
+
'Pause': 'Pause',
|
|
6
|
+
'Picture in Picture': 'Picture in Picture',
|
|
7
|
+
'Exit Picture in Picture': 'Exit Picture in Picture',
|
|
8
|
+
'Fullscreen': 'Fullscreen',
|
|
9
|
+
'Exit Fullscreen': 'Exit Fullscreen',
|
|
10
|
+
'Mute': 'Mute',
|
|
11
|
+
'Unmute': 'Unmute',
|
|
12
|
+
'The system does not support picture-in-picture mode': 'The system does not support picture-in-picture mode',
|
|
4
13
|
};
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export const resource = {
|
|
2
2
|
'No video': '暂无画面',
|
|
3
3
|
'Waiting for connection': '等待连线',
|
|
4
|
+
'Play': '播放',
|
|
5
|
+
'Pause': '暂停',
|
|
6
|
+
'Picture in Picture': '画中画',
|
|
7
|
+
'Exit Picture in Picture': '退出画中画',
|
|
8
|
+
'Fullscreen': '全屏',
|
|
9
|
+
'Exit Fullscreen': '退出全屏',
|
|
10
|
+
'Mute': '静音',
|
|
11
|
+
'Unmute': '取消静音',
|
|
12
|
+
'The system does not support picture-in-picture mode': '系统不支持画中画模式',
|
|
4
13
|
};
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
ref="liveCoreViewContainerRef"
|
|
4
|
+
id="live-core-view-container"
|
|
4
5
|
class="live-core-view-container"
|
|
5
6
|
:class="{ 'align-center': isAlignCenter }"
|
|
6
7
|
>
|
|
@@ -44,20 +45,27 @@
|
|
|
44
45
|
v-bind="{ style: localStreamViewInfo?.region }"
|
|
45
46
|
/>
|
|
46
47
|
</div>
|
|
48
|
+
<Teleport to="body" v-if="!isFullscreen" :disabled="!isMobile">
|
|
49
|
+
<PlayerControl v-if="isShowPlayerControl" />
|
|
50
|
+
</Teleport>
|
|
51
|
+
<PlayerControl v-if="isShowPlayerControl && isFullscreen" />
|
|
47
52
|
</div>
|
|
48
53
|
</template>
|
|
49
54
|
|
|
50
55
|
<script setup lang="ts">
|
|
51
|
-
import { ref, computed, watch, onMounted, onBeforeUnmount, useSlots } from 'vue';
|
|
52
|
-
import type { ComputedRef } from 'vue';
|
|
56
|
+
import { ref, computed, watch, onMounted, onBeforeUnmount, useSlots, type ComputedRef, Teleport } from 'vue';
|
|
53
57
|
import { useUIKit } from '@tencentcloud/uikit-base-component-vue3';
|
|
54
58
|
import { useLiveSeatState } from '../../states/LiveSeatState';
|
|
55
59
|
import { useLiveState } from '../../states/LiveState';
|
|
56
60
|
import { useLoginState } from '../../states/LoginState';
|
|
57
61
|
import { getContentSize } from '../../utils/domOperation';
|
|
58
62
|
import DefaultStreamViewUI from './DefaultStreamViewUI.vue';
|
|
63
|
+
import PlayerControl from './PlayerControl/PlayerControl.vue';
|
|
59
64
|
import type { SeatInfo, SeatUserInfo } from '../../types';
|
|
65
|
+
import { isMobile } from '../../utils';
|
|
66
|
+
import { usePlayerControlState } from './PlayerControl';
|
|
60
67
|
|
|
68
|
+
const { isFullscreen } = usePlayerControlState();
|
|
61
69
|
const { t } = useUIKit();
|
|
62
70
|
const { seatList, canvas, startPlayStream, stopPlayStream } = useLiveSeatState();
|
|
63
71
|
const { currentLive } = useLiveState();
|
|
@@ -75,6 +83,9 @@ const isAlignCenter = computed(() => {
|
|
|
75
83
|
}
|
|
76
84
|
return true;
|
|
77
85
|
});
|
|
86
|
+
const isShowPlayerControl = computed(() => {
|
|
87
|
+
return currentLive.value?.liveId && !seatList.value.some(item => item.userInfo?.userId === loginUserInfo.value?.userId);
|
|
88
|
+
});
|
|
78
89
|
|
|
79
90
|
onMounted(async () => {
|
|
80
91
|
isMounted.value = true;
|