tuikit-atomicx-vue3 3.3.1 → 3.3.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/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/CoGuestPanel/CoGuestPanel.js +6 -6
- 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 +252 -0
- package/dist/components/LiveCoreView/PlayerControl/AudioControl.vue.d.ts +38 -0
- package/dist/components/LiveCoreView/PlayerControl/PlayerControl.js +279 -0
- package/dist/components/LiveCoreView/PlayerControl/PlayerControl.vue.d.ts +15 -0
- package/dist/components/LiveCoreView/PlayerControl/PlayerControlState.d.ts +29 -0
- package/dist/components/LiveCoreView/PlayerControl/PlayerControlState.js +412 -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 +30 -4
- package/dist/components/StreamView/Layout/CustomLayout.js +2 -2
- package/dist/components/StreamView/Layout/GridLayout.js +2 -2
- package/dist/components/StreamView/common/StreamList/index.js +2 -2
- package/dist/styles/index.css +336 -31
- package/package.json +3 -3
- 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 +434 -0
- package/src/components/LiveCoreView/PlayerControl/PlayerControl.module.scss +52 -0
- package/src/components/LiveCoreView/PlayerControl/PlayerControl.vue +484 -0
- package/src/components/LiveCoreView/PlayerControl/PlayerControlState.ts +602 -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 +14 -3
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DOM operation helper utility module
|
|
3
|
+
*/
|
|
4
|
+
export declare const DOM_SELECTORS: {
|
|
5
|
+
LIVE_CORE_VIEW_CONTAINER: string;
|
|
6
|
+
LIVE_CORE_VIEW: string;
|
|
7
|
+
VIDEO_ELEMENT: string;
|
|
8
|
+
TCPLAYER_ELEMENT: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* DOM element getter
|
|
12
|
+
*/
|
|
13
|
+
export declare class DOMElementGetter {
|
|
14
|
+
/**
|
|
15
|
+
* Get live-core-view-container element
|
|
16
|
+
*/
|
|
17
|
+
static getLiveCoreViewContainer(): HTMLElement | null;
|
|
18
|
+
/**
|
|
19
|
+
* Get live-core-view element
|
|
20
|
+
*/
|
|
21
|
+
static getLiveCoreView(): HTMLElement | null;
|
|
22
|
+
/**
|
|
23
|
+
* Get video element
|
|
24
|
+
*/
|
|
25
|
+
static getVideoElement(): HTMLVideoElement | null;
|
|
26
|
+
/**
|
|
27
|
+
* Get all required DOM elements
|
|
28
|
+
*/
|
|
29
|
+
static getAllElements(): {
|
|
30
|
+
container: HTMLElement | null;
|
|
31
|
+
view: HTMLElement | null;
|
|
32
|
+
video: HTMLVideoElement | null;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Check if tcplayer element exists in live-core-view-container
|
|
36
|
+
*/
|
|
37
|
+
static hasTcPlayerElement(): boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Get tcplayer element from live-core-view-container
|
|
40
|
+
*/
|
|
41
|
+
static getTcPlayerElement(): HTMLElement | null;
|
|
42
|
+
/**
|
|
43
|
+
* Validate if elements exist
|
|
44
|
+
*/
|
|
45
|
+
static validateElements(elements: {
|
|
46
|
+
container?: HTMLElement | null;
|
|
47
|
+
view?: HTMLElement | null;
|
|
48
|
+
video?: HTMLVideoElement | null;
|
|
49
|
+
}): {
|
|
50
|
+
isValid: boolean;
|
|
51
|
+
missingElements: string[];
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Event listener manager
|
|
56
|
+
*/
|
|
57
|
+
export declare class EventListenerManager {
|
|
58
|
+
private listeners;
|
|
59
|
+
/**
|
|
60
|
+
* Add event listener
|
|
61
|
+
*/
|
|
62
|
+
addListener(id: string, element: EventTarget, event: string, handler: EventListener): void;
|
|
63
|
+
/**
|
|
64
|
+
* Remove specified event listener
|
|
65
|
+
*/
|
|
66
|
+
removeListener(id: string): void;
|
|
67
|
+
/**
|
|
68
|
+
* Remove all event listeners
|
|
69
|
+
*/
|
|
70
|
+
removeAllListeners(): void;
|
|
71
|
+
/**
|
|
72
|
+
* Get current listener count
|
|
73
|
+
*/
|
|
74
|
+
getListenerCount(): number;
|
|
75
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
const DOM_SELECTORS = {
|
|
5
|
+
LIVE_CORE_VIEW_CONTAINER: ".live-core-view-container",
|
|
6
|
+
LIVE_CORE_VIEW: ".live-core-view",
|
|
7
|
+
VIDEO_ELEMENT: "#atomicx-live-stream-content video",
|
|
8
|
+
TCPLAYER_ELEMENT: ".tcplayer"
|
|
9
|
+
};
|
|
10
|
+
class DOMElementGetter {
|
|
11
|
+
/**
|
|
12
|
+
* Get live-core-view-container element
|
|
13
|
+
*/
|
|
14
|
+
static getLiveCoreViewContainer() {
|
|
15
|
+
return document.querySelector(DOM_SELECTORS.LIVE_CORE_VIEW_CONTAINER);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get live-core-view element
|
|
19
|
+
*/
|
|
20
|
+
static getLiveCoreView() {
|
|
21
|
+
return document.querySelector(DOM_SELECTORS.LIVE_CORE_VIEW);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get video element
|
|
25
|
+
*/
|
|
26
|
+
static getVideoElement() {
|
|
27
|
+
return document.querySelector(DOM_SELECTORS.VIDEO_ELEMENT);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Get all required DOM elements
|
|
31
|
+
*/
|
|
32
|
+
static getAllElements() {
|
|
33
|
+
return {
|
|
34
|
+
container: DOMElementGetter.getLiveCoreViewContainer(),
|
|
35
|
+
view: DOMElementGetter.getLiveCoreView(),
|
|
36
|
+
video: DOMElementGetter.getVideoElement()
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if tcplayer element exists in live-core-view-container
|
|
41
|
+
*/
|
|
42
|
+
static hasTcPlayerElement() {
|
|
43
|
+
const container = DOMElementGetter.getLiveCoreViewContainer();
|
|
44
|
+
if (!container) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return container.querySelector(DOM_SELECTORS.TCPLAYER_ELEMENT) !== null;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get tcplayer element from live-core-view-container
|
|
51
|
+
*/
|
|
52
|
+
static getTcPlayerElement() {
|
|
53
|
+
const container = DOMElementGetter.getLiveCoreViewContainer();
|
|
54
|
+
if (!container) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
return container.querySelector(DOM_SELECTORS.TCPLAYER_ELEMENT);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Validate if elements exist
|
|
61
|
+
*/
|
|
62
|
+
static validateElements(elements) {
|
|
63
|
+
const missingElements = [];
|
|
64
|
+
if (elements.container === null) {
|
|
65
|
+
missingElements.push("live-core-view-container");
|
|
66
|
+
}
|
|
67
|
+
if (elements.view === null) {
|
|
68
|
+
missingElements.push("live-core-view");
|
|
69
|
+
}
|
|
70
|
+
if (elements.video === null) {
|
|
71
|
+
missingElements.push("video");
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
isValid: missingElements.length === 0,
|
|
75
|
+
missingElements
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
class EventListenerManager {
|
|
80
|
+
constructor() {
|
|
81
|
+
__publicField(this, "listeners", /* @__PURE__ */ new Map());
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Add event listener
|
|
85
|
+
*/
|
|
86
|
+
addListener(id, element, event, handler) {
|
|
87
|
+
this.removeListener(id);
|
|
88
|
+
element.addEventListener(event, handler);
|
|
89
|
+
this.listeners.set(id, { element, event, handler });
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Remove specified event listener
|
|
93
|
+
*/
|
|
94
|
+
removeListener(id) {
|
|
95
|
+
const listener = this.listeners.get(id);
|
|
96
|
+
if (listener) {
|
|
97
|
+
listener.element.removeEventListener(listener.event, listener.handler);
|
|
98
|
+
this.listeners.delete(id);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Remove all event listeners
|
|
103
|
+
*/
|
|
104
|
+
removeAllListeners() {
|
|
105
|
+
for (const [id] of this.listeners) {
|
|
106
|
+
this.removeListener(id);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get current listener count
|
|
111
|
+
*/
|
|
112
|
+
getListenerCount() {
|
|
113
|
+
return this.listeners.size;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export {
|
|
117
|
+
DOMElementGetter,
|
|
118
|
+
DOM_SELECTORS,
|
|
119
|
+
EventListenerManager
|
|
120
|
+
};
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { DeviceType } from './deviceDetection';
|
|
2
|
+
|
|
3
|
+
export type ScreenOrientation = 'landscape' | 'portrait';
|
|
4
|
+
export declare enum FullscreenMode {
|
|
5
|
+
STANDARD = "standard",// Standard API fullscreen
|
|
6
|
+
CSS_SIMULATED = "simulated"
|
|
7
|
+
}
|
|
8
|
+
export declare const CSS_CLASSES: {
|
|
9
|
+
readonly FULLSCREEN: "fullscreen-mode";
|
|
10
|
+
readonly FULLSCREEN_PORTRAIT: "fullscreen-mode-portrait";
|
|
11
|
+
readonly LANDSCAPE: "landscape-mode";
|
|
12
|
+
};
|
|
13
|
+
export interface FullscreenResult {
|
|
14
|
+
success: boolean;
|
|
15
|
+
mode: FullscreenMode;
|
|
16
|
+
shouldRotateToLandscape: boolean;
|
|
17
|
+
error?: Error;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Style management class
|
|
21
|
+
*/
|
|
22
|
+
export declare class StyleManager {
|
|
23
|
+
/**
|
|
24
|
+
* Apply fullscreen styles
|
|
25
|
+
*/
|
|
26
|
+
static applyFullscreenStyles(element: HTMLElement, isPortrait?: boolean): void;
|
|
27
|
+
/**
|
|
28
|
+
* Remove fullscreen styles
|
|
29
|
+
*/
|
|
30
|
+
static removeFullscreenStyles(element: HTMLElement): void;
|
|
31
|
+
/**
|
|
32
|
+
* Apply landscape styles
|
|
33
|
+
*/
|
|
34
|
+
static applyLandscapeStyles(element: HTMLElement): void;
|
|
35
|
+
/**
|
|
36
|
+
* Remove landscape styles
|
|
37
|
+
*/
|
|
38
|
+
static removeLandscapeStyles(element: HTMLElement): void;
|
|
39
|
+
/**
|
|
40
|
+
* Smart landscape style adjustment - determine if CSS rotation is needed based on current device orientation
|
|
41
|
+
*/
|
|
42
|
+
static smartApplyLandscapeStyles(element: HTMLElement, currentOrientation: 'portrait' | 'landscape' | 'unknown'): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Screen orientation management class
|
|
46
|
+
*/
|
|
47
|
+
export declare class OrientationManager {
|
|
48
|
+
private static orientationListeners;
|
|
49
|
+
/**
|
|
50
|
+
* Request screen orientation
|
|
51
|
+
*/
|
|
52
|
+
static requestOrientation(orientation: ScreenOrientation): Promise<boolean>;
|
|
53
|
+
/**
|
|
54
|
+
* Unlock screen orientation
|
|
55
|
+
*/
|
|
56
|
+
static unlockOrientation(): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Get current orientation
|
|
59
|
+
*/
|
|
60
|
+
static getCurrentOrientation(): 'portrait' | 'landscape' | 'unknown';
|
|
61
|
+
/**
|
|
62
|
+
* Add orientation change listener
|
|
63
|
+
*/
|
|
64
|
+
static addOrientationListener(id: string, callback: (orientation: 'portrait' | 'landscape' | 'unknown') => void): void;
|
|
65
|
+
/**
|
|
66
|
+
* Remove orientation change listener
|
|
67
|
+
*/
|
|
68
|
+
static removeOrientationListener(id: string): void;
|
|
69
|
+
/**
|
|
70
|
+
* Setup global orientation listening
|
|
71
|
+
*/
|
|
72
|
+
private static setupGlobalOrientationListener;
|
|
73
|
+
/**
|
|
74
|
+
* Cleanup global orientation listening
|
|
75
|
+
*/
|
|
76
|
+
private static cleanupGlobalOrientationListener;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Fullscreen API management class
|
|
80
|
+
*/
|
|
81
|
+
export declare class FullscreenAPI {
|
|
82
|
+
/**
|
|
83
|
+
* Request standard fullscreen
|
|
84
|
+
*/
|
|
85
|
+
static requestFullscreen(element: HTMLElement): Promise<boolean>;
|
|
86
|
+
/**
|
|
87
|
+
* Exit standard fullscreen
|
|
88
|
+
*/
|
|
89
|
+
static exitFullscreen(): Promise<boolean>;
|
|
90
|
+
/**
|
|
91
|
+
* Check if currently in fullscreen state
|
|
92
|
+
*/
|
|
93
|
+
static isCurrentlyFullscreen(): boolean;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Main fullscreen manager class
|
|
97
|
+
*/
|
|
98
|
+
export declare class FullscreenManager {
|
|
99
|
+
/**
|
|
100
|
+
* Smart fullscreen request
|
|
101
|
+
* Choose the best fullscreen method based on device type and support
|
|
102
|
+
*/
|
|
103
|
+
static requestFullscreen(containerElement: HTMLElement, viewElement: HTMLElement, deviceType: DeviceType, isPortraitStream: boolean, shouldRotateToLandscape: boolean): Promise<FullscreenResult>;
|
|
104
|
+
/**
|
|
105
|
+
* Smart fullscreen exit
|
|
106
|
+
*/
|
|
107
|
+
static exitFullscreen(viewElement: HTMLElement, deviceType: DeviceType, hadLandscapeRotation: boolean): Promise<FullscreenResult>;
|
|
108
|
+
/**
|
|
109
|
+
* CSS simulated fullscreen
|
|
110
|
+
*/
|
|
111
|
+
private static requestCSSFullscreen;
|
|
112
|
+
/**
|
|
113
|
+
* Standard API fullscreen
|
|
114
|
+
*/
|
|
115
|
+
private static requestStandardFullscreen;
|
|
116
|
+
/**
|
|
117
|
+
* Check if fullscreen is supported
|
|
118
|
+
*/
|
|
119
|
+
private static isFullscreenSupported;
|
|
120
|
+
}
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
|
+
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
var FullscreenMode = /* @__PURE__ */ ((FullscreenMode2) => {
|
|
5
|
+
FullscreenMode2["STANDARD"] = "standard";
|
|
6
|
+
FullscreenMode2["CSS_SIMULATED"] = "simulated";
|
|
7
|
+
return FullscreenMode2;
|
|
8
|
+
})(FullscreenMode || {});
|
|
9
|
+
const CSS_CLASSES = {
|
|
10
|
+
FULLSCREEN: "fullscreen-mode",
|
|
11
|
+
FULLSCREEN_PORTRAIT: "fullscreen-mode-portrait",
|
|
12
|
+
LANDSCAPE: "landscape-mode"
|
|
13
|
+
};
|
|
14
|
+
class StyleManager {
|
|
15
|
+
/**
|
|
16
|
+
* Apply fullscreen styles
|
|
17
|
+
*/
|
|
18
|
+
static applyFullscreenStyles(element, isPortrait = false) {
|
|
19
|
+
const className = isPortrait ? CSS_CLASSES.FULLSCREEN_PORTRAIT : CSS_CLASSES.FULLSCREEN;
|
|
20
|
+
element.classList.add(className);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Remove fullscreen styles
|
|
24
|
+
*/
|
|
25
|
+
static removeFullscreenStyles(element) {
|
|
26
|
+
element.classList.remove(CSS_CLASSES.FULLSCREEN);
|
|
27
|
+
element.classList.remove(CSS_CLASSES.FULLSCREEN_PORTRAIT);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Apply landscape styles
|
|
31
|
+
*/
|
|
32
|
+
static applyLandscapeStyles(element) {
|
|
33
|
+
element.classList.add(CSS_CLASSES.LANDSCAPE);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Remove landscape styles
|
|
37
|
+
*/
|
|
38
|
+
static removeLandscapeStyles(element) {
|
|
39
|
+
element.classList.remove(CSS_CLASSES.LANDSCAPE);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Smart landscape style adjustment - determine if CSS rotation is needed based on current device orientation
|
|
43
|
+
*/
|
|
44
|
+
static smartApplyLandscapeStyles(element, currentOrientation) {
|
|
45
|
+
if (currentOrientation === "landscape") {
|
|
46
|
+
this.removeLandscapeStyles(element);
|
|
47
|
+
} else {
|
|
48
|
+
this.applyLandscapeStyles(element);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
class OrientationManager {
|
|
53
|
+
/**
|
|
54
|
+
* Request screen orientation
|
|
55
|
+
*/
|
|
56
|
+
static async requestOrientation(orientation) {
|
|
57
|
+
try {
|
|
58
|
+
if (screen.orientation && screen.orientation.lock) {
|
|
59
|
+
await screen.orientation.lock(orientation);
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
if (screen.orientation.webkitLockOrientation) {
|
|
63
|
+
const result = screen.orientation.webkitLockOrientation(orientation);
|
|
64
|
+
return !!result;
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
} catch (error) {
|
|
68
|
+
console.warn(`Screen orientation setting failed (${orientation}):`, error);
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Unlock screen orientation
|
|
74
|
+
*/
|
|
75
|
+
static async unlockOrientation() {
|
|
76
|
+
try {
|
|
77
|
+
if (screen.orientation && screen.orientation.unlock) {
|
|
78
|
+
screen.orientation.unlock();
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
return false;
|
|
82
|
+
} catch (error) {
|
|
83
|
+
console.warn("Failed to unlock screen orientation:", error);
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Get current orientation
|
|
89
|
+
*/
|
|
90
|
+
static getCurrentOrientation() {
|
|
91
|
+
if (screen.orientation) {
|
|
92
|
+
const angle = screen.orientation.angle;
|
|
93
|
+
const type = screen.orientation.type;
|
|
94
|
+
if (type.includes("portrait")) {
|
|
95
|
+
return "portrait";
|
|
96
|
+
} else if (type.includes("landscape")) {
|
|
97
|
+
return "landscape";
|
|
98
|
+
}
|
|
99
|
+
if (angle === 0 || angle === 180) {
|
|
100
|
+
return "portrait";
|
|
101
|
+
} else if (angle === 90 || angle === 270) {
|
|
102
|
+
return "landscape";
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (window.innerHeight > window.innerWidth) {
|
|
106
|
+
return "portrait";
|
|
107
|
+
} else if (window.innerWidth > window.innerHeight) {
|
|
108
|
+
return "landscape";
|
|
109
|
+
}
|
|
110
|
+
return "unknown";
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Add orientation change listener
|
|
114
|
+
*/
|
|
115
|
+
static addOrientationListener(id, callback) {
|
|
116
|
+
this.orientationListeners.set(id, callback);
|
|
117
|
+
if (this.orientationListeners.size === 1) {
|
|
118
|
+
this.setupGlobalOrientationListener();
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Remove orientation change listener
|
|
123
|
+
*/
|
|
124
|
+
static removeOrientationListener(id) {
|
|
125
|
+
this.orientationListeners.delete(id);
|
|
126
|
+
if (this.orientationListeners.size === 0) {
|
|
127
|
+
this.cleanupGlobalOrientationListener();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Setup global orientation listening
|
|
132
|
+
*/
|
|
133
|
+
static setupGlobalOrientationListener() {
|
|
134
|
+
const handleOrientationChange = () => {
|
|
135
|
+
const currentOrientation = this.getCurrentOrientation();
|
|
136
|
+
console.log("Orientation change detected:", currentOrientation);
|
|
137
|
+
this.orientationListeners.forEach((callback) => {
|
|
138
|
+
try {
|
|
139
|
+
callback(currentOrientation);
|
|
140
|
+
} catch (error) {
|
|
141
|
+
console.error("Orientation change callback execution failed:", error);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
};
|
|
145
|
+
window.addEventListener("orientationchange", handleOrientationChange);
|
|
146
|
+
window.addEventListener("resize", handleOrientationChange);
|
|
147
|
+
if (screen.orientation) {
|
|
148
|
+
screen.orientation.addEventListener("change", handleOrientationChange);
|
|
149
|
+
}
|
|
150
|
+
this._cleanupOrientationListeners = () => {
|
|
151
|
+
window.removeEventListener("orientationchange", handleOrientationChange);
|
|
152
|
+
window.removeEventListener("resize", handleOrientationChange);
|
|
153
|
+
if (screen.orientation) {
|
|
154
|
+
screen.orientation.removeEventListener("change", handleOrientationChange);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Cleanup global orientation listening
|
|
160
|
+
*/
|
|
161
|
+
static cleanupGlobalOrientationListener() {
|
|
162
|
+
if (this._cleanupOrientationListeners) {
|
|
163
|
+
this._cleanupOrientationListeners();
|
|
164
|
+
delete this._cleanupOrientationListeners;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
__publicField(OrientationManager, "orientationListeners", /* @__PURE__ */ new Map());
|
|
169
|
+
class FullscreenAPI {
|
|
170
|
+
/**
|
|
171
|
+
* Request standard fullscreen
|
|
172
|
+
*/
|
|
173
|
+
static async requestFullscreen(element) {
|
|
174
|
+
try {
|
|
175
|
+
if (element.requestFullscreen) {
|
|
176
|
+
await element.requestFullscreen();
|
|
177
|
+
} else if (element.webkitRequestFullscreen) {
|
|
178
|
+
await element.webkitRequestFullscreen();
|
|
179
|
+
} else if (element.mozRequestFullScreen) {
|
|
180
|
+
await element.mozRequestFullScreen();
|
|
181
|
+
} else if (element.msRequestFullscreen) {
|
|
182
|
+
await element.msRequestFullscreen();
|
|
183
|
+
} else {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
return true;
|
|
187
|
+
} catch (error) {
|
|
188
|
+
console.error("Standard fullscreen request failed:", error);
|
|
189
|
+
return false;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Exit standard fullscreen
|
|
194
|
+
*/
|
|
195
|
+
static async exitFullscreen() {
|
|
196
|
+
try {
|
|
197
|
+
if (document.exitFullscreen) {
|
|
198
|
+
await document.exitFullscreen();
|
|
199
|
+
} else if (document.webkitExitFullscreen) {
|
|
200
|
+
await document.webkitExitFullscreen();
|
|
201
|
+
} else if (document.mozCancelFullScreen) {
|
|
202
|
+
await document.mozCancelFullScreen();
|
|
203
|
+
} else if (document.msExitFullscreen) {
|
|
204
|
+
await document.msExitFullscreen();
|
|
205
|
+
} else {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
return true;
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error("Exit standard fullscreen failed:", error);
|
|
211
|
+
return false;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Check if currently in fullscreen state
|
|
216
|
+
*/
|
|
217
|
+
static isCurrentlyFullscreen() {
|
|
218
|
+
return !!document.fullscreenElement;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
class FullscreenManager {
|
|
222
|
+
/**
|
|
223
|
+
* Smart fullscreen request
|
|
224
|
+
* Choose the best fullscreen method based on device type and support
|
|
225
|
+
*/
|
|
226
|
+
static async requestFullscreen(containerElement, viewElement, deviceType, isPortraitStream, shouldRotateToLandscape) {
|
|
227
|
+
if (!this.isFullscreenSupported(containerElement)) {
|
|
228
|
+
return this.requestCSSFullscreen(viewElement, isPortraitStream, shouldRotateToLandscape);
|
|
229
|
+
}
|
|
230
|
+
return this.requestStandardFullscreen(containerElement, viewElement, shouldRotateToLandscape);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Smart fullscreen exit
|
|
234
|
+
*/
|
|
235
|
+
static async exitFullscreen(viewElement, deviceType, hadLandscapeRotation) {
|
|
236
|
+
StyleManager.removeFullscreenStyles(viewElement);
|
|
237
|
+
StyleManager.removeLandscapeStyles(viewElement);
|
|
238
|
+
const success = await FullscreenAPI.exitFullscreen();
|
|
239
|
+
if (hadLandscapeRotation) {
|
|
240
|
+
await OrientationManager.unlockOrientation();
|
|
241
|
+
}
|
|
242
|
+
return {
|
|
243
|
+
success,
|
|
244
|
+
mode: success ? "standard" : "simulated",
|
|
245
|
+
shouldRotateToLandscape: hadLandscapeRotation
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* CSS simulated fullscreen
|
|
250
|
+
*/
|
|
251
|
+
static async requestCSSFullscreen(element, isPortraitStream, shouldRotateToLandscape) {
|
|
252
|
+
try {
|
|
253
|
+
StyleManager.applyFullscreenStyles(element, isPortraitStream);
|
|
254
|
+
if (shouldRotateToLandscape) {
|
|
255
|
+
const orientationSuccess = await OrientationManager.requestOrientation("landscape");
|
|
256
|
+
if (!orientationSuccess) {
|
|
257
|
+
const currentOrientation = OrientationManager.getCurrentOrientation();
|
|
258
|
+
StyleManager.smartApplyLandscapeStyles(element, currentOrientation);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return { success: true, mode: "simulated", shouldRotateToLandscape };
|
|
262
|
+
} catch (error) {
|
|
263
|
+
return {
|
|
264
|
+
success: false,
|
|
265
|
+
mode: "simulated",
|
|
266
|
+
shouldRotateToLandscape,
|
|
267
|
+
error
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Standard API fullscreen
|
|
273
|
+
*/
|
|
274
|
+
static async requestStandardFullscreen(containerElement, viewElement, shouldRotateToLandscape) {
|
|
275
|
+
try {
|
|
276
|
+
const success = await FullscreenAPI.requestFullscreen(containerElement);
|
|
277
|
+
if (!success) {
|
|
278
|
+
return { success: false, mode: "standard", shouldRotateToLandscape };
|
|
279
|
+
}
|
|
280
|
+
if (shouldRotateToLandscape) {
|
|
281
|
+
const orientationSuccess = await OrientationManager.requestOrientation("landscape");
|
|
282
|
+
if (!orientationSuccess) {
|
|
283
|
+
const currentOrientation = OrientationManager.getCurrentOrientation();
|
|
284
|
+
StyleManager.smartApplyLandscapeStyles(viewElement, currentOrientation);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
return { success: true, mode: "standard", shouldRotateToLandscape };
|
|
288
|
+
} catch (error) {
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
mode: "standard",
|
|
292
|
+
shouldRotateToLandscape,
|
|
293
|
+
error
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Check if fullscreen is supported
|
|
299
|
+
*/
|
|
300
|
+
static isFullscreenSupported(element) {
|
|
301
|
+
return !!(element.requestFullscreen || element.webkitRequestFullscreen || element.mozRequestFullScreen || element.msRequestFullscreen);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
export {
|
|
305
|
+
CSS_CLASSES,
|
|
306
|
+
FullscreenAPI,
|
|
307
|
+
FullscreenManager,
|
|
308
|
+
FullscreenMode,
|
|
309
|
+
OrientationManager,
|
|
310
|
+
StyleManager
|
|
311
|
+
};
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export declare const resource: {
|
|
2
2
|
'No video': string;
|
|
3
3
|
'Waiting for connection': string;
|
|
4
|
+
Play: string;
|
|
5
|
+
Pause: string;
|
|
6
|
+
'Picture in Picture': string;
|
|
7
|
+
'Exit Picture in Picture': string;
|
|
8
|
+
Fullscreen: string;
|
|
9
|
+
'Exit Fullscreen': string;
|
|
10
|
+
Mute: string;
|
|
11
|
+
Unmute: string;
|
|
12
|
+
'The system does not support picture-in-picture mode': string;
|
|
4
13
|
};
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
const resource = {
|
|
2
2
|
"No video": "No video",
|
|
3
|
-
"Waiting for connection": "Waiting for connection"
|
|
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
|
};
|
|
5
14
|
export {
|
|
6
15
|
resource
|
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
export declare const resource: {
|
|
2
2
|
'No video': string;
|
|
3
3
|
'Waiting for connection': string;
|
|
4
|
+
Play: string;
|
|
5
|
+
Pause: string;
|
|
6
|
+
'Picture in Picture': string;
|
|
7
|
+
'Exit Picture in Picture': string;
|
|
8
|
+
Fullscreen: string;
|
|
9
|
+
'Exit Fullscreen': string;
|
|
10
|
+
Mute: string;
|
|
11
|
+
Unmute: string;
|
|
12
|
+
'The system does not support picture-in-picture mode': string;
|
|
4
13
|
};
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
const resource = {
|
|
2
2
|
"No video": "暂无画面",
|
|
3
|
-
"Waiting for connection": "等待连线"
|
|
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
|
};
|
|
5
14
|
export {
|
|
6
15
|
resource
|