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
|
@@ -128,7 +128,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
128
128
|
_: 1
|
|
129
129
|
})) : createCommentVNode("", true),
|
|
130
130
|
createVNode(unref(TUIDialog), {
|
|
131
|
-
appendTo: "body",
|
|
132
131
|
visible: isShowTransferDialog.value,
|
|
133
132
|
title: unref(t)("ChatSetting.transfer_group_owner"),
|
|
134
133
|
"custom-classes": ["user-picker-dialog"],
|
|
@@ -154,7 +153,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
154
153
|
_: 1
|
|
155
154
|
}, 8, ["visible", "title"]),
|
|
156
155
|
createVNode(unref(TUIDialog), {
|
|
157
|
-
appendTo: "body",
|
|
158
156
|
visible: isShowDismissDialog.value,
|
|
159
157
|
title: unref(t)("ChatSetting.dismiss_group"),
|
|
160
158
|
onClose: _cache[5] || (_cache[5] = () => isShowDismissDialog.value = false),
|
|
@@ -162,7 +160,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
162
160
|
onConfirm: handleDismissGroup
|
|
163
161
|
}, null, 8, ["visible", "title"]),
|
|
164
162
|
createVNode(unref(TUIDialog), {
|
|
165
|
-
appendTo: "body",
|
|
166
163
|
visible: isShowQuitDialog.value,
|
|
167
164
|
title: unref(t)("ChatSetting.quit_group"),
|
|
168
165
|
onClose: _cache[7] || (_cache[7] = () => isShowQuitDialog.value = false),
|
|
@@ -178,7 +175,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
178
175
|
};
|
|
179
176
|
}
|
|
180
177
|
});
|
|
181
|
-
const GroupActions = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
178
|
+
const GroupActions = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-a8fcc66e"]]);
|
|
182
179
|
export {
|
|
183
180
|
GroupActions as default
|
|
184
181
|
};
|
|
@@ -227,7 +227,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
227
227
|
createVNode(unref(PersonalSettings)),
|
|
228
228
|
createVNode(unref(GroupActions)),
|
|
229
229
|
createVNode(unref(TUIDialog), {
|
|
230
|
-
appendTo: "body",
|
|
231
230
|
visible: isShowUserPickerDialog.value,
|
|
232
231
|
title: userPickerDialogTitle.value,
|
|
233
232
|
"custom-classes": ["user-picker-dialog"],
|
|
@@ -256,7 +255,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
256
255
|
};
|
|
257
256
|
}
|
|
258
257
|
});
|
|
259
|
-
const GroupChatSetting = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
258
|
+
const GroupChatSetting = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-7374cfa4"]]);
|
|
260
259
|
export {
|
|
261
260
|
GroupChatSetting as default
|
|
262
261
|
};
|
|
@@ -253,7 +253,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
253
253
|
_: 1
|
|
254
254
|
})) : createCommentVNode("", true),
|
|
255
255
|
createVNode(unref(TUIDialog), {
|
|
256
|
-
appendTo: "body",
|
|
257
256
|
"custom-classes": ["user-picker-dialog"],
|
|
258
257
|
visible: isShowUserPickerDialog.value,
|
|
259
258
|
title: userPickerTitle.value,
|
|
@@ -279,7 +278,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
279
278
|
};
|
|
280
279
|
}
|
|
281
280
|
});
|
|
282
|
-
const GroupManagement = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
281
|
+
const GroupManagement = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-a5ebaab5"]]);
|
|
283
282
|
export {
|
|
284
283
|
GroupManagement as default
|
|
285
284
|
};
|
|
@@ -131,7 +131,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
131
131
|
_: 1
|
|
132
132
|
}),
|
|
133
133
|
createVNode(unref(TUIDialog), {
|
|
134
|
-
appendTo: "body",
|
|
135
134
|
visible: visible.value,
|
|
136
135
|
title: canDismissGroup.value ? unref(t)("TUIContact.Confirm dismiss group") : unref(t)("TUIContact.Confirm quit group"),
|
|
137
136
|
"confirm-text": unref(t)("TUIContact.Submit"),
|
|
@@ -149,7 +148,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
149
148
|
};
|
|
150
149
|
}
|
|
151
150
|
});
|
|
152
|
-
const GroupInfo = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
151
|
+
const GroupInfo = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-8f45a224"]]);
|
|
153
152
|
export {
|
|
154
153
|
GroupInfo as default
|
|
155
154
|
};
|
|
@@ -180,7 +180,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
180
180
|
}, [
|
|
181
181
|
createVNode(ConversationCreateButton, { onClick: openCreateConversation }),
|
|
182
182
|
createVNode(unref(TUIDialog), {
|
|
183
|
-
appendTo: "body",
|
|
184
183
|
visible: showCreateConversation.value,
|
|
185
184
|
title: dialogTitles.value,
|
|
186
185
|
"confirm-text": dialogConfirmText.value,
|
|
@@ -212,7 +211,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
212
211
|
};
|
|
213
212
|
}
|
|
214
213
|
});
|
|
215
|
-
const ConversationCreateComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-
|
|
214
|
+
const ConversationCreateComponent = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-bdcdab3b"]]);
|
|
216
215
|
export {
|
|
217
216
|
ConversationCreateComponent as default
|
|
218
217
|
};
|
|
@@ -139,7 +139,6 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
139
139
|
}, null, 40, ["class", "variant", "SearchBar", "SearchResultsPresearch", "SearchResultsLoading", "SearchResultsEmpty", "SearchResultItem", "onSearchComplete", "onError"]))
|
|
140
140
|
], 2)) : createCommentVNode("", true),
|
|
141
141
|
createVNode(unref(TUIDialog), {
|
|
142
|
-
appendTo: "body",
|
|
143
142
|
customClasses: [_ctx.$style.conversationSearch__advanced],
|
|
144
143
|
visible: isShowStandard.value,
|
|
145
144
|
"show-close": false,
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
import { defineComponent, ref, computed, onUnmounted, createElementBlock, openBlock, normalizeStyle, createElementVNode, withDirectives, unref, createBlock, normalizeClass, toDisplayString, vShow } from "vue";
|
|
2
|
+
import { useUIKit, IconSpeakerOff, IconSpeakerOn } from "@tencentcloud/uikit-base-component-vue3";
|
|
3
|
+
import { isMobile } from "../../../utils/env.js";
|
|
4
|
+
import { _ as _export_sfc } from "../../../_plugin-vue_export-helper-1tPrXgE0.js";
|
|
5
|
+
const _hoisted_1 = ["title"];
|
|
6
|
+
const _hoisted_2 = { class: "volume-slider-container" };
|
|
7
|
+
const _hoisted_3 = { class: "volume-slider-wrapper-inner" };
|
|
8
|
+
const _hoisted_4 = { class: "slider-track" };
|
|
9
|
+
const _hoisted_5 = { class: "volume-value" };
|
|
10
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
11
|
+
__name: "AudioControl",
|
|
12
|
+
props: {
|
|
13
|
+
iconSize: { default: 20 },
|
|
14
|
+
enableVolumeControl: { type: Boolean, default: true }
|
|
15
|
+
},
|
|
16
|
+
emits: ["volume-change", "muted-change"],
|
|
17
|
+
setup(__props, { emit: __emit }) {
|
|
18
|
+
const props = __props;
|
|
19
|
+
const emit = __emit;
|
|
20
|
+
const { t } = useUIKit();
|
|
21
|
+
const volumeState = ref({
|
|
22
|
+
current: 1,
|
|
23
|
+
previous: 1
|
|
24
|
+
});
|
|
25
|
+
const isMuted = ref(false);
|
|
26
|
+
const isVolumeSliderVisible = ref(false);
|
|
27
|
+
const isDragging = ref(false);
|
|
28
|
+
const volumeSliderElement = ref();
|
|
29
|
+
const volumeSliderAutoHideTimer = ref(null);
|
|
30
|
+
const AUTO_HIDE_DELAY = {
|
|
31
|
+
PC: 500,
|
|
32
|
+
// 0.5 seconds for PC
|
|
33
|
+
MOBILE: 3e3
|
|
34
|
+
// 3 seconds for mobile
|
|
35
|
+
};
|
|
36
|
+
const volumePercentage = computed(() => {
|
|
37
|
+
if (props.enableVolumeControl === false) {
|
|
38
|
+
return isMuted.value ? 0 : 100;
|
|
39
|
+
}
|
|
40
|
+
return Math.round(volumeState.value.current * 100);
|
|
41
|
+
});
|
|
42
|
+
const iconSizeStyle = computed(() => ({
|
|
43
|
+
width: `${props.iconSize || 20}px`,
|
|
44
|
+
height: `${props.iconSize || 20}px`
|
|
45
|
+
}));
|
|
46
|
+
const updateVolume = (newVolume) => {
|
|
47
|
+
volumeState.value.current = newVolume;
|
|
48
|
+
volumeState.value.previous = newVolume;
|
|
49
|
+
isMuted.value = newVolume === 0;
|
|
50
|
+
emit("volume-change", newVolume);
|
|
51
|
+
};
|
|
52
|
+
const toggleMute = () => {
|
|
53
|
+
if (isMuted.value) {
|
|
54
|
+
isMuted.value = false;
|
|
55
|
+
volumeState.value.current = volumeState.value.previous || 0.2;
|
|
56
|
+
emit("muted-change", false);
|
|
57
|
+
} else {
|
|
58
|
+
isMuted.value = true;
|
|
59
|
+
volumeState.value.previous = volumeState.value.current;
|
|
60
|
+
volumeState.value.current = 0;
|
|
61
|
+
emit("muted-change", true);
|
|
62
|
+
}
|
|
63
|
+
updateVolume(volumeState.value.current);
|
|
64
|
+
};
|
|
65
|
+
const handleVolumeIconClick = () => {
|
|
66
|
+
if (props.enableVolumeControl === false) {
|
|
67
|
+
toggleMute();
|
|
68
|
+
} else {
|
|
69
|
+
if (isMobile) {
|
|
70
|
+
isVolumeSliderVisible.value = !isVolumeSliderVisible.value;
|
|
71
|
+
if (isVolumeSliderVisible.value) {
|
|
72
|
+
startVolumeSliderAutoHideTimer();
|
|
73
|
+
} else {
|
|
74
|
+
stopVolumeSliderAutoHideTimer();
|
|
75
|
+
}
|
|
76
|
+
} else {
|
|
77
|
+
toggleMute();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
const startVolumeSliderAutoHideTimer = () => {
|
|
82
|
+
stopVolumeSliderAutoHideTimer();
|
|
83
|
+
const delay = isMobile ? AUTO_HIDE_DELAY.MOBILE : AUTO_HIDE_DELAY.PC;
|
|
84
|
+
volumeSliderAutoHideTimer.value = window.setTimeout(() => {
|
|
85
|
+
if (props.enableVolumeControl) {
|
|
86
|
+
isVolumeSliderVisible.value = false;
|
|
87
|
+
}
|
|
88
|
+
}, delay);
|
|
89
|
+
};
|
|
90
|
+
const stopVolumeSliderAutoHideTimer = () => {
|
|
91
|
+
if (volumeSliderAutoHideTimer.value) {
|
|
92
|
+
clearTimeout(volumeSliderAutoHideTimer.value);
|
|
93
|
+
volumeSliderAutoHideTimer.value = null;
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
const handleMouseEnter = () => {
|
|
97
|
+
if (props.enableVolumeControl === false) return;
|
|
98
|
+
if (isMobile) return;
|
|
99
|
+
isVolumeSliderVisible.value = true;
|
|
100
|
+
startVolumeSliderAutoHideTimer();
|
|
101
|
+
};
|
|
102
|
+
const handleMouseLeave = () => {
|
|
103
|
+
if (props.enableVolumeControl === false) return;
|
|
104
|
+
if (isMobile) return;
|
|
105
|
+
if (!isDragging.value) {
|
|
106
|
+
startVolumeSliderAutoHideTimer();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const calculateVolumeFromPosition = (clientY, target) => {
|
|
110
|
+
const rect = target.getBoundingClientRect();
|
|
111
|
+
const clickY = clientY - rect.top;
|
|
112
|
+
const height = rect.height;
|
|
113
|
+
return Math.max(0, Math.min(1, 1 - clickY / height));
|
|
114
|
+
};
|
|
115
|
+
const addGlobalEventListeners = () => {
|
|
116
|
+
document.addEventListener("mousemove", handleSliderMove);
|
|
117
|
+
document.addEventListener("mouseup", handleSliderEnd);
|
|
118
|
+
document.addEventListener("touchmove", handleSliderMove);
|
|
119
|
+
document.addEventListener("touchend", handleSliderEnd);
|
|
120
|
+
};
|
|
121
|
+
const removeGlobalEventListeners = () => {
|
|
122
|
+
document.removeEventListener("mousemove", handleSliderMove);
|
|
123
|
+
document.removeEventListener("mouseup", handleSliderEnd);
|
|
124
|
+
document.removeEventListener("touchmove", handleSliderMove);
|
|
125
|
+
document.removeEventListener("touchend", handleSliderEnd);
|
|
126
|
+
};
|
|
127
|
+
const startDragging = () => {
|
|
128
|
+
isDragging.value = true;
|
|
129
|
+
if (props.enableVolumeControl) {
|
|
130
|
+
stopVolumeSliderAutoHideTimer();
|
|
131
|
+
}
|
|
132
|
+
addGlobalEventListeners();
|
|
133
|
+
};
|
|
134
|
+
const handleSliderMove = (event) => {
|
|
135
|
+
if (!isDragging.value) return;
|
|
136
|
+
event.preventDefault();
|
|
137
|
+
let clientY;
|
|
138
|
+
if (event instanceof MouseEvent) {
|
|
139
|
+
clientY = event.clientY;
|
|
140
|
+
} else {
|
|
141
|
+
clientY = event.touches[0].clientY;
|
|
142
|
+
}
|
|
143
|
+
const volumeValue = calculateVolumeFromPosition(clientY, volumeSliderElement.value);
|
|
144
|
+
updateVolume(volumeValue);
|
|
145
|
+
};
|
|
146
|
+
const handleSliderEnd = () => {
|
|
147
|
+
isDragging.value = false;
|
|
148
|
+
if (props.enableVolumeControl && isVolumeSliderVisible.value) {
|
|
149
|
+
startVolumeSliderAutoHideTimer();
|
|
150
|
+
}
|
|
151
|
+
removeGlobalEventListeners();
|
|
152
|
+
};
|
|
153
|
+
const handleSliderMouseDown = (event) => {
|
|
154
|
+
if (props.enableVolumeControl === false) return;
|
|
155
|
+
startDragging();
|
|
156
|
+
event.preventDefault();
|
|
157
|
+
};
|
|
158
|
+
const handleSliderTouchStart = (event) => {
|
|
159
|
+
if (props.enableVolumeControl === false) return;
|
|
160
|
+
startDragging();
|
|
161
|
+
event.preventDefault();
|
|
162
|
+
};
|
|
163
|
+
const handleVolumeSliderAreaClick = () => {
|
|
164
|
+
if (props.enableVolumeControl === false) return;
|
|
165
|
+
if (isMobile) {
|
|
166
|
+
isVolumeSliderVisible.value = !isVolumeSliderVisible.value;
|
|
167
|
+
if (isVolumeSliderVisible.value) {
|
|
168
|
+
startVolumeSliderAutoHideTimer();
|
|
169
|
+
} else {
|
|
170
|
+
stopVolumeSliderAutoHideTimer();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
const handleVolumeSliderMouseEnter = () => {
|
|
175
|
+
if (props.enableVolumeControl === false) return;
|
|
176
|
+
if (isMobile) return;
|
|
177
|
+
stopVolumeSliderAutoHideTimer();
|
|
178
|
+
};
|
|
179
|
+
const handleVolumeSliderMouseLeave = () => {
|
|
180
|
+
if (props.enableVolumeControl === false) return;
|
|
181
|
+
if (isMobile) return;
|
|
182
|
+
if (!isDragging.value) {
|
|
183
|
+
startVolumeSliderAutoHideTimer();
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
onUnmounted(() => {
|
|
187
|
+
removeGlobalEventListeners();
|
|
188
|
+
if (volumeSliderAutoHideTimer.value) {
|
|
189
|
+
clearTimeout(volumeSliderAutoHideTimer.value);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
return (_ctx, _cache) => {
|
|
193
|
+
return openBlock(), createElementBlock("div", {
|
|
194
|
+
class: "audio-control",
|
|
195
|
+
style: normalizeStyle(iconSizeStyle.value),
|
|
196
|
+
onMouseenter: handleMouseEnter,
|
|
197
|
+
onMouseleave: handleMouseLeave
|
|
198
|
+
}, [
|
|
199
|
+
createElementVNode("span", {
|
|
200
|
+
class: "control-btn volume-btn",
|
|
201
|
+
title: isMuted.value ? unref(t)("Unmute") : unref(t)("Mute"),
|
|
202
|
+
onClick: handleVolumeIconClick
|
|
203
|
+
}, [
|
|
204
|
+
isMuted.value ? (openBlock(), createBlock(unref(IconSpeakerOff), {
|
|
205
|
+
key: 0,
|
|
206
|
+
size: "20"
|
|
207
|
+
})) : (openBlock(), createBlock(unref(IconSpeakerOn), {
|
|
208
|
+
key: 1,
|
|
209
|
+
size: "20"
|
|
210
|
+
}))
|
|
211
|
+
], 8, _hoisted_1),
|
|
212
|
+
withDirectives(createElementVNode("div", _hoisted_2, [
|
|
213
|
+
createElementVNode("div", {
|
|
214
|
+
class: "volume-slider-wrapper",
|
|
215
|
+
onMouseenter: handleVolumeSliderMouseEnter,
|
|
216
|
+
onMouseleave: handleVolumeSliderMouseLeave
|
|
217
|
+
}, [
|
|
218
|
+
createElementVNode("div", _hoisted_3, [
|
|
219
|
+
createElementVNode("div", {
|
|
220
|
+
ref_key: "volumeSliderElement",
|
|
221
|
+
ref: volumeSliderElement,
|
|
222
|
+
class: "custom-volume-slider",
|
|
223
|
+
onMousedown: handleSliderMouseDown,
|
|
224
|
+
onTouchstart: handleSliderTouchStart,
|
|
225
|
+
onClick: handleVolumeSliderAreaClick
|
|
226
|
+
}, [
|
|
227
|
+
createElementVNode("div", _hoisted_4, [
|
|
228
|
+
createElementVNode("div", {
|
|
229
|
+
class: "slider-progress",
|
|
230
|
+
style: normalizeStyle({ height: `${volumePercentage.value}%` })
|
|
231
|
+
}, null, 4),
|
|
232
|
+
createElementVNode("div", {
|
|
233
|
+
class: normalizeClass(["slider-thumb", { "no-transition": isDragging.value }]),
|
|
234
|
+
style: normalizeStyle({ bottom: `${volumePercentage.value}%` })
|
|
235
|
+
}, null, 6)
|
|
236
|
+
])
|
|
237
|
+
], 544)
|
|
238
|
+
]),
|
|
239
|
+
createElementVNode("div", _hoisted_5, toDisplayString(volumePercentage.value), 1)
|
|
240
|
+
], 32)
|
|
241
|
+
], 512), [
|
|
242
|
+
[vShow, isVolumeSliderVisible.value]
|
|
243
|
+
])
|
|
244
|
+
], 36);
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
const AudioControl = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-81e72abd"]]);
|
|
249
|
+
export {
|
|
250
|
+
AudioControl as default
|
|
251
|
+
};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
interface AudioControlProps {
|
|
2
|
+
iconSize?: number;
|
|
3
|
+
enableVolumeControl?: boolean;
|
|
4
|
+
}
|
|
5
|
+
declare const _default: import('vue').DefineComponent<import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<AudioControlProps>, {
|
|
6
|
+
iconSize: number;
|
|
7
|
+
enableVolumeControl: boolean;
|
|
8
|
+
}>>, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
|
|
9
|
+
"volume-change": (value: number) => void;
|
|
10
|
+
"muted-change": (value: boolean) => void;
|
|
11
|
+
}, string, import('vue').PublicProps, Readonly<import('vue').ExtractPropTypes<__VLS_WithDefaults<__VLS_TypePropsToRuntimeProps<AudioControlProps>, {
|
|
12
|
+
iconSize: number;
|
|
13
|
+
enableVolumeControl: boolean;
|
|
14
|
+
}>>> & Readonly<{
|
|
15
|
+
"onVolume-change"?: ((value: number) => any) | undefined;
|
|
16
|
+
"onMuted-change"?: ((value: boolean) => any) | undefined;
|
|
17
|
+
}>, {
|
|
18
|
+
iconSize: number;
|
|
19
|
+
enableVolumeControl: boolean;
|
|
20
|
+
}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
21
|
+
export default _default;
|
|
22
|
+
type __VLS_NonUndefinedable<T> = T extends undefined ? never : T;
|
|
23
|
+
type __VLS_TypePropsToRuntimeProps<T> = {
|
|
24
|
+
[K in keyof T]-?: {} extends Pick<T, K> ? {
|
|
25
|
+
type: import('vue').PropType<__VLS_NonUndefinedable<T[K]>>;
|
|
26
|
+
} : {
|
|
27
|
+
type: import('vue').PropType<T[K]>;
|
|
28
|
+
required: true;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
type __VLS_WithDefaults<P, D> = {
|
|
32
|
+
[K in keyof Pick<P, keyof P>]: K extends keyof D ? __VLS_Prettify<P[K] & {
|
|
33
|
+
default: D[K];
|
|
34
|
+
}> : P[K];
|
|
35
|
+
};
|
|
36
|
+
type __VLS_Prettify<T> = {
|
|
37
|
+
[K in keyof T]: T[K];
|
|
38
|
+
} & {};
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import AudioControl from "./AudioControl.js";
|
|
2
|
+
import { defineComponent, ref, onMounted, onBeforeUnmount, createBlock, openBlock, Transition, withCtx, withDirectives, createElementVNode, normalizeClass, unref, createVNode, vShow } from "vue";
|
|
3
|
+
import { useUIKit, IconPause, IconPlay, IconPictureInPicture, IconFullScreen, TUIToast, TOAST_TYPE } from "@tencentcloud/uikit-base-component-vue3";
|
|
4
|
+
import { usePlayerControlState } from "./PlayerControlState.js";
|
|
5
|
+
import { isSafariBrowser, isFirefoxBrowser } from "./utils/deviceDetection.js";
|
|
6
|
+
import { isMobile } from "../../../utils/env.js";
|
|
7
|
+
import { _ as _export_sfc } from "../../../_plugin-vue_export-helper-1tPrXgE0.js";
|
|
8
|
+
const _hoisted_1 = { class: "control-buttons" };
|
|
9
|
+
const _hoisted_2 = ["title"];
|
|
10
|
+
const _hoisted_3 = { class: "right-controls" };
|
|
11
|
+
const _hoisted_4 = { class: "control-btn audio-control-btn" };
|
|
12
|
+
const _hoisted_5 = ["title"];
|
|
13
|
+
const _hoisted_6 = ["title"];
|
|
14
|
+
const AUTO_HIDE_DELAY = 3e3;
|
|
15
|
+
const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
16
|
+
__name: "PlayerControl",
|
|
17
|
+
setup(__props) {
|
|
18
|
+
const {
|
|
19
|
+
isPlaying,
|
|
20
|
+
isFullscreen,
|
|
21
|
+
isPictureInPicture,
|
|
22
|
+
pause,
|
|
23
|
+
resume,
|
|
24
|
+
requestPictureInPicture,
|
|
25
|
+
exitPictureInPicture,
|
|
26
|
+
requestFullscreen,
|
|
27
|
+
exitFullscreen,
|
|
28
|
+
setVolume,
|
|
29
|
+
cleanup
|
|
30
|
+
} = usePlayerControlState();
|
|
31
|
+
const { t } = useUIKit();
|
|
32
|
+
const currentVolume = ref(1);
|
|
33
|
+
const isMuted = ref(false);
|
|
34
|
+
const playerControlRef = ref();
|
|
35
|
+
const showControls = ref(false);
|
|
36
|
+
const hideTimeout = ref(null);
|
|
37
|
+
const isEnableVolumeControl = () => {
|
|
38
|
+
if (!isMobile) return true;
|
|
39
|
+
if (isSafariBrowser()) return false;
|
|
40
|
+
if (isFirefoxBrowser()) return false;
|
|
41
|
+
return true;
|
|
42
|
+
};
|
|
43
|
+
const handlePlayPause = () => {
|
|
44
|
+
if (isPlaying.value) {
|
|
45
|
+
pause();
|
|
46
|
+
} else {
|
|
47
|
+
resume();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const handlePictureInPicture = async () => {
|
|
51
|
+
let flag = false;
|
|
52
|
+
if (isPictureInPicture.value) {
|
|
53
|
+
flag = await exitPictureInPicture();
|
|
54
|
+
} else {
|
|
55
|
+
flag = await requestPictureInPicture();
|
|
56
|
+
}
|
|
57
|
+
if (!flag) {
|
|
58
|
+
TUIToast({
|
|
59
|
+
type: TOAST_TYPE.ERROR,
|
|
60
|
+
message: t("The system does not support picture-in-picture mode")
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
const handleFullscreen = () => {
|
|
65
|
+
console.log("handleFullscreen");
|
|
66
|
+
if (isFullscreen.value) {
|
|
67
|
+
exitFullscreen();
|
|
68
|
+
} else {
|
|
69
|
+
requestFullscreen();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
const handleVolumeChange = async (volume) => {
|
|
73
|
+
currentVolume.value = volume;
|
|
74
|
+
if (isMobile) {
|
|
75
|
+
startAutoHideControl();
|
|
76
|
+
}
|
|
77
|
+
await setVolume(volume);
|
|
78
|
+
};
|
|
79
|
+
const startAutoHideControl = () => {
|
|
80
|
+
stopAutoHideControl();
|
|
81
|
+
hideTimeout.value = window.setTimeout(() => {
|
|
82
|
+
showControls.value = false;
|
|
83
|
+
hideTimeout.value = null;
|
|
84
|
+
}, AUTO_HIDE_DELAY);
|
|
85
|
+
};
|
|
86
|
+
const stopAutoHideControl = () => {
|
|
87
|
+
if (hideTimeout.value) {
|
|
88
|
+
clearTimeout(hideTimeout.value);
|
|
89
|
+
hideTimeout.value = null;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
const handleMouseEnter = () => {
|
|
93
|
+
stopAutoHideControl();
|
|
94
|
+
showControls.value = true;
|
|
95
|
+
};
|
|
96
|
+
const handleMouseLeave = () => {
|
|
97
|
+
startAutoHideControl();
|
|
98
|
+
};
|
|
99
|
+
const setupParentMouseListener = () => {
|
|
100
|
+
if (!isMobile && playerControlRef.value) {
|
|
101
|
+
const parentElement = playerControlRef.value.parentElement;
|
|
102
|
+
if (parentElement) {
|
|
103
|
+
parentElement.addEventListener("mouseenter", handleMouseEnter);
|
|
104
|
+
parentElement.addEventListener("mouseleave", handleMouseLeave);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
const removeParentMouseListener = () => {
|
|
109
|
+
if (!isMobile && playerControlRef.value) {
|
|
110
|
+
const parentElement = playerControlRef.value.parentElement;
|
|
111
|
+
if (parentElement) {
|
|
112
|
+
parentElement.removeEventListener("mouseenter", handleMouseEnter);
|
|
113
|
+
parentElement.removeEventListener("mouseleave", handleMouseLeave);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
const touchStartCoords = ref(null);
|
|
118
|
+
const calculateTouchDistance = (start, end) => {
|
|
119
|
+
return Math.sqrt(Math.pow(end.clientX - start.x, 2) + Math.pow(end.clientY - start.y, 2));
|
|
120
|
+
};
|
|
121
|
+
const isPlayerControlTarget = (target) => {
|
|
122
|
+
var _a;
|
|
123
|
+
return ((_a = playerControlRef.value) == null ? void 0 : _a.contains(target)) || false;
|
|
124
|
+
};
|
|
125
|
+
const isLiveCoreViewTarget = (target) => {
|
|
126
|
+
const container = document.getElementById("live-core-view-container");
|
|
127
|
+
return (container == null ? void 0 : container.contains(target)) || false;
|
|
128
|
+
};
|
|
129
|
+
const handlePlayerControlTouch = () => {
|
|
130
|
+
stopAutoHideControl();
|
|
131
|
+
startAutoHideControl();
|
|
132
|
+
};
|
|
133
|
+
const handleLiveCoreViewTouch = () => {
|
|
134
|
+
showControls.value = !showControls.value;
|
|
135
|
+
if (showControls.value) {
|
|
136
|
+
startAutoHideControl();
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
const handleScreenTouchStart = (event) => {
|
|
140
|
+
if (event.touches.length === 1) {
|
|
141
|
+
const touch = event.touches[0];
|
|
142
|
+
touchStartCoords.value = {
|
|
143
|
+
x: touch.clientX,
|
|
144
|
+
y: touch.clientY
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
const handleScreenTouchMove = (event) => {
|
|
149
|
+
if (playerControlRef.value && playerControlRef.value.contains(event.target)) {
|
|
150
|
+
stopAutoHideControl();
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
const handleScreenTouchEnd = (event) => {
|
|
155
|
+
if (!touchStartCoords.value) {
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
const touchEnd = event.changedTouches[0];
|
|
159
|
+
const distance = calculateTouchDistance(touchStartCoords.value, touchEnd);
|
|
160
|
+
const MAX_CLICK_DISTANCE = 20;
|
|
161
|
+
if (distance > MAX_CLICK_DISTANCE) {
|
|
162
|
+
touchStartCoords.value = null;
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const target = event.target;
|
|
166
|
+
if (isPlayerControlTarget(target)) {
|
|
167
|
+
handlePlayerControlTouch();
|
|
168
|
+
} else if (isLiveCoreViewTarget(target)) {
|
|
169
|
+
handleLiveCoreViewTouch();
|
|
170
|
+
} else {
|
|
171
|
+
showControls.value = false;
|
|
172
|
+
}
|
|
173
|
+
touchStartCoords.value = null;
|
|
174
|
+
};
|
|
175
|
+
const setupTouchEventListeners = () => {
|
|
176
|
+
if (isMobile) {
|
|
177
|
+
document.addEventListener("touchstart", handleScreenTouchStart, true);
|
|
178
|
+
document.addEventListener("touchmove", handleScreenTouchMove, true);
|
|
179
|
+
document.addEventListener("touchend", handleScreenTouchEnd, true);
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
const removeTouchEventListeners = () => {
|
|
183
|
+
if (isMobile) {
|
|
184
|
+
document.removeEventListener("touchstart", handleScreenTouchStart, true);
|
|
185
|
+
document.removeEventListener("touchmove", handleScreenTouchMove, true);
|
|
186
|
+
document.removeEventListener("touchend", handleScreenTouchEnd, true);
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
const handleMutedChange = async (muted) => {
|
|
190
|
+
isMuted.value = muted;
|
|
191
|
+
if (muted) {
|
|
192
|
+
await setVolume(0);
|
|
193
|
+
} else {
|
|
194
|
+
await setVolume(currentVolume.value);
|
|
195
|
+
}
|
|
196
|
+
};
|
|
197
|
+
const cleanupEventListeners = () => {
|
|
198
|
+
removeTouchEventListeners();
|
|
199
|
+
removeParentMouseListener();
|
|
200
|
+
stopAutoHideControl();
|
|
201
|
+
};
|
|
202
|
+
onMounted(() => {
|
|
203
|
+
setupTouchEventListeners();
|
|
204
|
+
setupParentMouseListener();
|
|
205
|
+
});
|
|
206
|
+
onBeforeUnmount(() => {
|
|
207
|
+
cleanupEventListeners();
|
|
208
|
+
cleanup();
|
|
209
|
+
});
|
|
210
|
+
return (_ctx, _cache) => {
|
|
211
|
+
return openBlock(), createBlock(Transition, { name: "player-control" }, {
|
|
212
|
+
default: withCtx(() => [
|
|
213
|
+
withDirectives(createElementVNode("div", {
|
|
214
|
+
ref_key: "playerControlRef",
|
|
215
|
+
ref: playerControlRef,
|
|
216
|
+
class: normalizeClass(["playback-controls", unref(isMobile) ? "mobile-mode" : "pc-mode"])
|
|
217
|
+
}, [
|
|
218
|
+
createElementVNode("div", _hoisted_1, [
|
|
219
|
+
createElementVNode("span", {
|
|
220
|
+
class: "control-btn play-pause-btn",
|
|
221
|
+
title: unref(isPlaying) ? unref(t)("Pause") : unref(t)("Play"),
|
|
222
|
+
onClick: handlePlayPause
|
|
223
|
+
}, [
|
|
224
|
+
unref(isPlaying) ? (openBlock(), createBlock(unref(IconPause), {
|
|
225
|
+
key: 0,
|
|
226
|
+
size: "20"
|
|
227
|
+
})) : (openBlock(), createBlock(unref(IconPlay), {
|
|
228
|
+
key: 1,
|
|
229
|
+
size: "20"
|
|
230
|
+
}))
|
|
231
|
+
], 8, _hoisted_2),
|
|
232
|
+
_cache[0] || (_cache[0] = createElementVNode("div", { class: "center-controls" }, null, -1)),
|
|
233
|
+
createElementVNode("div", _hoisted_3, [
|
|
234
|
+
createElementVNode("span", _hoisted_4, [
|
|
235
|
+
createVNode(AudioControl, {
|
|
236
|
+
class: "audio-control-icon",
|
|
237
|
+
"icon-size": 20,
|
|
238
|
+
"enable-volume-control": isEnableVolumeControl(),
|
|
239
|
+
onVolumeChange: handleVolumeChange,
|
|
240
|
+
onMutedChange: handleMutedChange
|
|
241
|
+
}, null, 8, ["enable-volume-control"])
|
|
242
|
+
]),
|
|
243
|
+
createElementVNode("span", {
|
|
244
|
+
class: "control-btn",
|
|
245
|
+
title: unref(isPictureInPicture) ? unref(t)("Exit Picture in Picture") : unref(t)("Picture in Picture"),
|
|
246
|
+
onClick: handlePictureInPicture
|
|
247
|
+
}, [
|
|
248
|
+
createVNode(unref(IconPictureInPicture), { size: "20" })
|
|
249
|
+
], 8, _hoisted_5),
|
|
250
|
+
createElementVNode("span", {
|
|
251
|
+
class: "control-btn fullscreen-btn",
|
|
252
|
+
title: unref(isFullscreen) ? unref(t)("Exit Fullscreen") : unref(t)("Fullscreen"),
|
|
253
|
+
onClick: handleFullscreen
|
|
254
|
+
}, [
|
|
255
|
+
createVNode(unref(IconFullScreen), { size: "20" })
|
|
256
|
+
], 8, _hoisted_6)
|
|
257
|
+
])
|
|
258
|
+
])
|
|
259
|
+
], 2), [
|
|
260
|
+
[vShow, showControls.value]
|
|
261
|
+
])
|
|
262
|
+
]),
|
|
263
|
+
_: 1
|
|
264
|
+
});
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
const PlayerControl = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-cb28a3fe"]]);
|
|
269
|
+
export {
|
|
270
|
+
PlayerControl as default
|
|
271
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
declare const _default: import('vue').DefineComponent<{}, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, true, {}, any>;
|
|
2
|
+
export default _default;
|